feat(risk): 实现全面的风险服务逻辑
- 新增风险创建、更新、删除及详情查询功能 - 支持分页查询风险列表及风险统计信息 - 完成风险分配工单及批量更新风险状态功能 - 集成AI风险评估,包含项目数据构建和识别风险保存 - 实现风险等级计算和风险视图转换逻辑 - 实现权限校验确保项目和风险数据访问安全
This commit is contained in:
@@ -22,6 +22,7 @@ import cn.yinlihupo.mapper.TaskMapper;
|
||||
import cn.yinlihupo.mapper.WorkOrderMapper;
|
||||
import cn.yinlihupo.service.risk.RiskService;
|
||||
import cn.yinlihupo.service.risk.WorkOrderService;
|
||||
import cn.yinlihupo.service.system.ProjectPermissionService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -53,6 +54,7 @@ public class RiskServiceImpl implements RiskService {
|
||||
private final WorkOrderMapper workOrderMapper;
|
||||
private final WorkOrderService workOrderService;
|
||||
private final ChatClient chatClient;
|
||||
private final ProjectPermissionService projectPermissionService;
|
||||
|
||||
/**
|
||||
* AI风险评估系统提示词模板
|
||||
@@ -268,14 +270,49 @@ public class RiskServiceImpl implements RiskService {
|
||||
String category, String riskLevel, String status, String keyword) {
|
||||
log.info("分页查询风险列表, projectId: {}, pageNum: {}, pageSize: {}", projectId, pageNum, pageSize);
|
||||
|
||||
// 获取当前用户
|
||||
Long userId = SecurityUtils.getCurrentUserId();
|
||||
boolean isAdmin = SecurityUtils.isAdmin();
|
||||
|
||||
// 获取用户可见的项目ID列表
|
||||
List<Long> visibleProjectIds = null;
|
||||
if (!isAdmin) {
|
||||
// 非超管只能查看自己参与的项目风险
|
||||
visibleProjectIds = projectMemberMapper.selectList(
|
||||
new LambdaQueryWrapper<ProjectMember>()
|
||||
.eq(ProjectMember::getUserId, userId)
|
||||
.eq(ProjectMember::getDeleted, 0)
|
||||
).stream().map(ProjectMember::getProjectId).collect(Collectors.toList());
|
||||
|
||||
if (visibleProjectIds.isEmpty()) {
|
||||
// 没有参与任何项目,返回空结果
|
||||
return TableDataInfo.build(new Page<RiskVO>(pageNum, pageSize, 0).setRecords(new ArrayList<>()));
|
||||
}
|
||||
}
|
||||
|
||||
Page<Risk> page = new Page<>(pageNum, pageSize);
|
||||
|
||||
LambdaQueryWrapper<Risk> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Risk::getDeleted, 0);
|
||||
|
||||
if (projectId != null) {
|
||||
wrapper.eq(Risk::getProjectId, projectId);
|
||||
// 权限过滤:非超管只能查看参与项目的风险
|
||||
if (!isAdmin && visibleProjectIds != null) {
|
||||
if (projectId != null) {
|
||||
// 如果指定了项目ID,需要验证用户是否有权限访问该项目
|
||||
if (!visibleProjectIds.contains(projectId)) {
|
||||
return TableDataInfo.build(new Page<RiskVO>(pageNum, pageSize, 0).setRecords(new ArrayList<>()));
|
||||
}
|
||||
wrapper.eq(Risk::getProjectId, projectId);
|
||||
} else {
|
||||
wrapper.in(Risk::getProjectId, visibleProjectIds);
|
||||
}
|
||||
} else {
|
||||
// 超管可以查看所有项目的风险
|
||||
if (projectId != null) {
|
||||
wrapper.eq(Risk::getProjectId, projectId);
|
||||
}
|
||||
}
|
||||
|
||||
if (category != null && !category.isEmpty()) {
|
||||
wrapper.eq(Risk::getCategory, category);
|
||||
}
|
||||
@@ -308,13 +345,48 @@ public class RiskServiceImpl implements RiskService {
|
||||
public RiskStatisticsVO getRiskStatistics(Long projectId) {
|
||||
log.info("获取风险统计信息, projectId: {}", projectId);
|
||||
|
||||
// 获取当前用户
|
||||
Long userId = SecurityUtils.getCurrentUserId();
|
||||
boolean isAdmin = SecurityUtils.isAdmin();
|
||||
|
||||
// 获取用户可见的项目ID列表
|
||||
List<Long> visibleProjectIds = null;
|
||||
if (!isAdmin) {
|
||||
// 非超管只能查看自己参与的项目风险
|
||||
visibleProjectIds = projectMemberMapper.selectList(
|
||||
new LambdaQueryWrapper<ProjectMember>()
|
||||
.eq(ProjectMember::getUserId, userId)
|
||||
.eq(ProjectMember::getDeleted, 0)
|
||||
).stream().map(ProjectMember::getProjectId).collect(Collectors.toList());
|
||||
|
||||
if (visibleProjectIds.isEmpty()) {
|
||||
// 没有参与任何项目,返回空统计
|
||||
return new RiskStatisticsVO();
|
||||
}
|
||||
}
|
||||
|
||||
RiskStatisticsVO statistics = new RiskStatisticsVO();
|
||||
|
||||
// 构建查询条件
|
||||
LambdaQueryWrapper<Risk> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Risk::getDeleted, 0);
|
||||
if (projectId != null) {
|
||||
wrapper.eq(Risk::getProjectId, projectId);
|
||||
|
||||
// 权限过滤
|
||||
if (!isAdmin && visibleProjectIds != null) {
|
||||
if (projectId != null) {
|
||||
// 如果指定了项目ID,需要验证用户是否有权限访问该项目
|
||||
if (!visibleProjectIds.contains(projectId)) {
|
||||
return new RiskStatisticsVO();
|
||||
}
|
||||
wrapper.eq(Risk::getProjectId, projectId);
|
||||
} else {
|
||||
wrapper.in(Risk::getProjectId, visibleProjectIds);
|
||||
}
|
||||
} else {
|
||||
// 超管可以查看所有项目的风险统计
|
||||
if (projectId != null) {
|
||||
wrapper.eq(Risk::getProjectId, projectId);
|
||||
}
|
||||
}
|
||||
|
||||
List<Risk> risks = riskMapper.selectList(wrapper);
|
||||
@@ -509,16 +581,28 @@ public class RiskServiceImpl implements RiskService {
|
||||
public RiskAssessmentResult assessProjectRisk(Long projectId) {
|
||||
log.info("开始AI风险评估, projectId: {}", projectId);
|
||||
|
||||
// 获取当前用户
|
||||
Long userId = SecurityUtils.getCurrentUserId();
|
||||
boolean isAdmin = SecurityUtils.isAdmin();
|
||||
log.info("风险评估请求用户: userId={}, isAdmin={}", userId, isAdmin);
|
||||
|
||||
// 1. 验证项目存在
|
||||
Project project = projectMapper.selectById(projectId);
|
||||
if (project == null || project.getDeleted() == 1) {
|
||||
throw new RuntimeException("项目不存在");
|
||||
}
|
||||
|
||||
// 2. 构建项目数据上下文
|
||||
// 2. 权限校验:超管可评估所有项目,普通用户只能评估参与的项目
|
||||
if (!isAdmin) {
|
||||
if (!projectPermissionService.isProjectMember(userId, projectId)) {
|
||||
throw new RuntimeException("您没有权限评估该项目");
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 构建项目数据上下文
|
||||
String projectDataContext = buildProjectDataContext(projectId);
|
||||
|
||||
// 3. 构建用户提示词
|
||||
// 4. 构建用户提示词
|
||||
String userPrompt = """
|
||||
请根据以下项目数据,进行全面的风险评估分析:
|
||||
|
||||
@@ -527,7 +611,7 @@ public class RiskServiceImpl implements RiskService {
|
||||
请严格按照系统提示词中的JSON格式输出评估结果,确保识别的风险具体且可操作。
|
||||
""".formatted(projectDataContext);
|
||||
|
||||
// 4. 调用AI进行风险评估
|
||||
// 5. 调用AI进行风险评估
|
||||
log.info("调用AI进行风险评估...");
|
||||
RiskAssessmentResult result = chatClient.prompt()
|
||||
.system(RISK_ASSESSMENT_SYSTEM_PROMPT)
|
||||
@@ -535,7 +619,7 @@ public class RiskServiceImpl implements RiskService {
|
||||
.call()
|
||||
.entity(RiskAssessmentResult.class);
|
||||
|
||||
// 5. 设置项目信息
|
||||
// 6. 设置项目信息
|
||||
result.setProjectId(projectId);
|
||||
result.setProjectName(project.getProjectName());
|
||||
result.setAssessmentDate(LocalDate.now());
|
||||
|
||||
@@ -172,12 +172,8 @@ public class WorkOrderServiceImpl implements WorkOrderService {
|
||||
.like(WorkOrder::getDescription, keyword));
|
||||
}
|
||||
|
||||
// 按优先级和创建时间排序
|
||||
wrapper.orderByAsc(
|
||||
w -> "critical".equals(w.getPriority()) ? 1 :
|
||||
"high".equals(w.getPriority()) ? 2 :
|
||||
"medium".equals(w.getPriority()) ? 3 : 4
|
||||
).orderByDesc(WorkOrder::getCreateTime);
|
||||
// 按优先级和创建时间排序(使用原生SQL避免Lambda表达式问题)
|
||||
wrapper.last("ORDER BY CASE priority WHEN 'critical' THEN 1 WHEN 'high' THEN 2 WHEN 'medium' THEN 3 ELSE 4 END ASC, create_time DESC");
|
||||
|
||||
Page<WorkOrder> orderPage = workOrderMapper.selectPage(page, wrapper);
|
||||
|
||||
@@ -208,12 +204,8 @@ public class WorkOrderServiceImpl implements WorkOrderService {
|
||||
wrapper.eq(WorkOrder::getOrderType, orderType);
|
||||
}
|
||||
|
||||
// 按优先级和创建时间排序
|
||||
wrapper.orderByAsc(
|
||||
w -> "critical".equals(w.getPriority()) ? 1 :
|
||||
"high".equals(w.getPriority()) ? 2 :
|
||||
"medium".equals(w.getPriority()) ? 3 : 4
|
||||
).orderByDesc(WorkOrder::getCreateTime);
|
||||
// 按优先级和创建时间排序(使用原生SQL避免Lambda表达式问题)
|
||||
wrapper.last("ORDER BY CASE priority WHEN 'critical' THEN 1 WHEN 'high' THEN 2 WHEN 'medium' THEN 3 ELSE 4 END ASC, create_time DESC");
|
||||
|
||||
Page<WorkOrder> orderPage = workOrderMapper.selectPage(page, wrapper);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user