generated from youfool-project/youfool-prj-springboot3-template
feat: 监测规则操作历史接口 + 证据关联规则数量 + 法条详情补全
- 新增 MonitoringRuleController#getHistories 操作历史查询接口 - 规则详情补全法条 lawName/clauseCode/clauseContent 字段,避免前端二次查询 - 证据记录列表新增 relatedRuleCount,批量查询避免 N+1 - MonitoringRuleDetailVO 时间字段 Date → LocalDateTime - 新增 V10.0.1__CW_clue_transfer_init_data.sql 线索转办初始化数据 - CLAUDE.md 补充 Karpathy 编码准则 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
fce2858794
commit
bd9429d3de
32
CLAUDE.md
32
CLAUDE.md
|
|
@ -143,3 +143,35 @@ gz-oarms-web/docs/prd-llm/
|
|||
- F. Harness Engineering(全流程、模块开发进度总表、核心实体跨域依赖、待开发任务建议顺序)
|
||||
|
||||
前后端联调指南见 `docs/前后端联调指南.md`,包含 10 个模块的接口清单、DTO 字段、数据库表映射及高频错误模式。
|
||||
|
||||
## Coding Guidelines (Karpathy)
|
||||
|
||||
编码行为准则,偏向谨慎而非速度。简单任务可灵活判断。
|
||||
|
||||
### 1. 先思考再编码
|
||||
|
||||
- 不要假设。不确定时先问。
|
||||
- 存在多种理解时,列出选项而非静默选择。
|
||||
- 有更简单的方案时说出来。必要时反驳。
|
||||
- 不清楚就停,指出困惑点。
|
||||
|
||||
### 2. 简洁优先
|
||||
|
||||
- 只实现被要求的功能,不加额外特性。
|
||||
- 单次使用的代码不做抽象。
|
||||
- 没有要求的"灵活性"或"可配置性"不加。
|
||||
- 不可能发生的场景不加错误处理。
|
||||
- 200 行能缩减到 50 行就重写。
|
||||
|
||||
### 3. 精准修改
|
||||
|
||||
- 只改必须改的。不"改善"相邻代码、注释或格式。
|
||||
- 能用的代码不重构。匹配已有风格。
|
||||
- 发现无关死代码时提及但不删除。
|
||||
- 自己的改动产生的废弃 import/变量/函数要清理。
|
||||
|
||||
### 4. 目标驱动
|
||||
|
||||
- 将任务转化为可验证的目标。
|
||||
- 多步骤任务先列出简短计划和验证点。
|
||||
- 成功标准要明确,避免模糊目标(如"让它能用")。
|
||||
|
|
|
|||
|
|
@ -0,0 +1,119 @@
|
|||
-- ============================================================================
|
||||
-- OARMS - CW-4 线索转办管理 初始数据
|
||||
-- Database: DM8 (达梦)
|
||||
-- Schema: OARMS
|
||||
-- Version: V10.0.1
|
||||
-- Date: 2026-05-27
|
||||
-- Description: 基于 CW-MC-001 线索的转办记录 + 操作日志
|
||||
-- Note:
|
||||
-- 1. CW-MC-001 当前线索状态为 1(待转办),创建一条已转办记录
|
||||
-- 2. 同时将线索状态更新为 2(已转办)
|
||||
-- 3. 转办目标使用行政区划中的区域编码
|
||||
-- ============================================================================
|
||||
|
||||
-- 1. CW-MC-001(白云万达虚假宣传) → 转办到白云区市场监督管理局
|
||||
INSERT INTO OARMS.CW_CLUE_TRANSFER_RECORD (
|
||||
ID, CLUE_ID, TRANSFER_TARGET_DISTRICT, TRANSFER_TARGET_DEPARTMENT,
|
||||
TRANSFER_TARGET_PERSON, TRANSFER_DESCRIPTION, TRANSFER_PERSON,
|
||||
TRANSFERRED_AT, TRANSFER_STATUS, EXTERNAL_CLUE_ID,
|
||||
CREATE_BY, CREATE_TIME, CREATE_NAME, UPDATE_BY, UPDATE_TIME, UPDATE_NAME
|
||||
) VALUES (
|
||||
'CW-CTR-001', 'CW-MC-001', '440111', '白云区市场监督管理局',
|
||||
'张志明', '该线索涉及白云万达广场LED大屏虚假宣传"包治百病",建议转白云区市监局处理',
|
||||
'系统管理员',
|
||||
TO_TIMESTAMP('2026-05-25 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), 'transferred', 'EXT-CLUE-20260525-001',
|
||||
'system', TO_TIMESTAMP('2026-05-25 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), '系统',
|
||||
'system', TO_TIMESTAMP('2026-05-25 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), '系统'
|
||||
);
|
||||
|
||||
-- 2. CW-MC-001 → 转办记录2(天河区,已办结状态)
|
||||
INSERT INTO OARMS.CW_CLUE_TRANSFER_RECORD (
|
||||
ID, CLUE_ID, TRANSFER_TARGET_DISTRICT, TRANSFER_TARGET_DEPARTMENT,
|
||||
TRANSFER_TARGET_PERSON, TRANSFER_DESCRIPTION, TRANSFER_PERSON,
|
||||
TRANSFERRED_AT, TRANSFER_STATUS, EXTERNAL_CLUE_ID,
|
||||
DISPOSAL_RESULT, DISPOSAL_COMPLETED_AT,
|
||||
CREATE_BY, CREATE_TIME, CREATE_NAME, UPDATE_BY, UPDATE_TIME, UPDATE_NAME
|
||||
) VALUES (
|
||||
'CW-CTR-002', 'CW-MC-001', '440106', '天河区市场监督管理局',
|
||||
'李伟强', '同时转天河区市监局协助调查广告主信息',
|
||||
'系统管理员',
|
||||
TO_TIMESTAMP('2026-05-26 09:30:00', 'YYYY-MM-DD HH24:MI:SS'), 'completed', 'EXT-CLUE-20260526-002',
|
||||
'已联系广告主,责令拆除违规广告内容,罚款5000元',
|
||||
TO_TIMESTAMP('2026-05-26 16:00:00', 'YYYY-MM-DD HH24:MI:SS'),
|
||||
'system', TO_TIMESTAMP('2026-05-26 09:30:00', 'YYYY-MM-DD HH24:MI:SS'), '系统',
|
||||
'system', TO_TIMESTAMP('2026-05-26 16:00:00', 'YYYY-MM-DD HH24:MI:SS'), '系统'
|
||||
);
|
||||
|
||||
-- ===================== 转办操作日志 =====================
|
||||
|
||||
-- CW-CTR-001: 提交 + 推送成功
|
||||
INSERT INTO OARMS.CW_TRANSFER_OPERATION_LOG (
|
||||
ID, CLUE_TRANSFER_RECORD_ID, OPERATION_TYPE, OPERATION_DETAIL,
|
||||
FROM_STATUS, TO_STATUS, OPERATOR, OPERATED_AT
|
||||
) VALUES (
|
||||
'CW-TOL-001', 'CW-CTR-001', 'submit',
|
||||
'提交线索转办,目标:白云区市场监督管理局',
|
||||
NULL, 'transferred', '系统管理员',
|
||||
TO_TIMESTAMP('2026-05-25 10:00:00', 'YYYY-MM-DD HH24:MI:SS')
|
||||
);
|
||||
|
||||
INSERT INTO OARMS.CW_TRANSFER_OPERATION_LOG (
|
||||
ID, CLUE_TRANSFER_RECORD_ID, OPERATION_TYPE, OPERATION_DETAIL,
|
||||
FROM_STATUS, TO_STATUS, OPERATOR, OPERATED_AT
|
||||
) VALUES (
|
||||
'CW-TOL-002', 'CW-CTR-001', 'push_success',
|
||||
'线索推送成功,外部线索ID: EXT-CLUE-20260525-001',
|
||||
'transferred', 'transferred', '系统管理员',
|
||||
TO_TIMESTAMP('2026-05-25 10:00:05', 'YYYY-MM-DD HH24:MI:SS')
|
||||
);
|
||||
|
||||
-- CW-CTR-002: 提交 + 推送成功 + 状态同步 + 结果反馈
|
||||
INSERT INTO OARMS.CW_TRANSFER_OPERATION_LOG (
|
||||
ID, CLUE_TRANSFER_RECORD_ID, OPERATION_TYPE, OPERATION_DETAIL,
|
||||
FROM_STATUS, TO_STATUS, OPERATOR, OPERATED_AT
|
||||
) VALUES (
|
||||
'CW-TOL-003', 'CW-CTR-002', 'submit',
|
||||
'提交线索转办,目标:天河区市场监督管理局',
|
||||
NULL, 'transferred', '系统管理员',
|
||||
TO_TIMESTAMP('2026-05-26 09:30:00', 'YYYY-MM-DD HH24:MI:SS')
|
||||
);
|
||||
|
||||
INSERT INTO OARMS.CW_TRANSFER_OPERATION_LOG (
|
||||
ID, CLUE_TRANSFER_RECORD_ID, OPERATION_TYPE, OPERATION_DETAIL,
|
||||
FROM_STATUS, TO_STATUS, OPERATOR, OPERATED_AT
|
||||
) VALUES (
|
||||
'CW-TOL-004', 'CW-CTR-002', 'push_success',
|
||||
'线索推送成功,外部线索ID: EXT-CLUE-20260526-002',
|
||||
'transferred', 'transferred', '系统管理员',
|
||||
TO_TIMESTAMP('2026-05-26 09:30:05', 'YYYY-MM-DD HH24:MI:SS')
|
||||
);
|
||||
|
||||
INSERT INTO OARMS.CW_TRANSFER_OPERATION_LOG (
|
||||
ID, CLUE_TRANSFER_RECORD_ID, OPERATION_TYPE, OPERATION_DETAIL,
|
||||
FROM_STATUS, TO_STATUS, OPERATOR, OPERATED_AT
|
||||
) VALUES (
|
||||
'CW-TOL-005', 'CW-CTR-002', 'status_update',
|
||||
'状态从 transferred 变更为 processing',
|
||||
'transferred', 'processing', '外部系统回调',
|
||||
TO_TIMESTAMP('2026-05-26 14:00:00', 'YYYY-MM-DD HH24:MI:SS')
|
||||
);
|
||||
|
||||
INSERT INTO OARMS.CW_TRANSFER_OPERATION_LOG (
|
||||
ID, CLUE_TRANSFER_RECORD_ID, OPERATION_TYPE, OPERATION_DETAIL,
|
||||
FROM_STATUS, TO_STATUS, OPERATOR, OPERATED_AT
|
||||
) VALUES (
|
||||
'CW-TOL-006', 'CW-CTR-002', 'status_update',
|
||||
'状态从 processing 变更为 completed',
|
||||
'processing', 'completed', '外部系统回调',
|
||||
TO_TIMESTAMP('2026-05-26 16:00:00', 'YYYY-MM-DD HH24:MI:SS')
|
||||
);
|
||||
|
||||
-- ===================== 更新线索状态 =====================
|
||||
-- CW-MC-001 从待转办(1)更新为已转办(2)
|
||||
UPDATE OARMS.CW_MONITORING_CLUE
|
||||
SET CLUE_STATUS = 2,
|
||||
TRANSFERRED_AT = TO_TIMESTAMP('2026-05-25 10:00:00', 'YYYY-MM-DD HH24:MI:SS'),
|
||||
UPDATE_BY = 'system',
|
||||
UPDATE_TIME = TO_TIMESTAMP('2026-05-26 16:00:00', 'YYYY-MM-DD HH24:MI:SS'),
|
||||
UPDATE_NAME = '系统'
|
||||
WHERE ID = 'CW-MC-001';
|
||||
|
|
@ -112,4 +112,9 @@ public class EvidenceRecordDetailVO {
|
|||
* 状态变更历史列表
|
||||
*/
|
||||
private List<Map<String, Object>> statusHistory;
|
||||
|
||||
/**
|
||||
* 关联规则数量
|
||||
*/
|
||||
private Integer relatedRuleCount;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ import com.chinaweal.youfool.prj.modules.screen.entity.ScreenEntity;
|
|||
import com.chinaweal.youfool.prj.modules.system.entity.vo.LoginUserVO;
|
||||
import com.chinaweal.youfool.prj.modules.system.util.DataScopeHelper;
|
||||
import com.chinaweal.youfool.prj.modules.screen.mapper.ScreenMapper;
|
||||
import com.chinaweal.youfool.prj.modules.evidence.relation.entity.EvidenceRuleRelationEntity;
|
||||
import com.chinaweal.youfool.prj.modules.evidence.relation.mapper.EvidenceRuleRelationMapper;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
|
@ -30,6 +32,7 @@ import java.time.format.DateTimeFormatter;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
|
@ -45,6 +48,7 @@ public class EvidenceRecordServiceImpl extends ServiceImpl<EvidenceRecordMapper,
|
|||
implements IEvidenceRecordService {
|
||||
|
||||
private final EvidenceStatusHistoryMapper evidenceStatusHistoryMapper;
|
||||
private final EvidenceRuleRelationMapper evidenceRuleRelationMapper;
|
||||
private final ScreenMapper screenMapper;
|
||||
|
||||
@Override
|
||||
|
|
@ -89,9 +93,24 @@ public class EvidenceRecordServiceImpl extends ServiceImpl<EvidenceRecordMapper,
|
|||
// 转换为VO
|
||||
Page<EvidenceRecordDetailVO> voPage = new Page<>(entityPage.getCurrent(),
|
||||
entityPage.getSize(), entityPage.getTotal());
|
||||
|
||||
// 批量查询关联规则数量
|
||||
Set<String> evidenceIds = entityPage.getRecords().stream()
|
||||
.map(EvidenceRecordEntity::getId).collect(Collectors.toSet());
|
||||
Map<String, Long> ruleCountMap = Map.of();
|
||||
if (!evidenceIds.isEmpty()) {
|
||||
LambdaQueryWrapper<EvidenceRuleRelationEntity> ruleWrapper = new LambdaQueryWrapper<>();
|
||||
ruleWrapper.in(EvidenceRuleRelationEntity::getEvidenceId, evidenceIds);
|
||||
List<EvidenceRuleRelationEntity> allRelations = evidenceRuleRelationMapper.selectList(ruleWrapper);
|
||||
ruleCountMap = allRelations.stream()
|
||||
.collect(Collectors.groupingBy(EvidenceRuleRelationEntity::getEvidenceId, Collectors.counting()));
|
||||
}
|
||||
|
||||
Map<String, Long> finalRuleCountMap = ruleCountMap;
|
||||
List<EvidenceRecordDetailVO> voList = entityPage.getRecords().stream().map(entity -> {
|
||||
EvidenceRecordDetailVO vo = new EvidenceRecordDetailVO();
|
||||
BeanUtils.copyProperties(entity, vo);
|
||||
vo.setRelatedRuleCount(finalRuleCountMap.getOrDefault(entity.getId(), 0L).intValue());
|
||||
return vo;
|
||||
}).collect(Collectors.toList());
|
||||
voPage.setRecords(voList);
|
||||
|
|
|
|||
|
|
@ -192,4 +192,17 @@ public class MonitoringRuleController {
|
|||
log.info("[OK] 导出监测规则数据");
|
||||
return monitoringRuleService.exportData(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询规则操作历史
|
||||
*
|
||||
* @param id 规则ID
|
||||
* @return 操作历史列表
|
||||
*/
|
||||
@GetMapping("histories")
|
||||
@Operation(summary = "查询规则操作历史")
|
||||
public RestResult<List<Map<String, Object>>> getHistories(String id) {
|
||||
log.info("[OK] 查询规则操作历史: id={}", id);
|
||||
return monitoringRuleService.getHistories(id);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonFormat;
|
|||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -52,10 +52,10 @@ public class MonitoringRuleDetailVO {
|
|||
private Integer enableStatus;
|
||||
|
||||
@JsonFormat(pattern = DateUtil.DATETIME_DEFAULT_FORMAT, timezone = "GMT+8")
|
||||
private Date createTime;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@JsonFormat(pattern = DateUtil.DATETIME_DEFAULT_FORMAT, timezone = "GMT+8")
|
||||
private Date updateTime;
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
private String createName;
|
||||
|
||||
|
|
|
|||
|
|
@ -89,4 +89,12 @@ public interface IMonitoringRuleService {
|
|||
* @return 导出数据
|
||||
*/
|
||||
RestResult<List<Map<String, Object>>> exportData(MonitoringRuleQuery query);
|
||||
|
||||
/**
|
||||
* 查询规则操作历史
|
||||
*
|
||||
* @param id 规则ID
|
||||
* @return 操作历史列表
|
||||
*/
|
||||
RestResult<List<Map<String, Object>>> getHistories(String id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ import com.chinaweal.youfool.prj.modules.rule.mapper.MonitoringRuleMapper;
|
|||
import com.chinaweal.youfool.prj.modules.rule.mapper.RuleLawClauseRelMapper;
|
||||
import com.chinaweal.youfool.prj.modules.rule.mapper.RuleOperationHistoryMapper;
|
||||
import com.chinaweal.youfool.prj.modules.rule.service.IMonitoringRuleService;
|
||||
import com.chinaweal.youfool.prj.modules.law.entity.LawClauseEntity;
|
||||
import com.chinaweal.youfool.prj.modules.law.mapper.LawClauseMapper;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
|
@ -46,6 +48,7 @@ public class MonitoringRuleServiceImpl extends ServiceImpl<MonitoringRuleMapper,
|
|||
|
||||
private final RuleLawClauseRelMapper ruleLawClauseRelMapper;
|
||||
private final RuleOperationHistoryMapper ruleOperationHistoryMapper;
|
||||
private final LawClauseMapper lawClauseMapper;
|
||||
private final UserBaseService userBaseService;
|
||||
|
||||
@Override
|
||||
|
|
@ -98,9 +101,20 @@ public class MonitoringRuleServiceImpl extends ServiceImpl<MonitoringRuleMapper,
|
|||
clauseWrapper.eq(RuleLawClauseRelEntity::getRuleId, id);
|
||||
List<RuleLawClauseRelEntity> clauseRels = ruleLawClauseRelMapper.selectList(clauseWrapper);
|
||||
List<Map<String, Object>> lawClauses = clauseRels.stream().map(rel -> {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("id", rel.getId());
|
||||
map.put("clauseId", rel.getClauseId());
|
||||
LawClauseEntity clause = lawClauseMapper.selectById(rel.getClauseId());
|
||||
if (clause == null) {
|
||||
LambdaQueryWrapper<LawClauseEntity> codeWrapper = new LambdaQueryWrapper<>();
|
||||
codeWrapper.eq(LawClauseEntity::getClauseCode, rel.getClauseId());
|
||||
clause = lawClauseMapper.selectOne(codeWrapper);
|
||||
}
|
||||
if (clause != null) {
|
||||
map.put("lawName", clause.getLawName());
|
||||
map.put("clauseCode", clause.getClauseCode());
|
||||
map.put("clauseContent", clause.getClauseContent());
|
||||
}
|
||||
return map;
|
||||
}).collect(Collectors.toList());
|
||||
vo.setLawClauses(lawClauses);
|
||||
|
|
@ -301,6 +315,25 @@ public class MonitoringRuleServiceImpl extends ServiceImpl<MonitoringRuleMapper,
|
|||
return RestResult.ok(exportList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestResult<List<Map<String, Object>>> getHistories(String id) {
|
||||
LambdaQueryWrapper<RuleOperationHistoryEntity> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(RuleOperationHistoryEntity::getRuleId, id);
|
||||
wrapper.orderByDesc(RuleOperationHistoryEntity::getOperatedAt);
|
||||
List<RuleOperationHistoryEntity> histories = ruleOperationHistoryMapper.selectList(wrapper);
|
||||
List<Map<String, Object>> list = histories.stream().map(h -> {
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("id", h.getId());
|
||||
map.put("operator", h.getOperator());
|
||||
map.put("operationType", h.getOperationType());
|
||||
map.put("beforeChange", h.getBeforeChange());
|
||||
map.put("afterChange", h.getAfterChange());
|
||||
map.put("operatedAt", h.getOperatedAt());
|
||||
return map;
|
||||
}).collect(Collectors.toList());
|
||||
return RestResult.ok(list);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 私有方法
|
||||
// =========================================================================
|
||||
|
|
|
|||
Loading…
Reference in New Issue