This commit is contained in:
2025-10-27 13:42:21 +08:00
24 changed files with 475 additions and 104 deletions

View File

@@ -38,7 +38,7 @@ public class CIDUserResp implements Serializable{
private String email;
@Schema(description = "用户状态0-正常1-冻结默认值为0确保新用户默认正常")
private Boolean status;
private Integer status;
@Schema(description = "身份证号18位符合身份证格式可选建议唯一")
private String idCard;
@@ -56,10 +56,10 @@ public class CIDUserResp implements Serializable{
private LocalDate birthDate;
@Schema(description = "性别0-未知1-男性2-女性默认值为0")
private Boolean sex;
private Integer sex;
@Schema(description = "是否有员工账号0-无1-有布尔类型映射为tinyint默认0")
private Boolean noSysStaff;
private Integer noSysStaff;
@Schema(description = "用户所属租户ID多租户场景下的租户标识可选")
private Long tenantId;

View File

@@ -5,6 +5,7 @@ import com.sdm.data.model.req.*;
import com.sdm.data.service.IModelService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -14,7 +15,8 @@ import java.io.IOException;
* 模型训练控制器
*/
@RestController
@RequestMapping("/modelTraning")
@RequestMapping("/modelTraining")
@Tag(name = "模型训练")
public class ModelTraningController {
@Autowired
private IModelService modelService;
@@ -28,6 +30,41 @@ public class ModelTraningController {
return modelService.addModel(addModelReq);
}
/**
* 删除模型
*/
@GetMapping("/deleteModel")
@Operation(summary = "删除模型", description = "删除模型")
public SdmResponse deleteModel(@RequestParam Integer modelId) {
return modelService.deleteModel(modelId);
}
/**
* 获取模型列表
*/
@PostMapping("/getModelList")
@Operation(summary = "获取模型列表", description = "获取模型列表")
public SdmResponse getModelList(@RequestBody BaseReq baseReq) {
return modelService.getModelList(baseReq);
}
/**
* 获取模型详情
*/
@GetMapping("/getModelDetail")
@Operation(summary = "获取模型详情", description = "获取模型详情")
public SdmResponse getModelDetail(@RequestParam Integer modelId) {
return modelService.getModelDetail(modelId);
}
/**
* 修改模型
*/
@PostMapping("/updateModel")
@Operation(summary = "修改模型", description = "修改模型")
public SdmResponse updateModel(@RequestBody AddModelReq addModelReq) {
return modelService.updateModel(addModelReq);
}
/**
* 调用python脚本处理导入数据
*
@@ -74,6 +111,15 @@ public class ModelTraningController {
return modelService.submitTraining(algorithmParamReq);
}
/**
* 停止模型训练
*/
@GetMapping("/stopTraining")
@Operation(summary = "停止模型训练", description = "停止模型训练")
public SdmResponse stopTraining(@RequestParam Integer modelId) {
return modelService.stopTraining(modelId);
}
/**
* 获取训练曲线和训练日志
*

View File

@@ -8,6 +8,9 @@ import java.time.LocalDateTime;
@Data
public class AddModelReq {
@Schema(description = "模型ID")
private Integer modelId;
@Schema(description = "模型名称")
private String modelName;

View File

@@ -12,6 +12,26 @@ public interface IModelService {
*/
SdmResponse addModel(AddModelReq addModelReq);
/**
* 删除模型
*/
SdmResponse deleteModel(Integer modelId);
/**
* 获取模型列表
*/
SdmResponse getModelList(BaseReq baseReq);
/**
* 获取模型详情
*/
SdmResponse getModelDetail(Integer modelId);
/**
* 修改模型
*/
SdmResponse updateModel(AddModelReq addModelReq);
/**
* 调用python脚本处理导入数据
*/
@@ -38,6 +58,13 @@ public interface IModelService {
*/
SdmResponse submitTraining(AlgorithmParamReq algorithmParamReq);
/**
* 停止模型训练
* @param modelId 模型ID
* @return 模型训练结果
*/
SdmResponse stopTraining(Integer modelId);
/**
* 模型训练结果查询
* @param modelId 模型ID

View File

@@ -2,7 +2,10 @@ package com.sdm.data.service.impl;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sdm.common.common.SdmResponse;
import com.sdm.common.utils.PageUtils;
import com.sdm.data.model.entity.FileMetadataInfo;
import com.sdm.data.model.entity.TrainingModel;
import com.sdm.data.model.entity.TrainingModelAlgorithmParam;
@@ -22,7 +25,9 @@ import java.io.OutputStream;
import java.nio.file.Files;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
@Service
@Slf4j
@@ -100,6 +105,8 @@ public class ModelServiceImpl implements IModelService {
*/
private static final String PYTHON_SCRIPT_PARAM_FILE_NAME = "param.json";
// 用于存储正在运行的训练进程
private final Map<Integer, Process> runningProcesses = new ConcurrentHashMap<>();
@Autowired
IDataFileService dataFileService;
@@ -133,6 +140,41 @@ public class ModelServiceImpl implements IModelService {
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public SdmResponse deleteModel(Integer modelId) {
// 删除 training_model 和 training_model_algorithm_param 表数据
trainingModelService.removeById(modelId);
trainingModelAlgorithmParamService.lambdaUpdate().eq(TrainingModelAlgorithmParam::getModelId, modelId).remove();
return SdmResponse.success("删除训练模型成功");
}
@Override
public SdmResponse getModelList(BaseReq baseReq) {
PageHelper.startPage(baseReq.getCurrent(), baseReq.getSize());
List<TrainingModel> models = trainingModelService.list();
PageInfo<TrainingModel> page = new PageInfo<>(models);
return PageUtils.getJsonObjectSdmResponse(models,page);
}
@Override
public SdmResponse getModelDetail(Integer modelId) {
TrainingModel model = trainingModelService.getById(modelId);
if (model != null) {
return SdmResponse.success(model);
}
return SdmResponse.success();
}
@Override
public SdmResponse updateModel(AddModelReq addModelReq) {
trainingModelService.lambdaUpdate()
.set(TrainingModel::getModelName, addModelReq.getModelName())
.set(TrainingModel::getDescription, addModelReq.getDescription())
.eq(TrainingModel::getId, addModelReq.getModelId()).update();
return SdmResponse.success("更新训练模型成功");
}
@Override
public SdmResponse<String> handleLoadData(HandleLoadDataReq handleLoadDataReq) {
try {
@@ -489,50 +531,49 @@ public class ModelServiceImpl implements IModelService {
}
}
private void callPythonScript(String pythonScriptPath, String paramJsonPath) {
try {
// 直接拼接完整命令(注意空格分隔)
String command = String.format(
"python %s --param %s",
pythonScriptPath,
paramJsonPath
);
private Process callPythonScript(String pythonScriptPath, String paramJsonPath) throws Exception {
// 直接拼接完整命令(注意空格分隔)
String command = String.format(
"python %s --param %s",
pythonScriptPath,
paramJsonPath
);
// 打印执行的命令(便于调试)
log.info("执行的Python命令: {}", command);
// 打印执行的命令(便于调试)
log.info("执行的Python命令: {}", command);
// 使用Runtime执行命令
Process process = Runtime.getRuntime().exec(command);
// 读取输出流
// 使用Runtime执行命令
Process process = Runtime.getRuntime().exec(command);
// 异步读取输出流,避免阻塞
Thread outputThread = new Thread(() -> {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
log.info("Python脚本输出: {}", line);
}
} catch (IOException e) {
log.error("读取Python脚本输出异常", e);
}
// 读取错误流(单独处理错误输出,避免阻塞)
});
outputThread.start();
// 异步读取错误流,避免阻塞
Thread errorThread = new Thread(() -> {
try (BufferedReader errorReader = new BufferedReader(
new InputStreamReader(process.getErrorStream()))) {
String errorLine;
while ((errorLine = errorReader.readLine()) != null) {
log.error("Python脚本错误输出: {}", errorLine);
}
} catch (IOException e) {
log.error("读取Python脚本错误输出异常", e);
}
});
errorThread.start();
// 等待执行完成
int exitCode = process.waitFor();
if (exitCode == 0) {
log.info("Python 脚本执行成功");
} else {
log.error("Python 脚本执行失败,退出码: {}", exitCode);
}
} catch (Exception e) {
log.error("调用Python脚本失败", e);
throw new RuntimeException(e);
}
return process;
}
@Override
@@ -606,27 +647,63 @@ public class ModelServiceImpl implements IModelService {
*/
private void trainModelAsync(String paramJsonPath, Integer modelId, String exportFormat) {
new Thread(() -> {
Process process = null;
try {
long startTime = System.currentTimeMillis();
log.info("开始执行Python脚本, 训练模型ID: {}", modelId);
// 调用python脚本进行训练
callPythonScript(TRAINING_PYTHON_SCRIPTPATH, paramJsonPath);
process = callPythonScript(TRAINING_PYTHON_SCRIPTPATH, paramJsonPath);
// 将进程添加到运行进程映射中
runningProcesses.put(modelId, process);
// 等待进程执行完成
int exitCode = process.waitFor();
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
log.info("Python脚本执行完成, 训练模型ID: {}, 耗时: {} ms", modelId, duration);
// 根据退出码判断具体执行结果
if (exitCode == 0) {
log.info("Python脚本执行完成, 训练模型ID: {}, 耗时: {} ms", modelId, duration);
} else if (exitCode == 137) {
// 退出码137表示进程被SIGKILL信号强制终止如调用destroyForcibly()
log.warn("Python脚本执行被强制终止退出码: {}, 训练模型ID: {}, 耗时: {} ms", exitCode, modelId, duration);
} else {
log.error("Python脚本执行失败退出码: {}, 训练模型ID: {}, 耗时: {} ms", exitCode, modelId, duration);
}
// 从运行进程映射中移除已完成的进程
runningProcesses.remove(modelId);
// 将训练生成的生成 training.json、training.log、模型文件上传到minio
Integer trainingDataResultFileId = uploadResultFileToMinio(TANING_MODEL_BASE_DIR_PATH + MODEL_ID + modelId + "/" + TRAIN_RESULT_DIR_PATH + TRAINING_JSON_FILE_NAME);
Integer trainingDataLogFileId = uploadResultFileToMinio(TANING_MODEL_BASE_DIR_PATH + MODEL_ID + modelId + "/" + TRAIN_RESULT_DIR_PATH + TRAINING_LOG_FILE_NAME);
Integer trainingDataExportModelFileId = uploadResultFileToMinio(TANING_MODEL_BASE_DIR_PATH + MODEL_ID + modelId + "/" + TRAIN_RESULT_DIR_PATH + TRAINING_MODEL_PERFIX_NAME + exportFormat);
// 只有在训练成功时才上传结果文件到minio
Integer trainingDataResultFileId = null;
Integer trainingDataLogFileId = null;
Integer trainingDataExportModelFileId = null;
if (exitCode == 0) {
// 将训练生成的生成 training.json、training.log、模型文件上传到minio
trainingDataResultFileId = uploadResultFileToMinio(TANING_MODEL_BASE_DIR_PATH + MODEL_ID + modelId + "/" + TRAIN_RESULT_DIR_PATH + TRAINING_JSON_FILE_NAME);
trainingDataLogFileId = uploadResultFileToMinio(TANING_MODEL_BASE_DIR_PATH + MODEL_ID + modelId + "/" + TRAIN_RESULT_DIR_PATH + TRAINING_LOG_FILE_NAME);
trainingDataExportModelFileId = uploadResultFileToMinio(TANING_MODEL_BASE_DIR_PATH + MODEL_ID + modelId + "/" + TRAIN_RESULT_DIR_PATH + TRAINING_MODEL_PERFIX_NAME + exportFormat);
log.info("模型训练完成,结果文件: training.json文件ID: {}、training.log文件ID: {}、导出model文件ID: {}文件上传成功", trainingDataResultFileId, trainingDataLogFileId, trainingDataExportModelFileId);
log.info("模型训练完成,结果文件: training.json文件ID: {}、training.log文件ID: {}、导出model文件ID: {}文件上传成功", trainingDataResultFileId, trainingDataLogFileId, trainingDataExportModelFileId);
}
// 根据退出码设置训练状态
String trainingStatus;
if (exitCode == 0) {
trainingStatus = "成功";
} else if (exitCode == 137) {
trainingStatus = "已终止";
} else {
trainingStatus = "失败";
}
// 更新模型状态为训练完成
trainingModelService.lambdaUpdate()
.eq(TrainingModel::getId, modelId)
.set(TrainingModel::getTrainingStatus, "成功")
.set(TrainingModel::getTrainingStatus, trainingStatus)
.set(TrainingModel::getTrainingTime, new Date())
.set(TrainingModel::getTrainingDuration, duration)
.set(TrainingModel::getTrainingDataResultFileId, trainingDataResultFileId)
@@ -636,6 +713,9 @@ public class ModelServiceImpl implements IModelService {
log.info("模型训练完成模型ID: {}", modelId);
} catch (Exception e) {
// 从运行进程映射中移除失败的进程
runningProcesses.remove(modelId);
log.error("模型训练失败模型ID: {}", modelId, e);
// 更新模型状态为训练失败
trainingModelService.lambdaUpdate()
@@ -718,8 +798,8 @@ public class ModelServiceImpl implements IModelService {
if (trainingModel == null) {
return SdmResponse.failed("模型不存在");
}
if (trainingModel.getTrainingStatus().equals("失败")) {
return SdmResponse.failed("模型训练失败,请查看日志详情");
if (trainingModel.getTrainingStatus().equals("失败") || trainingModel.getTrainingStatus().equals("已终止") ) {
return SdmResponse.failed("模型训练失败或已终止,请查看日志详情");
}
if (trainingModel.getTrainingStatus().equals("待开始") || trainingModel.getTrainingStatus().equals("训练中")) {
@@ -828,8 +908,8 @@ public class ModelServiceImpl implements IModelService {
String predDirPath = TANING_MODEL_BASE_DIR_PATH + MODEL_ID + trainingModel.getId() + "/" + PRED_RESULT_DIR_PATH;
// 创建预测用的param.json文件
String predParamJsonFile = createPredParamJsonFile(modelPredictReq, trainingModel, trainingModelAlgorithmParam,predDirPath);
String predParamJsonFile = createPredParamJsonFile(modelPredictReq, trainingModel, trainingModelAlgorithmParam, predDirPath);
// 执行预测
try {
long startTime = System.currentTimeMillis();
@@ -845,13 +925,13 @@ public class ModelServiceImpl implements IModelService {
// 读取预测生成的结果文件并保存到数据库
String predResultPath = predDirPath + "/" + PRED_RESULT_FILE_NAME;
File predResultFile = new File(predResultPath);
if (predResultFile.exists()) {
try {
// 读取预测结果文件内容
String predResultJson = new String(Files.readAllBytes(predResultFile.toPath()));
predResultObject = JSONObject.parseObject(predResultJson);
// 将预测结果保存到数据库
trainingModelService.lambdaUpdate()
.eq(TrainingModel::getId, modelId)
@@ -869,20 +949,20 @@ public class ModelServiceImpl implements IModelService {
} catch (Exception e) {
log.error("模型预测失败模型ID: {}", modelId, e);
}
return SdmResponse.success(predResultObject);
}
/**
* 创建预测参数param.json文件
*
* @param modelPredictReq 预测请求参数
* @param trainingModel 训练模型
* @param modelPredictReq 预测请求参数
* @param trainingModel 训练模型
* @param trainingModelAlgorithmParam 训练模型算法参数
* @param predDirPath 预测目录路径
* @param predDirPath 预测目录路径
* @return param.json文件路径
*/
private String createPredParamJsonFile(ModelPredictReq modelPredictReq, TrainingModel trainingModel, TrainingModelAlgorithmParam trainingModelAlgorithmParam,String predDirPath) {
private String createPredParamJsonFile(ModelPredictReq modelPredictReq, TrainingModel trainingModel, TrainingModelAlgorithmParam trainingModelAlgorithmParam, String predDirPath) {
try {
// 确保目录存在
File predDir = new File(predDirPath);
@@ -908,18 +988,18 @@ public class ModelServiceImpl implements IModelService {
modelParams.put("inputSize", trainingModel.getInputSize());
modelParams.put("outputSize", trainingModel.getOutputSize());
modelParams.put("normalizerType", trainingModelAlgorithmParam.getDisposeMethod());
// 添加归一化参数
if (trainingModel.getNormalizerMax() != null) {
JSONArray normalizerMaxArray = JSONArray.parseArray(trainingModel.getNormalizerMax());
modelParams.put("normalizerMax", normalizerMaxArray);
}
if (trainingModel.getNormalizerMin() != null) {
JSONArray normalizerMinArray = JSONArray.parseArray(trainingModel.getNormalizerMin());
modelParams.put("normalizerMin", normalizerMinArray);
}
paramJson.put("modelParams", modelParams);
// 添加输入数据
@@ -948,6 +1028,34 @@ public class ModelServiceImpl implements IModelService {
}
}
/**
* 终止指定模型的训练进程
*
* @param modelId 模型ID
* @return 是否成功终止
*/
public SdmResponse stopTraining(Integer modelId) {
Process process = runningProcesses.get(modelId);
if (process != null) {
// 强制终止进程
process.destroyForcibly();
// 从映射中移除
runningProcesses.remove(modelId);
// 更新数据库状态
trainingModelService.lambdaUpdate()
.eq(TrainingModel::getId, modelId)
.set(TrainingModel::getTrainingStatus, "已终止")
.update();
log.info("模型训练已终止模型ID: {}", modelId);
} else {
log.warn("未找到正在运行的模型训练进程模型ID: {}", modelId);
}
return SdmResponse.success();
}
@Override
public SdmResponse getModelPredictResult(Integer modelId) {
JSONObject result = new JSONObject();

View File

@@ -184,4 +184,13 @@ public class SimulationNodeController implements ISimuluationNodeFeignClient {
return nodeService.getCommonCompleteStatistics(req);
}
/**
* 工位评审通过统计查询
*/
@PostMapping("/getWorkstationReviewStatistics")
@Operation(summary = "工位评审通过统计查询", description = "工位评审通过统计查询")
public SdmResponse getWorkstationReviewStatistics(@RequestBody GetWorkstationApproveStatusReq req) {
return nodeService.getWorkstationReviewStatistics(req);
}
}

View File

@@ -83,4 +83,6 @@ public interface SimulationNodeMapper extends BaseMapper<SimulationNode> {
List<CommonGetCompleteFromPerformanceVo> getCommonCompleteStatisticsFromPerformance(@Param("req")CommonGetCompleteStatisticsReq req);
List<WorkstationApproveStatusVo> getWorkstationApproveStatus(@Param("req") GetWorkstationApproveStatusReq req);
}

View File

@@ -0,0 +1,42 @@
package com.sdm.project.model.req;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class GetWorkstationApproveStatusReq {
@Schema(description = "数据返回Tag类型: tag1、tag2,tag3,tag4,tag5,tag6,tag7,tag8,tag9,tag10")
@NotNull
private String resultTagType;
@Schema(description = "标签1")
private String tag1;
@Schema(description = "标签2")
private String tag2;
@Schema(description = "标签3")
private String tag3;
@Schema(description = "标签4")
private String tag4;
@Schema(description = "标签5")
private String tag5;
@Schema(description = "标签6")
private String tag6;
@Schema(description = "标签7")
private String tag7;
@Schema(description = "标签8")
private String tag8;
@Schema(description = "标签9")
private String tag9;
@Schema(description = "标签10")
private String tag10;
}

View File

@@ -6,7 +6,7 @@ import java.util.HashMap;
import java.util.Map;
@Data
public class CommonCompleteStatisticsVo {
public class CommonStatisticsVo {
private String name;
private Map<String, Integer> statusCount = new HashMap<>();
}

View File

@@ -0,0 +1,10 @@
package com.sdm.project.model.vo;
import lombok.Data;
@Data
public class WorkstationApproveStatusVo {
private String tag;
private String nodeName;
private String approvalStatus;
}

View File

@@ -39,4 +39,7 @@ public interface INodeService extends IService<SimulationNode> {
SdmResponse getCommonCompleteStatistics(CommonGetCompleteStatisticsReq req);
// 工位评审通过统计查询
SdmResponse getWorkstationReviewStatistics(GetWorkstationApproveStatusReq req);
}

View File

@@ -817,13 +817,13 @@ public class NodeServiceImpl extends ServiceImpl<SimulationNodeMapper, Simulatio
List<CommonGetCompleteFromTaskVo> commonCompleteStatisticsFromTask = this.baseMapper.getCommonCompleteStatisticsFromTask(req);
// 按tag分组统计任务状态
Map<String, CommonCompleteStatisticsVo> taskStatisticsMap = new HashMap<>();
Map<String, CommonStatisticsVo> taskStatisticsMap = new HashMap<>();
// 统计每个tag的各种状态任务数量
for (CommonGetCompleteFromTaskVo item : commonCompleteStatisticsFromTask) {
String name = item.getNodeName();
CommonCompleteStatisticsVo stat = taskStatisticsMap.getOrDefault(name, new CommonCompleteStatisticsVo());
CommonStatisticsVo stat = taskStatisticsMap.getOrDefault(name, new CommonStatisticsVo());
stat.setName(name);
Map<String, Integer> statusCount = stat.getStatusCount();
@@ -839,7 +839,7 @@ public class NodeServiceImpl extends ServiceImpl<SimulationNodeMapper, Simulatio
}
// 转换为列表返回
List<CommonCompleteStatisticsVo> taskResult = new ArrayList<>(taskStatisticsMap.values());
List<CommonStatisticsVo> taskResult = new ArrayList<>(taskStatisticsMap.values());
JSONObject resultResponse = new JSONObject();
resultResponse.put("allExeStatus", allExeStatus);
resultResponse.put("result", taskResult);
@@ -849,13 +849,13 @@ public class NodeServiceImpl extends ServiceImpl<SimulationNodeMapper, Simulatio
List<CommonGetCompleteFromPerformanceVo> commonCompleteStatisticsFromPerformance = this.baseMapper.getCommonCompleteStatisticsFromPerformance(req);
// 按tag分组统计指标状态
Map<String, CommonCompleteStatisticsVo> performanceStatisticsMap = new HashMap<>();
Map<String, CommonStatisticsVo> performanceStatisticsMap = new HashMap<>();
// 统计每个tag的各种状态指标数量
for (CommonGetCompleteFromPerformanceVo item : commonCompleteStatisticsFromPerformance) {
String nodeName = item.getNodeName();
CommonCompleteStatisticsVo stat = performanceStatisticsMap.getOrDefault(nodeName, new CommonCompleteStatisticsVo());
CommonStatisticsVo stat = performanceStatisticsMap.getOrDefault(nodeName, new CommonStatisticsVo());
stat.setName(nodeName);
Map<String, Integer> statusCount = stat.getStatusCount();
@@ -872,7 +872,7 @@ public class NodeServiceImpl extends ServiceImpl<SimulationNodeMapper, Simulatio
}
// 转换为列表返回
List<CommonCompleteStatisticsVo> performanceResult = new ArrayList<>(performanceStatisticsMap.values());
List<CommonStatisticsVo> performanceResult = new ArrayList<>(performanceStatisticsMap.values());
JSONObject resultResponse = new JSONObject();
resultResponse.put("allExeStatus", allExeStatus);
resultResponse.put("result", performanceResult);
@@ -880,4 +880,41 @@ public class NodeServiceImpl extends ServiceImpl<SimulationNodeMapper, Simulatio
}
return SdmResponse.success(new ArrayList<>());
}
@Override
public SdmResponse getWorkstationReviewStatistics(GetWorkstationApproveStatusReq req) {
List<WorkstationApproveStatusVo> workstationApproveStatus = this.baseMapper.getWorkstationApproveStatus(req);
// 按tag分组统计审批状态
Map<String, CommonStatisticsVo> reviewStatisticsMap = new HashMap<>();
// 所有审批状态
Set<String> allApprovalStatus = new HashSet<>();
// 统计每个tag的各种审批状态数量
for (WorkstationApproveStatusVo item : workstationApproveStatus) {
String nodeName = item.getNodeName();
CommonStatisticsVo stat = reviewStatisticsMap.getOrDefault(nodeName, new CommonStatisticsVo());
stat.setName(nodeName);
Map<String, Integer> statusCount = stat.getStatusCount();
if (statusCount == null) {
statusCount = new HashMap<>();
stat.setStatusCount(statusCount);
}
String approvalStatus = item.getApprovalStatus();
allApprovalStatus.add(approvalStatus);
statusCount.put(approvalStatus, statusCount.getOrDefault(approvalStatus, 0) + 1);
reviewStatisticsMap.put(nodeName, stat);
}
// 转换为列表返回
List<CommonStatisticsVo> result = new ArrayList<>(reviewStatisticsMap.values());
JSONObject resultResponse = new JSONObject();
resultResponse.put("allApprovalStatus", allApprovalStatus);
resultResponse.put("result", result);
return SdmResponse.success(resultResponse);
}
}

View File

@@ -541,4 +541,48 @@
</if>
</where>
</select>
<select id="getWorkstationApproveStatus"
parameterType="com.sdm.project.model.req.GetWorkstationApproveStatusReq"
resultType="com.sdm.project.model.vo.WorkstationApproveStatusVo">
select
task.${req.resultTagType} as tag,
node.nodeName,
task.approval_status as approvalStatus
from simulation_task task
left join simulation_node node on task.${req.resultTagType} = node.uuid
<where>
1=1 and task.approval_status is not null
<if test="req.tag1 != null and req.tag1 !='' ">
and task.tag1 = #{req.tag1}
</if>
<if test="req.tag2 != null and req.tag2 !='' ">
and task.tag2 = #{req.tag2}
</if>
<if test="req.tag3 != null and req.tag3 !='' ">
and task.tag3 = #{req.tag3}
</if>
<if test="req.tag4 != null and req.tag4 !='' ">
and task.tag4 = #{req.tag4}
</if>
<if test="req.tag5 != null and req.tag5 !='' ">
and task.tag5 = #{req.tag5}
</if>
<if test="req.tag6 != null and req.tag6 !='' ">
and task.tag6 = #{req.tag6}
</if>
<if test="req.tag7 != null and req.tag7 !='' ">
and task.tag7 = #{req.tag7}
</if>
<if test="req.tag8 != null and req.tag8 !='' ">
and task.tag8 = #{req.tag8}
</if>
<if test="req.tag9 != null and req.tag9 !='' ">
and task.tag9 = #{req.tag9}
</if>
<if test="req.tag10 != null and req.tag10 !='' ">
and task.tag10 = #{req.tag10}
</if>
</where>
</select>
</mapper>

View File

@@ -114,12 +114,22 @@ public class UserController implements ISysUserFeignClient {
* @param req
* @return
*/
@Operation(summary = "更新用户角色", description = "更新用户角色接口,用于修改用户角色信息")
@Operation(summary = "更新用户角色", description = "更新用户角色,用于修改用户角色信息")
@PostMapping("/updateUserRole")
public SdmResponse updateUserRole(@Parameter(description = "用户角色更新请求参数") @RequestBody @Validated UpdateUserRoleReq req) {
public SdmResponse updateUserRole(@Parameter(description = "更新用户角色请求参数") @RequestBody UpdateUserRole req) {
return ISysUserService.updateUserRole(req);
}
/**
* 查询用户角色
* @param userId
*/
@Operation(summary = "查询用户角色", description = "查询用户角色接口,用于查询指定用户的角色列表")
@GetMapping("/queryUserRole")
public SdmResponse queryUserRole(@Parameter(description = "用户角色查询请求参数") @RequestParam("userId") Integer userId) {
return ISysUserService.queryUserRole(userId);
}
/**
* 新增用户组
*

View File

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -64,7 +65,7 @@ public class SysUser implements Serializable {
@Schema(description = "用户状态0-正常1-冻结默认值为0确保新用户默认正常")
@TableField("status")
private Boolean status;
private Integer status;
@Schema(description = "身份证号18位符合身份证格式可选建议唯一")
@TableField("id_card")
@@ -88,11 +89,11 @@ public class SysUser implements Serializable {
@Schema(description = "性别0-未知1-男性2-女性默认值为0")
@TableField("sex")
private Boolean sex;
private Integer sex;
@Schema(description = "是否有员工账号0-无1-有布尔类型映射为tinyint默认0")
@TableField("no_sys_staff")
private Boolean noSysStaff;
private Integer noSysStaff;
@Schema(description = "用户所属租户ID多租户场景下的租户标识可选")
@TableField("tenant_id")
@@ -104,11 +105,11 @@ public class SysUser implements Serializable {
@Schema(description = "记录创建时间(默认取当前时间,无需手动插入)")
@TableField("create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime createTime;
@Schema(description = "记录更新时间(每次更新数据时自动刷新)")
@TableField("update_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime updateTime;
}

View File

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -43,10 +44,12 @@ public class SysUserGroup implements Serializable {
@Schema(description = "创建时间")
@TableField("createdTime")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime createdTime;
@Schema(description = "更新时间")
@TableField("updatedTime")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime updatedTime;

View File

@@ -71,7 +71,7 @@ public class Tenant implements Serializable {
@Schema(description = "状态")
@TableField("status")
private String status;
private Integer status;
@Schema(description = "创建时间")
@TableField("createTime")

View File

@@ -44,7 +44,7 @@ public class TenantReq implements Serializable {
private String endTime;
@Schema(description = "状态")
private String status;
private Integer status;
@Schema(description = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")

View File

@@ -0,0 +1,15 @@
package com.sdm.system.model.req.user;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import io.swagger.v3.oas.annotations.media.Schema;
@Schema(description = "用户角色更新请求参数")
@Data
public class UpdateUserRole {
@Schema(description = "角色id", requiredMode = Schema.RequiredMode.REQUIRED)
private Integer roleId;
@Schema(description = "用户id", requiredMode = Schema.RequiredMode.REQUIRED)
private Integer userId;
}

View File

@@ -1,22 +0,0 @@
package com.sdm.system.model.req.user;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import io.swagger.v3.oas.annotations.media.Schema;
@Schema(description = "用户角色更新请求参数")
@Data
public class UpdateUserRoleReq {
@NotBlank(message = "role不能为空")
@Schema(description = "角色", requiredMode = Schema.RequiredMode.REQUIRED)
private String role;
@NotBlank(message = "jobNumber不能为空")
@Schema(description = "工号", requiredMode = Schema.RequiredMode.REQUIRED)
private String jobNumber;
@NotBlank(message = "company不能为空")
@Schema(description = "公司", requiredMode = Schema.RequiredMode.REQUIRED)
private String company;
}

View File

@@ -33,7 +33,7 @@ public class UserUpdateReq {
private String email;
@Schema(description = "用户状态0-正常1-冻结默认值为0确保新用户默认正常")
private Boolean status;
private Integer status;
@Schema(description = "身份证号18位符合身份证格式可选建议唯一")
private String idCard;
@@ -51,10 +51,10 @@ public class UserUpdateReq {
private LocalDate birthDate;
@Schema(description = "性别0-未知1-男性2-女性默认值为0")
private Boolean sex;
private Integer sex;
@Schema(description = "是否有员工账号0-无1-有布尔类型映射为tinyint默认0")
private Boolean noSysStaff;
private Integer noSysStaff;
@Schema(description = "用户所属租户ID多租户场景下的租户标识可选")
private Integer tenantId;

View File

@@ -28,7 +28,9 @@ public interface ISysUserService extends IService<SysUser> {
SdmResponse getUserImage();
SdmResponse updateUserRole(UpdateUserRoleReq req);
SdmResponse updateUserRole(UpdateUserRole req);
SdmResponse queryUserRole(Integer userId);
SdmResponse addGroup(GroupAddReq req);

View File

@@ -117,7 +117,12 @@ public class CIDISysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser>
}
@Override
public SdmResponse updateUserRole(UpdateUserRoleReq req) {
public SdmResponse updateUserRole(UpdateUserRole req) {
return null;
}
@Override
public SdmResponse queryUserRole(Integer userId) {
return null;
}

View File

@@ -11,19 +11,16 @@ import com.sdm.common.entity.req.system.UserQueryReq;
import com.sdm.common.entity.resp.PageDataResp;
import com.sdm.common.utils.PageUtils;
import com.sdm.system.dao.SysUserMapper;
import com.sdm.system.model.entity.SysUser;
import com.sdm.system.model.entity.SysUserGroup;
import com.sdm.system.model.entity.SysUserGroupRelation;
import com.sdm.system.model.entity.*;
import com.sdm.system.model.req.user.*;
import com.sdm.common.entity.resp.system.CIDUserResp;
import com.sdm.system.model.resp.SysUserGroupResp;
import com.sdm.system.service.ISysUserGroupRelationService;
import com.sdm.system.service.ISysUserGroupService;
import com.sdm.system.service.ISysUserService;
import com.sdm.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -43,6 +40,13 @@ public class LocalUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> im
@Autowired
private ISysUserGroupRelationService sysUserGroupRelationService;
@Autowired
private ISysUserRoleRelationService sysUserRoleRelationService;
@Autowired
@Qualifier("roleService")
private ISysRoleService sysRoleService;
@Override
public String getType() {
return type;
@@ -138,8 +142,30 @@ public class LocalUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> im
}
@Override
public SdmResponse updateUserRole(UpdateUserRoleReq req) {
return SdmResponse.success();
public SdmResponse updateUserRole(UpdateUserRole req) {
SysUserRoleRelation userRoleRelation = sysUserRoleRelationService.lambdaQuery().eq(SysUserRoleRelation::getUserId, req.getUserId()).one();
if (userRoleRelation == null) {
userRoleRelation = new SysUserRoleRelation();
userRoleRelation.setUserId(req.getUserId());
userRoleRelation.setRoleId(req.getRoleId());
sysUserRoleRelationService.save(userRoleRelation);
}else {
userRoleRelation.setRoleId(req.getRoleId());
sysUserRoleRelationService.lambdaUpdate()
.eq(SysUserRoleRelation::getUserId, req.getUserId())
.set(SysUserRoleRelation::getRoleId, req.getRoleId()).update();
}
return SdmResponse.success("更新用户角色成功");
}
@Override
public SdmResponse queryUserRole(Integer userId) {
SysUserRoleRelation userRoleRelation = sysUserRoleRelationService.lambdaQuery().eq(SysUserRoleRelation::getUserId, userId).one();
if (userRoleRelation == null) {
return SdmResponse.failed("用户角色不存在");
}
SysRole role = sysRoleService.getById(userRoleRelation.getRoleId());
return SdmResponse.success(role);
}
/**