[add] 用户文件关联,分包合同管理,分包单位类型,施工人员身份证加解密

This commit is contained in:
lcj
2025-06-25 19:47:58 +08:00
parent e492c08eef
commit 51bd7ed5d8
53 changed files with 2998 additions and 20 deletions

View File

@ -283,3 +283,6 @@ sparta:
url: http://119.3.204.120:8040 url: http://119.3.204.120:8040
client-id: test client-id: test
client-secret: 115fcb08fa6742a1b086d9bb80a6ad59 client-secret: 115fcb08fa6742a1b086d9bb80a6ad59
# 身份证加密密钥
id-card:
encrypt-key: 7ae260d150a14027d2238a1cf80a48ef

View File

@ -121,6 +121,7 @@ security:
- /*/api-docs/** - /*/api-docs/**
- /warm-flow-ui/token-name - /warm-flow-ui/token-name
- /other/ys7Device/webhook - /other/ys7Device/webhook
- /facility/matrix/**
# 多租户配置 # 多租户配置
tenant: tenant:

View File

@ -44,7 +44,8 @@ public class IncSyncYs7DeviceCapturePicData {
private final ExecutorService executorService = Executors.newFixedThreadPool(5); private final ExecutorService executorService = Executors.newFixedThreadPool(5);
// 每 30 分钟执行一次 // 每 30 分钟执行一次
@Scheduled(cron = "0 */30 7-19 * * ?") // todo 修改为 30 分钟
@Scheduled(cron = "0 0 7-19 * * ?")
public void run() { public void run() {
// 查询所有在线的摄像头设备,仅获取必要字段 // 查询所有在线的摄像头设备,仅获取必要字段
List<OthYs7Device> deviceList = ys7DeviceService.lambdaQuery() List<OthYs7Device> deviceList = ys7DeviceService.lambdaQuery()

View File

@ -0,0 +1,95 @@
package org.dromara.project.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.project.domain.dto.subcontract.BusSubcontractCreateReq;
import org.dromara.project.domain.dto.subcontract.BusSubcontractQueryReq;
import org.dromara.project.domain.dto.subcontract.BusSubcontractUpdateReq;
import org.dromara.project.domain.vo.subcontract.BusSubcontractVo;
import org.dromara.project.service.IBusSubcontractService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 分包合同
*
* @author lcj
* @date 2025-06-25
*/
@Validated
@RestController
@RequestMapping("/project/subcontract")
public class BusSubcontractController extends BaseController {
@Resource
private IBusSubcontractService subcontractService;
/**
* 查询分包合同列表
*/
@SaCheckPermission("project:subcontract:list")
@GetMapping("/list")
public TableDataInfo<BusSubcontractVo> list(BusSubcontractQueryReq req, PageQuery pageQuery) {
return subcontractService.queryPageList(req, pageQuery);
}
/**
* 获取分包合同详细信息
*
* @param id 主键
*/
@SaCheckPermission("project:subcontract:query")
@GetMapping("/{id}")
public R<BusSubcontractVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(subcontractService.queryById(id));
}
/**
* 新增分包合同
*/
@SaCheckPermission("project:subcontract:add")
@Log(title = "分包合同", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Long> add(@Validated(AddGroup.class) @RequestBody BusSubcontractCreateReq req) {
return R.ok(subcontractService.insertByBo(req));
}
/**
* 修改分包合同
*/
@SaCheckPermission("project:subcontract:edit")
@Log(title = "分包合同", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody BusSubcontractUpdateReq req) {
return toAjax(subcontractService.updateByBo(req));
}
/**
* 删除分包合同
*
* @param ids 主键串
*/
@SaCheckPermission("project:subcontract:remove")
@Log(title = "分包合同", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(subcontractService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -60,6 +60,11 @@ public class BusContractor extends BaseEntity {
*/ */
private String custodianPhone; private String custodianPhone;
/**
* 分包类型
*/
private String contractorType;
/** /**
* 公司相关文件 * 公司相关文件
*/ */

View File

@ -0,0 +1,86 @@
package org.dromara.project.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 分包合同对象 bus_subcontract
*
* @author lcj
* @date 2025-06-25
*/
@Data
@TableName("bus_subcontract")
public class BusSubcontract implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id")
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 合同文件id
*/
private Long contractFileId;
/**
* 合同编号
*/
private String contractNumber;
/**
* 合同名称
*/
private String contractName;
/**
* 合同类型
*/
private String contractType;
/**
* 合同金额
*/
private BigDecimal contractAmount;
/**
* 合同时间
*/
private Date contractTime;
/**
* 备注
*/
private String remark;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}

View File

@ -51,6 +51,11 @@ public class BusContractorCreateReq implements Serializable {
*/ */
private Map<String, Long> fileMap; private Map<String, Long> fileMap;
/**
* 分包类型
*/
private String contractorType;
/** /**
* 备注 * 备注
*/ */

View File

@ -50,6 +50,11 @@ public class BusContractorQueryReq implements Serializable {
*/ */
private String custodianPhone; private String custodianPhone;
/**
* 分包类型
*/
private String contractorType;
/** /**
* 备注 * 备注
*/ */

View File

@ -51,6 +51,11 @@ public class BusContractorUpdateReq implements Serializable {
*/ */
private String custodianPhone; private String custodianPhone;
/**
* 分包类型
*/
private String contractorType;
/** /**
* 公司相关文件 * 公司相关文件
*/ */

View File

@ -0,0 +1,65 @@
package org.dromara.project.domain.dto.subcontract;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author lcj
* @date 2025/6/25 16:36
*/
@Data
public class BusSubcontractCreateReq implements Serializable {
@Serial
private static final long serialVersionUID = -3386090526440868496L;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 合同文件id
*/
private Long contractFileId;
/**
* 合同编号
*/
private String contractNumber;
/**
* 合同名称
*/
private String contractName;
/**
* 合同类型
*/
private String contractType;
/**
* 合同金额
*/
private BigDecimal contractAmount;
/**
* 合同时间
*/
private Date contractTime;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,43 @@
package org.dromara.project.domain.dto.subcontract;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lcj
* @date 2025/6/25 16:37
*/
@Data
public class BusSubcontractQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = 3731492397283570840L;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 合同编号
*/
private String contractNumber;
/**
* 合同名称
*/
private String contractName;
/**
* 合同类型
*/
private String contractType;
}

View File

@ -0,0 +1,70 @@
package org.dromara.project.domain.dto.subcontract;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author lcj
* @date 2025/6/25 16:37
*/
@Data
public class BusSubcontractUpdateReq implements Serializable {
@Serial
private static final long serialVersionUID = -5617446079713109912L;
/**
* 主键id
*/
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 合同文件id
*/
private Long contractFileId;
/**
* 合同编号
*/
private String contractNumber;
/**
* 合同名称
*/
private String contractName;
/**
* 合同类型
*/
private String contractType;
/**
* 合同金额
*/
private BigDecimal contractAmount;
/**
* 合同时间
*/
private Date contractTime;
/**
* 备注
*/
private String remark;
}

View File

@ -68,6 +68,11 @@ public class BusContractorVo implements Serializable {
@ExcelProperty(value = "管理人联系电话") @ExcelProperty(value = "管理人联系电话")
private String custodianPhone; private String custodianPhone;
/**
* 分包类型
*/
private String contractorType;
/** /**
* 公司相关文件 * 公司相关文件
*/ */

View File

@ -0,0 +1,81 @@
package org.dromara.project.domain.vo.subcontract;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.project.domain.BusSubcontract;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 分包合同视图对象 bus_subcontract
*
* @author lcj
* @date 2025-06-25
*/
@Data
@AutoMapper(target = BusSubcontract.class)
public class BusSubcontractVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 分包方名称
*/
private String contractorName;
/**
* 合同文件id
*/
private Long contractFileId;
/**
* 合同编号
*/
private String contractNumber;
/**
* 合同名称
*/
private String contractName;
/**
* 合同类型
*/
private String contractType;
/**
* 合同金额
*/
private BigDecimal contractAmount;
/**
* 合同时间
*/
private Date contractTime;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,15 @@
package org.dromara.project.mapper;
import org.dromara.project.domain.BusSubcontract;
import org.dromara.project.domain.vo.subcontract.BusSubcontractVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 分包合同Mapper接口
*
* @author lcj
* @date 2025-06-25
*/
public interface BusSubcontractMapper extends BaseMapperPlus<BusSubcontract, BusSubcontractVo> {
}

View File

@ -14,6 +14,7 @@ import org.dromara.project.domain.vo.project.*;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture;
/** /**
* 项目Service接口 * 项目Service接口
@ -87,6 +88,14 @@ public interface IBusProjectService extends IService<BusProject> {
*/ */
Long insertSubByProject(BusProjectCreateSubReq dto); Long insertSubByProject(BusProjectCreateSubReq dto);
/**
* 创建项目需同步的事务
*
* @param id 项目id
* @return 是否同步成功
*/
CompletableFuture<Boolean> insertProjectSyncThing(Long id);
/** /**
* 修改项目 * 修改项目
* *

View File

@ -0,0 +1,99 @@
package org.dromara.project.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.project.domain.BusSubcontract;
import org.dromara.project.domain.dto.subcontract.BusSubcontractCreateReq;
import org.dromara.project.domain.dto.subcontract.BusSubcontractQueryReq;
import org.dromara.project.domain.dto.subcontract.BusSubcontractUpdateReq;
import org.dromara.project.domain.vo.subcontract.BusSubcontractVo;
import java.util.Collection;
import java.util.List;
/**
* 分包合同Service接口
*
* @author lcj
* @date 2025-06-25
*/
public interface IBusSubcontractService extends IService<BusSubcontract> {
/**
* 查询分包合同
*
* @param id 主键
* @return 分包合同
*/
BusSubcontractVo queryById(Long id);
/**
* 分页查询分包合同列表
*
* @param req 查询条件
* @param pageQuery 分页参数
* @return 分包合同分页列表
*/
TableDataInfo<BusSubcontractVo> queryPageList(BusSubcontractQueryReq req, PageQuery pageQuery);
/**
* 查询符合条件的分包合同列表
*
* @param req 查询条件
* @return 分包合同列表
*/
List<BusSubcontractVo> queryList(BusSubcontractQueryReq req);
/**
* 新增分包合同
*
* @param req 分包合同
* @return 新增主键id
*/
Long insertByBo(BusSubcontractCreateReq req);
/**
* 修改分包合同
*
* @param req 分包合同
* @return 是否修改成功
*/
Boolean updateByBo(BusSubcontractUpdateReq req);
/**
* 校验并批量删除分包合同信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 获取分包合同视图
*
* @param subcontract 分包合同
* @return 分包合同视图
*/
BusSubcontractVo getVo(BusSubcontract subcontract);
/**
* 获取用户和项目关联对象查询条件封装
*
* @param req 查询条件
* @return 查询条件封装
*/
LambdaQueryWrapper<BusSubcontract> buildQueryWrapper(BusSubcontractQueryReq req);
/**
* 获取分包合同分页视图
*
* @param subcontractPage 分包合同分页
* @return 分包合同分页视图
*/
Page<BusSubcontractVo> getVoPage(Page<BusSubcontract> subcontractPage);
}

View File

@ -1,5 +1,7 @@
package org.dromara.project.service.impl; package org.dromara.project.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdcardUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -23,6 +25,7 @@ import org.dromara.project.service.IBusConstructionBlacklistService;
import org.dromara.project.service.IBusConstructionUserService; import org.dromara.project.service.IBusConstructionUserService;
import org.dromara.project.service.IBusProjectService; import org.dromara.project.service.IBusProjectService;
import org.dromara.project.service.IBusProjectTeamMemberService; import org.dromara.project.service.IBusProjectTeamMemberService;
import org.dromara.utils.IdCardEncryptorUtil;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -51,6 +54,9 @@ public class BusConstructionBlacklistServiceImpl extends ServiceImpl<BusConstruc
@Resource @Resource
private IBusProjectTeamMemberService projectTeamMemberService; private IBusProjectTeamMemberService projectTeamMemberService;
@Resource
private IdCardEncryptorUtil idCardEncryptorUtil;
/** /**
* 查询黑名单 * 查询黑名单
* *
@ -59,7 +65,17 @@ public class BusConstructionBlacklistServiceImpl extends ServiceImpl<BusConstruc
*/ */
@Override @Override
public BusConstructionBlacklistVo queryById(Long id) { public BusConstructionBlacklistVo queryById(Long id) {
return baseMapper.selectVoById(id); BusConstructionBlacklist constructionBlacklist = this.getById(id);
if (constructionBlacklist == null) {
throw new ServiceException("查询黑名单用户不存在", HttpStatus.NOT_FOUND);
}
BusConstructionBlacklistVo vo = new BusConstructionBlacklistVo();
BeanUtils.copyProperties(constructionBlacklist, vo);
// 解密身份证号码
String decrypt = idCardEncryptorUtil.decrypt(constructionBlacklist.getSfzNumber());
String hide = IdcardUtil.hide(decrypt, 11, 17);
vo.setSfzNumber(hide);
return vo;
} }
/** /**
@ -72,8 +88,22 @@ public class BusConstructionBlacklistServiceImpl extends ServiceImpl<BusConstruc
@Override @Override
public TableDataInfo<BusConstructionBlacklistVo> queryPageList(BusConstructionBlacklistQueryReq req, PageQuery pageQuery) { public TableDataInfo<BusConstructionBlacklistVo> queryPageList(BusConstructionBlacklistQueryReq req, PageQuery pageQuery) {
LambdaQueryWrapper<BusConstructionBlacklist> lqw = buildQueryWrapper(req); LambdaQueryWrapper<BusConstructionBlacklist> lqw = buildQueryWrapper(req);
Page<BusConstructionBlacklistVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw); Page<BusConstructionBlacklist> result = this.page(pageQuery.build(), lqw);
return TableDataInfo.build(result); List<BusConstructionBlacklist> records = result.getRecords();
Page<BusConstructionBlacklistVo> resultPage = new Page<>(result.getCurrent(), result.getSize(), result.getTotal());
if (CollUtil.isEmpty(records)) {
return TableDataInfo.build(resultPage);
}
List<BusConstructionBlacklistVo> list = records.stream().map(entity -> {
BusConstructionBlacklistVo vo = new BusConstructionBlacklistVo();
BeanUtils.copyProperties(entity, vo);
String decrypt = idCardEncryptorUtil.decrypt(entity.getSfzNumber());
String hide = IdcardUtil.hide(decrypt, 11, 17);
vo.setSfzNumber(hide);
return vo;
}).toList();
resultPage.setRecords(list);
return TableDataInfo.build(resultPage);
} }
/** /**

View File

@ -20,23 +20,20 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.project.constant.BusConstructionUserConstant; import org.dromara.project.constant.BusConstructionUserConstant;
import org.dromara.project.domain.*; import org.dromara.project.domain.*;
import org.dromara.project.domain.dto.constructionuser.*;
import org.dromara.project.domain.enums.BusAttendanceClockStatusEnum; import org.dromara.project.domain.enums.BusAttendanceClockStatusEnum;
import org.dromara.project.domain.enums.BusAttendanceCommuterEnum; import org.dromara.project.domain.enums.BusAttendanceCommuterEnum;
import org.dromara.project.domain.enums.BusConstructionUserAttendanceStatusEnum; import org.dromara.project.domain.enums.BusConstructionUserAttendanceStatusEnum;
import org.dromara.project.domain.enums.BusConstructionUserFileStatusEnum; import org.dromara.project.domain.enums.BusConstructionUserFileStatusEnum;
import org.dromara.project.domain.exportvo.BusConstructionUserExportVo; import org.dromara.project.domain.exportvo.BusConstructionUserExportVo;
import org.dromara.project.domain.dto.constructionuser.*; import org.dromara.project.domain.vo.constructionuser.*;
import org.dromara.project.domain.vo.constructionuser.BusConstructionUserAttendanceByDay;
import org.dromara.project.domain.vo.constructionuser.BusConstructionUserAttendanceMonthVo;
import org.dromara.project.domain.vo.constructionuser.BusConstructionUserAttendanceTotalVo;
import org.dromara.project.domain.vo.constructionuser.BusConstructionUserGisVo;
import org.dromara.project.domain.vo.constructionuser.BusConstructionUserVo;
import org.dromara.project.domain.vo.contractor.BusContractorVo; import org.dromara.project.domain.vo.contractor.BusContractorVo;
import org.dromara.project.mapper.BusConstructionUserMapper; import org.dromara.project.mapper.BusConstructionUserMapper;
import org.dromara.project.service.*; import org.dromara.project.service.*;
import org.dromara.system.domain.vo.SysOssVo; import org.dromara.system.domain.vo.SysOssVo;
import org.dromara.system.service.ISysDictTypeService; import org.dromara.system.service.ISysDictTypeService;
import org.dromara.system.service.ISysOssService; import org.dromara.system.service.ISysOssService;
import org.dromara.utils.IdCardEncryptorUtil;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -89,6 +86,9 @@ public class BusConstructionUserServiceImpl extends ServiceImpl<BusConstructionU
@Resource @Resource
private IBusAttendanceService attendanceService; private IBusAttendanceService attendanceService;
@Resource
private IdCardEncryptorUtil idCardEncryptorUtil;
/** /**
* 查询施工人员 * 查询施工人员
* *
@ -180,10 +180,10 @@ public class BusConstructionUserServiceImpl extends ServiceImpl<BusConstructionU
// 填充打卡图片url // 填充打卡图片url
if (day != null) { if (day != null) {
if (day.getUpClockPicId() != null) { if (day.getUpClockPicId() != null) {
day.setUpClockPic(ossIdUrlMap.get(day.getUpClockPicId()).get(0).getUrl()); day.setUpClockPic(ossIdUrlMap.get(day.getUpClockPicId()).getFirst().getUrl());
} }
if (day.getDownClockPicId() != null) { if (day.getDownClockPicId() != null) {
day.setDownClockPic(ossIdUrlMap.get(day.getDownClockPicId()).get(0).getUrl()); day.setDownClockPic(ossIdUrlMap.get(day.getDownClockPicId()).getFirst().getUrl());
} }
} }
String clockInStatus = null; String clockInStatus = null;
@ -247,7 +247,7 @@ public class BusConstructionUserServiceImpl extends ServiceImpl<BusConstructionU
Long projectId = constructionUserVo.getProjectId(); Long projectId = constructionUserVo.getProjectId();
String projectName = null; String projectName = null;
if (projectIdProjectMap.containsKey(projectId)) { if (projectIdProjectMap.containsKey(projectId)) {
projectName = projectService.getVo(projectIdProjectMap.get(projectId).get(0)).getProjectName(); projectName = projectService.getVo(projectIdProjectMap.get(projectId).getFirst()).getProjectName();
} }
constructionUserExportVo.setProjectName(projectName); constructionUserExportVo.setProjectName(projectName);
return constructionUserExportVo; return constructionUserExportVo;
@ -299,6 +299,9 @@ public class BusConstructionUserServiceImpl extends ServiceImpl<BusConstructionU
validEntityBeforeSave(constructionUser, true); validEntityBeforeSave(constructionUser, true);
Long userId = LoginHelper.getUserId(); Long userId = LoginHelper.getUserId();
projectService.validAuth(req.getProjectId(), userId); projectService.validAuth(req.getProjectId(), userId);
// 对身份证号码进行加密
String encrypt = idCardEncryptorUtil.encrypt(req.getSfzNumber());
constructionUser.setSfzNumber(encrypt);
// 操作数据库 // 操作数据库
boolean save = this.save(constructionUser); boolean save = this.save(constructionUser);
if (!save) { if (!save) {
@ -328,6 +331,11 @@ public class BusConstructionUserServiceImpl extends ServiceImpl<BusConstructionU
// 判断当前操作用户是否有权限 // 判断当前操作用户是否有权限
Long userId = LoginHelper.getUserId(); Long userId = LoginHelper.getUserId();
projectService.validAuth(oldConstructionUser.getProjectId(), userId); projectService.validAuth(oldConstructionUser.getProjectId(), userId);
// 对身份证号码进行加密
if (req.getSfzNumber() != null) {
String encrypt = idCardEncryptorUtil.encrypt(req.getSfzNumber());
constructionUser.setSfzNumber(encrypt);
}
// 操作数据库 // 操作数据库
return this.updateById(constructionUser); return this.updateById(constructionUser);
} }
@ -531,6 +539,9 @@ public class BusConstructionUserServiceImpl extends ServiceImpl<BusConstructionU
if (StringUtils.isEmpty(wageMeasureUnit)) { if (StringUtils.isEmpty(wageMeasureUnit)) {
throw new ServiceException("工资计量单位不能为空", HttpStatus.BAD_REQUEST); throw new ServiceException("工资计量单位不能为空", HttpStatus.BAD_REQUEST);
} }
if (StringUtils.isEmpty(sfzNumber)) {
throw new ServiceException("身份证不能为空", HttpStatus.BAD_REQUEST);
}
} }
if (projectService.getById(projectId) == null) { if (projectService.getById(projectId) == null) {
throw new ServiceException("对应项目不存在", HttpStatus.NOT_FOUND); throw new ServiceException("对应项目不存在", HttpStatus.NOT_FOUND);
@ -641,6 +652,10 @@ public class BusConstructionUserServiceImpl extends ServiceImpl<BusConstructionU
constructionUserVo.setStandardSalary(workWage.getWage()); constructionUserVo.setStandardSalary(workWage.getWage());
} }
} }
// 解密身份证号码
String decrypt = idCardEncryptorUtil.decrypt(constructionUserVo.getSfzNumber());
String hide = IdcardUtil.hide(decrypt, 11, 17);
constructionUserVo.setSfzNumber(hide);
return constructionUserVo; return constructionUserVo;
} }
@ -751,6 +766,17 @@ public class BusConstructionUserServiceImpl extends ServiceImpl<BusConstructionU
(wage1, wage2) -> wage1 (wage1, wage2) -> wage1
)); ));
int fileTypeSize = dictTypeService.selectDictDataByType(BusConstructionUserConstant.USER_FILE_TYPE).size(); int fileTypeSize = dictTypeService.selectDictDataByType(BusConstructionUserConstant.USER_FILE_TYPE).size();
// 获取用户上传文件数量信息
List<Long> userIdList = constructionUserList.stream().map(BusConstructionUser::getId).toList();
List<BusConstructionUserFile> fileList = constructionUserFileService.lambdaQuery()
.select(BusConstructionUserFile::getId, BusConstructionUserFile::getUserId)
.in(BusConstructionUserFile::getUserId, userIdList)
.list();
Map<Long, Long> fileCountMap = fileList.stream()
.collect(Collectors.groupingBy(
BusConstructionUserFile::getUserId,
Collectors.counting()
));
// 填充信息 // 填充信息
List<BusConstructionUserVo> constructionUserVoList = constructionUserList.stream().map(constructionUser -> { List<BusConstructionUserVo> constructionUserVoList = constructionUserList.stream().map(constructionUser -> {
BusConstructionUserVo constructionUserVo = new BusConstructionUserVo(); BusConstructionUserVo constructionUserVo = new BusConstructionUserVo();
@ -759,7 +785,7 @@ public class BusConstructionUserServiceImpl extends ServiceImpl<BusConstructionU
Long contractorId = constructionUser.getContractorId(); Long contractorId = constructionUser.getContractorId();
BusContractorVo contractor = null; BusContractorVo contractor = null;
if (contractorIdContractorMap.containsKey(contractorId)) { if (contractorIdContractorMap.containsKey(contractorId)) {
contractor = contractorService.getVo(contractorIdContractorMap.get(contractorId).get(0)); contractor = contractorService.getVo(contractorIdContractorMap.get(contractorId).getFirst());
} }
constructionUserVo.setContractorVo(contractor); constructionUserVo.setContractorVo(contractor);
// 关联工资标准 // 关联工资标准
@ -770,9 +796,7 @@ public class BusConstructionUserServiceImpl extends ServiceImpl<BusConstructionU
constructionUserVo.setStandardSalary(workWageMap.get(key)); constructionUserVo.setStandardSalary(workWageMap.get(key));
} }
// 关联施工人员文件上传状态 // 关联施工人员文件上传状态
LambdaQueryWrapper<BusConstructionUserFile> constructionUserFileLqw = Wrappers.lambdaQuery(BusConstructionUserFile.class) long count = fileCountMap.getOrDefault(constructionUser.getId(), 0L);
.eq(BusConstructionUserFile::getUserId, constructionUser.getId());
long count = constructionUserFileService.count(constructionUserFileLqw);
if (count <= 0) { if (count <= 0) {
constructionUserVo.setFileUploadStatus(BusConstructionUserFileStatusEnum.NOUPLOAD.getValue()); constructionUserVo.setFileUploadStatus(BusConstructionUserFileStatusEnum.NOUPLOAD.getValue());
} else if (count < fileTypeSize) { } else if (count < fileTypeSize) {
@ -780,6 +804,10 @@ public class BusConstructionUserServiceImpl extends ServiceImpl<BusConstructionU
} else if (count == fileTypeSize) { } else if (count == fileTypeSize) {
constructionUserVo.setFileUploadStatus(BusConstructionUserFileStatusEnum.UPLOAD.getValue()); constructionUserVo.setFileUploadStatus(BusConstructionUserFileStatusEnum.UPLOAD.getValue());
} }
// 解密身份证号码
String decrypt = idCardEncryptorUtil.decrypt(constructionUserVo.getSfzNumber());
String hide = IdcardUtil.hide(decrypt, 11, 17);
constructionUserVo.setSfzNumber(hide);
return constructionUserVo; return constructionUserVo;
}).toList(); }).toList();
constructionUserVoPage.setRecords(constructionUserVoList); constructionUserVoPage.setRecords(constructionUserVoList);

View File

@ -260,6 +260,7 @@ public class BusContractorServiceImpl extends ServiceImpl<BusContractorMapper, B
String principalPhone = req.getPrincipalPhone(); String principalPhone = req.getPrincipalPhone();
String custodian = req.getCustodian(); String custodian = req.getCustodian();
String custodianPhone = req.getCustodianPhone(); String custodianPhone = req.getCustodianPhone();
String contractorType = req.getContractorType();
String remark = req.getRemark(); String remark = req.getRemark();
// 模糊查询 // 模糊查询
lqw.like(StringUtils.isNotBlank(name), BusContractor::getName, name); lqw.like(StringUtils.isNotBlank(name), BusContractor::getName, name);
@ -271,6 +272,7 @@ public class BusContractorServiceImpl extends ServiceImpl<BusContractorMapper, B
// 精确查询 // 精确查询
lqw.eq(ObjectUtils.isNotEmpty(id), BusContractor::getId, id); lqw.eq(ObjectUtils.isNotEmpty(id), BusContractor::getId, id);
lqw.eq(ObjectUtils.isNotEmpty(projectId), BusContractor::getProjectId, projectId); lqw.eq(ObjectUtils.isNotEmpty(projectId), BusContractor::getProjectId, projectId);
lqw.eq(StringUtils.isNotBlank(contractorType), BusContractor::getContractorType, contractorType);
return lqw; return lqw;
} }

View File

@ -47,6 +47,8 @@ import org.dromara.project.service.IBusContractorService;
import org.dromara.project.service.IBusProjectFileService; import org.dromara.project.service.IBusProjectFileService;
import org.dromara.project.service.IBusProjectService; import org.dromara.project.service.IBusProjectService;
import org.dromara.project.service.IBusUserProjectRelevancyService; import org.dromara.project.service.IBusUserProjectRelevancyService;
import org.dromara.quality.service.IQltKnowledgeDocumentService;
import org.dromara.safety.service.IHseKnowledgeDocumentService;
import org.dromara.system.domain.bo.SysDeptBo; import org.dromara.system.domain.bo.SysDeptBo;
import org.dromara.system.domain.vo.SysDeptVo; import org.dromara.system.domain.vo.SysDeptVo;
import org.dromara.system.service.ISysDeptService; import org.dromara.system.service.ISysDeptService;
@ -54,10 +56,12 @@ import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations; import org.springframework.data.redis.core.ValueOperations;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -97,6 +101,18 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
@Resource @Resource
private ISysDeptService deptService; private ISysDeptService deptService;
@Lazy
@Resource
private IHseKnowledgeDocumentService hseKnowledgeDocumentService;
@Lazy
@Resource
private IQltKnowledgeDocumentService qltKnowledgeDocumentService;
@Lazy
@Resource
private IBusProjectService self;
private final Cache<String, String> WEATHER_CACHE = private final Cache<String, String> WEATHER_CACHE =
Caffeine.newBuilder().initialCapacity(1024) Caffeine.newBuilder().initialCapacity(1024)
.maximumSize(10000L) .maximumSize(10000L)
@ -335,6 +351,15 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
if (!saveRelevancy) { if (!saveRelevancy) {
throw new ServiceException("新增用户与项目关联失败,数据库异常", HttpStatus.ERROR); throw new ServiceException("新增用户与项目关联失败,数据库异常", HttpStatus.ERROR);
} }
// 异步执行数据同步
self.insertProjectSyncThing(projectId)
.thenAccept(result -> {
log.info("项目[{}-{}]异步执行数据同步成功", req.getProjectName(), projectId);
})
.exceptionally(ex -> {
log.error("项目[{}-{}]异步执行数据同步失败", req.getProjectName(), projectId, ex);
return null;
});
// 返回新写入的数据 projectId // 返回新写入的数据 projectId
return projectId; return projectId;
} }
@ -382,6 +407,25 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
return subProjectId; return subProjectId;
} }
/**
* 创建项目需同步的事务
*
* @param id 项目id
* @return 是否同步成功
*/
@Async
@Override
public CompletableFuture<Boolean> insertProjectSyncThing(Long id) {
BusProject project = this.getById(id);
if (project == null) {
log.error("同步数据失败,项目[{}]不存在", id);
return CompletableFuture.completedFuture(false);
}
// 安全、质量知识库文件夹模版
return CompletableFuture.completedFuture(true);
}
/** /**
* 修改项目 * 修改项目
* *

View File

@ -0,0 +1,279 @@
package org.dromara.project.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.project.domain.BusContractor;
import org.dromara.project.domain.BusProject;
import org.dromara.project.domain.BusSubcontract;
import org.dromara.project.domain.dto.subcontract.BusSubcontractCreateReq;
import org.dromara.project.domain.dto.subcontract.BusSubcontractQueryReq;
import org.dromara.project.domain.dto.subcontract.BusSubcontractUpdateReq;
import org.dromara.project.domain.vo.subcontract.BusSubcontractVo;
import org.dromara.project.mapper.BusSubcontractMapper;
import org.dromara.project.service.IBusContractorService;
import org.dromara.project.service.IBusProjectService;
import org.dromara.project.service.IBusSubcontractService;
import org.dromara.system.service.ISysOssService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 分包合同Service业务层处理
*
* @author lcj
* @date 2025-06-25
*/
@Slf4j
@Service
public class BusSubcontractServiceImpl extends ServiceImpl<BusSubcontractMapper, BusSubcontract>
implements IBusSubcontractService {
@Resource
private IBusProjectService projectService;
@Resource
private IBusContractorService contractorService;
@Resource
private ISysOssService ossService;
/**
* 查询分包合同
*
* @param id 主键
* @return 分包合同
*/
@Override
public BusSubcontractVo queryById(Long id) {
BusSubcontract subcontract = this.getById(id);
if (subcontract == null) {
throw new ServiceException("分包合同信息不存在", HttpStatus.NOT_FOUND);
}
return this.getVo(subcontract);
}
/**
* 分页查询分包合同列表
*
* @param req 查询条件
* @param pageQuery 分页参数
* @return 分包合同分页列表
*/
@Override
public TableDataInfo<BusSubcontractVo> queryPageList(BusSubcontractQueryReq req, PageQuery pageQuery) {
LambdaQueryWrapper<BusSubcontract> lqw = buildQueryWrapper(req);
Page<BusSubcontract> result = this.page(pageQuery.build(), lqw);
return TableDataInfo.build(this.getVoPage(result));
}
/**
* 查询符合条件的分包合同列表
*
* @param req 查询条件
* @return 分包合同列表
*/
@Override
public List<BusSubcontractVo> queryList(BusSubcontractQueryReq req) {
LambdaQueryWrapper<BusSubcontract> lqw = buildQueryWrapper(req);
return this.list(lqw).stream().map(this::getVo).toList();
}
/**
* 新增分包合同
*
* @param req 分包合同
* @return 新增主键id
*/
@Override
public Long insertByBo(BusSubcontractCreateReq req) {
BusSubcontract subcontract = new BusSubcontract();
BeanUtils.copyProperties(req, subcontract);
validEntityBeforeSave(subcontract);
Long count = this.lambdaQuery()
.eq(BusSubcontract::getProjectId, req.getProjectId())
.eq(BusSubcontract::getContractorId, req.getContractorId())
.eq(BusSubcontract::getContractFileId, req.getContractFileId())
.count();
if (count > 0) {
throw new ServiceException("已关联该项目合同", HttpStatus.BAD_REQUEST);
}
boolean save = this.save(subcontract);
if (!save) {
throw new ServiceException("分包合同新增失败", HttpStatus.ERROR);
}
return subcontract.getId();
}
/**
* 修改分包合同
*
* @param req 分包合同
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(BusSubcontractUpdateReq req) {
BusSubcontract subcontract = new BusSubcontract();
BeanUtils.copyProperties(req, subcontract);
validEntityBeforeSave(subcontract);
Long id = req.getId();
BusSubcontract oldSubcontract = this.getById(id);
if (oldSubcontract == null) {
throw new ServiceException("修改分包合同失败,数据不存在", HttpStatus.NOT_FOUND);
}
Long count = this.lambdaQuery()
.eq(BusSubcontract::getProjectId, req.getProjectId())
.eq(BusSubcontract::getContractorId, req.getContractorId())
.eq(BusSubcontract::getContractFileId, req.getContractFileId())
.count();
if (count > 0) {
throw new ServiceException("已关联该项目合同", HttpStatus.BAD_REQUEST);
}
boolean result = this.updateById(subcontract);
if (!result) {
throw new ServiceException("修改分包合同失败", HttpStatus.ERROR);
}
return true;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(BusSubcontract entity) {
Long projectId = entity.getProjectId();
Long contractorId = entity.getContractorId();
if (projectId == null) {
throw new ServiceException("项目id不能为空", HttpStatus.BAD_REQUEST);
}
if (contractorId == null) {
throw new ServiceException("合同方id不能为空", HttpStatus.BAD_REQUEST);
}
BusProject project = projectService.getById(projectId);
if (project == null) {
throw new ServiceException("对应项目不存在", HttpStatus.NOT_FOUND);
}
BusContractor contractor = contractorService.getById(contractorId);
if (contractor == null) {
throw new ServiceException("对应合同方不存在", HttpStatus.NOT_FOUND);
}
if (!contractor.getProjectId().equals(projectId)) {
throw new ServiceException("分包方不属于当前项目,请重新选择", HttpStatus.BAD_REQUEST);
}
}
/**
* 校验并批量删除分包合同信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
Long userId = LoginHelper.getUserId();
List<BusSubcontract> list = this.listByIds(ids);
if (isValid) {
List<Long> projectIdList = list.stream().map(BusSubcontract::getProjectId).toList();
projectService.validAuth(projectIdList, userId);
}
// 关联删除文件
Set<Long> fileIdList = list.stream().map(BusSubcontract::getContractFileId).collect(Collectors.toSet());
Boolean result = ossService.deleteWithValidByIds(fileIdList, false);
if (!result) {
log.error("删除文件:{}失败", fileIdList);
}
return this.removeBatchByIds(ids);
}
/**
* 获取分包合同视图
*
* @param subcontract 分包合同
* @return 分包合同视图
*/
@Override
public BusSubcontractVo getVo(BusSubcontract subcontract) {
// 封装对象
BusSubcontractVo subcontractVo = new BusSubcontractVo();
if (subcontract == null) {
return subcontractVo;
}
BeanUtils.copyProperties(subcontract, subcontractVo);
return subcontractVo;
}
/**
* 获取用户和项目关联对象查询条件封装
*
* @param req 查询条件
* @return 查询条件封装
*/
@Override
public LambdaQueryWrapper<BusSubcontract> buildQueryWrapper(BusSubcontractQueryReq req) {
LambdaQueryWrapper<BusSubcontract> lqw = new LambdaQueryWrapper<>();
Long projectId = req.getProjectId();
Long contractorId = req.getContractorId();
String contractNumber = req.getContractNumber();
String contractName = req.getContractName();
String contractType = req.getContractType();
lqw.like(StringUtils.isNotBlank(contractNumber), BusSubcontract::getContractNumber, contractNumber);
lqw.like(StringUtils.isNotBlank(contractName), BusSubcontract::getContractName, contractName);
lqw.eq(ObjectUtils.isNotEmpty(projectId), BusSubcontract::getProjectId, projectId);
lqw.eq(ObjectUtils.isNotEmpty(contractorId), BusSubcontract::getContractorId, contractorId);
lqw.eq(StringUtils.isNotBlank(contractType), BusSubcontract::getContractType, contractType);
return lqw;
}
/**
* 获取分包合同分页视图
*
* @param subcontractPage 分包合同分页
* @return 分包合同分页视图
*/
@Override
public Page<BusSubcontractVo> getVoPage(Page<BusSubcontract> subcontractPage) {
List<BusSubcontract> subcontractList = subcontractPage.getRecords();
Page<BusSubcontractVo> subcontractVoPage = new Page<>(
subcontractPage.getCurrent(),
subcontractPage.getSize(),
subcontractPage.getTotal()
);
if (CollUtil.isEmpty(subcontractList)) {
return subcontractVoPage;
}
// 获取分包商信息
Set<Long> contractorIdList = subcontractList.stream().map(BusSubcontract::getContractorId).collect(Collectors.toSet());
Map<Long, BusContractor> contractorMap = contractorService.listByIds(contractorIdList)
.stream().collect(Collectors.toMap(BusContractor::getId, v -> v));
List<BusSubcontractVo> subcontractVoList = subcontractList.stream().map(entity -> {
BusSubcontractVo subcontractVo = new BusSubcontractVo();
BeanUtils.copyProperties(entity, subcontractVo);
Long contractorId = entity.getContractorId();
if (contractorMap.containsKey(contractorId)) {
BusContractor contractor = contractorMap.get(contractorId);
subcontractVo.setContractorName(contractor.getName());
}
return subcontractVo;
}).toList();
subcontractVoPage.setRecords(subcontractVoList);
return subcontractVoPage;
}
}

View File

@ -0,0 +1,104 @@
package org.dromara.quality.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.quality.domain.vo.knowledgedocument.QltKnowledgeDocumentVo;
import org.dromara.quality.domain.bo.QltKnowledgeDocumentBo;
import org.dromara.quality.service.IQltKnowledgeDocumentService;
/**
* 质量知识库
*
* @author lcj
* @date 2025-06-25
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/quality/knowledgeDocument")
public class QltKnowledgeDocumentController extends BaseController {
private final IQltKnowledgeDocumentService qltKnowledgeDocumentService;
/**
* 查询质量知识库列表
*/
@SaCheckPermission("quality:knowledgeDocument:list")
@GetMapping("/list")
public R<List<QltKnowledgeDocumentVo>> list(QltKnowledgeDocumentBo bo) {
List<QltKnowledgeDocumentVo> list = qltKnowledgeDocumentService.queryList(bo);
return R.ok(list);
}
/**
* 导出质量知识库列表
*/
@SaCheckPermission("quality:knowledgeDocument:export")
@Log(title = "质量知识库", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(QltKnowledgeDocumentBo bo, HttpServletResponse response) {
List<QltKnowledgeDocumentVo> list = qltKnowledgeDocumentService.queryList(bo);
ExcelUtil.exportExcel(list, "质量知识库", QltKnowledgeDocumentVo.class, response);
}
/**
* 获取质量知识库详细信息
*
* @param id 主键
*/
@SaCheckPermission("quality:knowledgeDocument:query")
@GetMapping("/{id}")
public R<QltKnowledgeDocumentVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(qltKnowledgeDocumentService.queryById(id));
}
/**
* 新增质量知识库
*/
@SaCheckPermission("quality:knowledgeDocument:add")
@Log(title = "质量知识库", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody QltKnowledgeDocumentBo bo) {
return toAjax(qltKnowledgeDocumentService.insertByBo(bo));
}
/**
* 修改质量知识库
*/
@SaCheckPermission("quality:knowledgeDocument:edit")
@Log(title = "质量知识库", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody QltKnowledgeDocumentBo bo) {
return toAjax(qltKnowledgeDocumentService.updateByBo(bo));
}
/**
* 删除质量知识库
*
* @param ids 主键串
*/
@SaCheckPermission("quality:knowledgeDocument:remove")
@Log(title = "质量知识库", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(qltKnowledgeDocumentService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,87 @@
package org.dromara.quality.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.util.Date;
/**
* 质量知识库对象 qlt_knowledge_document
*
* @author lcj
* @date 2025-06-25
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("qlt_knowledge_document")
public class QltKnowledgeDocument extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id")
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 父级0代表顶级
*/
private Long pid;
/**
* 文件名称
*/
private String fileName;
/**
* 文件路径
*/
private String filePath;
/**
* 文件访问路径
*/
private String fileUrl;
/**
* 文件类型1文件夹 2文件 3图片
*/
private String fileType;
/**
* 文件后缀
*/
private String fileSuffix;
/**
* 状态0正常 1删除
*/
private String fileStatus;
/**
* 原文件名
*/
private String originalName;
/**
* 备注
*/
private String remark;
/**
* 删除时间
*/
private Date deletedAt;
}

View File

@ -0,0 +1,87 @@
package org.dromara.quality.domain.bo;
import org.dromara.quality.domain.QltKnowledgeDocument;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* 质量知识库业务对象 qlt_knowledge_document
*
* @author lcj
* @date 2025-06-25
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = QltKnowledgeDocument.class, reverseConvertGenerate = false)
public class QltKnowledgeDocumentBo extends BaseEntity {
/**
* 主键id
*/
@NotNull(message = "主键id不能为空", groups = { EditGroup.class })
private Long id;
/**
* 项目id
*/
@NotNull(message = "项目id不能为空", groups = { AddGroup.class, EditGroup.class })
private Long projectId;
/**
* 父级0代表顶级
*/
@NotNull(message = "父级0代表顶级不能为空", groups = { AddGroup.class, EditGroup.class })
private Long pid;
/**
* 文件名称
*/
@NotBlank(message = "文件名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String fileName;
/**
* 文件路径
*/
private String filePath;
/**
* 文件访问路径
*/
private String fileUrl;
/**
* 文件类型1文件夹 2文件 3图片
*/
@NotBlank(message = "文件类型1文件夹 2文件 3图片不能为空", groups = { AddGroup.class, EditGroup.class })
private String fileType;
/**
* 文件后缀
*/
private String fileSuffix;
/**
* 状态0正常 1删除
*/
@NotBlank(message = "状态0正常 1删除不能为空", groups = { AddGroup.class, EditGroup.class })
private String fileStatus;
/**
* 原文件名
*/
private String originalName;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,106 @@
package org.dromara.quality.domain.vo.knowledgedocument;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.quality.domain.QltKnowledgeDocument;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 质量知识库视图对象 qlt_knowledge_document
*
* @author lcj
* @date 2025-06-25
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = QltKnowledgeDocument.class)
public class QltKnowledgeDocumentVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@ExcelProperty(value = "主键id")
private Long id;
/**
* 项目id
*/
@ExcelProperty(value = "项目id")
private Long projectId;
/**
* 父级0代表顶级
*/
@ExcelProperty(value = "父级", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=代表顶级")
private Long pid;
/**
* 文件名称
*/
@ExcelProperty(value = "文件名称")
private String fileName;
/**
* 文件路径
*/
@ExcelProperty(value = "文件路径")
private String filePath;
/**
* 文件访问路径
*/
@ExcelProperty(value = "文件访问路径")
private String fileUrl;
/**
* 文件类型1文件夹 2文件 3图片
*/
@ExcelProperty(value = "文件类型", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "1=文件夹,2=文件,3=图片")
private String fileType;
/**
* 文件后缀
*/
@ExcelProperty(value = "文件后缀")
private String fileSuffix;
/**
* 状态0正常 1删除
*/
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=正常,1=删除")
private String fileStatus;
/**
* 原文件名
*/
@ExcelProperty(value = "原文件名")
private String originalName;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
private Date createTime;
}

View File

@ -0,0 +1,15 @@
package org.dromara.quality.mapper;
import org.dromara.quality.domain.QltKnowledgeDocument;
import org.dromara.quality.domain.vo.knowledgedocument.QltKnowledgeDocumentVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 质量知识库Mapper接口
*
* @author lcj
* @date 2025-06-25
*/
public interface QltKnowledgeDocumentMapper extends BaseMapperPlus<QltKnowledgeDocument, QltKnowledgeDocumentVo> {
}

View File

@ -0,0 +1,58 @@
package org.dromara.quality.service;
import org.dromara.quality.domain.vo.knowledgedocument.QltKnowledgeDocumentVo;
import org.dromara.quality.domain.bo.QltKnowledgeDocumentBo;
import java.util.Collection;
import java.util.List;
/**
* 质量知识库Service接口
*
* @author lcj
* @date 2025-06-25
*/
public interface IQltKnowledgeDocumentService {
/**
* 查询质量知识库
*
* @param id 主键
* @return 质量知识库
*/
QltKnowledgeDocumentVo queryById(Long id);
/**
* 查询符合条件的质量知识库列表
*
* @param bo 查询条件
* @return 质量知识库列表
*/
List<QltKnowledgeDocumentVo> queryList(QltKnowledgeDocumentBo bo);
/**
* 新增质量知识库
*
* @param bo 质量知识库
* @return 是否新增成功
*/
Boolean insertByBo(QltKnowledgeDocumentBo bo);
/**
* 修改质量知识库
*
* @param bo 质量知识库
* @return 是否修改成功
*/
Boolean updateByBo(QltKnowledgeDocumentBo bo);
/**
* 校验并批量删除质量知识库信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@ -0,0 +1,122 @@
package org.dromara.quality.service.impl;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.dromara.quality.domain.bo.QltKnowledgeDocumentBo;
import org.dromara.quality.domain.vo.knowledgedocument.QltKnowledgeDocumentVo;
import org.dromara.quality.domain.QltKnowledgeDocument;
import org.dromara.quality.mapper.QltKnowledgeDocumentMapper;
import org.dromara.quality.service.IQltKnowledgeDocumentService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 质量知识库Service业务层处理
*
* @author lcj
* @date 2025-06-25
*/
@RequiredArgsConstructor
@Service
public class QltKnowledgeDocumentServiceImpl implements IQltKnowledgeDocumentService {
private final QltKnowledgeDocumentMapper baseMapper;
/**
* 查询质量知识库
*
* @param id 主键
* @return 质量知识库
*/
@Override
public QltKnowledgeDocumentVo queryById(Long id){
return baseMapper.selectVoById(id);
}
/**
* 查询符合条件的质量知识库列表
*
* @param bo 查询条件
* @return 质量知识库列表
*/
@Override
public List<QltKnowledgeDocumentVo> queryList(QltKnowledgeDocumentBo bo) {
LambdaQueryWrapper<QltKnowledgeDocument> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<QltKnowledgeDocument> buildQueryWrapper(QltKnowledgeDocumentBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<QltKnowledgeDocument> lqw = Wrappers.lambdaQuery();
lqw.orderByAsc(QltKnowledgeDocument::getId);
lqw.eq(bo.getProjectId() != null, QltKnowledgeDocument::getProjectId, bo.getProjectId());
lqw.eq(bo.getPid() != null, QltKnowledgeDocument::getPid, bo.getPid());
lqw.like(StringUtils.isNotBlank(bo.getFileName()), QltKnowledgeDocument::getFileName, bo.getFileName());
lqw.eq(StringUtils.isNotBlank(bo.getFilePath()), QltKnowledgeDocument::getFilePath, bo.getFilePath());
lqw.eq(StringUtils.isNotBlank(bo.getFileUrl()), QltKnowledgeDocument::getFileUrl, bo.getFileUrl());
lqw.eq(StringUtils.isNotBlank(bo.getFileType()), QltKnowledgeDocument::getFileType, bo.getFileType());
lqw.eq(StringUtils.isNotBlank(bo.getFileSuffix()), QltKnowledgeDocument::getFileSuffix, bo.getFileSuffix());
lqw.eq(StringUtils.isNotBlank(bo.getFileStatus()), QltKnowledgeDocument::getFileStatus, bo.getFileStatus());
lqw.like(StringUtils.isNotBlank(bo.getOriginalName()), QltKnowledgeDocument::getOriginalName, bo.getOriginalName());
return lqw;
}
/**
* 新增质量知识库
*
* @param bo 质量知识库
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(QltKnowledgeDocumentBo bo) {
QltKnowledgeDocument add = MapstructUtils.convert(bo, QltKnowledgeDocument.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改质量知识库
*
* @param bo 质量知识库
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(QltKnowledgeDocumentBo bo) {
QltKnowledgeDocument update = MapstructUtils.convert(bo, QltKnowledgeDocument.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(QltKnowledgeDocument entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除质量知识库信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
}

View File

@ -0,0 +1,104 @@
package org.dromara.safety.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.safety.domain.vo.knowledgedocument.HseKnowledgeDocumentVo;
import org.dromara.safety.domain.bo.HseKnowledgeDocumentBo;
import org.dromara.safety.service.IHseKnowledgeDocumentService;
/**
* 安全知识库
*
* @author lcj
* @date 2025-06-25
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/safety/knowledgeDocument")
public class HseKnowledgeDocumentController extends BaseController {
private final IHseKnowledgeDocumentService hseKnowledgeDocumentService;
/**
* 查询安全知识库列表
*/
@SaCheckPermission("safety:knowledgeDocument:list")
@GetMapping("/list")
public R<List<HseKnowledgeDocumentVo>> list(HseKnowledgeDocumentBo bo) {
List<HseKnowledgeDocumentVo> list = hseKnowledgeDocumentService.queryList(bo);
return R.ok(list);
}
/**
* 导出安全知识库列表
*/
@SaCheckPermission("safety:knowledgeDocument:export")
@Log(title = "安全知识库", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HseKnowledgeDocumentBo bo, HttpServletResponse response) {
List<HseKnowledgeDocumentVo> list = hseKnowledgeDocumentService.queryList(bo);
ExcelUtil.exportExcel(list, "安全知识库", HseKnowledgeDocumentVo.class, response);
}
/**
* 获取安全知识库详细信息
*
* @param id 主键
*/
@SaCheckPermission("safety:knowledgeDocument:query")
@GetMapping("/{id}")
public R<HseKnowledgeDocumentVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(hseKnowledgeDocumentService.queryById(id));
}
/**
* 新增安全知识库
*/
@SaCheckPermission("safety:knowledgeDocument:add")
@Log(title = "安全知识库", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody HseKnowledgeDocumentBo bo) {
return toAjax(hseKnowledgeDocumentService.insertByBo(bo));
}
/**
* 修改安全知识库
*/
@SaCheckPermission("safety:knowledgeDocument:edit")
@Log(title = "安全知识库", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody HseKnowledgeDocumentBo bo) {
return toAjax(hseKnowledgeDocumentService.updateByBo(bo));
}
/**
* 删除安全知识库
*
* @param ids 主键串
*/
@SaCheckPermission("safety:knowledgeDocument:remove")
@Log(title = "安全知识库", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(hseKnowledgeDocumentService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,87 @@
package org.dromara.safety.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.util.Date;
/**
* 安全知识库对象 hse_knowledge_document
*
* @author lcj
* @date 2025-06-25
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("hse_knowledge_document")
public class HseKnowledgeDocument extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id")
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 父级0代表顶级
*/
private Long pid;
/**
* 文件名称
*/
private String fileName;
/**
* 文件路径
*/
private String filePath;
/**
* 文件访问路径
*/
private String fileUrl;
/**
* 文件类型1文件夹 2文件 3图片
*/
private String fileType;
/**
* 文件后缀
*/
private String fileSuffix;
/**
* 状态0正常 1删除
*/
private String fileStatus;
/**
* 原文件名
*/
private String originalName;
/**
* 备注
*/
private String remark;
/**
* 删除时间
*/
private Date deletedAt;
}

View File

@ -0,0 +1,87 @@
package org.dromara.safety.domain.bo;
import org.dromara.safety.domain.HseKnowledgeDocument;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* 安全知识库业务对象 hse_knowledge_document
*
* @author lcj
* @date 2025-06-25
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = HseKnowledgeDocument.class, reverseConvertGenerate = false)
public class HseKnowledgeDocumentBo extends BaseEntity {
/**
* 主键id
*/
@NotNull(message = "主键id不能为空", groups = { EditGroup.class })
private Long id;
/**
* 项目id
*/
@NotNull(message = "项目id不能为空", groups = { AddGroup.class, EditGroup.class })
private Long projectId;
/**
* 父级0代表顶级
*/
@NotNull(message = "父级0代表顶级不能为空", groups = { AddGroup.class, EditGroup.class })
private Long pid;
/**
* 文件名称
*/
@NotBlank(message = "文件名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String fileName;
/**
* 文件路径
*/
private String filePath;
/**
* 文件访问路径
*/
private String fileUrl;
/**
* 文件类型1文件夹 2文件 3图片
*/
@NotBlank(message = "文件类型1文件夹 2文件 3图片不能为空", groups = { AddGroup.class, EditGroup.class })
private String fileType;
/**
* 文件后缀
*/
private String fileSuffix;
/**
* 状态0正常 1删除
*/
@NotBlank(message = "状态0正常 1删除不能为空", groups = { AddGroup.class, EditGroup.class })
private String fileStatus;
/**
* 原文件名
*/
private String originalName;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,98 @@
package org.dromara.safety.domain.vo.knowledgedocument;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.safety.domain.HseKnowledgeDocument;
import java.io.Serial;
import java.io.Serializable;
/**
* 安全知识库视图对象 hse_knowledge_document
*
* @author lcj
* @date 2025-06-25
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = HseKnowledgeDocument.class)
public class HseKnowledgeDocumentVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@ExcelProperty(value = "主键id")
private Long id;
/**
* 项目id
*/
@ExcelProperty(value = "项目id")
private Long projectId;
/**
* 父级0代表顶级
*/
@ExcelProperty(value = "父级", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=代表顶级")
private Long pid;
/**
* 文件名称
*/
@ExcelProperty(value = "文件名称")
private String fileName;
/**
* 文件路径
*/
@ExcelProperty(value = "文件路径")
private String filePath;
/**
* 文件访问路径
*/
@ExcelProperty(value = "文件访问路径")
private String fileUrl;
/**
* 文件类型1文件夹 2文件 3图片
*/
@ExcelProperty(value = "文件类型", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "1=文件夹,2=文件,3=图片")
private String fileType;
/**
* 文件后缀
*/
@ExcelProperty(value = "文件后缀")
private String fileSuffix;
/**
* 状态0正常 1删除
*/
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=正常,1=删除")
private String fileStatus;
/**
* 原文件名
*/
@ExcelProperty(value = "原文件名")
private String originalName;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@ -0,0 +1,15 @@
package org.dromara.safety.mapper;
import org.dromara.safety.domain.HseKnowledgeDocument;
import org.dromara.safety.domain.vo.knowledgedocument.HseKnowledgeDocumentVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 安全知识库Mapper接口
*
* @author lcj
* @date 2025-06-25
*/
public interface HseKnowledgeDocumentMapper extends BaseMapperPlus<HseKnowledgeDocument, HseKnowledgeDocumentVo> {
}

View File

@ -0,0 +1,58 @@
package org.dromara.safety.service;
import org.dromara.safety.domain.vo.knowledgedocument.HseKnowledgeDocumentVo;
import org.dromara.safety.domain.bo.HseKnowledgeDocumentBo;
import java.util.Collection;
import java.util.List;
/**
* 安全知识库Service接口
*
* @author lcj
* @date 2025-06-25
*/
public interface IHseKnowledgeDocumentService {
/**
* 查询安全知识库
*
* @param id 主键
* @return 安全知识库
*/
HseKnowledgeDocumentVo queryById(Long id);
/**
* 查询符合条件的安全知识库列表
*
* @param bo 查询条件
* @return 安全知识库列表
*/
List<HseKnowledgeDocumentVo> queryList(HseKnowledgeDocumentBo bo);
/**
* 新增安全知识库
*
* @param bo 安全知识库
* @return 是否新增成功
*/
Boolean insertByBo(HseKnowledgeDocumentBo bo);
/**
* 修改安全知识库
*
* @param bo 安全知识库
* @return 是否修改成功
*/
Boolean updateByBo(HseKnowledgeDocumentBo bo);
/**
* 校验并批量删除安全知识库信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@ -0,0 +1,122 @@
package org.dromara.safety.service.impl;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.dromara.safety.domain.bo.HseKnowledgeDocumentBo;
import org.dromara.safety.domain.vo.knowledgedocument.HseKnowledgeDocumentVo;
import org.dromara.safety.domain.HseKnowledgeDocument;
import org.dromara.safety.mapper.HseKnowledgeDocumentMapper;
import org.dromara.safety.service.IHseKnowledgeDocumentService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 安全知识库Service业务层处理
*
* @author lcj
* @date 2025-06-25
*/
@RequiredArgsConstructor
@Service
public class HseKnowledgeDocumentServiceImpl implements IHseKnowledgeDocumentService {
private final HseKnowledgeDocumentMapper baseMapper;
/**
* 查询安全知识库
*
* @param id 主键
* @return 安全知识库
*/
@Override
public HseKnowledgeDocumentVo queryById(Long id){
return baseMapper.selectVoById(id);
}
/**
* 查询符合条件的安全知识库列表
*
* @param bo 查询条件
* @return 安全知识库列表
*/
@Override
public List<HseKnowledgeDocumentVo> queryList(HseKnowledgeDocumentBo bo) {
LambdaQueryWrapper<HseKnowledgeDocument> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<HseKnowledgeDocument> buildQueryWrapper(HseKnowledgeDocumentBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<HseKnowledgeDocument> lqw = Wrappers.lambdaQuery();
lqw.orderByAsc(HseKnowledgeDocument::getId);
lqw.eq(bo.getProjectId() != null, HseKnowledgeDocument::getProjectId, bo.getProjectId());
lqw.eq(bo.getPid() != null, HseKnowledgeDocument::getPid, bo.getPid());
lqw.like(StringUtils.isNotBlank(bo.getFileName()), HseKnowledgeDocument::getFileName, bo.getFileName());
lqw.eq(StringUtils.isNotBlank(bo.getFilePath()), HseKnowledgeDocument::getFilePath, bo.getFilePath());
lqw.eq(StringUtils.isNotBlank(bo.getFileUrl()), HseKnowledgeDocument::getFileUrl, bo.getFileUrl());
lqw.eq(StringUtils.isNotBlank(bo.getFileType()), HseKnowledgeDocument::getFileType, bo.getFileType());
lqw.eq(StringUtils.isNotBlank(bo.getFileSuffix()), HseKnowledgeDocument::getFileSuffix, bo.getFileSuffix());
lqw.eq(StringUtils.isNotBlank(bo.getFileStatus()), HseKnowledgeDocument::getFileStatus, bo.getFileStatus());
lqw.like(StringUtils.isNotBlank(bo.getOriginalName()), HseKnowledgeDocument::getOriginalName, bo.getOriginalName());
return lqw;
}
/**
* 新增安全知识库
*
* @param bo 安全知识库
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(HseKnowledgeDocumentBo bo) {
HseKnowledgeDocument add = MapstructUtils.convert(bo, HseKnowledgeDocument.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改安全知识库
*
* @param bo 安全知识库
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(HseKnowledgeDocumentBo bo) {
HseKnowledgeDocument update = MapstructUtils.convert(bo, HseKnowledgeDocument.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(HseKnowledgeDocument entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除安全知识库信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
}

View File

@ -0,0 +1,101 @@
package org.dromara.system.controller.system;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.system.domain.dto.userfile.SysUserFileCreateReq;
import org.dromara.system.domain.dto.userfile.SysUserFileQueryReq;
import org.dromara.system.domain.vo.SysUserFileVo;
import org.dromara.system.service.ISysUserFileService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 用户文件关联
*
* @author lcj
* @date 2025-06-25
*/
@Validated
@RestController
@RequestMapping("/system/userFile")
public class SysUserFileController extends BaseController {
@Resource
private ISysUserFileService userFileService;
/**
* 查询用户文件关联列表
*/
@SaCheckPermission("system:userFile:list")
@GetMapping("/list")
public TableDataInfo<SysUserFileVo> list(SysUserFileQueryReq req, PageQuery pageQuery) {
return userFileService.queryPageList(req, pageQuery);
}
/**
* 获取用户文件关联详细信息
*
* @param id 主键
*/
@SaCheckPermission("system:userFile:query")
@GetMapping("/{id}")
public R<SysUserFileVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(userFileService.queryById(id));
}
/**
* 根据用户id获取用户文件关联列表
*/
@SaCheckPermission("system:userFile:query")
@GetMapping("/user/{userId}")
public R<List<SysUserFileVo>> getInfoByUserId(@NotNull(message = "用户id不能为空")
@PathVariable Long userId) {
return R.ok(userFileService.queryListByUserId(userId));
}
/**
* 获取登录用户文件关联列表
*/
@SaCheckPermission("system:userFile:query")
@GetMapping("/login/user")
public R<List<SysUserFileVo>> getInfoByLoginUser() {
return R.ok(userFileService.queryListByLoginUser());
}
/**
* 新增用户文件关联
*/
@SaCheckPermission("system:userFile:add")
@Log(title = "用户文件关联", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody SysUserFileCreateReq req) {
return toAjax(userFileService.insertByBo(req));
}
/**
* 删除用户文件关联
*
* @param id 主键
*/
@SaCheckPermission("system:userFile:remove")
@Log(title = "用户文件关联", businessType = BusinessType.DELETE)
@DeleteMapping("/{id}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long id) {
return toAjax(userFileService.deleteById(id));
}
}

View File

@ -0,0 +1,39 @@
package org.dromara.system.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 用户文件关联对象 sys_user_file
*
* @author lcj
* @date 2025-06-25
*/
@Data
@TableName("sys_user_file")
public class SysUserFile implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id")
private Long id;
/**
* 用户id
*/
private Long userId;
/**
* 文件id
*/
private Long fileId;
}

View File

@ -0,0 +1,28 @@
package org.dromara.system.domain.dto.userfile;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lcj
* @date 2025/6/25 16:58
*/
@Data
public class SysUserFileCreateReq implements Serializable {
@Serial
private static final long serialVersionUID = -5473752959026971387L;
/**
* 用户id
*/
private Long userId;
/**
* 文件列表id,分隔)
*/
private String fileId;
}

View File

@ -0,0 +1,28 @@
package org.dromara.system.domain.dto.userfile;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lcj
* @date 2025/6/25 16:58
*/
@Data
public class SysUserFileQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = 6499152510654651256L;
/**
* 用户id
*/
private Long userId;
/**
* 文件id
*/
private Long fileId;
}

View File

@ -0,0 +1,46 @@
package org.dromara.system.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.system.domain.SysUserFile;
import java.io.Serial;
import java.io.Serializable;
/**
* 用户文件关联视图对象 sys_user_file
*
* @author lcj
* @date 2025-06-25
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = SysUserFile.class)
public class SysUserFileVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@ExcelProperty(value = "主键id")
private Long id;
/**
* 用户id
*/
@ExcelProperty(value = "用户id")
private Long userId;
/**
* 文件id
*/
@ExcelProperty(value = "文件id")
private Long fileId;
}

View File

@ -2,13 +2,13 @@ package org.dromara.system.domain.vo;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.sensitive.annotation.Sensitive; import org.dromara.common.sensitive.annotation.Sensitive;
import org.dromara.common.sensitive.core.SensitiveStrategy; import org.dromara.common.sensitive.core.SensitiveStrategy;
import org.dromara.common.translation.annotation.Translation; import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant; import org.dromara.common.translation.constant.TransConstant;
import org.dromara.system.domain.SysUser; import org.dromara.system.domain.SysUser;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
@ -53,6 +53,11 @@ public class SysUserVo implements Serializable {
*/ */
private String nickName; private String nickName;
/**
* 用户文件列表
*/
private String filePath;
/** /**
* 用户类型sys_user系统用户 * 用户类型sys_user系统用户
*/ */

View File

@ -0,0 +1,15 @@
package org.dromara.system.mapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.system.domain.SysUserFile;
import org.dromara.system.domain.vo.SysUserFileVo;
/**
* 用户文件关联Mapper接口
*
* @author lcj
* @date 2025-06-25
*/
public interface SysUserFileMapper extends BaseMapperPlus<SysUserFile, SysUserFileVo> {
}

View File

@ -0,0 +1,103 @@
package org.dromara.system.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.system.domain.SysUserFile;
import org.dromara.system.domain.dto.userfile.SysUserFileCreateReq;
import org.dromara.system.domain.dto.userfile.SysUserFileQueryReq;
import org.dromara.system.domain.vo.SysUserFileVo;
import java.util.List;
/**
* 用户文件关联Service接口
*
* @author lcj
* @date 2025-06-25
*/
public interface ISysUserFileService extends IService<SysUserFile> {
/**
* 查询用户文件关联
*
* @param id 主键
* @return 用户文件关联
*/
SysUserFileVo queryById(Long id);
/**
* 分页查询用户文件关联列表
*
* @param req 查询条件
* @param pageQuery 分页参数
* @return 用户文件关联分页列表
*/
TableDataInfo<SysUserFileVo> queryPageList(SysUserFileQueryReq req, PageQuery pageQuery);
/**
* 查询符合条件的用户文件关联列表
*
* @param req 查询条件
* @return 用户文件关联列表
*/
List<SysUserFileVo> queryList(SysUserFileQueryReq req);
/**
* 根据用户ID查询用户文件关联列表
*
* @param userId 用户ID
* @return 用户文件关联列表
*/
List<SysUserFileVo> queryListByUserId(Long userId);
/**
* 当前登录用户文件关联列表
*
* @return 用户文件关联列表
*/
List<SysUserFileVo> queryListByLoginUser();
/**
* 新增用户文件关联
*
* @param req 用户文件关联
* @return 是否新增成功
*/
Boolean insertByBo(SysUserFileCreateReq req);
/**
* 删除用户文件关联信息
*
* @param id 待删除的主键
* @return 是否删除成功
*/
Boolean deleteById(Long id);
/**
* 获取用户文件视图
*
* @param userFile 用户文件
* @return 用户文件视图
*/
SysUserFileVo getVo(SysUserFile userFile);
/**
* 获取用户和项目关联对象查询条件封装
*
* @param req 查询条件
* @return 查询条件封装
*/
LambdaQueryWrapper<SysUserFile> buildQueryWrapper(SysUserFileQueryReq req);
/**
* 获取用户文件分页视图
*
* @param userFilePage 用户文件分页
* @return 用户文件分页视图
*/
Page<SysUserFileVo> getVoPage(Page<SysUserFile> userFilePage);
}

View File

@ -0,0 +1,245 @@
package org.dromara.system.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.domain.SysUserFile;
import org.dromara.system.domain.dto.userfile.SysUserFileCreateReq;
import org.dromara.system.domain.dto.userfile.SysUserFileQueryReq;
import org.dromara.system.domain.vo.SysUserFileVo;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.mapper.SysUserFileMapper;
import org.dromara.system.service.ISysOssService;
import org.dromara.system.service.ISysUserFileService;
import org.dromara.system.service.ISysUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
/**
* 用户文件关联Service业务层处理
*
* @author lcj
* @date 2025-06-25
*/
@Service
public class SysUserFileServiceImpl extends ServiceImpl<SysUserFileMapper, SysUserFile>
implements ISysUserFileService {
@Resource
private ISysUserService userService;
@Resource
private ISysOssService ossService;
/**
* 查询用户文件关联
*
* @param id 主键
* @return 用户文件关联
*/
@Override
public SysUserFileVo queryById(Long id) {
SysUserFile userFile = getById(id);
if (userFile == null) {
throw new ServiceException("对应用户文件关联信息不存在", HttpStatus.NOT_FOUND);
}
return this.getVo(userFile);
}
/**
* 分页查询用户文件关联列表
*
* @param req 查询条件
* @param pageQuery 分页参数
* @return 用户文件关联分页列表
*/
@Override
public TableDataInfo<SysUserFileVo> queryPageList(SysUserFileQueryReq req, PageQuery pageQuery) {
LambdaQueryWrapper<SysUserFile> lqw = buildQueryWrapper(req);
Page<SysUserFile> result = this.page(pageQuery.build(), lqw);
return TableDataInfo.build(this.getVoPage(result));
}
/**
* 查询符合条件的用户文件关联列表
*
* @param req 查询条件
* @return 用户文件关联列表
*/
@Override
public List<SysUserFileVo> queryList(SysUserFileQueryReq req) {
LambdaQueryWrapper<SysUserFile> lqw = this.buildQueryWrapper(req);
return this.list(lqw).stream().map(this::getVo).toList();
}
/**
* 根据用户ID查询用户文件关联列表
*
* @param userId 用户ID
* @return 用户文件关联列表
*/
@Override
public List<SysUserFileVo> queryListByUserId(Long userId) {
SysUserVo user = userService.selectUserById(userId);
if (user == null) {
throw new ServiceException("用户不存在", HttpStatus.NOT_FOUND);
}
return baseMapper.selectVoList(new LambdaQueryWrapper<SysUserFile>()
.eq(SysUserFile::getUserId, userId));
}
/**
* 当前登录用户文件关联列表
*
* @return 用户文件关联列表
*/
@Override
public List<SysUserFileVo> queryListByLoginUser() {
Long userId = LoginHelper.getUserId();
return baseMapper.selectVoList(new LambdaQueryWrapper<SysUserFile>()
.eq(SysUserFile::getUserId, userId));
}
/**
* 新增用户文件关联
*
* @param req 用户文件关联
* @return 是否新增成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByBo(SysUserFileCreateReq req) {
SysUserFile userFile = new SysUserFile();
BeanUtils.copyProperties(req, userFile);
validEntityBeforeSave(userFile);
String fileId = req.getFileId();
if (StringUtils.isBlank(fileId)) {
throw new ServiceException("用户文件不能为空", HttpStatus.BAD_REQUEST);
}
List<Long> fileIdList = Arrays.stream(fileId.split(",")).map(Long::parseLong).toList();
List<SysUserFile> newUserFileList = fileIdList.stream().map(id -> {
SysUserFile newUserFile = new SysUserFile();
newUserFile.setUserId(userFile.getUserId());
newUserFile.setFileId(id);
return newUserFile;
}).toList();
boolean save = this.saveOrUpdateBatch(newUserFileList);
if (!save) {
throw new ServiceException("保存用户文件关联失败,数据库异常", HttpStatus.ERROR);
}
return true;
}
/**
* 删除用户文件关联信息
*
* @param id 待删除的主键
* @return 是否删除成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean deleteById(Long id) {
SysUserFile userFile = this.getById(id);
if (userFile == null) {
throw new ServiceException("用户文件关联不存在", HttpStatus.BAD_REQUEST);
}
Long fileId = userFile.getFileId();
// 删除文件
Boolean result = ossService.deleteWithValidByIds(List.of(fileId), true);
if (!result) {
throw new ServiceException("用户文件删除失败", HttpStatus.ERROR);
}
boolean remove = this.removeById(id);
if (!remove) {
throw new ServiceException("用户文件关联删除失败", HttpStatus.ERROR);
}
return true;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(SysUserFile entity) {
// TODO 做一些数据校验,如唯一约束
Long userId = entity.getUserId();
if (userId == null) {
throw new ServiceException("用户ID不能为空", HttpStatus.NOT_FOUND);
}
if (userService.selectUserById(userId) == null) {
throw new ServiceException("对应用户不存在", HttpStatus.NOT_FOUND);
}
}
/**
* 获取用户文件视图
*
* @param userFile 用户文件
* @return 用户文件视图
*/
@Override
public SysUserFileVo getVo(SysUserFile userFile) {
SysUserFileVo userFileVo = new SysUserFileVo();
if (userFile == null) {
return userFileVo;
}
BeanUtils.copyProperties(userFile, userFileVo);
return userFileVo;
}
/**
* 获取用户和项目关联对象查询条件封装
*
* @param req 查询条件
* @return 查询条件封装
*/
@Override
public LambdaQueryWrapper<SysUserFile> buildQueryWrapper(SysUserFileQueryReq req) {
LambdaQueryWrapper<SysUserFile> lqw = new LambdaQueryWrapper<>();
if (req == null) {
return lqw;
}
Long userId = req.getUserId();
Long fileId = req.getFileId();
lqw.eq(ObjectUtils.isNotEmpty(userId), SysUserFile::getUserId, userId);
lqw.eq(ObjectUtils.isNotEmpty(fileId), SysUserFile::getFileId, fileId);
return lqw;
}
/**
* 获取用户文件分页视图
*
* @param userFilePage 用户文件分页
* @return 用户文件分页视图
*/
@Override
public Page<SysUserFileVo> getVoPage(Page<SysUserFile> userFilePage) {
List<SysUserFile> userFileList = userFilePage.getRecords();
Page<SysUserFileVo> userFileVoPage = new Page<>(
userFilePage.getCurrent(),
userFilePage.getSize(),
userFilePage.getTotal());
if (CollUtil.isEmpty(userFileList)) {
return userFileVoPage;
}
List<SysUserFileVo> userFileVoList = userFileList.stream().map(userFile -> {
SysUserFileVo userFileVo = new SysUserFileVo();
BeanUtils.copyProperties(userFile, userFileVo);
return userFileVo;
}).toList();
userFileVoPage.setRecords(userFileVoList);
return userFileVoPage;
}
}

View File

@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.CacheNames; import org.dromara.common.core.constant.CacheNames;
@ -29,9 +30,11 @@ import org.dromara.system.domain.vo.SysRoleVo;
import org.dromara.system.domain.vo.SysUserExportVo; import org.dromara.system.domain.vo.SysUserExportVo;
import org.dromara.system.domain.vo.SysUserVo; import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.mapper.*; import org.dromara.system.mapper.*;
import org.dromara.system.service.ISysUserFileService;
import org.dromara.system.service.ISysUserService; import org.dromara.system.service.ISysUserService;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -39,6 +42,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
/** /**
* 用户 业务层处理 * 用户 业务层处理
@ -57,9 +61,32 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
private final SysUserRoleMapper userRoleMapper; private final SysUserRoleMapper userRoleMapper;
private final SysUserPostMapper userPostMapper; private final SysUserPostMapper userPostMapper;
@Lazy
@Resource
private ISysUserFileService userFileService;
@Override @Override
public TableDataInfo<SysUserVo> selectPageUserList(SysUserBo user, PageQuery pageQuery) { public TableDataInfo<SysUserVo> selectPageUserList(SysUserBo user, PageQuery pageQuery) {
Page<SysUserVo> page = baseMapper.selectPageUserList(pageQuery.build(), this.buildQueryWrapper(user)); Page<SysUserVo> page = baseMapper.selectPageUserList(pageQuery.build(), this.buildQueryWrapper(user));
List<SysUserVo> userVoList = page.getRecords();
List<Long> userIdList = userVoList.stream().map(SysUserVo::getUserId).toList();
if (CollUtil.isNotEmpty(userIdList)) {
List<SysUserFile> userFileList = userFileService.lambdaQuery()
.in(SysUserFile::getUserId, userIdList)
.list();
Map<Long, List<SysUserFile>> userFileMap = userFileList.stream().collect(Collectors.groupingBy(SysUserFile::getUserId));
userVoList.forEach(userVo -> {
Long userId = userVo.getUserId();
if (userFileMap.containsKey(userId)) {
List<SysUserFile> fileList = userFileMap.get(userId);
String fileIdStr = fileList.stream()
.map(file -> String.valueOf(file.getFileId()))
.collect(Collectors.joining(","));
userVo.setFilePath(fileIdStr);
}
});
page.setRecords(userVoList);
}
return TableDataInfo.build(page); return TableDataInfo.build(page);
} }

View File

@ -0,0 +1,51 @@
package org.dromara.utils;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @author lcj
* @date 2025/6/25 10:57
*/
@Slf4j
@Component
public class IdCardEncryptorUtil {
@Value("${id-card.encrypt-key}")
private String encryptKeyHex;
private AES aes;
@PostConstruct
public void init() {
byte[] keyBytes = HexUtil.decodeHex(encryptKeyHex);
this.aes = SecureUtil.aes(keyBytes);
log.info("身份证 AES 加解密工具初始化成功");
}
/**
* 加密
*
* @param idCard 身份证号码
* @return 加密后的身份证号码
*/
public String encrypt(String idCard) {
return aes.encryptBase64(idCard);
}
/**
* 解密
*
* @param encrypted 密文
* @return 解密后的身份证号码
*/
public String decrypt(String encrypted) {
return aes.decryptStr(encrypted);
}
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.project.mapper.BusSubcontractMapper">
</mapper>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.quality.mapper.QltKnowledgeDocumentMapper">
</mapper>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.safety.mapper.HseKnowledgeDocumentMapper">
</mapper>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.system.mapper.SysUserFileMapper">
</mapper>

View File

@ -737,3 +737,63 @@ values(1937338721300996102, '识别记录删除', 1937338721300996098, '4', '#'
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1937338721300996103, '识别记录导出', 1937338721300996098, '5', '#', '', 1, 0, 'F', '0', '0', 'safety:recognizeRecord:export', '#', 103, 1, sysdate(), null, null, ''); values(1937338721300996103, '识别记录导出', 1937338721300996098, '5', '#', '', 1, 0, 'F', '0', '0', 'safety:recognizeRecord:export', '#', 103, 1, sysdate(), null, null, '');
-- 菜单 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1937790795423707138, '分包合同', '1937684147828957185', '1', 'subcontract', 'project/subcontract/index', 1, 0, 'C', '0', '0', 'project:subcontract:list', '#', 103, 1, sysdate(), null, null, '分包合同菜单');
-- 按钮 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1937790795423707139, '分包合同查询', 1937790795423707138, '1', '#', '', 1, 0, 'F', '0', '0', 'project:subcontract:query', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1937790795423707140, '分包合同新增', 1937790795423707138, '2', '#', '', 1, 0, 'F', '0', '0', 'project:subcontract:add', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1937790795423707141, '分包合同修改', 1937790795423707138, '3', '#', '', 1, 0, 'F', '0', '0', 'project:subcontract:edit', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1937790795423707142, '分包合同删除', 1937790795423707138, '4', '#', '', 1, 0, 'F', '0', '0', 'project:subcontract:remove', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1937790795423707143, '分包合同导出', 1937790795423707138, '5', '#', '', 1, 0, 'F', '0', '0', 'project:subcontract:export', '#', 103, 1, sysdate(), null, null, '');
-- 菜单 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1937825328848191490, '安全知识库', '1902191175640604673', '1', 'knowledgeDocument', 'safety/knowledgeDocument/index', 1, 0, 'C', '0', '0', 'safety:knowledgeDocument:list', '#', 103, 1, sysdate(), null, null, '安全知识库菜单');
-- 按钮 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1937825328848191491, '安全知识库查询', 1937825328848191490, '1', '#', '', 1, 0, 'F', '0', '0', 'safety:knowledgeDocument:query', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1937825328848191492, '安全知识库新增', 1937825328848191490, '2', '#', '', 1, 0, 'F', '0', '0', 'safety:knowledgeDocument:add', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1937825328848191493, '安全知识库修改', 1937825328848191490, '3', '#', '', 1, 0, 'F', '0', '0', 'safety:knowledgeDocument:edit', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1937825328848191494, '安全知识库删除', 1937825328848191490, '4', '#', '', 1, 0, 'F', '0', '0', 'safety:knowledgeDocument:remove', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1937825328848191495, '安全知识库导出', 1937825328848191490, '5', '#', '', 1, 0, 'F', '0', '0', 'safety:knowledgeDocument:export', '#', 103, 1, sysdate(), null, null, '');
-- 菜单 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1937825131464245250, '质量知识库', '1912336811971096577', '1', 'knowledgeDocument', 'quality/knowledgeDocument/index', 1, 0, 'C', '0', '0', 'quality:knowledgeDocument:list', '#', 103, 1, sysdate(), null, null, '质量知识库菜单');
-- 按钮 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1937825131464245251, '质量知识库查询', 1937825131464245250, '1', '#', '', 1, 0, 'F', '0', '0', 'quality:knowledgeDocument:query', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1937825131464245252, '质量知识库新增', 1937825131464245250, '2', '#', '', 1, 0, 'F', '0', '0', 'quality:knowledgeDocument:add', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1937825131464245253, '质量知识库修改', 1937825131464245250, '3', '#', '', 1, 0, 'F', '0', '0', 'quality:knowledgeDocument:edit', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1937825131464245254, '质量知识库删除', 1937825131464245250, '4', '#', '', 1, 0, 'F', '0', '0', 'quality:knowledgeDocument:remove', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1937825131464245255, '质量知识库导出', 1937825131464245250, '5', '#', '', 1, 0, 'F', '0', '0', 'quality:knowledgeDocument:export', '#', 103, 1, sysdate(), null, null, '');

View File

@ -1164,4 +1164,80 @@ CREATE TABLE `hse_recognize_record`
`is_delete` tinyint(4) default 0 not null comment '是否删除0正常 1删除', `is_delete` tinyint(4) default 0 not null comment '是否删除0正常 1删除',
primary key (`id`) using btree, primary key (`id`) using btree,
index `idx_project_id` (`project_id` asc) using btree comment '项目id' index `idx_project_id` (`project_id` asc) using btree comment '项目id'
) comment = '识别记录' COLLATE = utf8mb4_unicode_ci; ) comment = '识别记录' collate = utf8mb4_unicode_ci;
DROP TABLE IF EXISTS `sys_user_file`;
CREATE TABLE `sys_user_file`
(
`id` bigint not null auto_increment comment '主键id',
`user_id` bigint not null comment '用户id',
`file_id` bigint not null comment '文件id',
primary key (`id`) using btree,
unique index `idx_user_file` (`user_id`, `file_id`) using btree comment '用户id_文件id'
) comment = '用户文件关联' collate = utf8mb4_unicode_ci;
DROP TABLE IF EXISTS `bus_subcontract`;
CREATE TABLE `bus_subcontract`
(
`id` bigint not null auto_increment comment '主键id',
`project_id` bigint not null comment '项目id',
`contractor_id` bigint not null comment '分包方id',
`contract_file_id` bigint not null comment '合同文件id',
`contract_number` varchar(255) null comment '合同编号',
`contract_name` varchar(255) null comment '合同名称',
`contract_type` char(1) not null comment '合同类型',
`contract_amount` decimal(12, 2) null comment '合同金额',
`contract_time` datetime null comment '合同时间',
`remark` varchar(512) null comment '备注',
`create_time` datetime default CURRENT_TIMESTAMP null comment '创建时间',
`update_time` datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
primary key (`id`) using btree,
index `idx_project_id` (`project_id` asc) using btree comment '项目id',
index `idx_contractor_id` (`contractor_id` asc) using btree comment '分包方id'
) comment = '分包合同' collate = utf8mb4_unicode_ci;
DROP TABLE IF EXISTS `hse_knowledge_document`;
CREATE TABLE `hse_knowledge_document`
(
`id` bigint not null auto_increment comment '主键id',
`project_id` bigint not null comment '项目id',
`pid` bigint default 0 not null comment '父级0代表顶级',
`file_name` varchar(255) not null comment '文件名称',
`file_path` varchar(512) null comment '文件路径',
`file_url` varchar(512) null comment '文件访问路径',
`file_type` char(1) not null comment '文件类型1文件夹 2文件 3图片',
`file_suffix` varchar(20) null comment '文件后缀',
`file_status` char(1) default '0' not null comment '状态0正常 1删除',
`original_name` varchar(255) null comment '原文件名',
`remark` varchar(512) null comment '备注',
`create_by` varchar(64) null comment '创建者',
`update_by` varchar(64) null comment '更新者',
`create_time` datetime default CURRENT_TIMESTAMP null comment '创建时间',
`update_time` datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
`deleted_at` datetime null comment '删除时间',
primary key (`id`) using btree,
index `idx_project_id` (`project_id` asc) using btree comment '项目id'
) comment '安全知识库' collate = utf8mb4_unicode_ci;
DROP TABLE IF EXISTS `qlt_knowledge_document`;
CREATE TABLE `qlt_knowledge_document`
(
`id` bigint not null auto_increment comment '主键id',
`project_id` bigint not null comment '项目id',
`pid` bigint default 0 not null comment '父级0代表顶级',
`file_name` varchar(255) not null comment '文件名称',
`file_path` varchar(512) null comment '文件路径',
`file_url` varchar(512) null comment '文件访问路径',
`file_type` char(1) not null comment '文件类型1文件夹 2文件 3图片',
`file_suffix` varchar(20) null comment '文件后缀',
`file_status` char(1) default '0' not null comment '状态0正常 1删除',
`original_name` varchar(255) null comment '原文件名',
`remark` varchar(512) null comment '备注',
`create_by` varchar(64) null comment '创建者',
`update_by` varchar(64) null comment '更新者',
`create_time` datetime default CURRENT_TIMESTAMP null comment '创建时间',
`update_time` datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
`deleted_at` datetime null comment '删除时间',
primary key (`id`) using btree,
index `idx_project_id` (`project_id` asc) using btree comment '项目id'
) comment '质量知识库' collate = utf8mb4_unicode_ci;