Commit 0d2ef3ea authored by jiatao's avatar jiatao

提交初始化配置

parent cb79e7eb
version: '3.1'
services:
mysql:
container_name: mysql
image: mysql:8.0.33
ports:
- "3306:3306"
volumes:
- ./mysql/conf:/etc/mysql/conf.d
- ./mysql/logs:/logs
- ./mysql/data:/var/lib/mysql
- ./db:/db
command: [
'mysqld',
'--innodb-buffer-pool-size=80M',
'--character-set-server=utf8mb4',
'--collation-server=utf8mb4_general_ci',
'--default-time-zone=+8:00',
'--lower-case-table-names=1'
]
environment:
MYSQL_DATABASE: 'rs_dev'
MYSQL_ROOT_PASSWORD: xjtu@gwyy.
MYSQL_CHARSET: 'utf8mb4'
MYSQL_COLLATION: 'utf8mb4_general_ci'
healthcheck: # MySQL健康检查
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-p$$MYSQL_ROOT_PASSWORD"] # 使用环境变量进行连接检查
interval: 10s
timeout: 5s
retries: 3
start_period: 30s # 给MySQL足够的初始化时间
restart: always # 容器退出时总是重启容器
nginx:
image: nginx:1.24.0 # 镜像`nginx:1.21.1`
container_name: nginx # 容器名为'nginx'
restart: unless-stopped # 指定容器退出后的重启策略为始终重启,但是不考虑在Docker守护进程启动时就已经停止了的容器
volumes: # 数据卷挂载路径设置,将本机目录映射到容器目录
- "./nginx/conf/nginx.conf:/etc/nginx/nginx.conf"
- "./nginx/html:/usr/share/nginx/html"
- "./nginx/log:/var/log/nginx"
- "./nginx/conf.d:/etc/nginx/conf.d"
environment: # 设置环境变量,相当于docker run命令中的-e
TZ: Asia/Shanghai
LANG: en_US.UTF-8
ports: # 映射端口
- "80:80"
networks:
- my-network
redis:
image: redis:7.0.5 # 镜像'redis:7.0.5'
container_name: redis # 容器名为'redis'
restart: unless-stopped # 指定容器退出后的重启策略为始终重启,但是不考虑在Docker守护进程启动时就已经停止了的容器
command: redis-server /etc/redis/redis.conf --appendonly no # 启动redis服务并添加密码为:123456,默认不开启redis-aof方式持久化配置
# command: redis-server --requirepass 123456 --appendonly yes # 启动redis服务并添加密码为:123456,并开启redis持久化配置
environment: # 设置环境变量,相当于docker run命令中的-e
TZ: Asia/Shanghai
LANG: en_US.UTF-8
volumes: # 数据卷挂载路径设置,将本机目录映射到容器目录
- "./redis/data:/data"
- "./redis/conf/redis.conf:/etc/redis/redis.conf" # `redis.conf`文件内容`http://download.redis.io/redis-stable/redis.conf`
ports: # 映射端口
- "6379:6379"
healthcheck: # Redis健康检查
test: ["CMD", "redis-cli", "ping"] # 发送PING命令,期待返回PONG
interval: 5s
timeout: 3s
retries: 5
start_period: 10s
networks:
- my-network
rs-service:
container_name: rs-service
build:
context: ./service
dockerfile: dockerfile
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://10.47.2.11:3306/rs_dev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
SPRING_DATASOURCE_USERNAME: rs_service
SPRING_DATASOURCE_PASSWORD: ezGkNdezsZJE
REDIS_HOST: 10.47.2.10
REDIS_PORT: 6379
REDIS_PASSWORD:
UPLOAD_PATH: /home/rs/uploadPath
# 将时区设置为Asia/Shanghai
TZ: Asia/Shanghai
depends_on: # 依赖关系定义
redis:
condition: service_healthy # 明确等待Redis健康
mysql:
condition: service_healthy # 明确等待MySQL健康
volumes:
- ./service/logs:/home/rs/logs
- ./service/uploadPath:/home/rs/uploadPath
networks:
- my-network
networks:
my-network:
name: my-network
driver: bridge
# 基础镜像
FROM openjdk:8
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/rs
# 创建目录
RUN mkdir -p /home/rs
# 指定路径
WORKDIR /home/rs
# 复制jar文件到路径
COPY ./jar/ruoyi-admin.jar /home/rs/ruoyi-admin.jar
# 启动应用
ENTRYPOINT ["java","-jar","ruoyi-admin.jar"]
This diff is collapsed.
package com.ruoyi.cas;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
@RestController
@RequestMapping("/api/cas")
public class CasController extends BaseController {
@Autowired
private CasAuthService casAuthService;
@Autowired
private TokenService tokenService;
/**
* 跳转到CAS登录
*/
@GetMapping("/login")
public AjaxResult login(HttpServletRequest request,
@RequestParam String redirect) throws IOException {
String loginUrl = casAuthService.buildLoginUrl(redirect);
return AjaxResult.success().put("loginUrl",loginUrl);
}
/**
* CAS回调接口
*/
@GetMapping("/callback")
public AjaxResult callback(
@RequestParam String ticket,
@RequestParam(required = false) String redirect) throws IOException {
try {
String service = buildServiceUrl(redirect);
return casAuthService.validateTicket(ticket, service);
} catch (Exception e) {
logger.error("CAS回调处理异常", e);
return AjaxResult.error(e.getMessage());
}
}
/**
* 退出登录
*/
@PostMapping("/logout")
public AjaxResult logout(HttpServletRequest request, @RequestParam(required = false) String redirect) {
// 获取当前登录用户
LoginUser loginUser = tokenService.getLoginUser(request);
if (loginUser != null) {
// 删除本地用户缓存
tokenService.delLoginUser(loginUser.getToken());
}
// 构建CAS登出URL
String logoutUrl = casAuthService.buildLogoutUrl(redirect);
return AjaxResult.success().put("logoutUrl",logoutUrl);
}
/**
* 构建服务URL
*/
private String buildServiceUrl(String redirect) {
String baseUrl = getBaseUrl();
String service = baseUrl + "/api/cas/callback";
if (StringUtils.isNotEmpty(redirect)) {
try {
service += "?redirect=" + URLEncoder.encode(redirect, String.valueOf(StandardCharsets.UTF_8));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
return service;
}
/**
* 构建带Token的重定向URL
*/
private String buildRedirectUrlWithToken(String redirectUrl, String token) {
String separator = redirectUrl.contains("?") ? "&" : "?";
return redirectUrl + separator + "token=" + token;
}
/**
* 获取默认重定向URL
*/
private String getDefaultRedirectUrl() {
return getBaseUrl() + "/index";
}
/**
* 获取基础URL
*/
private String getBaseUrl() {
// 根据实际情况实现获取当前系统URL的逻辑
return "http://gwyy.xjtu.edu.cn";
}
}
\ No newline at end of file
package com.ruoyi.web.controller.system;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.ApprovalStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.ReservationApproval;
import com.ruoyi.system.domain.SpaceSeat;
import com.ruoyi.system.service.IReservationApprovalService;
import com.ruoyi.system.service.ISpaceSeatService;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
@RequestMapping("/system/approval")
@RestController
public class ReservationApprovalController extends BaseController {
@Autowired
public IReservationApprovalService reservationApprovalService;
@Autowired
private ISpaceSeatService spaceSeatService;
@Autowired
private ISysUserService userService;
@PreAuthorize("@ss.hasPermi('system:approval:list')")
@GetMapping("/list")
public TableDataInfo list(ReservationApproval reservationApproval){
startPage();
List<ReservationApproval> list = reservationApprovalService.list(new LambdaQueryWrapper<ReservationApproval>()
.eq(StringUtils.isNotEmpty(reservationApproval.getSeatCode()),ReservationApproval::getSeatCode,reservationApproval.getSeatCode())
.eq(StringUtils.isNotEmpty(reservationApproval.getSubmitBy()),ReservationApproval::getSubmitBy,reservationApproval.getSubmitBy())
.eq(StringUtils.isNotEmpty(reservationApproval.getStatus()),ReservationApproval::getStatus,reservationApproval.getStatus())
.orderByDesc(ReservationApproval::getSubmitAt));
List<String> seatCodes = list.stream().map(ReservationApproval::getSeatCode).collect(Collectors.toList());
Map<String, SpaceSeat> spaceSeatMap = spaceSeatService.selectSpaceSeatByCodes(seatCodes)
.stream().collect(Collectors.toMap(SpaceSeat::getSeatCode, Function.identity()));
List<String> submitPersonNos = list.stream().map(ReservationApproval::getSubmitBy).collect(Collectors.toList());
List<String> approvedPersonNos = list.stream().map(ReservationApproval::getApprovedBy).collect(Collectors.toList());
submitPersonNos.addAll(approvedPersonNos);
submitPersonNos.add("default");
Map<String,String> personNameMap = userService.selectUsersByUserName(submitPersonNos)
.stream().collect(Collectors.toMap(SysUser::getUserName,SysUser::getNickName));
for (ReservationApproval approval : list) {
approval.setSpaceSeat(spaceSeatMap.getOrDefault(approval.getSeatCode(),new SpaceSeat()));
approval.setSubmitByName(personNameMap.getOrDefault(approval.getSubmitBy(),""));
approval.setApprovedByName(personNameMap.getOrDefault(approval.getApprovedBy(),""));
}
return getDataTable(list);
}
/**
* 最近预约
* @return
*/
@PreAuthorize("@ss.hasPermi('system:approval:RecentReservation')")
@GetMapping("/recentReservation")
public AjaxResult RecentReservation(){
List<ReservationApproval> list = reservationApprovalService.list(new LambdaQueryWrapper<ReservationApproval>()
.eq(ReservationApproval::getSubmitBy,SecurityUtils.getUsername())
.in(ReservationApproval::getStatus, ApprovalStatus.PASS.getCode(),ApprovalStatus.WAITING.getCode())
.ge(ReservationApproval::getStartAt,new Date()));
List<String> seatCodes = list.stream().map(ReservationApproval::getSeatCode).collect(Collectors.toList());
Map<String, SpaceSeat> spaceSeatMap = spaceSeatService.selectSpaceSeatByCodes(seatCodes)
.stream().collect(Collectors.toMap(SpaceSeat::getSeatCode, Function.identity()));
for (ReservationApproval approval : list) {
approval.setSpaceSeat(spaceSeatMap.getOrDefault(approval.getSeatCode(),new SpaceSeat()));
}
return AjaxResult.success(list);
}
/**
* 提交审核
* @param reservationApproval
* @return
*/
@PostMapping("/submit")
public AjaxResult submit(@RequestBody ReservationApproval reservationApproval){
return AjaxResult.success(reservationApprovalService.submitApproval(reservationApproval));
}
/**
* 审核 工位申请
* @param reservationApproval
* @return
*/
@PostMapping("/approval")
public AjaxResult approval(@RequestBody ReservationApproval reservationApproval){
if (!reservationApproval.getStatus().equals(ApprovalStatus.PASS.getCode())
&& !reservationApproval.getStatus().equals(ApprovalStatus.FAILED.getCode())){
throw new ServiceException("审核参数错误!");
}
ReservationApproval entity = reservationApprovalService.getById(reservationApproval.getApprovalId());
if (StringUtils.isNull(entity)){
throw new ServiceException("参数错误,无法查询指定申请");
}
if (!entity.getStatus().equals(ApprovalStatus.WAITING.getCode())){
throw new ServiceException("请刷新重试,该申请无法审核");
}
ReservationApproval updateEntity = new ReservationApproval();
updateEntity.setApprovedBy(SecurityUtils.getUsername());
updateEntity.setApprovedAt(new Date());
updateEntity.setApprovalId(reservationApproval.getApprovalId());
updateEntity.setStatus(reservationApproval.getStatus());
return AjaxResult.success(reservationApprovalService.updateById(updateEntity));
}
/**
* 签到
* @param approvalId
* @return
*/
@PostMapping("/sign/{approvalId}")
public AjaxResult sign(@PathVariable("approvalId") Long approvalId){
ReservationApproval reservationApproval = reservationApprovalService.getById(approvalId);
if (StringUtils.isNull(reservationApproval)){
throw new ServiceException("参数错误,查询不到指定的申请");
}
// Date currDate = new Date();
// if (currDate.getTime() < DateUtil.offsetMinute(reservationApproval.getStartAt(),-10).getTime()){
// throw new ServiceException("还未到签到时间");
// }
//
// if (currDate.getTime() > reservationApproval.getEndAt().getTime()){
// throw new ServiceException("已过签到时间");
// }
reservationApproval.setStatus(ApprovalStatus.ALREADY_SIGN.getCode());
return AjaxResult.success(reservationApprovalService.updateById(reservationApproval));
}
/**
* 撤销申请
* @param approvalId
* @return
*/
@PostMapping("/cancel/{approvalId}")
public AjaxResult cancelApproval(@PathVariable("approvalId") Long approvalId){
ReservationApproval reservationApproval = reservationApprovalService.getById(approvalId);
if (StringUtils.isNull(reservationApproval)){
throw new ServiceException("参数错误,查询不到指定的申请");
}
return AjaxResult.success(reservationApprovalService.removeById(approvalId));
}
}
package com.ruoyi.web.controller.system;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.enums.BlacklistStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.ReservationBlacklist;
import com.ruoyi.system.service.IReservationBlacklistService;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 黑名单
Controller
*
* @author ruoyi
* @date 2025-11-04
*/
@RestController
@RequestMapping("/system/blacklist")
public class ReservationBlacklistController extends BaseController
{
@Autowired
private IReservationBlacklistService reservationBlacklistService;
/**
* 查询黑名单
列表
*/
@PreAuthorize("@ss.hasPermi('system:blacklist:list')")
@GetMapping("/list")
public TableDataInfo list(ReservationBlacklist reservationBlacklist)
{
startPage();
List<ReservationBlacklist> list = reservationBlacklistService.selectReservationBlacklistList(reservationBlacklist);
return getDataTable(list);
}
/**
* 获取黑名单
详细信息
*/
@PreAuthorize("@ss.hasPermi('system:blacklist:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(reservationBlacklistService.selectReservationBlacklistById(id));
}
/**
* 新增黑名单
*/
@PreAuthorize("@ss.hasPermi('system:blacklist:add')")
@Log(title = "黑名单 ", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody ReservationBlacklist reservationBlacklist)
{
long count = reservationBlacklistService.count(new LambdaQueryWrapper<ReservationBlacklist>()
.eq(ReservationBlacklist::getPersonNo,reservationBlacklist.getPersonNo()));
if (count>0){
throw new ServiceException("黑名单已有成员,请勿重复添加");
}
if (StringUtils.isEmpty(reservationBlacklist.getStatus())){
reservationBlacklist.setStatus(BlacklistStatus.OPEN.getCode());
}
return toAjax(reservationBlacklistService.insertReservationBlacklist(reservationBlacklist));
}
/**
* 修改黑名单
*/
@PreAuthorize("@ss.hasPermi('system:blacklist:edit')")
@Log(title = "黑名单", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody ReservationBlacklist reservationBlacklist)
{
return toAjax(reservationBlacklistService.updateReservationBlacklist(reservationBlacklist));
}
/**
* 删除黑名单
*/
@PreAuthorize("@ss.hasPermi('system:blacklist:remove')")
@Log(title = "黑名单", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(reservationBlacklistService.deleteReservationBlacklistByIds(ids));
}
}
package com.ruoyi.web.controller.system;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.SchoolBuildService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.SchoolBuild;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 楼宇Controller
*
* @author ruoyi
* @date 2025-11-03
*/
@RestController
@RequestMapping("/system/build")
public class SchoolBuildController extends BaseController
{
@Autowired
private SchoolBuildService schoolBuildService;
/**
* 查询楼宇列表
*/
@PreAuthorize("@ss.hasPermi('system:build:list')")
@GetMapping("/list")
public TableDataInfo list(SchoolBuild schoolBuild)
{
startPage();
List<SchoolBuild> list = schoolBuildService.list(new LambdaQueryWrapper<SchoolBuild>()
.eq(StringUtils.isNotEmpty(schoolBuild.getCampusCode()),SchoolBuild::getCampusCode,schoolBuild.getCampusCode())
.like(StringUtils.isNotEmpty(schoolBuild.getBuildName()),SchoolBuild::getBuildName,schoolBuild.getBuildName()));
return getDataTable(list);
}
/**
* 获取楼宇详细信息
*/
@PreAuthorize("@ss.hasPermi('system:build:query')")
@GetMapping(value = "/{buildId}")
public AjaxResult getInfo(@PathVariable("buildId") Long buildId)
{
return success(schoolBuildService.getBuildById(buildId));
}
/**
* 新增楼宇
*/
@PreAuthorize("@ss.hasPermi('system:build:add')")
@Log(title = "楼宇", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SchoolBuild schoolBuild)
{
return toAjax(schoolBuildService.insertBuild(schoolBuild));
}
/**
* 修改楼宇
*/
@PreAuthorize("@ss.hasPermi('system:build:edit')")
@Log(title = "楼宇", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SchoolBuild schoolBuild)
{
return toAjax(schoolBuildService.updateBuild(schoolBuild));
}
/**
* 删除楼宇
*/
@PreAuthorize("@ss.hasPermi('system:build:remove')")
@Log(title = "楼宇", businessType = BusinessType.DELETE)
@DeleteMapping("/{buildId}")
public AjaxResult remove(@PathVariable Long buildId)
{
return toAjax(schoolBuildService.deleteBuild(buildId));
}
}
package com.ruoyi.web.controller.system;
import java.util.List;
import java.util.stream.Collectors;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.tree.TreeDto;
import com.ruoyi.common.core.tree.TreeUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.SchoolBuildService;
import com.ruoyi.system.service.SchoolCampusService;
import com.ruoyi.system.service.SchoolFloorService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.SchoolCampus;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 校区Controller
*
* @author ruoyi
* @date 2025-11-03
*/
@RestController
@RequestMapping("/system/campus")
public class SchoolCampusController extends BaseController
{
@Autowired
private SchoolCampusService schoolCampusService;
@Autowired
private SchoolBuildService schoolBuildService;
@Autowired
private SchoolFloorService schoolFloorService;
/**
* 查询校区列表
*/
@PreAuthorize("@ss.hasPermi('system:campus:list')")
@GetMapping("/list")
public TableDataInfo list(SchoolCampus schoolCampus)
{
startPage();
List<SchoolCampus> list = schoolCampusService.list(new LambdaQueryWrapper<SchoolCampus>()
.like(StringUtils.isNotEmpty(schoolCampus.getName()),SchoolCampus::getName,schoolCampus.getName()));
return getDataTable(list);
}
/**
* 获取校区详细信息
*/
@PreAuthorize("@ss.hasPermi('system:campus:query')")
@GetMapping(value = "/{campusId}")
public AjaxResult getInfo(@PathVariable("campusId") Long campusId)
{
return success(schoolCampusService.getById(campusId));
}
/**
* 新增校区
*/
@PreAuthorize("@ss.hasPermi('system:campus:add')")
@Log(title = "校区", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SchoolCampus schoolCampus)
{
return toAjax(schoolCampusService.insertCampus(schoolCampus));
}
/**
* 修改校区
*/
@PreAuthorize("@ss.hasPermi('system:campus:edit')")
@Log(title = "校区", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SchoolCampus schoolCampus)
{
return toAjax(schoolCampusService.updateCampus(schoolCampus));
}
/**
* 删除校区
*/
@PreAuthorize("@ss.hasPermi('system:campus:remove')")
@Log(title = "校区", businessType = BusinessType.DELETE)
@DeleteMapping("/{campusId}")
public AjaxResult remove(@PathVariable Long campusId)
{
return toAjax(schoolCampusService.deleteCampus(campusId));
}
/**
* 获取校区 - 楼栋 - 楼层 树
* @return
*/
@GetMapping("/get-campus-tree")
public AjaxResult getCampusTree(){
// 1:获取校区
List<TreeDto> schoolCampuses = schoolCampusService.selectTreeDto(null,null);
List<String> campusCodes = schoolCampuses.stream().map(TreeDto::getCode)
.collect(Collectors.toList());
campusCodes.add("default");
List<TreeDto> builds = schoolBuildService.selectTreeDtos(campusCodes);
List<String> buildCodes = builds.stream().map(TreeDto::getCode).collect(Collectors.toList());
buildCodes.add("default");
List<TreeDto> floors = schoolFloorService.selectTreeDtos(buildCodes);
schoolCampuses.addAll(builds);
schoolCampuses.addAll(floors);
return AjaxResult.success(TreeUtil.buildTree(schoolCampuses));
}
}
package com.ruoyi.web.controller.system;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.SchoolFloorService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.SchoolFloor;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 楼层Controller
*
* @author ruoyi
* @date 2025-11-03
*/
@RestController
@RequestMapping("/system/floor")
public class SchoolFloorController extends BaseController
{
@Autowired
private SchoolFloorService schoolFloorService;
/**
* 查询楼层列表
*/
@PreAuthorize("@ss.hasPermi('system:floor:list')")
@GetMapping("/list")
public TableDataInfo list(SchoolFloor schoolFloor)
{
startPage();
List<SchoolFloor> list = schoolFloorService.list(new LambdaQueryWrapper<SchoolFloor>()
.eq(StringUtils.isNotEmpty(schoolFloor.getBuildCode()),SchoolFloor::getBuildCode,schoolFloor.getBuildCode())
.like(StringUtils.isNotEmpty(schoolFloor.getFloorName()),SchoolFloor::getFloorName,schoolFloor.getFloorName()));
return getDataTable(list);
}
/**
* 获取楼层详细信息
*/
@PreAuthorize("@ss.hasPermi('system:floor:query')")
@GetMapping(value = "/{floorId}")
public AjaxResult getInfo(@PathVariable("floorId") Long floorId)
{
return success(schoolFloorService.getById(floorId));
}
/**
* 新增楼层
*/
@PreAuthorize("@ss.hasPermi('system:floor:add')")
@Log(title = "楼层", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SchoolFloor schoolFloor)
{
return toAjax(schoolFloorService.insertFloor(schoolFloor));
}
/**
* 修改楼层
*/
@PreAuthorize("@ss.hasPermi('system:floor:edit')")
@Log(title = "楼层", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SchoolFloor schoolFloor)
{
return toAjax(schoolFloorService.updateFloor(schoolFloor));
}
/**
* 删除楼层
*/
@PreAuthorize("@ss.hasPermi('system:floor:remove')")
@Log(title = "楼层", businessType = BusinessType.DELETE)
@DeleteMapping("/{floorId}")
public AjaxResult remove(@PathVariable Long floorId)
{
return toAjax(schoolFloorService.deleteFloor(floorId));
}
}
package com.ruoyi.web.controller.system;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.service.ISpaceSeatService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.Space;
import com.ruoyi.system.service.ISpaceService;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 房间Controller
*
* @author ruoyi
* @date 2025-11-03
*/
@RestController
@RequestMapping("/system/space")
public class SpaceController extends BaseController
{
@Autowired
private ISpaceService spaceService;
@Autowired
private ISpaceSeatService spaceSeatService;
/**
* 查询房间列表
*/
@PreAuthorize("@ss.hasPermi('system:space:list')")
@GetMapping("/list")
public TableDataInfo list(Space space)
{
startPage();
List<Space> list = spaceService.list(new LambdaQueryWrapper<Space>()
.eq(StringUtils.isNotEmpty(space.getBuildCode()),Space::getBuildCode,space.getBuildCode())
.eq(StringUtils.isNotEmpty(space.getCampusCode()),Space::getCampusCode,space.getCampusCode())
.eq(StringUtils.isNotEmpty(space.getFloorCode()),Space::getFloorCode,space.getFloorCode())
.like(StringUtils.isNotEmpty(space.getName()),Space::getName,space.getName()));
if (StringUtils.isNotEmpty(list)) {
List<String> spaceCodes = list.stream().map(Space::getSpaceCode).collect(Collectors.toList());
Map<String, Long> spaceSeatNumberMap = spaceSeatService.selectSpaceSeatCount(spaceCodes)
.stream().collect(Collectors.toMap(Space::getSpaceCode,Space::getActualNumberOfSeats));
for (Space s : list) {
s.setActualNumberOfSeats(spaceSeatNumberMap.getOrDefault(s.getSpaceCode(), 0L));
}
}
return getDataTable(list);
}
/**
* 获取房间详细信息
*/
@PreAuthorize("@ss.hasPermi('system:space:query')")
@GetMapping(value = "/{spaceId}")
public AjaxResult getInfo(@PathVariable("spaceId") Long spaceId)
{
return success(spaceService.getById(spaceId));
}
/**
* 新增房间
*/
@PreAuthorize("@ss.hasPermi('system:space:add')")
@Log(title = "房间", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody Space space)
{
space.setSpaceCode(IdUtils.randomUUID());
return toAjax(spaceService.save(space));
}
/**
* 修改房间
*/
@PreAuthorize("@ss.hasPermi('system:space:edit')")
@Log(title = "房间", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody Space space)
{
space.setUpdateTime(new Date());
space.setUpdateBy(SecurityUtils.getUsername());
return toAjax(spaceService.updateById(space));
}
/**
* 删除房间
*/
@PreAuthorize("@ss.hasPermi('system:space:remove')")
@Log(title = "房间", businessType = BusinessType.DELETE)
@DeleteMapping("/{spaceIds}")
public AjaxResult remove(@PathVariable Long[] spaceIds)
{
return toAjax(spaceService.deleteSpaceBySpaceIds(spaceIds));
}
/**
* 检查房间座位空闲
* @param spaceId
* @param startAt
* @param endAt
* @return
*/
@GetMapping("/check-space-seat/{spaceId}")
public AjaxResult checkSpaceSeat(@PathVariable("spaceId") Long spaceId,
@RequestParam("startAt") Date startAt,
@RequestParam("endAt") Date endAt){
return AjaxResult.success(spaceService.checkSpaceSeat(spaceId, startAt, endAt));
}
}
package com.ruoyi.web.controller.system;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.SpaceSeat;
import com.ruoyi.system.service.ISpaceSeatService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 座位Controller
*
* @author ruoyi
* @date 2025-11-03
*/
@RestController
@RequestMapping("/system/seat")
public class SpaceSeatController extends BaseController
{
@Autowired
private ISpaceSeatService spaceSeatService;
/**
* 查询座位列表
*/
@PreAuthorize("@ss.hasPermi('system:seat:list')")
@GetMapping("/list")
public TableDataInfo list(SpaceSeat spaceSeat)
{
startPage();
List<SpaceSeat> list = spaceSeatService.selectSpaceSeatList(spaceSeat);
return getDataTable(list);
}
/**
* 导出座位列表
*/
@PreAuthorize("@ss.hasPermi('system:seat:export')")
@Log(title = "座位", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, SpaceSeat spaceSeat)
{
List<SpaceSeat> list = spaceSeatService.selectSpaceSeatList(spaceSeat);
ExcelUtil<SpaceSeat> util = new ExcelUtil<SpaceSeat>(SpaceSeat.class);
util.exportExcel(response, list, "座位数据");
}
/**
* 获取座位详细信息
*/
@PreAuthorize("@ss.hasPermi('system:seat:query')")
@GetMapping(value = "/{seatId}")
public AjaxResult getInfo(@PathVariable("seatId") Long seatId)
{
return success(spaceSeatService.selectSpaceSeatBySeatId(seatId));
}
/**
* 新增座位
*/
@PreAuthorize("@ss.hasPermi('system:seat:add')")
@Log(title = "座位", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SpaceSeat spaceSeat)
{
return toAjax(spaceSeatService.insertSpaceSeat(spaceSeat));
}
/**
* 修改座位
*/
@PreAuthorize("@ss.hasPermi('system:seat:edit')")
@Log(title = "座位", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SpaceSeat spaceSeat)
{
return toAjax(spaceSeatService.updateSpaceSeat(spaceSeat));
}
/**
* 删除座位
*/
@PreAuthorize("@ss.hasPermi('system:seat:remove')")
@Log(title = "座位", businessType = BusinessType.DELETE)
@DeleteMapping("/{seatIds}")
public AjaxResult remove(@PathVariable Long[] seatIds)
{
return toAjax(spaceSeatService.deleteSpaceSeatBySeatIds(seatIds));
}
}
......@@ -3,17 +3,16 @@ package com.ruoyi.web.controller.system;
import java.util.Date;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.domain.model.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
......@@ -30,6 +29,7 @@ import com.ruoyi.system.service.ISysMenuService;
* @author ruoyi
*/
@RestController
@Slf4j
public class SysLoginController
{
@Autowired
......@@ -47,6 +47,8 @@ public class SysLoginController
@Autowired
private ISysConfigService configService;
/**
* 登录方法
*
......@@ -128,4 +130,12 @@ public class SysLoginController
}
return false;
}
}
......@@ -99,3 +99,10 @@ swagger:
enabled: true
# 请求前缀
pathMapping: /prod-api
# CAS配置
cas:
server-url: https://login.xjtu.edu.cn/cas
client-host-url: http://gwyy.xjtu.edu.cn # 你的业务系统地址
validation-type: CAS3
\ No newline at end of file
......@@ -100,3 +100,10 @@ swagger:
enabled: true
# 请求前缀
pathMapping: /prod-api
# CAS配置
cas:
server-url: https://login.xjtu.edu.cn/cas
client-host-url: http://gwyy.xjtu.edu.cn # 你的业务系统地址
validation-type: CAS3
\ No newline at end of file
......@@ -16,7 +16,7 @@ ruoyi:
# 开发环境配置
server:
# 服务器的HTTP端口,默认为8080
port: 8080
port: 8100
servlet:
# 应用的访问路径
context-path: /
......@@ -95,7 +95,7 @@ token:
# 令牌密钥
secret: abcdefghijklmnopqrstuvwxyz
# 令牌有效期(默认30分钟)
expireTime: 30
expireTime: 120
# MyBatis Plus配置
mybatis-plus:
......@@ -109,8 +109,8 @@ mybatis-plus:
global-config:
db-config:
logic-delete-field: delFlag # 全局逻辑删除字段名(deleted为实体类属性名称)
logic-delete-value: 1 # 逻辑已删除值。可选,默认值为 1
logic-not-delete-value: 2 # 逻辑未删除值。可选,默认值为 0
logic-delete-value: 2 # 逻辑已删除值。可选,默认值为 1
logic-not-delete-value: 0 # 逻辑未删除值。可选,默认值为 0
# 关闭Banner
banner: false
......
<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
<cas:authenticationSuccess>
<cas:user>test001</cas:user>
<cas:attributes>
<cas:attribute name="name">测试用户</cas:attribute>
<cas:attribute name="accountId">1001</cas:attribute>
<cas:attribute name="userId">1001</cas:attribute>
<cas:attribute name="userName">student003</cas:attribute>
<cas:attribute name="identityTypeId">1</cas:attribute>
<cas:attribute name="identityTypeCode">S01</cas:attribute>
<cas:attribute name="identityTypeName">本科生</cas:attribute>
<cas:attribute name="organizationId">1</cas:attribute>
<cas:attribute name="organizationCode">13002000</cas:attribute>
<cas:attribute name="organizationName">计算机学院</cas:attribute>
</cas:attributes>
</cas:authenticationSuccess>
</cas:serviceResponse>
\ No newline at end of file
......@@ -126,6 +126,31 @@
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- Redisson 锁功能 -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.16.2</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.38</version>
</dependency>
<!-- CAS Client -->
<dependency>
<groupId>org.jasig.cas.client</groupId>
<artifactId>cas-client-core</artifactId>
<version>3.6.4</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.ruoyi.common.config;
import org.jasig.cas.client.authentication.AuthenticationFilter;
import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class CasConfig {
@Value("${cas.server-url}")
private String casServerUrl;
@Value("${cas.client-host-url}")
private String clientHostUrl;
// /**
// * CAS认证过滤器 - 简化配置
// */
// @Bean
// public FilterRegistrationBean<AuthenticationFilter> casAuthenticationFilter() {
// FilterRegistrationBean<AuthenticationFilter> registration = new FilterRegistrationBean<>();
// AuthenticationFilter filter = new AuthenticationFilter();
//
// Map<String, String> initParameters = new HashMap<>();
// initParameters.put("casServerLoginUrl", casServerUrl + "/login");
// initParameters.put("serverName", clientHostUrl);
// initParameters.put("ignorePattern", "/api/cas/callback|/logout|/error");
//
// registration.setFilter(filter);
// registration.setInitParameters(initParameters);
// registration.addUrlPatterns("/*");
// registration.setOrder(1);
// return registration;
// }
/**
* CAS票据验证器
*/
@Bean
public Cas20ServiceTicketValidator cas20ServiceTicketValidator() {
Cas20ServiceTicketValidator validator = new Cas20ServiceTicketValidator(casServerUrl);
// 设置自定义属性解析器
validator.setCustomParameters(Collections.singletonMap("format", "XML"));
return validator;
}
}
......@@ -170,4 +170,12 @@ public class Constants
*/
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
"org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config", "com.ruoyi.generator" };
// 老师类型
public static final String TEACHER = "teacher";
// 学生类型
public static final String STUDENT = "student";
}
......@@ -4,6 +4,9 @@ import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
......@@ -19,20 +22,25 @@ public class BaseEntity implements Serializable
/** 搜索值 */
@JsonIgnore
@TableField(exist = false)
private String searchValue;
/** 创建者 */
@TableField(fill = FieldFill.INSERT)
private String createBy;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/** 更新者 */
@TableField(fill = FieldFill.UPDATE)
private String updateBy;
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@TableField(fill = FieldFill.UPDATE)
private Date updateTime;
/** 备注 */
......@@ -40,6 +48,7 @@ public class BaseEntity implements Serializable
/** 请求参数 */
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@TableField(exist = false)
private Map<String, Object> params;
public String getSearchValue()
......
......@@ -6,6 +6,9 @@ import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.core.domain.BaseEntity;
......@@ -15,6 +18,7 @@ import com.ruoyi.common.core.domain.BaseEntity;
*
* @author ruoyi
*/
@Data
public class SysDept extends BaseEntity
{
private static final long serialVersionUID = 1L;
......@@ -22,6 +26,9 @@ public class SysDept extends BaseEntity
/** 部门ID */
private Long deptId;
/** 部门编码 */
public String deptCode;
/** 父部门ID */
private Long parentId;
......@@ -50,9 +57,11 @@ public class SysDept extends BaseEntity
private String delFlag;
/** 父部门名称 */
@TableField(exist = false)
private String parentName;
/** 子部门 */
@TableField(exist = false)
private List<SysDept> children = new ArrayList<SysDept>();
public Long getDeptId()
......
......@@ -3,6 +3,8 @@ package com.ruoyi.common.core.domain.entity;
import java.util.Date;
import java.util.List;
import javax.validation.constraints.*;
import com.baomidou.mybatisplus.annotation.TableField;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
......@@ -78,18 +80,23 @@ public class SysUser extends BaseEntity
@Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT),
@Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT)
})
@TableField(exist = false)
private SysDept dept;
/** 角色对象 */
@TableField(exist = false)
private List<SysRole> roles;
/** 角色组 */
@TableField(exist = false)
private Long[] roleIds;
/** 岗位组 */
@TableField(exist = false)
private Long[] postIds;
/** 角色ID */
@TableField(exist = false)
private Long roleId;
public SysUser()
......
......@@ -2,6 +2,7 @@ package com.ruoyi.common.core.domain.model;
import com.alibaba.fastjson2.annotation.JSONField;
import com.ruoyi.common.core.domain.entity.SysUser;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
......@@ -12,6 +13,7 @@ import java.util.Set;
*
* @author ruoyi
*/
@Data
public class LoginUser implements UserDetails
{
private static final long serialVersionUID = 1L;
......@@ -71,6 +73,9 @@ public class LoginUser implements UserDetails
*/
private SysUser user;
private String gsessionId;
public LoginUser()
{
}
......
package com.ruoyi.common.core.redis;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* redis锁工具类
*
* @author ruoyi
*/
@Component
public class RedisLock {
@Autowired
private RedissonClient redissonClient;
/**
* 获取锁
*
* @param lockKey 锁实例key
* @return 锁信息
*/
public RLock getRLock(String lockKey) {
return redissonClient.getLock(lockKey);
}
/**
* 加锁
*
* @param lockKey 锁实例key
* @return 锁信息
*/
public RLock lock(String lockKey) {
RLock lock = getRLock(lockKey);
lock.lock();
return lock;
}
/**
* 加锁
*
* @param lockKey 锁实例key
* @param leaseTime 上锁后自动释放锁时间
* @return true=成功;false=失败
*/
public Boolean tryLock(String lockKey, long leaseTime) {
return tryLock(lockKey, 0, leaseTime, TimeUnit.SECONDS);
}
/**
* 加锁
*
* @param lockKey 锁实例key
* @param leaseTime 上锁后自动释放锁时间
* @param unit 时间颗粒度
* @return true=加锁成功;false=加锁失败
*/
public Boolean tryLock(String lockKey, long leaseTime, TimeUnit unit) {
return tryLock(lockKey, 0, leaseTime, unit);
}
/**
* 加锁
*
* @param lockKey 锁实例key
* @param waitTime 最多等待时间
* @param leaseTime 上锁后自动释放锁时间
* @param unit 时间颗粒度
* @return true=加锁成功;false=加锁失败
*/
public Boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit) {
RLock rLock = getRLock(lockKey);
boolean tryLock = false;
try {
tryLock = rLock.tryLock(waitTime, leaseTime, unit);
} catch (InterruptedException e) {
return false;
}
return tryLock;
}
/**
* 释放锁
*
* @param lockKey 锁实例key
*/
public void unlock(String lockKey) {
RLock lock = getRLock(lockKey);
lock.unlock();
}
/**
* 释放锁
*
* @param lock 锁信息
*/
public void unlock(RLock lock) {
lock.unlock();
}
}
\ No newline at end of file
package com.ruoyi.common.core.redis;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* redisson配置
*
* @author ruoyi
*/
@Configuration
public class RedissonConfig
{
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private String port;
@Value("${spring.redis.password}")
private String password;
@Bean(destroyMethod = "shutdown")
@ConditionalOnMissingBean(RedissonClient.class)
public RedissonClient redissonClient()
{
Config config = new Config();
config.useSingleServer().setAddress("redis://" + host + ":" + port); // 更多.set
return Redisson.create(config);
}
}
\ No newline at end of file
package com.ruoyi.common.core.tree;
import java.util.ArrayList;
import java.util.List;
public interface BaseTree<T> {
// code
String getCode();
// pCode
String getParentCode();
// 节点集合
List<T> getChildren();
// 添加集合
void setChildren(List<T> t);
default void addChild(T t){
if (this.getChildren() == null) {
this.setChildren(new ArrayList<T>());
}
this.getChildren().add(t);
}
}
package com.ruoyi.common.core.tree;
import lombok.Data;
import java.util.List;
@Data
public class TreeDto implements BaseTree<TreeDto> {
private Long id;
private String code;
private String parentCode;
private String treeName;
private String type;
// 附加信息
private String attachment;
private List<TreeDto> children;
}
package com.ruoyi.common.core.tree;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
public class TreeUtil {
public static final String FIRST_PARENT_CODE = "0";
/**
* 封装整个树状图数据
* @param listNodes 要处理列表集合节点数据
*/
public static <T extends BaseTree> List<T> assembleTree(List<T> listNodes) {
List<T> newTreeNodes = new ArrayList<>();
// 循环赋值最上面的节点数据
// 赋值最上面节点的值
//这一步操作时找到root节点
newTreeNodes.addAll(listNodes.stream()
.filter(t -> t.getParentCode().equals("0"))
.collect(Collectors.toList()));
// 循环处理子节点数据
for (T t : newTreeNodes) {
//递归
assembleTree(t, listNodes);
}
return newTreeNodes;
}
/**
* 根据节点封装树状图集合数据
*
* @param node 处理的节点(当前节点)
* @param listNodes 要处理的列表数据
*/
private static <T extends BaseTree> void assembleTree(T node, List<T> listNodes) {
if (node != null && !CollectionUtils.isEmpty(listNodes)) {
// 循环节点数据,如果是子节点则添加起来
listNodes.stream()
.filter(t -> t.getParentCode().equals(node.getCode()))
.forEachOrdered(node::addChild);
// 循环处理子节点数据,递归
if (!CollectionUtils.isEmpty(node.getChildren())) {
for (Object t : node.getChildren()) {
//递归
assembleTree((T) t, listNodes);
}
}
}
}
// =====================================组装树========================================
public static <T extends BaseTree> List<T> buildTree(List<T> listNodes) {
List<T> returnList = new ArrayList<>();
if(listNodes == null){
return returnList;
}
List<String> tempList = listNodes.stream().map(BaseTree::getCode).collect(Collectors.toList());
for (T tree : listNodes) {
// 如果是顶级节点, 遍历该父节点的所有子节点
if (!tempList.contains(tree.getParentCode())) {
recursionFn(listNodes, tree);
returnList.add(tree);
}
}
if (returnList.isEmpty()) {
returnList = listNodes;
}
return returnList;
}
/**
* 递归列表
*/
private static <T extends BaseTree> void recursionFn(List<T> list, T t) {
// 得到子节点列表
List<T> childList = getChildList(list, t);
t.setChildren(childList);
for (T tChild : childList) {
if (hasChild(list, tChild)) {
recursionFn(list, tChild);
}
}
}
/**
* 得到子节点列表
*/
private static <T extends BaseTree> List<T> getChildList(List<T> list, T t) {
List<T> tlist = new ArrayList<T>();
Iterator<T> it = list.iterator();
while (it.hasNext()) {
T n = it.next();
if (StringUtils.isNotNull(n.getParentCode()) && n.getParentCode().equals(t.getCode())) {
tlist.add(n);
}
}
return tlist;
}
/**
* 判断是否有子节点
*/
private static <T extends BaseTree> boolean hasChild(List<T> list, T t) {
return getChildList(list, t).size() > 0 ? true : false;
}
}
\ No newline at end of file
package com.ruoyi.common.enums;
public enum ApprovalStatus {
NOT_SIGN("-2","未签到"),
FAILED("-1","审核未通过"),
WAITING("0","待审核"),
PASS("1","审核通过"),
ALREADY_SIGN("2","已签到");
private final String code;
private final String info;
ApprovalStatus(String code, String info)
{
this.code = code;
this.info = info;
}
public String getCode()
{
return code;
}
public String getInfo()
{
return info;
}
}
package com.ruoyi.common.enums;
public enum BlacklistStatus {
CLOSE("0","关闭"),
OPEN("1","启用"),
;
private final String code;
private final String info;
BlacklistStatus(String code, String info)
{
this.code = code;
this.info = info;
}
public String getCode()
{
return code;
}
public String getInfo()
{
return info;
}
}
package com.ruoyi.common.enums;
public enum IdentityTypeCode {
Undergraduate("S01","student","本科生"),
GraduateStudent("S02","student","研究生"),
InternationalStudent("SO3","student","留学生"),
Alumnus("XY","","校友"),
teacher("T01","teacher","老师"),
;
private final String code;
private final String roleKey;
private final String message;
IdentityTypeCode(String code, String roleKey,String message)
{
this.code = code;
this.roleKey = roleKey;
this.message = message;
}
public String getCode()
{
return code;
}
public String getRoleKey()
{
return roleKey;
}
public String getMessage() {
return message;
}
public static IdentityTypeCode getEnumByCode(String code){
for (IdentityTypeCode value : IdentityTypeCode.values()) {
if (value.getCode().equals(code)){
return value;
}
}
return null;
}
}
package com.ruoyi.common.enums;
public enum SsoUserType {
STUDENT("1","student"),
TEACHER("2","teacher");
;
private final String code;
private final String roleKey;
SsoUserType(String code, String roleKey)
{
this.code = code;
this.roleKey = roleKey;
}
public String getCode()
{
return code;
}
public String getRoleKey()
{
return roleKey;
}
public static SsoUserType getEnumByCode(String code){
for (SsoUserType value : SsoUserType.values()) {
if (value.getCode().equals(code)){
return value;
}
}
return null;
}
}
package com.ruoyi.common.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.ruoyi.common.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {
private static final String NO_DEL_VALUE = "0";
@Override
public void insertFill(MetaObject metaObject) {
// log.info("开始插入填充...");
this.strictInsertFill(metaObject, "createBy", String.class, SecurityUtils.getUsername());
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
this.strictInsertFill(metaObject,"delFlag",String.class,NO_DEL_VALUE);
}
@Override
public void updateFill(MetaObject metaObject) {
// log.info("开始插入填充...");
this.strictInsertFill(metaObject, "updateBy", String.class, SecurityUtils.getUsername());
this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());
}
}
package com.ruoyi.common.utils;
import cn.hutool.core.date.DateUtil;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
public class SimpleTimeRangeChecker {
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
/**
* 检查时间段是否在开放时间范围内
* @param openStart 开放开始时间 (格式: HH:mm:ss)
* @param openEnd 开放结束时间 (格式: HH:mm:ss)
* @param checkStart 检查开始时间 (格式: yyyy-MM-dd HH:mm:ss)
* @param checkEnd 检查结束时间 (格式: yyyy-MM-dd HH:mm:ss)
* @return 如果在开放时间范围内返回true,否则返回false
*/
public static boolean isTimeInRange(String openStart, String openEnd, Date checkStart ,Date checkEnd) {
try {
LocalTime openStartTime = LocalTime.parse(openStart, TIME_FORMATTER);
LocalTime openEndTime = LocalTime.parse(openEnd, TIME_FORMATTER);
LocalTime checkStartTime = checkStart.toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
LocalTime checkEndTime = checkEnd.toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
return !checkStartTime.isBefore(openStartTime) && !checkEndTime.isAfter(openEndTime);
} catch (Exception e) {
throw new IllegalArgumentException("时间格式解析错误", e);
}
}
// 测试
public static void main(String[] args) {
String openStart = "08:00:00";
String openEnd = "10:00:00";
String checkStart = "2025-11-03 08:30:00";
String checkEnd = "2025-11-03 11:30:00";
boolean result = isTimeInRange(openStart, openEnd, DateUtil.parse(checkStart,"yyyy-MM-dd HH:mm:ss"), DateUtil.parse(checkEnd,"yyyy-MM-dd HH:mm:ss"));
System.out.println("时间段是否在开放范围内: " + result); // true
}
}
......@@ -112,6 +112,7 @@ public class SecurityConfig
permitAllUrl.getUrls().forEach(url -> requests.antMatchers(url).permitAll());
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
requests.antMatchers("/login", "/register", "/captchaImage").permitAll()
.antMatchers("/api/cas/login","/api/cas/callback").permitAll()
// 静态资源,可匿名访问
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
.antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
......
package com.ruoyi.framework.web.service;
import javax.annotation.Resource;
import com.ruoyi.common.core.domain.entity.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
......@@ -27,6 +29,7 @@ import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.security.context.AuthenticationContextHolder;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.transaction.annotation.Transactional;
/**
* 登录校验方法
......@@ -63,7 +66,7 @@ public class SysLoginService
public String login(String username, String password, String code, String uuid)
{
// 验证码校验
validateCaptcha(username, code, uuid);
// validateCaptcha(username, code, uuid);
// 登录前置校验
loginPreCheck(username, password);
// 用户验证
......@@ -173,4 +176,6 @@ public class SysLoginService
{
userService.updateLoginInfo(userId, IpUtils.getIpAddr(), DateUtils.getNowDate());
}
}
......@@ -23,6 +23,7 @@
<artifactId>ruoyi-common</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.ruoyi.system.cas;
import lombok.Data;
@Data
public class CasUserInfo {
/**
* 用户名(登录账号)
*/
private String username;
/**
* 姓名
*/
private String name;
/**
* 用户ID
*/
private String userId;
/**
* 身份代码
*/
private String identityTypeCode;
/**
* 组织机构编码
*/
private String organizationCode;
/**
* 组织机构名称
*/
private String organizationName;
}
\ No newline at end of file
package com.ruoyi.system.cas;
import lombok.Data;
@Data
public class CasValidationResult {
private boolean success;
private CasUserInfo userInfo;
private String errorCode;
private String errorMessage;
}
\ No newline at end of file
package com.ruoyi.system.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import java.util.Date;
@Data
@TableName("reservation_approval")
public class ReservationApproval extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 申请id
*/
@TableId(type = IdType.AUTO)
private Long approvalId;
/** 座位编码 */
private String seatCode;
/** 提交时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date submitAt;
/** 提交人 */
private String submitBy;
@TableField(exist = false)
private String submitByName;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date startAt;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endAt;
/** 审核时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date approvedAt;
/** 审核人 */
private String approvedBy;
@TableField(exist = false)
private String approvedByName;
/** 审核状态 -1=未通过 0=待审核 1= 通过*/
private String status;
@TableLogic
private String delFlag;
@TableField(exist = false)
private SpaceSeat spaceSeat;
}
package com.ruoyi.system.domain;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 黑名单
对象 reservation_blacklist
*
* @author ruoyi
* @date 2025-11-04
*/
@Data
public class ReservationBlacklist extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键id */
@TableId(type = IdType.AUTO)
private Long id;
/** 人员工号 */
@Excel(name = "人员工号")
private String personNo;
@TableField(exist = false)
private String personName;
/** 状态 0=未启用 1=已启用 */
private String status;
/** 缘由 */
@Excel(name = "缘由")
private String reason;
/** 记录时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "记录时间", width = 30, dateFormat = "yyyy-MM-dd ")
private Date arrestedAt;
/** 创建人 */
@Excel(name = "创建人")
private String createdBy;
/** 删除标记 */
private String delFlag;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setReason(String reason)
{
this.reason = reason;
}
public String getReason()
{
return reason;
}
public void setArrestedAt(Date arrestedAt)
{
this.arrestedAt = arrestedAt;
}
public Date getArrestedAt()
{
return arrestedAt;
}
public void setCreatedBy(String createdBy)
{
this.createdBy = createdBy;
}
public String getCreatedBy()
{
return createdBy;
}
public void setDelFlag(String delFlag)
{
this.delFlag = delFlag;
}
public String getDelFlag()
{
return delFlag;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("personNo", getPersonNo())
.append("reason", getReason())
.append("arrestedAt", getArrestedAt())
.append("createdBy", getCreatedBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.append("delFlag", getDelFlag())
.toString();
}
}
package com.ruoyi.system.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.xss.Xss;
import com.ruoyi.system.service.impl.SchoolCampusServiceImpl;
import lombok.Data;
import org.apache.commons.lang3.ArrayUtils;
import java.util.List;
/**
* 楼宇
*/
@Data
public class SchoolBuild extends BaseEntity {
/**
* id
*/
@TableId(value = "build_id", type = IdType.AUTO)
private Long buildId;
/**
* 楼宇编码
*/
@TableField("build_code")
private String buildCode;
/**
* 楼宇父编码
*/
@TableField("campus_code")
private String campusCode;
/**
* 楼宇名称
*/
@Xss(message = "楼宇名称不能包含脚本字符")
@TableField("build_name")
private String buildName;
/**
* 排序
*/
@TableField("sort")
private Long sort;
/**
* 属性
*/
@Xss(message = "属性不能包含脚本字符")
@TableField("attribute")
private String attribute;
/**
* 删除标志(0代表存在 2代表删除)
*/
@TableField(value = "del_flag",fill = FieldFill.INSERT)
@TableLogic
private String delFlag;
/**
* 楼层
*/
@TableField(exist = false)
private List<SchoolFloor> schoolFloors;
public String getAttribute() {
if(ArrayUtils.isEmpty(this.attributes)){
return "";
}
return String.join(",", this.attributes);
}
//===============扩展字段=================
@TableField(exist = false)
private String[] attributes;
public String[] getAttributes() {
if(StringUtils.isNotEmpty(this.attribute)){
return this.attribute.split(",");
}
return null;
}
public String getCampusName(){
if (StringUtils.isNotEmpty(this.campusCode)){
return DictUtils.getDictLabel(SchoolCampusServiceImpl.DICT_TYPE,this.campusCode);
}
return "";
}
}
package com.ruoyi.system.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.xss.Xss;
import lombok.Data;
import java.util.List;
/**
* 校区
*/
@Data
public class SchoolCampus extends BaseEntity {
/**
* id
*/
@TableId(value = "campus_id", type = IdType.AUTO)
private Long campusId;
/**
* 校区编码
*/
@TableField("campus_code")
private String campusCode;
/**
* 校区名称
*/
@Xss(message = "校区名称不能包含脚本字符")
@TableField("name")
private String name;
/**
* 排序
*/
@TableField("sort")
private Long sort;
/**
* 删除标志(0代表存在 2代表删除)
*/
@TableField(value = "del_flag",fill = FieldFill.INSERT)
@TableLogic
private String delFlag;
/**
* 楼宇
*/
@TableField(exist = false)
private List<SchoolBuild> schoolBuilds;
}
package com.ruoyi.system.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.xss.Xss;
import com.ruoyi.system.service.impl.SchoolBuildServiceImpl;
import lombok.Data;
import org.apache.commons.lang3.ArrayUtils;
/**
* 楼层
*/
@Data
public class SchoolFloor extends BaseEntity {
/**
* id
*/
@TableId(value = "floor_id", type = IdType.AUTO)
private Long floorId;
/**
* 楼层编码
*/
@TableField("floor_code")
private String floorCode;
/**
* 楼层父编码
*/
@TableField("build_code")
private String buildCode;
/**
* 房间号
*/
@Xss(message = "房间号不能包含脚本字符")
@TableField("floor_name")
private String floorName;
/**
* 排序
*/
@TableField("sort")
private Long sort;
/**
* 属性
*/
@Xss(message = "属性不能包含脚本字符")
@TableField("attribute")
private String attribute;
/**
* 删除标志(0代表存在 2代表删除)
*/
@TableField(value = "del_flag",fill = FieldFill.INSERT)
@TableLogic
private String delFlag;
public String getAttribute() {
if(ArrayUtils.isEmpty(this.attributes)){
return "";
}
return String.join(",", this.attributes);
}
//===============扩展字段=================
@TableField(exist = false)
private String[] attributes;
public String[] getAttributes() {
if(StringUtils.isNotEmpty(this.attribute)){
return this.attribute.split(",");
}
return null;
}
public String getBuildName(){
if (StringUtils.isNotEmpty(this.buildCode)){
return DictUtils.getDictLabel(SchoolBuildServiceImpl.DICT_TYPE,this.buildCode);
}
return "";
}
}
package com.ruoyi.system.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.vo.OpenTime;
import com.ruoyi.system.service.impl.SchoolBuildServiceImpl;
import com.ruoyi.system.service.impl.SchoolCampusServiceImpl;
import com.ruoyi.system.service.impl.SchoolFloorServiceImpl;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import java.util.List;
/**
* 房间对象 space
*
* @author ruoyi
* @date 2025-11-03
*/
@Data
@TableName(value = "space",autoResultMap = true)
public class Space extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键id */
@TableId(type = IdType.AUTO)
private Long spaceId;
private String spaceCode;
/** 校区编码 */
@Excel(name = "校区编码")
private String campusCode;
/** 建筑编码 */
@Excel(name = "建筑编码")
private String buildCode;
/** 楼层编码 */
@Excel(name = "楼层编码")
private String floorCode;
/** 名称 */
@Excel(name = "名称")
private String name;
/** 容量 */
@Excel(name = "容量")
private Long seatCount;
/** 实际座位数 */
@TableField(exist = false)
private Long actualNumberOfSeats;
/** 预约区间 */
@Excel(name = "预约区间")
@TableField(value = "open_time",typeHandler = JacksonTypeHandler.class)
private OpenTime openTime;
/** 最小预约时长/分钟 */
@Excel(name = "最小预约时长/分钟")
private Long miniMumDuration;
/** 最小预约天数 */
@Excel(name = "最小预约天数")
private Long inAdvanceDuration;
/** 删除标记 */
@TableField(value = "del_flag",fill = FieldFill.INSERT)
@TableLogic
private String delFlag;
@TableField(exist = false)
private List<SpaceSeat> spaceSeats;
public void setCampusCode(String campusCode)
{
this.campusCode = campusCode;
}
public String getCampusCode()
{
return campusCode;
}
public void setBuildCode(String buildCode)
{
this.buildCode = buildCode;
}
public String getBuildCode()
{
return buildCode;
}
public void setFloorCode(String floorCode)
{
this.floorCode = floorCode;
}
public String getFloorCode()
{
return floorCode;
}
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
public void setSeatCount(Long seatCount)
{
this.seatCount = seatCount;
}
public Long getSeatCount()
{
return seatCount;
}
public void setMiniMumDuration(Long miniMumDuration)
{
this.miniMumDuration = miniMumDuration;
}
public Long getMiniMumDuration()
{
return miniMumDuration;
}
public void setInAdvanceDuration(Long inAdvanceDuration)
{
this.inAdvanceDuration = inAdvanceDuration;
}
public Long getInAdvanceDuration()
{
return inAdvanceDuration;
}
public void setDelFlag(String delFlag)
{
this.delFlag = delFlag;
}
public String getDelFlag()
{
return delFlag;
}
public String getCampusName(){
if (StringUtils.isNotEmpty(this.campusCode)){
return DictUtils.getDictLabel(SchoolCampusServiceImpl.DICT_TYPE,this.campusCode);
}
return "";
}
public String getBuildName(){
if (StringUtils.isNotEmpty(this.buildCode)){
return DictUtils.getDictLabel(SchoolBuildServiceImpl.DICT_TYPE,this.buildCode);
}
return "";
}
public String getFloorName(){
if (StringUtils.isNotEmpty(this.floorCode)){
return DictUtils.getDictLabel(SchoolFloorServiceImpl.DICT_TYPE,this.floorCode);
}
return "";
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("spaceId", getSpaceId())
.append("campusCode", getCampusCode())
.append("buildCode", getBuildCode())
.append("floorCode", getFloorCode())
.append("name", getName())
.append("seatCount", getSeatCount())
.append("openTime", getOpenTime())
.append("miniMumDuration", getMiniMumDuration())
.append("inAdvanceDuration", getInAdvanceDuration())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.append("delFlag", getDelFlag())
.toString();
}
}
package com.ruoyi.system.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 座位对象 space_seat
*
* @author ruoyi
* @date 2025-11-03
*/
@Data
public class SpaceSeat extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键id */
@TableId(type = IdType.AUTO)
private Long seatId;
private String seatCode;
/** 房间编码 */
@Excel(name = "房间编码")
private String spaceCode;
/** 座位名称 */
@Excel(name = "座位名称")
private String seatName;
/** 删除标记 */
@TableField(value = "del_flag",fill = FieldFill.INSERT)
private String delFlag;
@TableField
private Space space;
/**
* 是否可预约的
*/
@TableField(exist = false)
private Boolean reservable = false;
public void setSeatId(Long seatId)
{
this.seatId = seatId;
}
public Long getSeatId()
{
return seatId;
}
public void setSeatName(String seatName)
{
this.seatName = seatName;
}
public String getSeatName()
{
return seatName;
}
public void setDelFlag(String delFlag)
{
this.delFlag = delFlag;
}
public String getDelFlag()
{
return delFlag;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("seatId", getSeatId())
.append("spaceCode", getSpaceCode())
.append("seatName", getSeatName())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.append("delFlag", getDelFlag())
.toString();
}
}
package com.ruoyi.system.domain.vo;
import lombok.Data;
import java.io.Serializable;
@Data
public class OpenTime implements Serializable {
private String startAt;
private String endAt;
}
package com.ruoyi.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.system.domain.ReservationApproval;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
@Mapper
public interface ReservationApprovalMapper extends BaseMapper<ReservationApproval> {
/**
* 查询已预约的的座位编码
* @param seatCodes 座位编码组
* @param startAt 开始时间
* @param endAt 结束时间
* @return
*/
List<String> selectReservedSeatCodes(@Param("seatCodes") List<String> seatCodes,
@Param("startAt")Date startAt,
@Param("endAt") Date endAt);
}
package com.ruoyi.system.mapper;
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.system.domain.ReservationBlacklist;
import org.apache.ibatis.annotations.Mapper;
/**
* 黑名单
Mapper接口
*
* @author ruoyi
* @date 2025-11-04
*/
@Mapper
public interface ReservationBlacklistMapper extends BaseMapper<ReservationBlacklist>
{
/**
* 查询黑名单
*
* @param id 黑名单
主键
* @return 黑名单
*/
public ReservationBlacklist selectReservationBlacklistById(Long id);
/**
* 查询黑名单
列表
*
* @param reservationBlacklist 黑名单
* @return 黑名单
集合
*/
public List<ReservationBlacklist> selectReservationBlacklistList(ReservationBlacklist reservationBlacklist);
/**
* 新增黑名单
*
* @param reservationBlacklist 黑名单
* @return 结果
*/
public int insertReservationBlacklist(ReservationBlacklist reservationBlacklist);
/**
* 修改黑名单
*
* @param reservationBlacklist 黑名单
* @return 结果
*/
public int updateReservationBlacklist(ReservationBlacklist reservationBlacklist);
/**
* 删除黑名单
*
* @param id 黑名单
主键
* @return 结果
*/
public int deleteReservationBlacklistById(Long id);
/**
* 批量删除黑名单
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteReservationBlacklistByIds(Long[] ids);
}
package com.ruoyi.system.mapper;
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.common.core.tree.TreeDto;
import com.ruoyi.system.domain.SchoolBuild;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* 楼宇Mapper接口
*
* @author ruoyi
* @date 2025-11-03
*/
@Mapper
public interface SchoolBuildMapper extends BaseMapper<SchoolBuild>
{
/**
* 查询楼宇
*
* @param buildId 楼宇主键
* @return 楼宇
*/
public SchoolBuild selectSchoolBuildByBuildId(Long buildId);
/**
* 查询楼宇列表
*
* @param schoolBuild 楼宇
* @return 楼宇集合
*/
public List<SchoolBuild> selectSchoolBuildList(SchoolBuild schoolBuild);
/**
* 查询楼宇树结构
* @param campusCodes 校区编码
* @return
*/
public List<TreeDto> selectTreeDtos(@Param("campusCodes") List<String> campusCodes);
/**
* 新增楼宇
*
* @param schoolBuild 楼宇
* @return 结果
*/
public int insertSchoolBuild(SchoolBuild schoolBuild);
/**
* 修改楼宇
*
* @param schoolBuild 楼宇
* @return 结果
*/
public int updateSchoolBuild(SchoolBuild schoolBuild);
/**
* 删除楼宇
*
* @param buildId 楼宇主键
* @return 结果
*/
public int deleteSchoolBuildByBuildId(Long buildId);
/**
* 批量删除楼宇
*
* @param buildIds 需要删除的数据主键集合
* @return 结果
*/
public int deleteSchoolBuildByBuildIds(Long[] buildIds);
}
package com.ruoyi.system.mapper;
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.common.core.tree.TreeDto;
import com.ruoyi.system.domain.SchoolCampus;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* 校区Mapper接口
*
* @author ruoyi
* @date 2025-11-03
*/
@Mapper
public interface SchoolCampusMapper extends BaseMapper<SchoolCampus>
{
/**
* 查询校区
*
* @param campusId 校区主键
* @return 校区
*/
public SchoolCampus selectSchoolCampusByCampusId(Long campusId);
/**
* 查询树结构信息
* @param campusCode 校区编码
* @param name 名称
* @return
*/
public List<TreeDto> selectTreeDto(@Param("campusCode") String campusCode,
@Param("name") String name);
/**
* 查询校区列表
*
* @param schoolCampus 校区
* @return 校区集合
*/
public List<SchoolCampus> selectSchoolCampusList(SchoolCampus schoolCampus);
/**
* 新增校区
*
* @param schoolCampus 校区
* @return 结果
*/
public int insertSchoolCampus(SchoolCampus schoolCampus);
/**
* 修改校区
*
* @param schoolCampus 校区
* @return 结果
*/
public int updateSchoolCampus(SchoolCampus schoolCampus);
/**
* 删除校区
*
* @param campusId 校区主键
* @return 结果
*/
public int deleteSchoolCampusByCampusId(Long campusId);
/**
* 批量删除校区
*
* @param campusIds 需要删除的数据主键集合
* @return 结果
*/
public int deleteSchoolCampusByCampusIds(Long[] campusIds);
}
package com.ruoyi.system.mapper;
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.common.core.tree.TreeDto;
import com.ruoyi.system.domain.SchoolFloor;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* 楼层Mapper接口
*
* @author ruoyi
* @date 2025-11-03
*/
@Mapper
public interface SchoolFloorMapper extends BaseMapper<SchoolFloor>
{
/**
* 查询楼层
*
* @param floorId 楼层主键
* @return 楼层
*/
public SchoolFloor selectSchoolFloorByFloorId(Long floorId);
/**
* 查询楼层树结构
* @param buildCodes
* @return
*/
public List<TreeDto> selectTreeDtos(@Param("buildCodes") List<String> buildCodes);
/**
* 查询楼层列表
*
* @param schoolFloor 楼层
* @return 楼层集合
*/
public List<SchoolFloor> selectSchoolFloorList(SchoolFloor schoolFloor);
/**
* 新增楼层
*
* @param schoolFloor 楼层
* @return 结果
*/
public int insertSchoolFloor(SchoolFloor schoolFloor);
/**
* 修改楼层
*
* @param schoolFloor 楼层
* @return 结果
*/
public int updateSchoolFloor(SchoolFloor schoolFloor);
/**
* 删除楼层
*
* @param floorId 楼层主键
* @return 结果
*/
public int deleteSchoolFloorByFloorId(Long floorId);
/**
* 批量删除楼层
*
* @param floorIds 需要删除的数据主键集合
* @return 结果
*/
public int deleteSchoolFloorByFloorIds(Long[] floorIds);
}
package com.ruoyi.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.system.domain.Space;
import java.util.List;
import java.util.Map;
/**
* 房间Mapper接口
*
* @author ruoyi
* @date 2025-11-03
*/
public interface SpaceMapper extends BaseMapper<Space>
{
/**
* 批量删除房间
*
* @param spaceIds 需要删除的数据主键集合
* @return 结果
*/
public int deleteSpaceBySpaceIds(Long[] spaceIds);
}
package com.ruoyi.system.mapper;
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.system.domain.Space;
import com.ruoyi.system.domain.SpaceSeat;
import org.apache.ibatis.annotations.Param;
/**
* 座位Mapper接口
*
* @author ruoyi
* @date 2025-11-03
*/
public interface SpaceSeatMapper extends BaseMapper<SpaceSeat>
{
/**
* 查询座位
*
* @param seatId 座位主键
* @return 座位
*/
public SpaceSeat selectSpaceSeatBySeatId(Long seatId);
/**
* 查询座位列表
*
* @param spaceSeat 座位
* @return 座位集合
*/
public List<SpaceSeat> selectSpaceSeatList(SpaceSeat spaceSeat);
/**
* 查询房间座位信息
* @return
*/
public List<Space> selectSpaceSeatCount(@Param("spaceCodes") List<String> spaceCodes);
/**
* 批量删除座位
*
* @param seatIds 需要删除的数据主键集合
* @return 结果
*/
public int deleteSpaceSeatBySeatIds(Long[] seatIds);
}
......@@ -36,6 +36,15 @@ public interface SysDeptMapper
*/
public SysDept selectDeptById(Long deptId);
/**
* 根据部门ID查询信息
*
* @param deptCode 部门编码
* @return 部门信息
*/
public SysDept selectDeptByCode(String deptCode);
/**
* 根据ID查询所有子部门
*
......
......@@ -41,6 +41,24 @@ public interface SysRoleMapper
*/
public List<Long> selectRoleListByUserId(Long userId);
/**
* 通过角色KEY查询角色
*
* @param roleKey 角色KEY
* @return 角色对象信息
*/
public SysRole selectRoleByKey(String roleKey);
/**
* 通过角色KEY查询角色
*
* @param roleKey 角色KEY
* @return 角色对象信息
*/
public Long[] selectRoleIdsByKeys(List<String> roleKey);
/**
* 通过角色ID查询角色
*
......
......@@ -2,6 +2,8 @@ package com.ruoyi.system.mapper;
import java.util.Date;
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import com.ruoyi.common.core.domain.entity.SysUser;
......@@ -52,6 +54,14 @@ public interface SysUserMapper
*/
public SysUser selectUserById(Long userId);
/**
* 通过用户昵称查询用户
* @param userNames
* @return
*/
public List<SysUser> selectUsersByUserName(@Param("userNames") List<String> userNames);
/**
* 新增用户信息
*
......
package com.ruoyi.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.system.domain.ReservationApproval;
import java.util.Date;
import java.util.List;
public interface IReservationApprovalService extends IService<ReservationApproval> {
/**
* 提交工位预约申请
* @param reservationApproval 申请
* @return
*/
public Boolean submitApproval(ReservationApproval reservationApproval);
/**
* 查询已预约的的座位编码
* @param seatCodes 座位编码组
* @param startAt 开始时间
* @param endAt 结束时间
* @return
*/
public List<String> selectReservedSeatCodes(List<String> seatCodes, Date startAt, Date endAt);
}
package com.ruoyi.system.service;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.system.domain.ReservationBlacklist;
/**
* 黑名单
Service接口
*
* @author ruoyi
* @date 2025-11-04
*/
public interface IReservationBlacklistService extends IService<ReservationBlacklist>
{
/**
* 查询黑名单
*
* @param id 黑名单
主键
* @return 黑名单
*/
public ReservationBlacklist selectReservationBlacklistById(Long id);
/**
* 查询黑名单
列表
*
* @param reservationBlacklist 黑名单
* @return 黑名单
集合
*/
public List<ReservationBlacklist> selectReservationBlacklistList(ReservationBlacklist reservationBlacklist);
/**
* 新增黑名单
*
* @param reservationBlacklist 黑名单
* @return 结果
*/
public int insertReservationBlacklist(ReservationBlacklist reservationBlacklist);
/**
* 修改黑名单
*
* @param reservationBlacklist 黑名单
* @return 结果
*/
public int updateReservationBlacklist(ReservationBlacklist reservationBlacklist);
/**
* 批量删除黑名单
*
* @param ids 需要删除的黑名单
主键集合
* @return 结果
*/
public int deleteReservationBlacklistByIds(Long[] ids);
/**
* 删除黑名单
信息
*
* @param id 黑名单
主键
* @return 结果
*/
public int deleteReservationBlacklistById(Long id);
}
package com.ruoyi.system.service;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.system.domain.Space;
import com.ruoyi.system.domain.SpaceSeat;
import org.apache.ibatis.annotations.Param;
/**
* 座位Service接口
*
* @author ruoyi
* @date 2025-11-03
*/
public interface ISpaceSeatService extends IService<SpaceSeat>
{
/**
* 查询座位
*
* @param seatId 座位主键
* @return 座位
*/
public SpaceSeat selectSpaceSeatBySeatId(Long seatId);
/**
* 查询座位列表
*
* @param spaceSeat 座位
* @return 座位集合
*/
public List<SpaceSeat> selectSpaceSeatList(SpaceSeat spaceSeat);
/**
* 查询座位信息
* @param seatCodes
* @return
*/
public List<SpaceSeat> selectSpaceSeatByCodes(List<String> seatCodes);
/**
* 查询房间座位信息
* @return
*/
public List<Space> selectSpaceSeatCount(List<String> spaceCodes);
/**
* 新增座位
*
* @param spaceSeat 座位
* @return 结果
*/
public Boolean insertSpaceSeat(SpaceSeat spaceSeat);
/**
* 修改座位
*
* @param spaceSeat 座位
* @return 结果
*/
public Boolean updateSpaceSeat(SpaceSeat spaceSeat);
/**
* 批量删除座位
*
* @param seatIds 需要删除的座位主键集合
* @return 结果
*/
public int deleteSpaceSeatBySeatIds(Long[] seatIds);
/**
* 删除座位信息
*
* @param seatId 座位主键
* @return 结果
*/
public Boolean deleteSpaceSeatBySeatId(Long seatId);
}
package com.ruoyi.system.service;
import java.util.Date;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.system.domain.Space;
/**
* 房间Service接口
*
* @author ruoyi
* @date 2025-11-03
*/
public interface ISpaceService extends IService<Space>
{
/**
* 批量删除房间
*
* @param spaceIds 需要删除的房间主键集合
* @return 结果
*/
public int deleteSpaceBySpaceIds(Long[] spaceIds);
/**
* 检查房间空闲
* @param spaceId 房间id
* @param startAt 开始时间
* @param endAt 结束时间
* @return
*/
public Space checkSpaceSeat(Long spaceId, Date startAt,Date endAt);
}
......@@ -59,6 +59,15 @@ public interface ISysDeptService
*/
public SysDept selectDeptById(Long deptId);
/**
* 根据部门ID查询信息
*
* @param deptCode 部门编码
* @return 部门信息
*/
public SysDept selectDeptByCode(String deptCode);
/**
* 根据ID查询所有子部门(正常状态)
*
......
......@@ -59,6 +59,15 @@ public interface ISysRoleService
*/
public SysRole selectRoleById(Long roleId);
/**
* 通过角色ID查询角色
*
* @param roleKey 角色ID
* @return 角色对象信息
*/
public SysRole selectRoleByRoleKey(String roleKey);
/**
* 校验角色名称是否唯一
*
......
......@@ -2,7 +2,10 @@ package com.ruoyi.system.service;
import java.util.Date;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.common.core.domain.entity.SysUser;
import org.apache.ibatis.annotations.Param;
/**
* 用户 业务层
......@@ -51,6 +54,14 @@ public interface ISysUserService
*/
public SysUser selectUserById(Long userId);
/**
* 通过用户昵称查询用户
* @param userNames
* @return
*/
public List<SysUser> selectUsersByUserName(List<String> userNames);
/**
* 根据用户ID查询用户所属角色组
*
......@@ -113,6 +124,7 @@ public interface ISysUserService
*/
public int insertUser(SysUser user);
/**
* 注册用户信息
*
......@@ -214,4 +226,8 @@ public interface ISysUserService
* @return 结果
*/
public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName);
}
package com.ruoyi.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.common.core.tree.TreeDto;
import com.ruoyi.system.domain.SchoolBuild;
import java.util.List;
public interface SchoolBuildService extends IService<SchoolBuild> {
/**
* 查询建筑信息
* @param build
* @return
*/
List<SchoolBuild> selectSchoolBuildList(SchoolBuild build);
/**
* 根据id 查询 楼宇信息
* @param buildingId
* @return
*/
SchoolBuild getBuildById(Long buildingId);
/**
* 查询楼宇树结构
* @param campusCodes 校区编码
* @return
*/
public List<TreeDto> selectTreeDtos( List<String> campusCodes);
/**
* 添加 楼宇信息
* @param building
* @return
*/
Boolean insertBuild(SchoolBuild building);
/**
* 修改 楼宇信息
* @param building
* @return
*/
Boolean updateBuild(SchoolBuild building);
/**
* 删除 楼宇信息
* @param buildingId
* @return
*/
Boolean deleteBuild(Long buildingId);
}
package com.ruoyi.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.common.core.tree.TreeDto;
import com.ruoyi.system.domain.SchoolCampus;
import java.util.List;
public interface SchoolCampusService extends IService<SchoolCampus> {
/**
* 查询树结构信息
* @param campusCode 校区编码
* @param name 名称
* @return
*/
public List<TreeDto> selectTreeDto(String campusCode, String name);
/**
* 添加 校区信息
* @param campus
* @return
*/
Boolean insertCampus(SchoolCampus campus);
/**
* 修改 校区信息
* @param campus
* @return
*/
Boolean updateCampus(SchoolCampus campus);
/**
* 删除 校区信息
* @param campusId
* @return
*/
Boolean deleteCampus(Long campusId);
}
package com.ruoyi.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.common.core.tree.TreeDto;
import com.ruoyi.system.domain.SchoolFloor;
import java.util.List;
public interface SchoolFloorService extends IService<SchoolFloor> {
/**
* 查询楼层树结构
* @param buildCodes
* @return
*/
public List<TreeDto> selectTreeDtos( List<String> buildCodes);
/**
* 添加 楼层信息
* @param floor
* @return
*/
Boolean insertFloor(SchoolFloor floor);
/**
* 修改 楼层信息
* @param floor
* @return
*/
Boolean updateFloor(SchoolFloor floor);
/**
* 删除 楼层信息
* @param floorId
* @return
*/
Boolean deleteFloor(Long floorId);
}
package com.ruoyi.system.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.enums.ApprovalStatus;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.ReservationApproval;
import com.ruoyi.system.mapper.ReservationApprovalMapper;
import com.ruoyi.system.service.IReservationApprovalService;
import com.ruoyi.system.task.verifyReservationApproval.VerifyReservationApprovalProcessor;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
@Service
public class ReservationApprovalImpl extends ServiceImpl<ReservationApprovalMapper,ReservationApproval>
implements IReservationApprovalService {
@Autowired
List<VerifyReservationApprovalProcessor> processors;
@Autowired
private RedissonClient redissonClient;
private static final String LOCK = "APPROVAL-";
/**
* 提交工位预约申请
* @param reservationApproval 申请
* @return
*/
@Override
public Boolean submitApproval(ReservationApproval reservationApproval) {
RLock lock = redissonClient.getLock(LOCK+reservationApproval.getSeatCode());
try {
lock.lock();
for (VerifyReservationApprovalProcessor processor : processors) {
processor.VerifyReservationApproval(reservationApproval);
}
reservationApproval.setSubmitAt(new Date());
reservationApproval.setSubmitBy(SecurityUtils.getUsername());
reservationApproval.setStatus(ApprovalStatus.WAITING.getCode());
return save(reservationApproval);
} finally {
lock.unlock();
}
}
/**
* 查询已预约的的座位编码
* @param seatCodes 座位编码组
* @param startAt 开始时间
* @param endAt 结束时间
* @return
*/
@Override
public List<String> selectReservedSeatCodes(List<String> seatCodes, Date startAt, Date endAt) {
return baseMapper.selectReservedSeatCodes(seatCodes, startAt, endAt);
}
}
package com.ruoyi.system.service.impl;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.ReservationBlacklistMapper;
import com.ruoyi.system.domain.ReservationBlacklist;
import com.ruoyi.system.service.IReservationBlacklistService;
/**
* 黑名单
Service业务层处理
*
* @author ruoyi
* @date 2025-11-04
*/
@Service
public class ReservationBlacklistServiceImpl extends ServiceImpl<ReservationBlacklistMapper,ReservationBlacklist> implements IReservationBlacklistService
{
@Autowired
private ReservationBlacklistMapper reservationBlacklistMapper;
/**
* 查询黑名单
*
* @param id 黑名单
主键
* @return 黑名单
*/
@Override
public ReservationBlacklist selectReservationBlacklistById(Long id)
{
return reservationBlacklistMapper.selectReservationBlacklistById(id);
}
/**
* 查询黑名单
列表
*
* @param reservationBlacklist 黑名单
* @return 黑名单
*/
@Override
public List<ReservationBlacklist> selectReservationBlacklistList(ReservationBlacklist reservationBlacklist)
{
return reservationBlacklistMapper.selectReservationBlacklistList(reservationBlacklist);
}
/**
* 新增黑名单
*
* @param reservationBlacklist 黑名单
* @return 结果
*/
@Override
public int insertReservationBlacklist(ReservationBlacklist reservationBlacklist)
{
reservationBlacklist.setCreatedBy(SecurityUtils.getUsername());
reservationBlacklist.setCreateTime(DateUtils.getNowDate());
return reservationBlacklistMapper.insertReservationBlacklist(reservationBlacklist);
}
/**
* 修改黑名单
*
* @param reservationBlacklist 黑名单
* @return 结果
*/
@Override
public int updateReservationBlacklist(ReservationBlacklist reservationBlacklist)
{
reservationBlacklist.setUpdateBy(SecurityUtils.getUsername());
reservationBlacklist.setUpdateTime(DateUtils.getNowDate());
return reservationBlacklistMapper.updateReservationBlacklist(reservationBlacklist);
}
/**
* 批量删除黑名单
*
* @param ids 需要删除的黑名单
主键
* @return 结果
*/
@Override
public int deleteReservationBlacklistByIds(Long[] ids)
{
return reservationBlacklistMapper.deleteReservationBlacklistByIds(ids);
}
/**
* 删除黑名单
信息
*
* @param id 黑名单
主键
* @return 结果
*/
@Override
public int deleteReservationBlacklistById(Long id)
{
return reservationBlacklistMapper.deleteReservationBlacklistById(id);
}
}
package com.ruoyi.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.core.tree.TreeDto;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.domain.SchoolBuild;
import com.ruoyi.system.domain.SchoolFloor;
import com.ruoyi.system.mapper.SchoolBuildMapper;
import com.ruoyi.system.mapper.SchoolFloorMapper;
import com.ruoyi.system.service.SchoolBuildService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* 楼宇 服务层
*/
@Service
public class SchoolBuildServiceImpl
extends ServiceImpl<SchoolBuildMapper, SchoolBuild> implements SchoolBuildService {
@Autowired
private SchoolFloorMapper schoolFloorMapper;
@Autowired
private RedissonClient redissonClient;
private static final String LOCK = "BUILDING";
public static final String DICT_TYPE = "sys_school_build";
@PostConstruct
public void info(){
List<SchoolBuild> schoolBuilds = list();
List<SysDictData> dictDatas =
schoolBuilds.stream().map(build->{
SysDictData dictData = new SysDictData();
dictData.setDictValue(build.getBuildCode());
dictData.setDictLabel(build.getBuildName());
dictData.setDictType(DICT_TYPE);
dictData.setDictSort(build.getSort());
return dictData;
}).collect(Collectors.toList());
if(StringUtils.isNotEmpty(dictDatas)){
DictUtils.setDictCache(DICT_TYPE,dictDatas);
}
}
/**
* 查询建筑信息
* @param build
* @return
*/
@Override
public List<SchoolBuild> selectSchoolBuildList(SchoolBuild build) {
return baseMapper.selectSchoolBuildList(build);
}
/**
* 根据id 查询 楼宇信息
* @param buildingId
* @return
*/
@Override
public SchoolBuild getBuildById(Long buildingId) {
if(buildingId == null || buildingId <= 0){
throw new ServiceException("查询参数错误,无法查询到楼宇信息");
}
return baseMapper.selectById(buildingId);
}
/**
* 查询楼宇树结构
* @param campusCodes 校区编码
* @return
*/
@Override
public List<TreeDto> selectTreeDtos(List<String> campusCodes) {
return baseMapper.selectTreeDtos(campusCodes)
.stream().filter(t->StringUtils.isNotEmpty(t.getParentCode()))
.collect(Collectors.toList());
}
/**
* 添加 楼宇信息
* @param build;
* @return
*/
@Override
public Boolean insertBuild(SchoolBuild build) {
RLock lock = redissonClient.getLock(LOCK);
try {
lock.lock();
long count =count(new LambdaQueryWrapper<SchoolBuild>()
.eq(SchoolBuild::getBuildName,build.getBuildName())
.eq(SchoolBuild::getCampusCode,build.getCampusCode()));
if(count > 0){
throw new ServiceException("楼宇名重复,不能重复添加");
}
build.setBuildCode(IdUtils.randomUUID());
build.setCreateBy(SecurityUtils.getUsername());
build.setCreateTime(new Date());
Boolean flag = save(build);
info();
return flag;
} finally {
lock.unlock();
}
}
/**
* 修改 楼宇信息
* @param updateBuild
* @return
*/
@Override
public Boolean updateBuild(SchoolBuild updateBuild) {
if(updateBuild.getBuildId() == null || updateBuild.getBuildId() <= 0){
throw new ServiceException("参数错误,无法修改楼宇信息");
}
RLock lock = redissonClient.getLock(LOCK);
try {
lock.lock();
SchoolBuild entity = baseMapper.selectById(updateBuild.getBuildId());
if (StringUtils.isNull(entity)){
throw new ServiceException("参数错误,查询不到需要修改的数据");
}
long count = count(new LambdaQueryWrapper<SchoolBuild>()
.eq(SchoolBuild::getBuildName,updateBuild.getBuildName())
.eq(SchoolBuild::getCampusCode,updateBuild.getCampusCode())
.ne(SchoolBuild::getBuildId,entity.getBuildId()));
if(count > 0){
throw new ServiceException("楼宇名重复,请重写修改");
}
updateBuild.setUpdateBy(SecurityUtils.getUsername());
updateBuild.setUpdateTime(new Date());
Boolean flag = updateById(updateBuild);
info();
return flag;
} finally {
lock.unlock();
}
}
/**
* 删除 楼宇信息
* @param buildingId
* @return
*/
@Override
public Boolean deleteBuild(Long buildingId) {
if(buildingId == null || buildingId <= 0){
throw new ServiceException("参数错误,无法删除楼宇信息");
}
SchoolBuild build = baseMapper.selectById(buildingId);
if (StringUtils.isNull(build)){
throw new ServiceException("参数错误,查询不到指定的建筑");
}
long count = schoolFloorMapper.selectCount(new LambdaQueryWrapper<SchoolFloor>()
.eq(SchoolFloor::getBuildCode,build.getBuildCode()));
if(count > 0){
throw new ServiceException("楼宇还包含楼层,无法删除楼宇信息");
}
Boolean flag= removeById(buildingId);
info();
return flag;
}
}
package com.ruoyi.system.service.impl;
import cn.hutool.core.lang.Snowflake;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.core.tree.TreeDto;
import com.ruoyi.common.core.tree.TreeUtil;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.domain.SchoolBuild;
import com.ruoyi.system.domain.SchoolCampus;
import com.ruoyi.system.mapper.SchoolBuildMapper;
import com.ruoyi.system.mapper.SchoolCampusMapper;
import com.ruoyi.system.service.SchoolCampusService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* 校区 服务层
*/
@Service
public class SchoolCampusServiceImpl
extends ServiceImpl<SchoolCampusMapper, SchoolCampus> implements SchoolCampusService {
@Autowired
private SchoolBuildMapper schoolBuildingMapper;
@Autowired
private RedissonClient redissonClient;
private static final String LOCK = "CAMPUS";
public static final String DICT_TYPE = "sys_school_campus";
@PostConstruct
public void info(){
List<SchoolCampus> schoolCampuses = list();
List<SysDictData> dictDatas =
schoolCampuses.stream().map(campus->{
SysDictData dictData = new SysDictData();
dictData.setDictValue(campus.getCampusCode());
dictData.setDictLabel(campus.getName());
dictData.setDictType(DICT_TYPE);
dictData.setDictSort(campus.getSort());
return dictData;
}).collect(Collectors.toList());
if(StringUtils.isNotEmpty(dictDatas)){
DictUtils.setDictCache(DICT_TYPE,dictDatas);
}
}
@Override
public List<TreeDto> selectTreeDto(String campusCode, String name) {
return baseMapper.selectTreeDto(campusCode, name)
.stream().peek(t-> t.setParentCode(TreeUtil.FIRST_PARENT_CODE)
).collect(Collectors.toList());
}
/**
* 添加 校区信息
* @param campus
* @return
*/
@Override
public Boolean insertCampus(SchoolCampus campus) {
RLock lock = redissonClient.getLock(LOCK);
try {
lock.lock();
Long count = count(new LambdaQueryWrapper<SchoolCampus>()
.eq(SchoolCampus::getName,campus.getName()));
if(count > 0){
throw new ServiceException("校区名重复,不能重复添加");
}
campus.setCampusId(null);
campus.setCampusCode(IdUtils.randomUUID());
campus.setCreateBy(SecurityUtils.getUsername());
campus.setCreateTime(new Date());
Boolean flag = save(campus);
info();
return flag;
} finally {
lock.unlock();
}
}
/**
* 修改 校区信息
* @param campus
* @return
*/
@Override
public Boolean updateCampus(SchoolCampus campus) {
RLock lock = redissonClient.getLock(LOCK);
try {
lock.lock();
Long count = count(new LambdaQueryWrapper<SchoolCampus>()
.eq(SchoolCampus::getName,campus.getName())
.ne(SchoolCampus::getCampusId,campus.getCampusId()));
if(count > 0){
throw new ServiceException("校区名重复,请重写修改");
}
campus.setUpdateBy(SecurityUtils.getUsername());
campus.setUpdateTime(new Date());
Boolean flag = updateById(campus);
info();
return flag;
} finally {
lock.unlock();
}
}
/**
* 删除 校区信息
* @param campusId
* @return
*/
@Override
public Boolean deleteCampus(Long campusId) {
if(campusId == null || campusId <= 0){
throw new ServiceException("参数错误,无法删除校区信息");
}
SchoolCampus campus = baseMapper.selectById(campusId);
if (StringUtils.isNull(campus)){
throw new ServiceException("信息错误,无法查询指定校区");
}
long count = schoolBuildingMapper.selectCount(new LambdaQueryWrapper<SchoolBuild>()
.eq(SchoolBuild::getCampusCode,campus.getCampusCode()));
if(count > 0){
throw new ServiceException("校区还包含楼宇,无法删除校区信息");
}
return removeById(campusId);
}
}
package com.ruoyi.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.core.tree.TreeDto;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.domain.SchoolFloor;
import com.ruoyi.system.service.SchoolFloorService;
import com.ruoyi.system.mapper.SchoolFloorMapper;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 楼层 服务层
*/
@Service
public class SchoolFloorServiceImpl
extends ServiceImpl<SchoolFloorMapper, SchoolFloor> implements SchoolFloorService {
@Autowired
private RedissonClient redissonClient;
private static final String LOCK = "FLOOR";
public static final String DICT_TYPE = "sys_school_floor";
@PostConstruct
public void info(){
List<SchoolFloor> schoolCampuses = list();
List<SysDictData> dictDatas =
schoolCampuses.stream().map(f->{
SysDictData dictData = new SysDictData();
dictData.setDictValue(f.getFloorCode());
dictData.setDictLabel(f.getFloorName());
dictData.setDictType(DICT_TYPE);
dictData.setDictSort(f.getSort());
return dictData;
}).collect(Collectors.toList());
if(StringUtils.isNotEmpty(dictDatas)){
DictUtils.setDictCache(DICT_TYPE,dictDatas);
}
}
/**
* 查询楼层树结构
* @param buildCodes 楼宇编码
* @return
*/
@Override
public List<TreeDto> selectTreeDtos(List<String> buildCodes) {
return baseMapper.selectTreeDtos(buildCodes)
.stream().filter(t->StringUtils.isNotEmpty(t.getParentCode()))
.collect(Collectors.toList());
}
/**
* 添加 楼层信息
* @param floor
* @return
*/
@Override
public Boolean insertFloor(SchoolFloor floor) {
RLock lock = redissonClient.getLock(LOCK);
try {
lock.lock();
Long count = count(new LambdaQueryWrapper<SchoolFloor>()
.eq(SchoolFloor::getBuildCode,floor.getBuildCode())
.eq(SchoolFloor::getFloorName,floor.getFloorName()));
if(count > 0){
throw new ServiceException("楼层名重复,不能重复添加");
}
floor.setFloorCode(IdUtils.randomUUID());
floor.setCreateBy(SecurityUtils.getUsername());
floor.setCreateTime(new Date());
Boolean flag = save(floor);
info();
return flag;
} finally {
lock.unlock();
}
}
/**
* 修改 楼层信息
* @param floor
* @return
*/
@Override
public Boolean updateFloor(SchoolFloor floor) {
if (StringUtils.isNull(floor.getFloorId())){
throw new ServiceException("参数缺失,无法查询指定的楼层");
}
RLock lock = redissonClient.getLock(LOCK);
try {
lock.lock();
SchoolFloor entity = baseMapper.selectById(floor.getFloorId());
if (StringUtils.isNull(entity)){
throw new ServiceException("参数错误,无法查询指定的楼层");
}
long count = count(new LambdaQueryWrapper<SchoolFloor>()
.eq(SchoolFloor::getBuildCode,floor.getBuildCode())
.eq(SchoolFloor::getFloorName,floor.getFloorName())
.ne(SchoolFloor::getFloorId,floor.getFloorId()));
if(count > 0){
throw new ServiceException("楼层名重复,请重写修改");
}
floor.setUpdateBy(SecurityUtils.getUsername());
floor.setUpdateTime(new Date());
Boolean flag = updateById(floor);
info();
return flag;
} finally {
lock.unlock();
}
}
/**
* 删除 楼层信息
* @param floorId
* @return
*/
@Override
public Boolean deleteFloor(Long floorId) {
if(floorId == null || floorId <= 0){
throw new ServiceException("参数错误,无法删除楼层信息");
}
Boolean flag= removeById(floorId);
info();
return flag;
}
}
......@@ -126,6 +126,17 @@ public class SysDeptServiceImpl implements ISysDeptService
return deptMapper.selectDeptById(deptId);
}
/**
* 根据部门ID查询信息
*
* @param deptCode 部门编码
* @return 部门信息
*/
@Override
public SysDept selectDeptByCode(String deptCode){
return deptMapper.selectDeptByCode(deptCode);
}
/**
* 根据ID查询所有子部门(正常状态)
*
......
......@@ -139,6 +139,11 @@ public class SysRoleServiceImpl implements ISysRoleService
return roleMapper.selectRoleById(roleId);
}
@Override
public SysRole selectRoleByRoleKey(String roleKey) {
return roleMapper.selectRoleByKey(roleKey);
}
/**
* 校验角色名称是否唯一
*
......
package com.ruoyi.system.task.verifyReservationApproval;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.enums.ApprovalStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.ReservationApproval;
import com.ruoyi.system.service.IReservationApprovalService;
import com.ruoyi.system.service.ISysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class AlreadyApprovalProcessor implements VerifyReservationApprovalProcessor {
@Autowired
private IReservationApprovalService reservationApprovalService;
@Autowired
private ISysConfigService configService;
private static final String CONFIG_KEY = "approval.max.wait";
@Override
public void VerifyReservationApproval(ReservationApproval reservationApproval) {
int maxWait = Integer.parseInt(configService.selectConfigByKey(CONFIG_KEY));
long count = reservationApprovalService.count(new LambdaQueryWrapper<ReservationApproval>()
.eq(ReservationApproval::getSubmitBy, SecurityUtils.getUsername())
.in(ReservationApproval::getStatus, ApprovalStatus.PASS.getCode(),ApprovalStatus.WAITING.getCode())
.ge(ReservationApproval::getStartAt,new Date()));
if (count >= maxWait){
throw new ServiceException("已超过最大预约数,暂无法预约");
}
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment