Compare commits

..

147 Commits

Author SHA1 Message Date
xueqingkun cbb60203e3 1. 修复bug
xueqingkun 52dcd6996a 1. 修复bug
xueqingkun 2205b05d85 1. 修复bug
xueqingkun c9a90e7bcd 1. 修复bug
xueqingkun a2c1b3ea35 1. 修复bug
xueqingkun fcb619d8ed 1. 添加多模型接入功能
xueqingkun 8513c7c590 1. 添加多模型接入功能
xueqingkun 863c0783e8 1. 添加多模型接入功能
xueqingkun dfe3782d67 1. 添加多模型接入功能
xueqingkun 91941cc015 1. 指代消除功能开发-变更sql
xueqingkun bdb1c8558f 1. 指代消除功能开发
xueqingkun c199b6f3ff 1. 指代消除功能开发
xueqingkun 0e0cdc4a50 1. 指代消除功能开发
xueqingkun e014b70574 1. 三元组抽取完成后直接入图
xueqingkun 14b0e79c7f 1. 删除案件导入设计文件。相关文档已经更新到订钉钉文档中
yaxin bddcac8eb3 Merge remote-tracking branch 'origin/dev' into dev
yaxin 879c30c051 migration2.2.1.sql
xueqingkun 4a7d087f47 1. 案件对接概设
yaxin 7197e192a1 获取节点ID语句修正
xueqingkun d30c1d3957 1. 任务列表添加完成时间字段
2. 修复一键提取task_case状态有误问题
yaxin 69ed1095b8 异步创建并调用提取任务
xueqingkun 7d35492df5 Merge branch 'dev-neo4j-debug' into dev
xueqingkun cd77190a16 1. 任务列表添加完成时间字段
2. 修复一键提取task_case状态有误问题
yaxin a7cb70e44f 全量提示词一键提取初版,追加日志
xueqingkun 8f03ed6b6f 1. 图片调试移除没有关系的图节点
xueqingkun dcedd984dc 1. 案件一键分析 添加异常捕获,防止案件状态一直停留在正在分析中
xueqingkun 5997fef737 1. 提交sql变更
xueqingkun d649f619fd 1. 提交sql变更
xueqingkun 7b9e46b8e5 1. 修复bug
yaxin 4dbc1e1142 回退删除CYPHER,当节点有多条边时,删除抛异常是期望结果,不能使用detach直接删除节点
yaxin 35c90d44b8 证据文件获取异常时需抛出
xueqingkun a58b95a94d 1. 表model_atomic_result添加索引
xueqingkun 4d7f0077ba 1. 修复 bug
xueqingkun ee53b54a2b 1. 修复 bug
xueqingkun b67874772b 1. 修复 bug
yaxin aa2227df08 更新如图状态,修改删除节点语句,n.id改为id(n)
xueqingkun 3047c2b81c 1. 修复 neo4j数据与mysql不一致
xueqingkun 27004d84fb 1. 添加sql脚本
1.1 案件分析状态字典
1.2 添加运营管理菜单
yaxin 434942c718 任务命名方法封装
yaxin a7913a7b0e 导出指标数据excel
xueqingkun 7df3c82d6d 1. 修复bugs
xueqingkun 9979750f24 1. 优化代码
yaxin 170654b31c Merge remote-tracking branch 'origin/dev' into dev
yaxin e91aac7f61 2.2版本SQL
xueqingkun a30adbb451 1. 优化代码
xueqingkun 881929f683 1. 优化代码
xueqingkun dcca6ce2e8 1. 优化代码
yaxin 4f35931353 mybatis统一管理
yaxin 55f9f2c768 创建人赋值
yaxin b502732fde 任务执行过程中,检测到A案件正在模型分析,尝试每隔5s查询分析状态,待A案件模型分析成功后,继续提取任务。若超过2分钟仍未完成,判定A案件模型分析异常,任务继续执行A案件提取。
xueqingkun 0e5ef9da7e 1. 优化代码
xueqingkun a4b2707318 1. 优化代码
yaxin 92b35c2758 自动命名
yaxin 43d0798849 任务相关业务方法抽取到taskRecord controller、service中
xueqingkun a944c115ff 1. 优化代码
xueqingkun 434b3bd598 1. 优化代码
xueqingkun 2d4734e163 1. 修复新增案件知识图谱保存不进去问题
xueqingkun 35dc073b90 1. 修复新增案件创建知识库报错问题
xueqingkun d45b18a40e 1. 添加removeCaseDataSet
yaxin 3d22bb579c 任务、案件任务状态管理,code format
xueqingkun 0aa8469ed8 1. 添加单个提示词分析笔录功能
xueqingkun 022aaf3a51 1. 添加单个提示词分析笔录功能
yaxin 4ebfda4b34 方法提取
异常处理
xueqingkun 791e133780 1. 添加单个提示词分析笔录功能
yaxin c388c1eaf5 单例bean需要final关键字
yaxin d3f7290413 任务执行接口,xxl-job接口任务、案件层业务逻辑提交
yaxin 9e733ebb97 Merge branch 'master' into dev
yaxin 7349399d28 如果关系判断要求“不存在”,则判断条数需要大于0,如果关系判断要求“存在”,则判断count是否大于value
xueqingkun d478b1ff6d 1. 添加任务列表功能
yaxin 39150345df 如果关系判断要求“存在”,则判断count是否大于value
yaxin a48d5a7ef1 创建任务触发xxl-job task外层逻辑
xueqingkun 5aac77ec1b 1. 添加案件批处理功能
yaxin f136c64ed5 常量定义
yaxin ae558a5086 提示词提取任务模型设计
yaxin 79d835eeab 按照最新要求,前端显示由“符合/不符合”改为“存在/不存在”,故取消和judgeLogic的比较
yaxin 88e5fbe0c1 提示词调试支持图谱提取
yaxin f9a36a2428 Merge remote-tracking branch 'origin/dev' into dev
yaxin ae7f1414b8 将原先的值进行赋值,设置到pre_result
如果关系判断要求“不存在”,则判断count是否为0,如果关系判断要求“存在”,则判断count是否大于value
xueqingkun d5151811ca 1. 修改证据属性详情为空展示未null的问题
xueqingkun 2ff0f918fc 1. 修改证据属性详情为空展示未null的问题
yaxin 5d52c82806 删除关系后并不能保证节点不存在关系,所以删除节点时需要加上没有关系的条件判断
yaxin 48065841fb 配置要求
yaxin cc1256b3e0 指标名称需精确匹配
xueqingkun 3f45aaaf9d 1. 添加model_atomic_index更新语句
xueqingkun ad9662bf51 1. 添加发版说明
2. 更新docker-compose配置文件
yaxin 738c2583d4 Merge remote-tracking branch 'origin/dev' into dev
yaxin 021f2208cb 1212上线资料更新
xueqingkun 0e413f709b 1. 优化代码
xueqingkun 7cbf8d79e3 1. 优化代码
xueqingkun 8b5e53225d Merge remote-tracking branch 'origin/dev' into dev
xueqingkun 36331c994a 1. 优化代码
yaxin 69e8eafdaf answerText无论如何都要尝试赋值
yaxin 5de8ab3787 更新DIFY API key
yaxin 2a699d38b5 更新DIFY API key
yaxin 29aefed932 dialogueCount始终透传
xueqingkun e412ccb84b 1. 修复远程地址不准的问题
xueqingkun b38e45bbea Merge remote-tracking branch 'origin/dev' into dev
xueqingkun 80a122ef37 1. 删除测试代码
yaxin fb072bfcec query trim
xueqingkun 4d09ada685 Merge remote-tracking branch 'origin/dev' into dev
xueqingkun 3c7151010b 1. 修改下载文件接口,支持自定义是否需要打水印和是否需要下载文件
yaxin 868a71364c 问题修复
xueqingkun 619f5b162b 1. 添加日志审计功能对应的表结构
xueqingkun aae0920d6a Merge remote-tracking branch 'origin/dev' into dev
xueqingkun 2fdbc3f2f0 1. 添加日志审计功能
yaxin 9580155a56 模糊意图识别,引导对话
xueqingkun f8340cfcf3 1. 添加开发环境设置默认登录用户功能
xueqingkun 1ac95b7e9a 1. 优化代码
xueqingkun 13f1ea4c71 1. 优化代码
xueqingkun 77246070d0 1. 优化代码
xueqingkun 7ce757592d 1. 优化代码
xueqingkun d24bf731e0 1. 修改用户信息从threadLocal中获取
2. 把用户信息写入到cookie中
3. 下载的图片或者pdf添加水印
yaxin b9fcbb5153 聊天方法改名
yaxin 9f216fa844 Merge branch 'master' into dev
# Conflicts:
#	src/main/java/com/supervision/police/service/impl/ModelServiceImpl.java
yaxin 4393f59212 问题修复,功能优化等
yaxin e26a95b504 如果是数字的比较,需要做类型转换
xueqingkun 5adb4403fa Merge remote-tracking branch 'origin/dev' into dev
xueqingkun bdcd1b7aa9 1. 案件对话列表返回结果添加日期字段
xueqingkun c5a4178d29 1. 案件文件同步dify知识库-支持图片类型
yaxin 3d1278722f Merge remote-tracking branch 'origin/dev' into dev
yaxin 52341c66c4 问题修复
xueqingkun 68dd52ff81 1. 修改日志中的错别字
xueqingkun 8792ecaee1 Merge remote-tracking branch 'origin/dev' into dev
xueqingkun bb15011253 1. 暴露知识库迁移接口
yaxin b846e9c168 问题修复
xueqingkun a3a1bdf1e8 1. 调整对话内容排序
xueqingkun 6749e79ba7 1. 调整对话内容排序
DESKTOP-DDTUS3E\yaxin c778df4571 Merge remote-tracking branch 'origin/dev' into dev
DESKTOP-DDTUS3E\yaxin 295e2108ee 证据下载接口,聊天功能优化
xueqingkun 3893fb34d6 1. 添加对话接口
DESKTOP-DDTUS3E\yaxin 92e799e9ae Merge remote-tracking branch 'origin/dev' into dev
DESKTOP-DDTUS3E\yaxin 3fc0495cea improve
xueqingkun 2389e70ee2 1. 添加对话接口
xueqingkun 120129d55d 1. merger
xueqingkun 9f7c9a4277 Merge remote-tracking branch 'origin/dev' into dev
# Conflicts:
#	src/main/java/com/supervision/police/vo/ChatResVO.java
xueqingkun 3ec4963db1 1. 添加案件证据文件到知识库文库
2. 添加对话接口
DESKTOP-DDTUS3E\yaxin dac315f28c DIFY知识库问答
xueqingkun 6baed0d345 Merge remote-tracking branch 'origin/dev' into dev
xueqingkun eee3a9b8eb 1. 笔录维护到dify知识库功能(只有已经分析的案件才会上传文档)
DESKTOP-DDTUS3E\yaxin 0bb59ced04 improve
DESKTOP-DDTUS3E\yaxin b54400454f 数字民警对话改造初版
DESKTOP-DDTUS3E\yaxin d53bca3ada fastjson依赖
DESKTOP-DDTUS3E\yaxin 08477d961f merge
xueqingkun ac8a9ea483 1. 添加变更sql
xueqingkun 851c50cb13 Merge branch 'dev-chat' into dev
DESKTOP-DDTUS3E\yaxin 1fd191a54b 数据库初始化脚本
xueqingkun 5e7ab3ebd9 1. 添加笔录维护到dify知识库功能

@ -2,13 +2,92 @@
宁夏刑侦大模型后台服务
# Release Notes
# 发布时间 2025-02-20
# Release Notes
## 新特性
- 增加多模型接入的能力
## 变更
- 调整原子指标、指标的详情展示样式
## 更新步骤
- 备份mysql数据库、前后端包
- 执行变更sql脚本
- 替换后端服务包(fu-hsi-service-1.0.0.jar)
- 替换前端包(dist)
- 重启后端服务,并查看服务是否正常启动
- 重启前端服务,并查看服务是否正常启动
- 验证更新内容
# 发布时间 2024-12-26
## 新特性
- 页面确保在不同尺寸宽度的屏幕上均能正常显示,并支持用户通过滚动查看完整内容。
- 案件列表添加鼠标悬停效果,悬停行背景颜色加深
- 证据图像上传加载页面时,增加骨架屏效果优化用户体验。
- 模型分析功能按钮增加防抖限制,避免短时间内重复触发导致的性能问题
## 变更
- 指标结果-原子指标结果显示“存在/不存在”
- 统计案件状态:未分析、已分析、正在分析
- 证据列表删除分页、指标结果删除分页
- 修复问题未调整案件及指标相关配置执行模型分析后指标结果仍显示new标识
# 发布时间 2024-12-13
## 新特性
- 上线dify服务
- 数字民警对话功能改造,支持精确、模糊意图识别,知识检索,历史记录,关联证据文件下载等
- 存量案件同步到dify知识库
- Http请求、响应日志审计功能
## 变更
- 下线langChain-Chatchat服务
- 数字民警UI交互改造独立tab页展示支持快捷操作功能
## 更新步骤
0. 备份fu-hsi-mysql数据库中的所有数据
1. 导入fu-hsi-web1.1.0镜像 (docker load -i fu-hsi-web.1.1.0.tar.gz)
2. 修改docker-compose.yml配置文件
- 在services.fu-hsi-web.command配置下添加以下参数
--dify.server.url=${DIFY_SERVER_URL}
--dify.dataset.auth=${DIFY_DATASET_AUTH}
--dify.app.auth=${DIFY_APP_AUTH}
- 修改services.fu-hsi-web.image为fu-hsi-web:1.1.0
3. 修改.env配置文件追加参数(注意Bearer后面的空格前面需要添加转移符号):
DIFY_SERVER_URL=http://192.168.10.137/v1
DIFY_DATASET_AUTH="Bearer\ dataset-g3RctoaHdvXAAQjUVNMuUWCY"
DIFY_APP_AUTH="Bearer\ app-YrNuU7Puxr3ko8ftUdWtDKhz"
4. 执行变更sql(migration_2.1.sql)
5. 安装dify服务
6. 启动服务(docker compose up -d)
7. 迁移案件数据到dify知识库调用接口 GET /modelCase/migrateRecordKnowledgeBase
8. 验证更新内容
# 发布时间 2024-12-03
## 变更
- 案件图谱优化,支持多种节点颜色样式,引力布局调整,交互体验优化
# 发布时间 2024-11-21
## 变更
- 案件图谱展示优化,支持搜索,全屏,节点/关系过滤等
- 原子指标-图谱查询支持在线调试
# 发布时间 2024-11-06
# 变更
## 变更
- 优化了案件指标(原子指标)结果详情笔录、证据的展示,统一为右侧抽屉弹框展示详情
- 优化了提示词配置的交互,支持结构化提示词的创建与修改,支持提示词的调试
- 优化了原子指标-指标算法交互,数据库、图谱推理指标保留配置语句方式,结构化提取可选择对应提示词
@ -27,9 +106,9 @@
1. 加载镜像如果docker可以访问外网直接下载否则需要先上传到服务器
- docker load -i xxl-job-admin:2.4.1.tar.gz
2. 修改.env中的xxl-job中对应的配置
- XXl_JOB_PASSWORD=sT7SSTiX8s
- XXL_JOB_PORT_HTTP=8081
- SPRING_DATASOURCE_URL=jdbc:mysql://fu-hsi-mysql:3306/xxl-job?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
- XXl_JOB_PASSWORD=sT7SSTiX8s
- XXL_JOB_PORT_HTTP=8081
- SPRING_DATASOURCE_URL=jdbc:mysql://fu-hsi-mysql:3306/xxl-job?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
3. 替换docker-compose-base.yml、docker-compose.yml配置文件
4. 备份mysql数据库
5. 执行数据初始化脚本(在文档末尾处)
@ -38,45 +117,53 @@
8. 调用案件证据归档刷新接口完成历史案件证据归档整理(get ip:port/caseEvidence/fresh)、初始化指标计算规则数据
9. 验证更新内容
# 发布时间 2024-09-20
# 变更
- 修复编辑ocr识别证据异常问题
- 优化前端等待展示样式
# 安装包
- /data/archives/fu-hsi/20240920/fu-hsi-service-1.0.0.tar.gz
- /data/archives/fu-hsi/20240920/dist
# 发布时间 2024-09-19
## 新特性
- 增加笔录和证据上传OCR识别功能
- 首页数据统计接口
- 日志输出规范配置
## 变更
- 案件查询列表查询条件变更
- 增加过滤条件已分析、未分析、全部
- 增加按照分数排序的规则
## 优化
- 数据库提示词优化
## 安装步骤
1. 修改.env 和docker-compose-base.yml 文件
2. 加载镜像 paddleocr:v2.1
3. 备份mysql所有数据文件
4. 重新启动服务 docker-compose up -d
# 安装包
- /data/archives/fu-hsi/20240919/fu-hsi-service-1.0.0.tar.gz
- /data/archives/fu-hsi/20240919/dist
- /data/archives/fu-hsi/20240919/paddleocr:v2.1.tar.gz
# 发布时间 2024-09-12
# 变更记录
- 调整提示词后,笔录列表增加“笔录提取”功能,并显示更新标签
- 指标结果各项标题显示总分
- 首页统计项7项案件数量、行为数、月新增、较上月、模型分析<70
@ -84,34 +171,44 @@
- 经侦案件列表根据模型分析状态进行分类,分别在“全部”、“已分析”、“未分析”三个标签下展示对应案件。
# 安装包
- /data/archives/fu-hsi/20240912/fu-hsi-service-1.0.0.tar.gz
- /data/archives/fu-hsi/20240912/dist
# 发布时间 2024-09-05
# 变更记录
- 修复案件证据分页失效问题
- 修复经侦模型指标数据只展示部分数据问题
# 安装包
- /data/archives/fu-hsi/20240905/dist
# 发布时间 2024-09-03
# 变更记录
- 修复三元组提取进度问题不准确的问题
- 解除首页页面限制
- 优化原子指标提示
- 解除模型分析需要有数据变动校验限制
# 安装包
- /data/archives/fu-hsi/20240903/fu-hsi-service-1.0.0.tar.gz
- /data/archives/fu-hsi/20240903/dist
# 发布时间 2024-08-29
# 变更记录
- 案件笔录列表调整,仅展示子列表
- 字典值配置生效
- 案件笔录列表调整,仅展示子列表
- 字典值配置生效
# 安装包
- /data/archives/fu-hsi/20240828/fu-hsi-service-1.0.0.tar.gz
- /data/archives/fu-hsi/20240828/dist
- /data/archives/fu-hsi/20240828/dist

@ -25,6 +25,12 @@ THREAD_POOL_TRIPLE_CORE=1
THREAD_POOL_TYPE_CORE=1
XXl_JOB_PASSWORD=sT7SSTiX8s
# dify相关配置内容,空格前面需要加转移符
DIFY_SERVER_URL=http://192.168.10.137/v1
DIFY_DATASET_AUTH="Bearer\ dataset-g3RctoaHdvXAAQjUVNMuUWCY"
DIFY_APP_AUTH="Bearer\ app-YrNuU7Puxr3ko8ftUdWtDKhz"
# ocr相关配置内容
OCR_PORT_HTTP=8866
OCR_MINIO_ENDPOINT_URL=http://fu-hsi-minio:9000

@ -1,11 +1,28 @@
## 🎬 快速开始
### 📝 前提条件
- CPU >= 16 核
- RAM >= 32 GB
- Disk >= 500 GB
- Docker >= 24.0.6 & Docker Compose >= v2.27.0
## 配置要求
### 最低配置
- CPU:16核Intel i5或AMD Ryzen 3以上
- GPU:NVIDIA RTX 4090 24GB × 1
- RAM:32GB
- Disk:500GB
- Docker:24.0.6+
- Docker Compose:v2.27.0+
- OS:Ubuntu 22.04+
- 网络带宽:100M+
### 推荐配置
- CPU:32核Intel i7或AMD Ryzen 5及以上
- GPU:NVIDIA RTX 4090 24GB × 2 或 NVIDIA A6000 48GB × 1
- RAM:64GB
- Disk:1TB
- Docker:24.0.6+
- Docker Compose:v2.27.0+
- OS:Ubuntu 22.04+
- 网络带宽:500M+
### 安装包结构说明

@ -11,7 +11,7 @@ services:
condition: service_started
minio:
condition: service_started
image: fu-hsi-web:1.0.0
image: fu-hsi-web:1.1.0
container_name: fu-hsi-web
ports:
- ${WEB_HTTP_PORT}:8097
@ -31,6 +31,9 @@ services:
--fu-hsi-config.thread-pool.triple.core=${THREAD_POOL_TRIPLE_CORE}
--fu-hsi-config.thread-pool.type.core=${THREAD_POOL_TYPE_CORE}
--xxl.job.admin.password=${XXl_JOB_PASSWORD}
--dify.server.url=${DIFY_SERVER_URL}
--dify.dataset.auth=${DIFY_DATASET_AUTH}
--dify.app.auth=${DIFY_APP_AUTH}
environment:
- TZ=${TIMEZONE}
networks:

@ -0,0 +1,70 @@
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `conversation`;
CREATE TABLE `conversation` (
`id` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`title` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '标题',
`type` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '类型',
`case_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '案件ID',
`user_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '用户ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin COMMENT = '会话记录表' ROW_FORMAT = DYNAMIC;
DROP TABLE IF EXISTS `conversation_qa`;
CREATE TABLE `conversation_qa` (
`id` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`type` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '问答类型 0DIFY问答 1NX_LLM问答',
`intent_type` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '意图类型 0指标结果 1案件分析结果 2案件概况 3案件证据指引',
`dialog_count` int(11) NULL DEFAULT NULL COMMENT '多轮对话轮数',
`question` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`complete_question` text CHARACTER SET utf8 COLLATE utf8_bin NULL,
`question_time` datetime NOT NULL,
`answer` text CHARACTER SET utf8 COLLATE utf8_bin NULL,
`answer_map` text CHARACTER SET utf8 COLLATE utf8_bin NULL,
`segment_list` text CHARACTER SET utf8 COLLATE utf8_bin NULL COMMENT 'RAG片段',
`complete_answer` text CHARACTER SET utf8 COLLATE utf8_bin NULL,
`answer_time` datetime NULL DEFAULT NULL,
`time_interval` int(11) NULL DEFAULT NULL,
`user_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`case_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`conversation_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = DYNAMIC;
alter table model_case
add knowledge_base_id varchar(64) null comment '知识库id' after id;
ALTER TABLE `nx_llm`.`note_record_split`
ADD COLUMN `note_file_id` varchar(64) NULL COMMENT '笔录文件ID' AFTER `person_name`;
create table audit_log
(
id varchar(64) not null comment '主键id'
primary key,
record_type varchar(64) null comment '记录类型0-正常操作记录1-异常记录',
user_id varchar(64) null comment '用户id',
user_name varchar(128) null comment '用户名',
ip varchar(255) null comment '操作人ip地址',
method varchar(64) null comment '请求类型 GET POST PUT DELETE',
url varchar(1024) null comment 'url地址',
request_params text null comment '请求参数',
cost_time int null comment '操作耗时 单位ms',
response text null comment '响应结果',
exception_desc text null comment '异常描述',
create_time datetime null comment '创建时间',
create_user_id varchar(64) null comment '创建人',
update_time datetime null comment '更新时间',
update_user_id varchar(255) null comment '更新用户id'
)
comment '日志审计表';
create index audit_log_record_type_index
on audit_log (record_type);
create index audit_log_user_id_index
on audit_log (user_id);
UPDATE model_atomic_index SET query_lang = 'select * from note_record where case_id = #{caseId} and role = \'4\';' WHERE id = '2d678232-3ea7-4bad-a7e3-875eb2aa9242';

@ -0,0 +1,164 @@
INSERT INTO `nx_llm`.`com_dictionary` (`id`, `name`, `code`, `pid`, `type`, `status`, `note`, `priority`, `creator`,
`update_time`, `create_time`, `updater`, `data_status`, `create_user_id`,
`update_user_id`)
VALUES (89, '任务状态', NULL, 0, 'task_status', '1', NULL, 0, NULL, NULL, CURRENT_TIMESTAMP, NULL, '1', NULL, NULL);
INSERT INTO `nx_llm`.`com_dictionary` (`id`, `name`, `code`, `pid`, `type`, `status`, `note`, `priority`, `creator`,
`update_time`, `create_time`, `updater`, `data_status`, `create_user_id`,
`update_user_id`)
VALUES (90, '待处理', '0', 89, 'task_status', '1', NULL, 0, NULL, NULL, CURRENT_TIMESTAMP, NULL, '1', NULL, NULL);
INSERT INTO `nx_llm`.`com_dictionary` (`id`, `name`, `code`, `pid`, `type`, `status`, `note`, `priority`, `creator`,
`update_time`, `create_time`, `updater`, `data_status`, `create_user_id`,
`update_user_id`)
VALUES (91, '处理中', '1', 89, 'task_status', '1', NULL, 0, NULL, NULL, CURRENT_TIMESTAMP, NULL, '1', NULL, NULL);
INSERT INTO `nx_llm`.`com_dictionary` (`id`, `name`, `code`, `pid`, `type`, `status`, `note`, `priority`, `creator`,
`update_time`, `create_time`, `updater`, `data_status`, `create_user_id`,
`update_user_id`)
VALUES (92, '取消中', '2', 89, 'task_status', '1', NULL, 0, NULL, NULL, CURRENT_TIMESTAMP, NULL, '1', NULL, NULL);
INSERT INTO `nx_llm`.`com_dictionary` (`id`, `name`, `code`, `pid`, `type`, `status`, `note`, `priority`, `creator`,
`update_time`, `create_time`, `updater`, `data_status`, `create_user_id`,
`update_user_id`)
VALUES (93, '已取消', '3', 89, 'task_status', '1', NULL, 0, NULL, NULL, CURRENT_TIMESTAMP, NULL, '1', NULL, NULL);
INSERT INTO `nx_llm`.`com_dictionary` (`id`, `name`, `code`, `pid`, `type`, `status`, `note`, `priority`, `creator`,
`update_time`, `create_time`, `updater`, `data_status`, `create_user_id`,
`update_user_id`)
VALUES (94, '处理成功', '4', 89, 'task_status', '1', NULL, 0, NULL, NULL, CURRENT_TIMESTAMP, NULL, '1', NULL, NULL);
INSERT INTO `nx_llm`.`com_dictionary` (`id`, `name`, `code`, `pid`, `type`, `status`, `note`, `priority`, `creator`,
`update_time`, `create_time`, `updater`, `data_status`, `create_user_id`,
`update_user_id`)
VALUES (95, '处理失败', '5', 89, 'task_status', '1', NULL, 0, NULL, NULL, CURRENT_TIMESTAMP, NULL, '1', NULL, NULL);
-- 案件分析状态字典
INSERT INTO nx_llm.com_dictionary (id, name, code, pid, type, status, note, priority, creator, update_time, create_time, updater, data_status, create_user_id, update_user_id) VALUES (97, '分析状态', null, 0, 'case_analysis_status', '1', null, 0, null, null, '2024-12-31 14:26:52', null, '1', null, null);
INSERT INTO nx_llm.com_dictionary (id, name, code, pid, type, status, note, priority, creator, update_time, create_time, updater, data_status, create_user_id, update_user_id) VALUES (98, '未分析', '0', 97, 'case_analysis_status', '1', null, 0, null, null, '2024-12-31 14:26:52', null, '1', null, null);
INSERT INTO nx_llm.com_dictionary (id, name, code, pid, type, status, note, priority, creator, update_time, create_time, updater, data_status, create_user_id, update_user_id) VALUES (99, '正在分析', '1', 97, 'case_analysis_status', '1', null, 0, null, null, '2024-12-31 14:26:52', null, '1', null, null);
INSERT INTO nx_llm.com_dictionary (id, name, code, pid, type, status, note, priority, creator, update_time, create_time, updater, data_status, create_user_id, update_user_id) VALUES (100, '分析成功', '2', 97, 'case_analysis_status', '1', null, 0, null, null, '2024-12-31 14:26:52', null, '1', null, null);
INSERT INTO nx_llm.com_dictionary (id, name, code, pid, type, status, note, priority, creator, update_time, create_time, updater, data_status, create_user_id, update_user_id) VALUES (101, '分析失败', '3', 97, 'case_analysis_status', '1', null, 0, null, null, '2024-12-31 14:26:52', null, '1', null, null);
-- 添加运营管理菜单
INSERT INTO nx_llm.system_menu (id, label, label_code, label_type, parent_id, create_user_id, create_time, update_user_id, update_time) VALUES ('16', '运营管理', 'p_operationManagement', 0, null, null, '2025-01-02 14:29:10', null, '2025-01-02 14:29:10');
INSERT INTO nx_llm.system_menu (id, label, label_code, label_type, parent_id, create_user_id, create_time, update_user_id, update_time) VALUES ('17', '任务列表', 'p_taskList', 0, '16', null, '2025-01-02 14:29:47', null, '2025-01-02 14:29:47');
INSERT INTO nx_llm.system_menu (id, label, label_code, label_type, parent_id, create_user_id, create_time, update_user_id, update_time) VALUES ('18', '案件批量处理', 'p_handleCases', 0, '16', null, '2025-01-02 16:13:47', null, '2025-01-02 16:13:47');
-- 给管理员角色添加权限
INSERT INTO nx_llm.system_role_menu_relation (id, role_id, menu_id, create_user_id, create_time, update_user_id, update_time) VALUES ('1830865690704818280', '1820688378166366209', '16', null, '2025-01-02 15:09:31', null, '2025-01-02 15:09:31');
INSERT INTO nx_llm.system_role_menu_relation (id, role_id, menu_id, create_user_id, create_time, update_user_id, update_time) VALUES ('1830865690704818281', '1820688378166366209', '17', null, '2025-01-02 15:09:31', null, '2025-01-02 15:09:31');
INSERT INTO nx_llm.system_role_menu_relation (id, role_id, menu_id, create_user_id, create_time, update_user_id, update_time) VALUES ('1830865690704818282', '1820688378166366209', '18', null, '2024-09-03 15:09:31', null, '2024-09-03 15:09:31');
CREATE TABLE `task_record`
(
`id` varchar(64) NOT NULL,
`name` varchar(255) DEFAULT NULL COMMENT '名称',
`prompt_id` varchar(64) DEFAULT NULL,
`case_id` text COMMENT '案件ID英文逗号分隔',
`record_id` text COMMENT '笔录ID英文逗号分隔',
`evidence_id` text COMMENT '证据ID英文逗号分隔',
`type` varchar(1) DEFAULT NULL COMMENT '0全部案件 1部分案件 2部分笔录 3部分证据',
`status` varchar(1) DEFAULT '0' COMMENT '0待处理 1处理中 2取消中 3已取消 4处理成功 5处理失败',
`cancel_time` datetime DEFAULT NULL COMMENT '取消时间',
`create_user_id` varchar(64) DEFAULT NULL COMMENT '创建人ID',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_user_id` varchar(64) DEFAULT NULL COMMENT '更新人ID',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
CREATE TABLE `task_case_record`
(
`id` varchar(64) NOT NULL,
`task_record_id` varchar(64) DEFAULT NULL COMMENT '任务ID',
`case_id` varchar(64) DEFAULT NULL COMMENT '案件ID',
`waiting_id` text COMMENT '等待处理的ID逗号分隔',
`processed_id` text COMMENT '处理完成的ID逗号分隔',
`exception_id` text COMMENT '异常ID逗号分隔',
`status` varchar(1) DEFAULT NULL COMMENT '0待处理 1处理中 2取消中 3已取消 4处理成功 5处理失败',
`create_user_id` varchar(64) DEFAULT NULL COMMENT '创建人ID',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_user_id` varchar(64) DEFAULT NULL COMMENT '更新人ID',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
-- 创建索引
create index model_atomic_result_case_id_index
on model_atomic_result (case_id);
-- 修改属性表字段长度
alter table attribute_mmht
modify part_a varchar(1024) null comment '甲方';
alter table attribute_mmht
modify part_b varchar(1024) null comment '乙方';
alter table attribute_mmht
modify part_c varchar(1024) null comment '乙方';
alter table attribute_mmht
modify qualifications varchar(1024) null comment '资质要求';
alter table attribute_mmht
modify subject_matter varchar(1024) null comment '合同标的物';
alter table attribute_mmht
modify number varchar(1024) null comment '数量';
alter table attribute_mmht
modify amount_money varchar(1024) null comment '金额';
alter table attribute_mmht
modify payment_method varchar(1024) null comment '支付方式';
alter table attribute_mmht
modify payment_time varchar(1024) null comment '支付时间';
alter table attribute_mmht
modify performance_period varchar(1024) null comment '履行期限';
alter table attribute_mmht
modify place_performance varchar(1024) null comment '履行地点';
alter table attribute_mmht
modify signing_date varchar(1024) null comment '签订日期';
alter table attribute_gwzs
modify project_name varchar(1024) null comment '项目名称';
alter table attribute_gwzs
modify project_status varchar(1024) null comment '项目状态';
alter table attribute_gwzs
modify publishing_unit varchar(1024) null comment '发布单位';
alter table attribute_gwzs
modify conclusion varchar(1024) null comment '结论';
alter table attribute_gwzs
modify publication_time varchar(1024) null comment '发文时间';
alter table attribute_xmht
modify project_name varchar(1024) null comment '项目名称';
alter table attribute_xmht
modify part_a varchar(1024) null comment '甲方';
alter table attribute_xmht
modify part_b varchar(1024) null comment '乙方';
alter table attribute_xmht
modify scope varchar(1024) null comment '项目范围';
alter table attribute_xmht
modify project_start_time varchar(1024) null comment '项目开始时间';
alter table attribute_xmht
modify project_end_time varchar(1024) null comment '项目结束时间';
alter table attribute_xmht
modify signing_time varchar(1024) null comment '签订日期';
alter table attribute_xmht
modify project_status varchar(1024) null comment '项目状态';
alter table attribute_yhls
modify account_information varchar(1024) null comment '账户信息';
alter table attribute_yhls
modify other_account_information varchar(1024) null comment '对方账户信息';
alter table attribute_yhls
modify amount varchar(1024) null comment '金额';
alter table attribute_yhls
modify trading_time varchar(1024) null comment '交易时间';
alter table attribute_yhls
modify revenue_expenditure_identification varchar(1024) null comment '收入支出标识';
alter table attribute_yhls
modify abstract_info varchar(1024) null comment '摘要';
alter table attribute_zfpz
modify payer_name varchar(1024) null comment '付款方名称';
alter table attribute_zfpz
modify payee_name varchar(1024) null comment '收款方名称';
alter table attribute_zfpz
modify payment_time varchar(1024) null comment '支付时间';
alter table attribute_zfpz
modify amount varchar(1024) null comment '金额';
alter table attribute_zfpz
modify describe_info varchar(1024) null comment '说明';

@ -0,0 +1,4 @@
alter table task_record
add finish_time datetime null comment '结束时间' after cancel_time;
alter table task_case_record
add prompt_id varchar(64) null comment '提示词ID' after task_record_id;

@ -0,0 +1,7 @@
alter table model_atomic_result
modify record_split_id text null comment '笔录片段id';
alter table note_record_split
add processed_question text null comment '处理后的回答' after answer;
alter table note_record_split
add processed_answer text null comment '处理后的回答' after processed_question;

@ -0,0 +1,20 @@
create table scoring_model_info
(
id varchar(64) not null comment '主键',
model_name varchar(128) null comment '模型名',
model_desc varchar(2048) null comment '模型说明',
scoring_rules varchar(2048) null comment '模型设置及赋分规则',
create_user_id varchar(64) null comment '创建人id',
create_time datetime null comment '创建时间',
update_user_id varchar(64) null comment '更新人',
update_time datetime null comment '更新时间'
)
comment '赋分模型信息表' collate = utf8mb4_bin;
-- 初始化数据
INSERT INTO scoring_model_info (id, model_name, model_desc, scoring_rules, create_user_id, create_time, update_user_id, update_time) VALUES ('1', '工程类合同诈骗案规则', '针对工程类合同诈骗案高发态势以及办理合同诈骗案存在的诸多问题和困难,宁夏总队在梳理近年来侦办的百余起合同诈骗案基础上,分析了有罪、无罪判决、绝对不起诉、存疑不起诉案件的取证情况、证据证明力、断案依据等,搭建了宁夏工程类合同诈骗案取证智能分析模型。', '模型采取赋分制的方法来综合判定案件证据充分与否分为三个模块第一模块是共性证据指标赋30分第二模块是有罪证据指标赋70分第三模块是无罪证据指标赋70分。采取“共性指标+入罪指标”或“共性指标+出罪指标”的计算方式评定综合得分。综合得分70分以上判定证据较充分司法机关对案件形成一致认定意见的概率较大综合得分50分至70分判定案件事实不清、证据不足司法机关认定意见不一致的概率较大综合得分50分以下判定证据不充分司法机关会作出绝对不起诉或存疑不起诉的决定。', null, current_timestamp(), null, null);
alter table model_index
modify case_type varchar(64) null comment '案件类型';
-- 修改菜单
UPDATE system_menu SET label = '赋分模型', label_code = 'p_scoringModele' WHERE id = '7';

@ -180,6 +180,43 @@
<version>2.4.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83_noneautotype</version>
</dependency>
<!--pdf水印-->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.10</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>4.1.2</version>
</dependency>
</dependencies>
<dependencyManagement>

@ -1,15 +1,28 @@
package com.supervision.common.constant;
public class DifyConstants {
public static final String QA_TYPE_DIFY = "0";
public static final String QA_TYPE_NX_LLM = "1";
public static final String INTENT_TYPE_INDEX_RESULT = "0";
public static final String INTENT_TYPE_CASE_RESULT = "1";
public static final String INTENT_TYPE_CASE_OVERVIEW = "2";
public static final String INTENT_TYPE_CASE_EVIDENCE_GUIDE = "3";
public static final String METHOD_DATASET = "/datasets";
public static final String METHOD_DOCUMENT = "/document";
public static final String METHOD_DOCUMENTS = "/documents";
public static final String METHOD_CREATE_BY_FILE = "/create-by-file";
public static final String METHOD_CREATE_BY_TEXT = "/create_by_text";
public static final String METHOD_CHAT_MESSAGES = "/chat-messages";
public static final String DATASET_INDEXING_TECHNIQUE_HIGH_QUALITY = "high_quality";
public static final String CHAT_RESPONSE_MODE_BLOCKING = "blocking";
public static final String CHAT_RESPONSE_MODE_STREAMING = "streaming";
public static final String INTENT_TYPE_TEXT_CASE_RESULT = "案件分析结果";
public static final String INTENT_TYPE_TEXT_CASE_OVERVIEW = "案件概况";
public static final String INTENT_TYPE_TEXT_CASE_EVIDENCE_GUIDE = "案件证据指引";
}

@ -0,0 +1,23 @@
package com.supervision.common.constant;
public class TaskRecordConstants {
// 任务名称前缀
public static final String TASK_NAME_PREFIX = "任务";
public static final String TASK_NAME_PREFIX_TYPE_ALL_CASE = "全部案件";
public static final String TASK_NAME_PREFIX_TYPE_SPECIFIED_CASE = "指定案件";
public static final String TASK_NAME_PREFIX_TYPE_SPECIFIED_RECORD = "指定笔录";
public static final String TASK_NAME_PREFIX_TYPE_SPECIFIED_EVIDENCE = "指定证据";
// 任务类型
public static final String TASK_TYPE_ALL_CASE = "0";
public static final String TASK_TYPE_SPECIFIED_CASE = "1";
public static final String TASK_TYPE_SPECIFIED_RECORD = "2";
public static final String TASK_TYPE_SPECIFIED_EVIDENCE = "3";
public static final String TASK_TYPE_ONE_CLICK = "4";
// 任务状态
public static final String TASK_STATUS_WAITING = "0";
public static final String TASK_STATUS_PROCESSING = "1";
public static final String TASK_STATUS_CANCELLING = "2";
public static final String TASK_STATUS_CANCELED = "3";
public static final String TASK_STATUS_SUCCESS = "4";
public static final String TASK_STATUS_FAIL = "5";
}

@ -4,4 +4,6 @@ public class XxlJobConstants {
public static final String URL_LOGIN = "/login";
public static final String URL_JOB_INFO_PAGE_LIST = "/jobinfo/pageList";
public static final String URL_JOB_INFO_TRIGGER = "/jobinfo/trigger";
public static final String TASK_NAME_PROMPT_EXTRACT_TASK= "promptExtractTask";
public static final String TASK_NAME_EVIDENCE_ANALYSIS = "evidenceAnalysis";
}

@ -5,7 +5,9 @@ import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.supervision.police.dto.user.UserInfoDTO;
import com.supervision.utils.TokenUtil;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@ -20,16 +22,24 @@ import java.util.Map;
@Slf4j
public class JwtInterceptor implements HandlerInterceptor {
private UserInfoDTO forgeryUser;
public JwtInterceptor() {
}
public void setForgeryUser(UserInfoDTO forgeryUser) {
this.forgeryUser = forgeryUser;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
//请求消息头获取用户ID
String token = request.getHeader("token");
String token = findTokenInRequest(request);
if (StrUtil.isBlank(token)) {
if (forgeryUser != null){
JWT jwt = JWTUtil.parseToken(TokenUtil.creatToken(JSONUtil.toJsonStr(forgeryUser)));
cacheAuth(jwt);
return true;
}
// 如果是swagger来的接口,说明这里是测试的,会伪造一个用户
String referer = request.getHeader("Referer");
if (StrUtil.isNotBlank(referer) && StrUtil.contains(referer, "swagger-ui")) {
@ -41,7 +51,18 @@ public class JwtInterceptor implements HandlerInterceptor {
}
JWT jwt = JWTUtil.parseToken(token);
// 校验token是否过期,如果过期了,需要提示过期重新登录
checkTokenExpire(jwt);
boolean expire = checkTokenExpire(jwt);
if (expire){
throw new BusinessException("用户登录已过期,请重新登录", HttpStatus.UNAUTHORIZED.value());
}
String cookieToken = findTokenInCookie(request.getCookies());
if (!StrUtil.equals(cookieToken, token)){
Cookie tokenCookie = new Cookie("token", token);
tokenCookie.setMaxAge((int) TokenUtil.EXPIRE_TIME);
tokenCookie.setPath("/");
tokenCookie.setAttribute("SameSite", "Lax");
response.addCookie(tokenCookie);
}
cacheAuth(jwt);
return true;
}
@ -55,15 +76,38 @@ public class JwtInterceptor implements HandlerInterceptor {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
private String findTokenInRequest(HttpServletRequest request) {
String token = request.getHeader("token");
if (StrUtil.isEmpty(token)) {
// 尝试从cookie中获取token数据
token = findTokenInCookie(request.getCookies());
}
return token;
}
private void checkTokenExpire(JWT jwt) {
private String findTokenInCookie(Cookie[] cookies) {
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("token")) {
return cookie.getValue();
}
}
}
return null;
}
/**
* token
* @param jwt jwt
* @return true ,false
*/
private boolean checkTokenExpire(JWT jwt) {
Object expireTime = jwt.getPayload("expireTime");
long l = Long.parseLong(String.valueOf(expireTime));
// 校验是否比当前时间大
long currentTimeMillis = System.currentTimeMillis();
if (currentTimeMillis > l) {
throw new BusinessException("用户登录已过期,请重新登录", HttpStatus.UNAUTHORIZED.value());
}
return currentTimeMillis > l;
}

@ -1,14 +1,16 @@
package com.supervision.config;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.supervision.police.dto.user.UserInfoDTO;
import com.supervision.utils.UserUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import java.time.LocalDateTime;
import java.util.Date;
/**
* @author Ray
*/
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {
public MyMetaObjectHandler() {
}
@ -17,11 +19,30 @@ public class MyMetaObjectHandler implements MetaObjectHandler {
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime", LocalDateTime.now(), metaObject);
this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
if (null == this.getFieldValByName("createUserId", metaObject)){
// 只有为空才会继续创建
try {
UserInfoDTO user = UserUtil.getUser();
this.setFieldValByName("createUserId", user.getId(), metaObject);
}catch (Exception e){
log.info("获取用户信息失败");
}
}
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
if (null == this.getFieldValByName("updateUserId", metaObject)){
// 只有为空才会继续创建
try {
UserInfoDTO user = UserUtil.getUser();
this.setFieldValByName("updateUserId", user.getId(), metaObject);
}catch (Exception e){
log.info("获取用户信息失败");
}
}
}
}

@ -2,6 +2,8 @@ package com.supervision.config;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.supervision.police.dto.AuditLogDTO;
import com.supervision.police.service.AuditLogService;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
@ -9,16 +11,17 @@ import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@ -34,22 +37,48 @@ import java.util.Map;
public class RequestLogConfig {
@Autowired
private AuditLogService auditLogService;
@SuppressWarnings("all")
@Around("within(com..*..controller..*) && @within(org.springframework.web.bind.annotation.RestController)")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
long start = System.currentTimeMillis();
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
AuditLogDTO auditLogDTO = new AuditLogDTO(request);
Map<String, Object> requestParams = getRequestParamsByProceedingJoinPoint(proceedingJoinPoint);
auditLogDTO.setRequestParams(JSONUtil.toJsonStr(requestParams));
ThreadCache.AUDIT_LOG.set(auditLogDTO);// 把数据缓存到treadLocal中
// 执行目标方法
Object result = proceedingJoinPoint.proceed();
// 目标方法执行后
RequestInfo requestInfo = new RequestInfo();
requestInfo.setUrl(request.getRequestURL().toString());
requestInfo.setHttpMethod(request.getMethod());
requestInfo.setClassMethod(String.format("%s.%s", proceedingJoinPoint.getSignature().getDeclaringTypeName(),
proceedingJoinPoint.getSignature().getName()));
requestInfo.setRequestParams(getRequestParamsByProceedingJoinPoint(proceedingJoinPoint));
requestInfo.setResult(proceedResult(result));
requestInfo.setRequestParams(requestParams);
Object response = proceedResult(result);
requestInfo.setResult(response);
requestInfo.setTimeCost(System.currentTimeMillis() - start);
log.info("Request Info: {}", JSONUtil.toJsonStr(requestInfo));
try {
auditLogDTO.setRecordType("0");
if (response instanceof String){
auditLogDTO.setResponse((String) response);
}
auditLogDTO.setEndTime(LocalDateTime.now());
auditLogService.saveAuditLog(auditLogDTO);
} catch (Exception e) {
log.error("保存审计信息出错,保存内容:{}",JSONUtil.toJsonStr(auditLogDTO), e);
}
return result;
}
@ -64,6 +93,9 @@ public class RequestLogConfig {
value = value.substring(0, 1024) + "......" + value.substring(value.length() - 1024);
return value;
}
if (StrUtil.isNotEmpty(value)){
return value;
}
return result;
}
@ -81,8 +113,35 @@ public class RequestLogConfig {
requestErrorInfo.setRequestParams(getRequestParamsByJoinPoint(joinPoint));
requestErrorInfo.setException(e);
log.info("Error Request Info : {}", JSONUtil.toJsonStr(requestErrorInfo));
AuditLogDTO auditLogDTO = ThreadCache.AUDIT_LOG.get();
if (null != auditLogDTO){
try {
auditLogDTO.setEndTime(LocalDateTime.now());
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
auditLogDTO.setExceptionDesc(sw.toString());
auditLogDTO.setRecordType("1");
auditLogService.saveAuditLog(auditLogDTO);
} catch (Exception ex) {
log.warn("保存审计信息出错,保存内容:{}",JSONUtil.toJsonStr(auditLogDTO), ex);
}
}
}
@After(value = "@within(org.springframework.web.bind.annotation.RestController)")
public void doAfter(JoinPoint joinPoint) {
// 清理线程变量
ThreadCache.AUDIT_LOG.remove();
}
/**
*
*
@ -125,13 +184,13 @@ public class RequestLogConfig {
MultipartFile file = (MultipartFile) value;
//获取文件名
value = file.getOriginalFilename();
} else if (value instanceof String) {
} /*else if (value instanceof String) {
// 如果参数很长,就对参数进行修剪
String temp = (String) value;
if (!ObjectUtils.isEmpty(temp) && temp.length() > 1024) {
value = temp.substring(0, 10) + "......" + temp.substring(temp.length() - 10);
}
}
}*/
requestParams.put(paramNames[i], value);
}

@ -10,6 +10,7 @@
*/
package com.supervision.config;
import com.supervision.police.dto.AuditLogDTO;
/**
* <>
@ -27,4 +28,7 @@ public class ThreadCache {
public static final ThreadLocal<String> USER = new ThreadLocal<>();
public static final ThreadLocal<AuditLogDTO> AUDIT_LOG = new ThreadLocal<>();
}

@ -1,6 +1,10 @@
package com.supervision.config;
import cn.hutool.core.util.StrUtil;
import com.supervision.police.dto.user.UserInfoDTO;
import com.supervision.police.service.SystemUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
@ -8,16 +12,31 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {
private final Environment environment;
private final SystemUserService systemUserService;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 添加权限拦截器
registry.addInterceptor(new JwtInterceptor())
JwtInterceptor interceptor = new JwtInterceptor();
// ***切记**** 此属性仅可以通过idea设置环境变量千万不要写入配置文件中.....
String userAccount = environment.getProperty("fu-hsi-config.local.user.forgery");
if (StrUtil.isNotEmpty(userAccount)){
log.info("已配置本地模拟用户:{}",userAccount);
UserInfoDTO userInfo = systemUserService.getUserInfo(userAccount);
if (null == userInfo){
log.warn("本地模拟用户不存在:{}",userAccount);
}else {
interceptor.setForgeryUser(userInfo);
}
}
registry.addInterceptor(interceptor)
.addPathPatterns("/**")
.excludePathPatterns(ignorePathPatterns());
}
@ -27,7 +46,7 @@ public class WebConfig implements WebMvcConfigurer {
paths.add("/error");
paths.add("/favicon.ico");
paths.add("/user/login");
paths.add("/minio/downloadFile");
// paths.add("/minio/downloadFile");
paths.add("/minio/uploadFile");
paths.add("/user/changePassWord");
paths.add("/fileManage/downloadFile");

@ -1,22 +1,47 @@
package com.supervision.job;
import com.supervision.police.service.CaseEvidenceService;
import com.alibaba.fastjson.JSON;
import com.supervision.common.constant.XxlJobConstants;
import com.supervision.constant.CaseAnalysisStatusEnum;
import com.supervision.police.domain.ModelCase;
import com.supervision.police.domain.NotePrompt;
import com.supervision.police.domain.TaskCaseRecord;
import com.supervision.police.domain.TaskRecord;
import com.supervision.police.service.*;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import java.util.List;
import java.util.Map;
import static com.supervision.common.constant.NotePromptConstants.TYPE_GRAPH_REASONING;
import static com.supervision.common.constant.NotePromptConstants.TYPE_STRUCTURAL_REASONING;
import static com.supervision.common.constant.TaskRecordConstants.*;
import static com.supervision.common.constant.XxlJobConstants.TASK_NAME_PROMPT_EXTRACT_TASK;
@Slf4j
@Component
@RequiredArgsConstructor
public class XxlJobTask {
@Autowired
private CaseEvidenceService caseEvidenceService;
private final CaseEvidenceService caseEvidenceService;
private final TaskRecordService taskRecordService;
private final TaskCaseRecordService taskCaseRecordService;
private final NotePromptService notePromptService;
private final ModelCaseService modelCaseService;
/**
*
*/
@XxlJob("evidenceAnalysis")
@XxlJob(XxlJobConstants.TASK_NAME_EVIDENCE_ANALYSIS)
public void evidenceAnalysis() {
String param = XxlJobHelper.getJobParam();
log.info("【证据解析】任务开始。ID: 【{}】", param);
@ -28,4 +53,103 @@ public class XxlJobTask {
log.info("任务执行完成");
}
}
/**
*
*/
@XxlJob(TASK_NAME_PROMPT_EXTRACT_TASK)
public void promptExtractTask() {
String jobParam = XxlJobHelper.getJobParam();
log.info("【提取任务】任务开始。参数: {}", jobParam);
StopWatch stopWatch = new StopWatch(TASK_NAME_PROMPT_EXTRACT_TASK + " stopwatch");
stopWatch.start("Data preparation and task status check");
Map<String, String> map = JSON.parseObject(XxlJobHelper.getJobParam(), Map.class);
String taskId = map.get("taskId");
String caseId = map.get("caseId");
String promptId = map.get("promptId");
String executeId = map.get("executeId");
try {
NotePrompt prompt = notePromptService.getBaseMapper().selectById(promptId);
boolean executable = true;
TaskRecord taskRecord = taskRecordService.getById(taskId);
switch (taskRecord.getStatus()) {
case TASK_STATUS_WAITING:
log.info("任务状态为等待中任务状态更新为处理中任务ID: 【{}】", taskId);
taskRecord.setStatus(TASK_STATUS_PROCESSING);
taskRecordService.updateById(taskRecord);
break;
case TASK_STATUS_CANCELLING:
log.info("任务状态为取消中任务状态更新为已取消任务ID: 【{}】", taskId);
taskRecord.setStatus(TASK_STATUS_CANCELED);
taskRecordService.updateById(taskRecord);
executable = false;
break;
case TASK_STATUS_CANCELED:
log.info("任务状态为已取消任务不可执行任务ID: 【{}】", taskId);
taskCaseRecordService.updateStatus(taskId, List.of(TASK_STATUS_WAITING, TASK_STATUS_PROCESSING), TASK_STATUS_CANCELED);
executable = false;
break;
case TASK_STATUS_FAIL:
log.info("任务状态为失败任务不可执行任务ID: 【{}】", taskId);
executable = false;
break;
default:
break;
}
stopWatch.stop();
if (executable) {
stopWatch.start("Model case analysis status check");
this.modelCaseAnalyzingStatusCheck(caseId);
TaskCaseRecord taskCaseRecord = taskCaseRecordService.lambdaQuery().eq(TaskCaseRecord::getCaseId, caseId).eq(TaskCaseRecord::getTaskRecordId, taskId).eq(TaskCaseRecord::getPromptId, promptId).one();
if (TASK_STATUS_WAITING.equals(taskCaseRecord.getStatus())) {
log.info("任务状态为等待中任务状态更新为处理中任务案件ID: 【{}】", taskCaseRecord.getId());
taskCaseRecord.setStatus(TASK_STATUS_PROCESSING);
taskCaseRecordService.updateById(taskCaseRecord);
}
stopWatch.stop();
stopWatch.start("Extract task execution");
switch (prompt.getType()) {
case TYPE_GRAPH_REASONING:
log.info("【图推理】任务开始。任务ID: 【{}】", taskId);
taskRecordService.graphExtract(prompt, caseId, executeId);
break;
case TYPE_STRUCTURAL_REASONING:
log.info("【结构推理】任务开始。任务ID: 【{}】", taskId);
taskRecordService.structureExtract(executeId);
break;
default:
log.error("未知的任务类型");
break;
}
stopWatch.stop();
stopWatch.start("Complete task");
taskRecordService.completeTask(taskId, map.get("executeId"),promptId, true);
stopWatch.stop();
}
} catch (Exception e) {
stopWatch.stop();
log.error("任务执行失败Task ID:{}", taskId, e);
taskRecordService.completeTask(map.get("taskId"), map.get("executeId"), promptId,false);
} finally {
log.info("【提取任务】任务结束。任务ID: 【{}】。耗时:{}", taskId, stopWatch.prettyPrint());
}
}
/**
*
* 552
*/
private void modelCaseAnalyzingStatusCheck(String caseId) throws InterruptedException {
ModelCase modelCase = modelCaseService.getById(caseId);
int count = 0;
while (CaseAnalysisStatusEnum.ANALYZING.getCode() == modelCase.getCaseAnalysisStatus() && count < 24) {
Thread.sleep(5000);
modelCase = modelCaseService.getById(caseId);
count++;
if (count == 24) {
log.error("案件模型分析状态检查超时默认继续执行提取任务。案件ID: 【{}】", caseId);
}
}
}
}

@ -1,6 +1,7 @@
package com.supervision.minio.client;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.supervision.minio.exception.SysObsException;
import io.minio.*;
import io.minio.errors.MinioException;
@ -87,7 +88,9 @@ public class MinioTemplate {
response.setHeader("Content-Disposition", "inline;filename=" + fileName);
response.setCharacterEncoding("UTF-8");
response.setContentLengthLong(statObjectResponse.size());
response.setContentType(statObjectResponse.contentType());
if (StrUtil.isEmpty(response.getContentType())){
response.setContentType(statObjectResponse.contentType());
}
IoUtil.copy(inputStream, response.getOutputStream());
inputStream.close();

@ -23,8 +23,13 @@ public class MinioController {
}
@GetMapping("/downloadFile")
public void downloadFile(@RequestParam String fileId, HttpServletResponse response) {
minioService.downloadFile(fileId, response);
public void downloadFile(@RequestParam("fileId") String fileId,@RequestParam(value = "printWaterMarket",defaultValue = "false") boolean printWaterMarket,
@RequestParam(value = "download",defaultValue = "false") boolean download,HttpServletResponse response) {
if (download){
response.setContentType("application/octet-stream");
}
minioService.downloadFile(fileId, printWaterMarket,response);
}
@PostMapping("/delFile")

@ -15,7 +15,9 @@ public interface MinioService {
String uploadFile(MultipartFile file, boolean temp) throws IOException;
void downloadFile(String fileId, HttpServletResponse response);
void downloadFile(String fileId, boolean printWaterMarket, HttpServletResponse response);
void downloadFileWithWatermark(String fileId, String fileType, String waterMarkName, HttpServletResponse response);
R<?> delFile(String fileId);

@ -1,23 +1,32 @@
package com.supervision.minio.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.itextpdf.text.DocumentException;
import com.supervision.common.domain.R;
import com.supervision.common.utils.StringUtils;
import com.supervision.minio.client.MinioTemplate;
import com.supervision.minio.domain.MinioFile;
import com.supervision.minio.mapper.MinioFileMapper;
import com.supervision.minio.service.MinioService;
import com.supervision.utils.UserUtil;
import com.supervision.utils.WatermarkUtil;
import io.minio.StatObjectResponse;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
@Slf4j
@Service
@RequiredArgsConstructor
public class MinioServiceImpl implements MinioService {
@ -29,6 +38,9 @@ public class MinioServiceImpl implements MinioService {
private final MinioFileMapper minioFileMapper;
@Value("${fu-hsi-config.watermark.template}")
private String watermarkTemplate;
@Override
public String uploadFile(MultipartFile file) throws IOException {
return uploadFile(file, false);
@ -57,10 +69,58 @@ public class MinioServiceImpl implements MinioService {
}
@Override
public void downloadFile(String fileId, HttpServletResponse response) {
public void downloadFile(String fileId,boolean printWaterMarket, HttpServletResponse response) {
MinioFile minioFile = minioFileMapper.selectById(fileId);
Assert.notNull(minioFile, "文件不存在");
String fileType = minioFile.getFileType();
minioTemplate.getObject(bucketName, fileId, fileType, response);
if (printWaterMarket){
String waterMarkName = StrUtil.format(watermarkTemplate, Map.of("userName", UserUtil.getUser().getUserName()));
this.downloadFileWithWatermark(fileId, fileType, waterMarkName, response);
}else {
minioTemplate.getObject(bucketName, minioFile.getId(),fileType, response);
}
}
@Override
public void downloadFileWithWatermark(String fileId, String fileType, String waterMarkName, HttpServletResponse response) {
try {
InputStream inputStream = minioTemplate.getObjectInputStream(bucketName,fileId);
StatObjectResponse statObjectResponse = minioTemplate.statObject(bucketName, fileId);
String fileName = fileId + "." + fileType;
response.setHeader("Content-Disposition", "inline;filename=" + fileName);
response.setCharacterEncoding("UTF-8");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if (StrUtil.equalsIgnoreCase("pdf", fileType)){
WatermarkUtil.pdfByText(inputStream, baos, waterMarkName, Map.of());
response.setContentLengthLong(baos.size());
if (StrUtil.isEmpty(response.getContentType())){
response.setContentType(statObjectResponse.contentType());
}
response.getOutputStream().write(baos.toByteArray());
}else if (StrUtil.equalsAnyIgnoreCase(fileType,"jpg", "jpeg", "png","bmp")){
WatermarkUtil.imageByText(waterMarkName, inputStream, baos, Map.of("formatName", fileType));
if (StrUtil.isEmpty(response.getContentType())){
response.setContentType(statObjectResponse.contentType());
}
response.setContentLengthLong(baos.size());
response.getOutputStream().write(baos.toByteArray());
}else {
response.setContentLengthLong(statObjectResponse.size());
if (StrUtil.isEmpty(response.getContentType())){
response.setContentType(statObjectResponse.contentType());
}
IoUtil.copy(inputStream, response.getOutputStream());
}
baos.close();
inputStream.close();
}catch (IOException | DocumentException e){
log.error("文件下载失败", e);
}
}
@Override

@ -5,6 +5,7 @@ import com.supervision.common.domain.R;
import com.supervision.neo4j.domain.CaseNode;
import com.supervision.neo4j.domain.Rel;
import com.supervision.neo4j.dto.WebRelDTO;
import com.supervision.police.domain.TripleInfo;
import org.neo4j.driver.Record;
import com.supervision.police.vo.GraphReqVO;
@ -67,4 +68,8 @@ public interface Neo4jService {
void mockTestGraph(String path, String sheetName, String recordId, String recordSplitId, String caseId);
List<Record> executeCypher(String cypher, Map<String, Object> parameters);
TripleInfo saveTripleInfo(TripleInfo tripleInfo);
void deleteTripleInfo(TripleInfo tripleInfo);
}

@ -1,6 +1,7 @@
package com.supervision.neo4j.service.impl;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
@ -10,6 +11,7 @@ import com.supervision.neo4j.domain.Rel;
import com.supervision.neo4j.dto.WebRelDTO;
import com.supervision.neo4j.service.Neo4jService;
import com.supervision.neo4j.utils.Neo4jUtils;
import com.supervision.police.domain.TripleInfo;
import com.supervision.police.vo.GraphReqVO;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@ -98,6 +100,7 @@ public class Neo4jServiceImpl implements Neo4jService {
run.next();
}
} catch (Exception e) {
//如果报错,说明存在未删除的关系,是合理的
log.error(e.getMessage(), e);
}
}
@ -107,13 +110,14 @@ public class Neo4jServiceImpl implements Neo4jService {
try {
Session session = driver.session();
StringBuilder cql = new StringBuilder();
cql.append("MATCH (n) WHERE n.id = ").append(id).append(" AND NOT (n)--() DELETE n");
cql.append("MATCH (n) WHERE id(n) = ").append(id).append(" AND NOT (n)--() DELETE n");
log.info(cql.toString());
Result run = session.run(cql.toString());
while (run.hasNext()) {
run.next();
}
} catch (Exception e) {
//如果报错,说明存在未删除的关系,是合理的
log.error(e.getMessage(), e);
}
}
@ -631,6 +635,69 @@ public class Neo4jServiceImpl implements Neo4jService {
@Override
public List<Record> executeCypher(String cypher, Map<String, Object> parameters) {
return this.driver.session().run(cypher, parameters).list();
try (Session session = this.driver.session()) {
return session.run(cypher, parameters).list();
}
}
@Override
public TripleInfo saveTripleInfo(TripleInfo tripleInfo) {
//开始节点
String start = tripleInfo.getStartNode();
// 首先看是否已经存在了,如果已经存在了,就不添加了
CaseNode startNode = this.findOneByName(tripleInfo.getCaseId(), tripleInfo.getRecordId(), tripleInfo.getStartNodeType(), start, "1");
if (startNode == null) {
startNode = new CaseNode(start, tripleInfo.getStartNodeType(), tripleInfo.getRecordSplitId(), tripleInfo.getRecordId(), tripleInfo.getCaseId(), "1");
CaseNode save = this.save(startNode);
startNode.setId(save.getId());
}
//结束节点
String end = tripleInfo.getEndNode();
CaseNode endNode = this.findOneByName(tripleInfo.getCaseId(), tripleInfo.getRecordId(), tripleInfo.getEndNodeType(), end, "1");
if (endNode == null) {
endNode = new CaseNode(end, tripleInfo.getEndNodeType(), tripleInfo.getRecordSplitId(), tripleInfo.getRecordId(), tripleInfo.getCaseId(), "1");
CaseNode save = this.save(endNode);
endNode.setId(save.getId());
}
//关系
Rel rel = new Rel(startNode.getId(), tripleInfo.getRelation(), endNode.getId());
Rel relation = this.findRelation(rel);
if (relation == null) {
relation = this.saveRelation(rel);
}
tripleInfo.setStartNodeGraphId(startNode.getId());
tripleInfo.setRelGraphId(relation.getId());
tripleInfo.setEndNodeGraphId(endNode.getId());
return tripleInfo;
}
@Override
public void deleteTripleInfo(TripleInfo tripleInfo) {
if (ObjectUtil.isNotEmpty(tripleInfo.getRelGraphId())) {
// 先移除关系
try {
this.deleteRel(tripleInfo.getRelGraphId());
} catch (Exception e) {
log.error("删除关系失败:{}", tripleInfo.getRelation(), e);
return;
}
}
if (ObjectUtil.isNotEmpty(tripleInfo.getEndNodeGraphId())) {
// 再移除尾节点
try {
this.deleteNoRelationNode(tripleInfo.getEndNodeGraphId());
} catch (Exception e) {
log.error("删除尾节点失败:{}", tripleInfo.getEndNode(), e);
return;
}
}
if (ObjectUtil.isNotEmpty(tripleInfo.getStartNodeGraphId())) {
// 尝试删除头节点(只有头节点不存在任何关系的时候才进行删除)
try {
this.deleteNoRelationNode(tripleInfo.getStartNodeGraphId());
} catch (Exception e) {
log.error("删除头节点失败:{}", tripleInfo.getStartNode(), e);
}
}
}
}

@ -2,6 +2,7 @@ package com.supervision.police.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.itextpdf.text.DocumentException;
import com.supervision.common.domain.R;
import com.supervision.police.domain.EvidenceDirectory;
import com.supervision.police.dto.*;
@ -12,9 +13,12 @@ import com.supervision.police.vo.VerifyEvidenceReqVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
@ -186,11 +190,16 @@ public class CaseEvidenceController {
return R.ok(directoryName);
}
@Operation(summary = "查询证据详情-结果以树的方式展示")
@Operation(summary = "迁移证据信息")
@GetMapping("/fresh")
public R<String> generateDirectoryName() {
caseEvidenceService.refreshCaseEvidence();
return R.ok("success");
}
@GetMapping("/downloadEvidence")
public void downloadEvidence(@RequestParam String evidenceId, HttpServletResponse response) throws DocumentException, IOException {
caseEvidenceService.downloadEvidence(evidenceId, response);
}
}

@ -1,16 +1,19 @@
package com.supervision.police.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.common.domain.R;
import com.supervision.police.service.ChatService;
import com.supervision.police.vo.ChatReqVO;
import com.supervision.police.vo.ChatResVO;
import com.supervision.police.vo.ConversationResVo;
import com.supervision.utils.UserUtil;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Slf4j
@RestController
@ -23,9 +26,37 @@ public class ChatController {
@PostMapping("/chat")
public R<ChatResVO> chat(@RequestBody ChatReqVO chatReqVO) {
return chatService.chatNew(chatReqVO);
}
/**
*
* @param pageNum
* @param pageSize
* @return
*/
@GetMapping("/conversation/list")
public R<IPage<ConversationResVo>> queryUserConversationList(@RequestParam(defaultValue = "1") @Parameter(name = "pageNum",description = "页码") Integer pageNum,
@RequestParam(defaultValue = "10") @Parameter(name = "pageSize",description = "每页数量") Integer pageSize){
ChatResVO chatResVO = chatService.chat(chatReqVO);
return R.ok(chatResVO);
IPage<ConversationResVo> conversationResVoIPage = chatService.queryUserConversationList(UserUtil.getUser().getId(),pageNum, pageSize);
return R.ok(conversationResVoIPage);
}
@GetMapping("/conversation/infoList")
public R<IPage<ChatResVO>> queryConversationInfoList(@RequestParam String conversationId,
@RequestParam(defaultValue = "1") @Parameter(name = "pageNum",description = "页码") Integer pageNum,
@RequestParam(defaultValue = "10") @Parameter(name = "pageSize",description = "每页数量") Integer pageSize){
IPage<ChatResVO> chatResVOIPage = chatService.queryConversationInfoList(conversationId, pageNum, pageSize);
return R.ok(chatResVOIPage);
}
@PostMapping("/conversation/delete")
public R<Boolean> deleteConversation(@RequestBody List<String> conversationIdList) {
chatService.deleteConversation(conversationIdList);
return R.ok(true);
}
}

@ -144,4 +144,11 @@ public class ModelCaseController {
return R.ok(indexDetail);
}
@GetMapping("/migrateRecordKnowledgeBase")
public R<String> initCaseKnowledgeBase() {
modelCaseService.migrateRecordKnowledgeBase();
return R.ok("success");
}
}

@ -10,7 +10,6 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
@RestController
@ -25,7 +24,7 @@ public class ModelController {
@PostMapping("/analyseCase")
@Operation(summary = "分析指标")
public R<?> analyseCase(@RequestBody AnalyseCaseDTO analyseCaseDTO) {
return modelService.analyseCase(analyseCaseDTO);
return modelService.analyseCaseWrapper(analyseCaseDTO);
}
@GetMapping("/caseScoreDetail")

@ -3,6 +3,7 @@ package com.supervision.police.controller;
import com.supervision.common.domain.R;
import com.supervision.police.domain.ModelAtomicIndex;
import com.supervision.police.domain.ModelIndex;
import com.supervision.police.dto.AtomicIndexUsedDTO;
import com.supervision.police.dto.CaseAtomicIndexDTO;
import com.supervision.police.dto.CaseAtomicResultWrapper;
import com.supervision.police.vo.GraphDebugReqVO;
@ -106,6 +107,14 @@ public class ModelIndexController {
}
@Operation(summary = "查询原子指标被使用情况")
@GetMapping("/atomic/used")
public R<List<AtomicIndexUsedDTO>> atomicUsed(@RequestParam String atomicIndexId) {
List<AtomicIndexUsedDTO> atomicIndexUsedDTOS = modelIndexService.atomicUsed(atomicIndexId);
return R.ok(atomicIndexUsedDTOS);
}
/**
*
* @return

@ -0,0 +1,46 @@
package com.supervision.police.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.common.domain.R;
import com.supervision.police.dto.CaseProcessDTO;
import com.supervision.police.dto.TaskInfoDTO;
import com.supervision.police.service.MroService;
import com.supervision.police.vo.CaseProcessReqVO;
import com.supervision.police.vo.TaskInfoReqVO;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @ClassName MroController
* @Description MaintenanceRepair and Operations
* @Date 2024/12/23 15:09
**/
@RestController
@RequestMapping("/mro")
@RequiredArgsConstructor
public class MroController {
private final MroService mroService;
@Operation(summary = "查询案件列表")
@PostMapping("/caseList")
public R<IPage<CaseProcessDTO>> queryCaseList(@RequestBody CaseProcessReqVO caseProcessReqVO,
@RequestParam(required = false, defaultValue = "1") Integer page,
@RequestParam(required = false, defaultValue = "20") Integer size) {
IPage<CaseProcessDTO> list = mroService.queryCaseList(caseProcessReqVO, page, size);
return R.ok(list);
}
@Operation(summary = "案件一键分析")
@PostMapping("/caseAnalysis")
public R<String> analysisCase(@RequestBody List<String> caseIds) {
mroService.analysisCase(caseIds);
return R.ok();
}
}

@ -0,0 +1,57 @@
package com.supervision.police.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.common.domain.R;
import com.supervision.police.domain.ScoringModelInfo;
import com.supervision.police.service.ScoringModelInfoService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
@Tag(name = "赋分模型信息")
@RestController
@RequestMapping("/scoringModel")
@RequiredArgsConstructor
public class ScoringModelInfoController {
private final ScoringModelInfoService scoringModelInfoService;
@Operation(summary = "保存赋分模型")
@PostMapping("/save")
public R<String> saveScoringModel(@RequestBody ScoringModelInfo modelInfo) {
String roleId = scoringModelInfoService.saveScoringModel(modelInfo);
return R.ok(roleId);
}
@Operation(summary = "删除赋分模型")
@PostMapping("/delete")
public R<?> deleteScoringModel(@RequestBody ScoringModelInfo modelInfo) {
scoringModelInfoService.deleteScoringModel(modelInfo.getId());
return R.ok();
}
@Operation(summary = "修改赋分模型")
@PostMapping("/update")
public R<?> updateScoringModel(@RequestBody ScoringModelInfo modelInfo) {
scoringModelInfoService.updateScoringModel(modelInfo);
return R.ok();
}
@Operation(summary = "复制赋分模型")
@PostMapping("/copy")
public R<String> copyScoringModel(@RequestBody ScoringModelInfo modelInfo) {
String modelId = scoringModelInfoService.copyScoringModel(modelInfo);
return R.ok(modelId);
}
@Operation(summary = "查看赋分模型列表")
@GetMapping("/pageList")
public R<IPage<ScoringModelInfo>> pageList(@RequestParam(required = false) @Parameter(name = "modelName",description = "模型名称") String modelName,
@RequestParam(defaultValue = "1") @Parameter(name = "pageNum",description = "页码") Integer pageNum,
@RequestParam(defaultValue = "99999") @Parameter(name = "pageSize",description = "每页数量") Integer pageSize) {
IPage<ScoringModelInfo> page = scoringModelInfoService.pageList(modelName,pageNum, pageSize);
return R.ok(page);
}
}

@ -0,0 +1,64 @@
package com.supervision.police.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.common.domain.R;
import com.supervision.police.dto.TaskInfoDTO;
import com.supervision.police.dto.taskRecord.TaskRecordVo;
import com.supervision.police.service.TaskCaseRecordService;
import com.supervision.police.service.TaskRecordService;
import com.supervision.police.vo.TaskInfoReqVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Tag(name = "任务管理")
@RestController
@RequestMapping("/taskRecord")
@RequiredArgsConstructor
public class TaskRecordController {
private final TaskRecordService taskRecordService;
@Operation(summary = "执行提示词提取任务")
@PostMapping("/executePromptExtractTask")
public R<?> executePromptExtractTask(@RequestBody TaskRecordVo taskRecordVo) {
taskRecordService.executePromptExtractTask(taskRecordVo);
return R.ok();
}
@Operation(summary = "一键提取任务")
@PostMapping("/executeAllPromptExtractTask")
public R<?> executeAllPromptExtractTask() {
taskRecordService.executeAllPromptExtractTask();
return R.ok();
}
@Operation(summary = "查询任务列表")
@PostMapping("/taskList")
public R<IPage<TaskInfoDTO>> queryTaskList(@RequestBody TaskInfoReqVO taskInfoReqVO,
@RequestParam(required = false, defaultValue = "1") Integer page,
@RequestParam(required = false, defaultValue = "20") Integer size) {
IPage<TaskInfoDTO> iPage = taskRecordService.queryTaskList(taskInfoReqVO, page, size);
return R.ok(iPage);
}
@Operation(summary = "取消任务")
@PostMapping("/cancelTask")
public R<Boolean> cancelTask(@RequestBody List<String> taskIds) {
taskRecordService.cancelTask(taskIds);
return R.ok(true);
}
@Operation(summary = "删除任务")
@PostMapping("/deleteTask")
public R<Boolean> deleteTask(@RequestBody List<String> taskIds) {
taskRecordService.deleteTask(taskIds);
return R.ok(true);
}
}

@ -9,7 +9,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
*
*
* @TableName attribute_gwzs
*/
@TableName(value ="attribute_gwzs")

@ -9,7 +9,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
*
*
* @TableName attribute_xmht
*/
@TableName(value ="attribute_xmht")

@ -0,0 +1,96 @@
package com.supervision.police.domain;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Data;
/**
*
* @TableName audit_log
*/
@TableName(value ="audit_log")
@Data
public class AuditLog implements Serializable {
/**
* id
*/
@TableId
private String id;
/**
* 0-1-
*/
private String recordType;
/**
* id
*/
private String userId;
/**
*
*/
private String userName;
/**
* ip
*/
private String ip;
/**
* GET POST PUT DELETE
*/
private String method;
/**
* url
*/
private String url;
/**
*
*/
private String requestParams;
/**
* ms
*/
private Long costTime;
/**
*
*/
private String response;
/**
*
*/
private String exceptionDesc;
/**
*
*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
*
*/
private String createUserId;
/**
*
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
/**
* id
*/
private String updateUserId;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

@ -0,0 +1,56 @@
package com.supervision.police.domain;
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 java.io.Serializable;
import java.util.Date;
import lombok.Data;
/**
*
* @TableName conversation
*/
@TableName(value ="conversation")
@Data
public class Conversation implements Serializable {
/**
*
*/
@TableId
private String id;
/**
*
*/
private String title;
/**
*
*/
private String type;
/**
* ID
*/
private String caseId;
/**
* ID
*/
private String userId;
/**
*
*/
private Date createTime;
/**
*
*/
private Date updateTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

@ -0,0 +1,115 @@
package com.supervision.police.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.supervision.police.handler.KnowledgeBaseSegmentVOTypeHandler;
import com.supervision.police.vo.dify.KnowledgeBaseSegmentVO;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
*
*/
@TableName(value = "conversation_qa", autoResultMap = true)
@Data
public class ConversationQa implements Serializable {
/**
*
*/
@TableId
private String id;
/**
* 0DIFY 1NX_LLM
*/
private String type;
/**
* 0 1 2 3
*/
private String intentType;
/**
*
*/
private int dialogCount;
/**
*
*/
private String question;
/**
*
*/
private String completeQuestion;
/**
*
*/
private Date questionTime;
/**
*
*/
private String answer;
/**
*
*/
private String answerMap;
/**
*
*/
@TableField(typeHandler = KnowledgeBaseSegmentVOTypeHandler.class)
private List<KnowledgeBaseSegmentVO> segmentList;
/**
*
*/
private String completeAnswer;
/**
*
*/
private Date answerTime;
/**
*
*/
private String timeInterval;
/**
*
*/
private String userId;
/**
*
*/
private String caseId;
/**
*
*/
private String conversationId;
/**
*
*/
private Date createTime;
/**
*
*/
private Date updateTime;
@TableField(exist = false)
private static final long
VersionUID = 1L;
}

@ -8,6 +8,7 @@ import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
import static com.baomidou.mybatisplus.annotation.IdType.INPUT;
/**
*
@ -20,7 +21,7 @@ public class EvidenceCategory implements Serializable {
/**
* id
*/
@TableId
@TableId(type = INPUT)
private String id;
/**

@ -35,8 +35,9 @@ public class ModelAtomicIndex implements Serializable {
private String remark;
/**
*
* case_type
*/
@Deprecated(since = "dev_2.3 time:2024-07-05")
private String caseType;

@ -3,10 +3,7 @@ package com.supervision.police.domain;
import java.time.LocalDateTime;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
@ -26,6 +23,8 @@ public class ModelCase implements Serializable {
*/
@TableId
private String id;
private String knowledgeBaseId;
/**
*
@ -93,6 +92,7 @@ public class ModelCase implements Serializable {
/**
*
*/
@TableField(updateStrategy = FieldStrategy.ALWAYS, insertStrategy = FieldStrategy.ALWAYS)
private String identifyResult;
@TableField(exist=false)
private String identifyResultName;
@ -100,6 +100,7 @@ public class ModelCase implements Serializable {
/**
*
*/
@TableField(updateStrategy = FieldStrategy.ALWAYS, insertStrategy = FieldStrategy.ALWAYS)
private Integer totalScore;
/**
@ -120,6 +121,7 @@ public class ModelCase implements Serializable {
*
*/
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
@TableField(updateStrategy = FieldStrategy.ALWAYS, insertStrategy = FieldStrategy.ALWAYS)
private LocalDateTime caseAnalysisSuccessTime;
/**

@ -1,5 +1,7 @@
package com.supervision.police.domain;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
@ -131,4 +133,29 @@ public class NotePrompt implements Serializable {
@TableField(exist = false)
private static final long serialVersionUID = 1L;
public String findRelationValue(){
return filterValue("relation");
}
public String findHeadEntityValue(){
return filterValue("headEntityType");
}
public String findTailEntityValue(){
return filterValue("tailEntityType");
}
private String filterValue(String templateName){
if (CollUtil.isEmpty(this.tripleList)){
return null;
}
// 匹配出关系的value
TripleInfoDTO tripleInfoDTO1 = this.tripleList.stream()
.filter(tripleInfoDTO -> StrUtil.equals(tripleInfoDTO.getTemplateName(), templateName)).findFirst().orElse(null);
if (tripleInfoDTO1 == null){
return null;
}
return tripleInfoDTO1.getValue();
}
}

@ -1,5 +1,6 @@
package com.supervision.police.domain;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
@ -33,6 +34,11 @@ public class NoteRecordSplit implements Serializable {
*/
private String personName;
/**
* ID
*/
private String noteFileId;
/**
*
*/
@ -48,6 +54,16 @@ public class NoteRecordSplit implements Serializable {
*/
private String answer;
/**
*
*/
private String processedQuestion;
/**
*
*/
private String processedAnswer;
/**
* ()
*/
@ -85,4 +101,11 @@ public class NoteRecordSplit implements Serializable {
@TableField(exist = false)
private static final long serialVersionUID = 1L;
public String getAnswerIfProcessedAbsent() {
return StrUtil.isNotEmpty(this.processedAnswer) ? this.processedAnswer : this.answer;
}
public String getQuestionIfProcessedAbsent() {
return StrUtil.isNotEmpty(this.processedQuestion) ? this.processedQuestion : this.question;
}
}

@ -0,0 +1,68 @@
package com.supervision.police.domain;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serializable;
import java.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
/**
*
* @TableName scoring_model_info
*/
@Data
@TableName(value ="scoring_model_info")
public class ScoringModelInfo implements Serializable {
/**
*
*/
@TableId
private String id;
/**
*
*/
private String modelName;
/**
*
*/
private String modelDesc;
/**
*
*/
private String scoringRules;
/**
* id
*/
private String createUserId;
/**
*
*/
@TableField(fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
/**
*
*/
private String updateUserId;
/**
*
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

@ -0,0 +1,85 @@
package com.supervision.police.domain;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
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.time.LocalDateTime;
/**
* @TableName task_case_record
*/
@TableName(value = "task_case_record")
@Data
public class TaskCaseRecord implements Serializable {
/**
*
*/
@TableId
private String id;
/**
* ID
*/
private String taskRecordId;
/**
* ID
*/
private String caseId;
/**
* ID
*/
private String promptId;
/**
* ID
*/
private String waitingId;
/**
* ID
*/
private String processedId;
/**
* ID
*/
private String exceptionId;
/**
* 0 1 2 3 4 5
*/
private String status;
/**
* ID
*/
private String createUserId;
/**
*
*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* ID
*/
private String updateUserId;
/**
*
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@Serial
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

@ -0,0 +1,95 @@
package com.supervision.police.domain;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
/**
* @author dxy
* @TableName task_record
*/
@TableName(value = "task_record")
@Data
public class TaskRecord implements Serializable {
/**
*
*/
@TableId
private String id;
/**
*
*/
private String name;
/**
* ID
*/
private String promptId;
/**
* ID
*/
private String caseId;
/**
* ID
*/
private String recordId;
/**
* ID
*/
private String evidenceId;
/**
* 0 1 2 3
*/
private String type;
/**
* 0 1 2 3 4 5
*/
private String status;
/**
*
*/
private LocalDateTime cancelTime;
private LocalDateTime finishTime;
/**
* ID
*/
@TableField(fill = FieldFill.INSERT)
private String createUserId;
/**
*
*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* ID
*/
@TableField(fill = FieldFill.UPDATE)
private String updateUserId;
/**
*
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

@ -113,7 +113,6 @@ public class TripleInfo implements Serializable {
public TripleInfo() {
}
// todo
public TripleInfo(String startNode, String endNode, String relation,String caseId, String recordId, String recordSplitId, LocalDateTime createTime, String startNodeType, String endNodeType) {
this.startNode = startNode;
this.endNode = endNode;

@ -66,7 +66,8 @@ public class AtomicIndexDTO {
// 2.指标判断不符合,规则要求符合,返回false
// 3.指标判断符合,规则要求符合,返回true
// 4.指标判断不符合,规则要求不符合,返回true
if (StrUtil.equals(judgeLogic, this.atomicResult)) {
// 按照最新要求,前端显示由“符合/不符合”改为“存在/不存在”故取消和judgeLogic的比较
if (StrUtil.equals("3", this.atomicResult)) {
this.indexResult = "true";
} else {
this.indexResult = "false";

@ -0,0 +1,22 @@
package com.supervision.police.dto;
import lombok.Data;
/**
* 使DTO
*/
@Data
public class AtomicIndexUsedDTO {
private String atomicIndexId;
private String atomicIndexName;
private String indexId;
private String indexName;
private String modelName;
private String modelId;
}

@ -0,0 +1,142 @@
package com.supervision.police.dto;
import cn.hutool.core.util.StrUtil;
import com.supervision.police.domain.AuditLog;
import com.supervision.police.dto.user.UserInfoDTO;
import com.supervision.utils.UserUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
@Slf4j
@Data
public class AuditLogDTO implements Serializable {
/**
* id
*/
private String id;
/**
* 0-1-
*/
private String recordType;
/**
* id
*/
private String userId;
/**
*
*/
private String userName;
/**
* ip
*/
private String ip;
/**
* GET POST PUT DELETE
*/
private String method;
/**
* url
*/
private String url;
/**
*
*/
private String requestParams;
/**
*
*/
private String response;
/**
*
*/
private String exceptionDesc;
/**
*
*/
private LocalDateTime createTime;
/**
*
*/
private String createUserId;
/**
*
*/
private LocalDateTime updateTime;
/**
* id
*/
private String updateUserId;
private LocalDateTime startTime;
private LocalDateTime endTime;
public AuditLogDTO() {
}
public AuditLogDTO(HttpServletRequest request) {
try {
UserInfoDTO user = UserUtil.getUser();
this.userName = user.getUserName();
this.userId = user.getId();
} catch (Exception e) {
log.warn("未获取到用户信息", e);
}
this.url = request.getRequestURI();
this.method = request.getMethod();
if (StrUtil.isNotBlank(request.getHeader("X-Real-IP"))){
this.ip = request.getHeader("X-Real-IP");
}else {
this.ip = request.getRemoteAddr();
}
this.startTime = LocalDateTime.now();
}
public AuditLog toAuditLog(){
AuditLog auditLog = new AuditLog();
auditLog.setId(id);
auditLog.setRecordType(recordType);
auditLog.setUserId(userId);
auditLog.setUserName(userName);
auditLog.setIp(ip);
auditLog.setMethod(method);
auditLog.setUrl(url);
auditLog.setRequestParams(requestParams);
auditLog.setCostTime(this.evaluateCostTime());
auditLog.setResponse(response);
auditLog.setExceptionDesc(exceptionDesc);
auditLog.setCreateTime(createTime);
auditLog.setCreateUserId(createUserId);
auditLog.setUpdateTime(updateTime);
auditLog.setUpdateUserId(updateUserId);
return auditLog;
}
public long evaluateCostTime() {
if (null == this.startTime || null == this.endTime){
return 0;
}
return ChronoUnit.MILLIS.between(this.startTime, this.endTime);
}
}

@ -0,0 +1,53 @@
package com.supervision.police.dto;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.supervision.police.domain.ModelCase;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class CaseProcessDTO {
private String caseId;
private String caseName;
/**
* 0: 1 2 3
*/
private String analysisStatus;
/**
*
*/
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private LocalDateTime analysisSuccessTime;
/**
* 1: 2 3:
*/
private String identifyResult;
/**
* 0 1
*/
private String enableAnalyse;
public CaseProcessDTO() {
}
public CaseProcessDTO(ModelCase modelCase) {
if (null == modelCase){
return;
}
this.caseId = modelCase.getId();
this.caseName = modelCase.getCaseName();
this.analysisStatus = StrUtil.toString(modelCase.getCaseAnalysisStatus());
this.analysisSuccessTime = modelCase.getCaseAnalysisSuccessTime();
this.identifyResult = modelCase.getIdentifyResult();
this.enableAnalyse = modelCase.getCaseAnalysisStatus() == 1 ? "1" : "0";
}
}

@ -7,10 +7,13 @@ import lombok.Data;
public class IndexResultQuery {
@Schema(description = "案件id")
private String caseId;
private String caseId;
@Schema(description = "指标类型")
private String indexType;
private String indexType;
private String caseType;
@Schema(description = "指标名称")
private String indexName;

@ -27,6 +27,9 @@ public class RecordFileDTO {
@Schema(description = "文件大小")
private String fileSize;
@Schema(description = "文件类型")
private String fileType;
@Schema(description = "文件识别状态 -1:未识别 0正在识别 1识别成功 2识别失败")
private String ocrStatus;

@ -0,0 +1,72 @@
package com.supervision.police.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class TaskInfoDTO {
/**
* id
*/
private String taskId;
/**
* id
*/
private String caseId;
/**
*
*/
private String caseName;
/**
*
*/
private String taskName;
private String taskType;
private String promptId;
private String promptName;
/**
*
*/
private String taskStatus;
/**
*
*/
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private LocalDateTime cancelTime;
/**
*
*/
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private LocalDateTime finishTime;
/**
*
*/
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private LocalDateTime createTime;
/**
* id
*/
private String createUserId;
/**
*
*/
private String createUserName;
}

@ -457,9 +457,7 @@ public class CaseScoreDetailBuilder {
new LambdaQueryWrapper<ModelIndexResult>().eq(ModelIndexResult::getCaseId, caseId));
// 3.3 获取原子指标信息
List<ModelAtomicIndex> modelAtomicIndices = modelAtomicIndexMapper.selectList(
new LambdaQueryWrapper<ModelAtomicIndex>().eq(ModelAtomicIndex::getCaseType, modelCase.getCaseType())
.eq(ModelAtomicIndex::getDataStatus, "1"));
List<ModelAtomicIndex> modelAtomicIndices = modelAtomicIndexMapper.listCaseAtomicIndex(null, modelCase.getCaseType(), "1");
// 3.4 获取原子指标结果
List<ModelAtomicResult> modelAtomicResults = modelAtomicResultMapper.selectList(

@ -0,0 +1,12 @@
package com.supervision.police.dto.taskRecord;
import lombok.Data;
@Data
public class TaskRecordVo {
private String caseId;
private String recordId;
private String evidenceId;
private String promptId;
private String type;
}

@ -0,0 +1,32 @@
package com.supervision.police.handler;
import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.supervision.police.dto.NotePromptExtractAttributesDto;
import com.supervision.police.vo.dify.KnowledgeBaseSegmentVO;
import java.util.List;
public class KnowledgeBaseSegmentVOTypeHandler extends AbstractJsonTypeHandler<List<KnowledgeBaseSegmentVO>> {
private static final ObjectMapper objectMapper = new ObjectMapper();
@Override
protected List<KnowledgeBaseSegmentVO> parse(String json) {
try {
return objectMapper.readValue(json, new TypeReference<List<KnowledgeBaseSegmentVO>>() {
});
} catch (Exception e) {
throw new RuntimeException("Failed to parse JSON to List<KnowledgeBaseSegmentVO>", e);
}
}
@Override
protected String toJson(List<KnowledgeBaseSegmentVO> obj) {
try {
return objectMapper.writeValueAsString(obj);
} catch (Exception e) {
throw new RuntimeException("Failed to convert List<KnowledgeBaseSegmentVO> to JSON", e);
}
}
}

@ -0,0 +1,18 @@
package com.supervision.police.mapper;
import com.supervision.police.domain.AuditLog;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author Administrator
* @description audit_log()Mapper
* @createDate 2024-12-09 13:19:15
* @Entity com.supervision.police.domain.AuditLog
*/
public interface AuditLogMapper extends BaseMapper<AuditLog> {
}

@ -0,0 +1,23 @@
package com.supervision.police.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.supervision.police.domain.Conversation;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.supervision.police.vo.ConversationResVo;
import java.util.Date;
/**
* @author yaxin
* @description conversation()Mapper
* @createDate 2024-11-25 13:43:52
* @Entity com.supervision.police.domain.Conversation
*/
public interface ConversationMapper extends BaseMapper<Conversation> {
IPage<ConversationResVo> queryUserConversationList(String userId, Date startTime,Date endTime, Page<ConversationResVo> page);
}

@ -0,0 +1,18 @@
package com.supervision.police.mapper;
import com.supervision.police.domain.ConversationQa;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author yaxin
* @description conversation_qaMapper
* @createDate 2024-11-22 11:37:02
* @Entity com.supervision.police.domain.ConversationQa
*/
public interface ConversationQaMapper extends BaseMapper<ConversationQa> {
}

@ -3,6 +3,7 @@ package com.supervision.police.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.police.domain.ModelAtomicIndex;
import com.supervision.police.dto.AtomicIndexUsedDTO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@ -22,5 +23,7 @@ public interface ModelAtomicIndexMapper extends BaseMapper<ModelAtomicIndex> {
List<ModelAtomicIndex> listCaseAtomicIndex(@Param("indexIdList") List<String> indexIdList,
@Param("caseType") String caseType,
@Param("indexSource") String indexSource);
List<AtomicIndexUsedDTO> atomicUsed(@Param("atomicIndexId") String atomicIndexId);
}

@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.supervision.police.domain.ModelAtomicResult;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* (ModelAtomicResult)访
*
@ -17,5 +19,7 @@ public interface ModelAtomicResultMapper extends BaseMapper<ModelAtomicResult> {
@Param("indexId") String indexId,
@Param("atomicId") String atomicId);
List<ModelAtomicResult> queryByCaseIdForUpdate(@Param("caseId") String caseId);
}

@ -0,0 +1,18 @@
package com.supervision.police.mapper;
import com.supervision.police.domain.ScoringModelInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author Administrator
* @description scoring_model_info()Mapper
* @createDate 2025-02-14 16:27:25
* @Entity com.supervision.police.domain.ScoringModelInfo
*/
public interface ScoringModelInfoMapper extends BaseMapper<ScoringModelInfo> {
}

@ -0,0 +1,18 @@
package com.supervision.police.mapper;
import com.supervision.police.domain.TaskCaseRecord;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author dxy
* @description task_case_recordMapper
* @createDate 2024-12-25 09:57:08
* @Entity com.supervision.police.domain.TaskCaseRecord
*/
public interface TaskCaseRecordMapper extends BaseMapper<TaskCaseRecord> {
}

@ -0,0 +1,23 @@
package com.supervision.police.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.police.domain.TaskRecord;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.supervision.police.dto.TaskInfoDTO;
import com.supervision.police.vo.TaskInfoReqVO;
import org.apache.ibatis.annotations.Param;
/**
* @author dxy
* @description task_recordMapper
* @createDate 2024-12-24 14:44:43
* @Entity com.supervision.police.domain.TaskRecord
*/
public interface TaskRecordMapper extends BaseMapper<TaskRecord> {
IPage<TaskInfoDTO> queryTaskList(@Param("taskInfo") TaskInfoReqVO taskInfo, @Param("page")IPage<TaskInfoDTO> page);
}

@ -0,0 +1,16 @@
package com.supervision.police.service;
import com.supervision.police.domain.AuditLog;
import com.baomidou.mybatisplus.extension.service.IService;
import com.supervision.police.dto.AuditLogDTO;
/**
* @author Administrator
* @description audit_log()Service
* @createDate 2024-12-09 13:19:15
*/
public interface AuditLogService extends IService<AuditLog> {
void saveAuditLog(AuditLogDTO auditLogDTO);
}

@ -2,6 +2,7 @@ package com.supervision.police.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.itextpdf.text.DocumentException;
import com.supervision.police.domain.CaseEvidence;
import com.supervision.police.domain.EvidenceDirectory;
import com.supervision.police.domain.EvidenceFile;
@ -10,6 +11,9 @@ import com.supervision.police.dto.*;
import com.supervision.police.vo.EvidenceDirectoryReqVO;
import com.supervision.police.vo.VerifyEvidenceReqVO;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@ -163,4 +167,6 @@ public interface CaseEvidenceService extends IService<CaseEvidence> {
void updateEvidenceAppendProcessingNewTransaction(String evidenceId, String status,String appendProcessing);
void redoExtractAttributes(String caseId, List<CaseEvidence> caseEvidences);
void downloadEvidence(String evidenceId, HttpServletResponse response) throws IOException, DocumentException;
}

@ -19,4 +19,7 @@ public interface CasePersonService extends IService<CasePerson> {
List<CasePerson> listByEvidenceId(String evidenceId);
CasePerson getMainActor(String caseId);
}

@ -1,8 +1,23 @@
package com.supervision.police.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.common.domain.R;
import com.supervision.police.vo.ChatReqVO;
import com.supervision.police.vo.ChatResVO;
import com.supervision.police.vo.ConversationResVo;
import java.util.List;
public interface ChatService {
ChatResVO chat(ChatReqVO chatReqVO);
R<ChatResVO> chatNew(ChatReqVO chatReqVO);
IPage<ChatResVO> queryConversationInfoList(String conversationId, int page, int size);
IPage<ConversationResVo> queryUserConversationList(String userId, int page, int size);
void deleteConversation(List<String> conversationIdList);
}

@ -0,0 +1,13 @@
package com.supervision.police.service;
import com.supervision.police.domain.ConversationQa;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @author yaxin
* @description conversation_qaService
* @createDate 2024-11-22 11:37:02
*/
public interface ConversationQaService extends IService<ConversationQa> {
}

@ -0,0 +1,19 @@
package com.supervision.police.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.supervision.police.domain.Conversation;
import com.baomidou.mybatisplus.extension.service.IService;
import com.supervision.police.vo.ConversationResVo;
import java.util.Date;
/**
* @author yaxin
* @description conversation()Service
* @createDate 2024-11-25 13:43:52
*/
public interface ConversationService extends IService<Conversation> {
IPage<ConversationResVo> queryUserConversationList(String userId, Date startTime, Date endTime, Page<ConversationResVo> page);
}

@ -15,4 +15,6 @@ public interface EvidenceCategoryService extends IService<EvidenceCategory> {
List<EvidenceCategoryDTO> listCategoryTree(String caseType);
List<EvidenceCategory> listCategoryByCaseType(String caseType);
}

@ -1,6 +1,18 @@
package com.supervision.police.service;
import com.supervision.police.domain.CasePerson;
import com.supervision.police.domain.NotePrompt;
import com.supervision.police.domain.NoteRecordSplit;
import com.supervision.police.domain.TripleInfo;
import java.util.List;
public interface ExtractTripleInfoService {
void extractTripleInfo(String caseId, String name, String recordSplitId);
List<TripleInfo> extractTripleInfo(NotePrompt notePrompt, CasePerson mainActor, List<NoteRecordSplit> noteRecordSplitList);
List<TripleInfo> extractTripleInfo(NotePrompt notePrompt, String caseId, String recordId);
}

@ -3,6 +3,7 @@ package com.supervision.police.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.supervision.police.domain.ModelAtomicIndex;
import com.supervision.police.dto.AtomicIndexUsedDTO;
import com.supervision.police.mapper.ModelAtomicIndexMapper;
import java.util.List;
@ -21,12 +22,12 @@ public interface ModelAtomicIndexService extends IService<ModelAtomicIndex> {
/**
* id
* @param indexIdList id
* @param caseId id
* @param atomicIndexIds id
* @param caseType
* @param indexSource
* @return
*/
List<ModelAtomicIndex> listCaseAtomicIndex(List<String> indexIdList, String caseId, String indexSource);
List<ModelAtomicIndex> listCaseAtomicIndex(List<String> atomicIndexIds, String caseType, String indexSource);
@ -36,4 +37,7 @@ public interface ModelAtomicIndexService extends IService<ModelAtomicIndex> {
* @param atomicIndexId id
*/
void whenDeleteAtomicIndex(String caseType,String atomicIndexId);
List<AtomicIndexUsedDTO> atomicUsed(String atomicIndexId);
}

@ -2,9 +2,13 @@ package com.supervision.police.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.supervision.police.domain.ModelAtomicResult;
import com.supervision.police.dto.EvidentIndexResultDTO;
import java.util.List;
public interface ModelAtomicResultService extends IService<ModelAtomicResult> {
List<ModelAtomicResult> queryByCaseIdForUpdate(String caseId);
void replaceResultCaseId(String oldCaseId, String newCaseId);
}

@ -49,5 +49,19 @@ public interface ModelCaseService extends IService<ModelCase> {
IPage<IndexDetail> getIndexDetail(IndexResultQuery query, Integer page, Integer size);
boolean initCaseKnowledgeBase(String caseId);
/**
*
*/
void migrateRecordKnowledgeBase();
List<String> listCaseFileIds(String caseId);
boolean scoringModelIsUsed(String modelId);
}

@ -39,6 +39,6 @@ public interface ModelIndexAtomicRelationService extends IService<ModelIndexAtom
*/
void deleteByModelIndex(String modelIndexId);
void deleteByIndexIds(List<String> indexIds);
}

@ -0,0 +1,8 @@
package com.supervision.police.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.supervision.police.domain.ModelIndexResult;
public interface ModelIndexResultService extends IService<ModelIndexResult> {
void removeByCaseId(String caseId);
}

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.supervision.common.domain.R;
import com.supervision.police.domain.ModelAtomicIndex;
import com.supervision.police.domain.ModelIndex;
import com.supervision.police.dto.AtomicIndexUsedDTO;
import com.supervision.police.dto.CaseAtomicIndexDTO;
import com.supervision.police.dto.CaseAtomicResultWrapper;
import com.supervision.police.dto.ValueCalculateScopeDTO;
@ -28,6 +29,8 @@ public interface ModelIndexService extends IService<ModelIndex> {
R<?> del(String id);
void deleteModelIndexByCaseType(String caseType);
R<?> selectAllAtomic(ModelAtomicIndex modelAtomicIndex, Integer page, Integer size);
R<?> addOrUpdAtomic(ModelAtomicIndex modelAtomicIndex);
@ -59,5 +62,14 @@ public interface ModelIndexService extends IService<ModelIndex> {
Map<String,List<ValueCalculateScopeDTO>> listAtomicIndexAttributeScope(List<String> atomicIndexIds);
GraphDebugResVO graphDebug(GraphDebugReqVO graphDebugDTO);
/**
*
* @param oldModelId id
* @param newModelId id
*/
void copyIndex(String oldModelId, String newModelId);
List<AtomicIndexUsedDTO> atomicUsed(String atomicIndexId);
}

@ -11,6 +11,8 @@ public interface ModelService {
R<?> analyseCase(AnalyseCaseDTO analyseCaseDTO);
R<?> analyseCaseWrapper(AnalyseCaseDTO analyseCaseDTO);
/**
*

@ -0,0 +1,15 @@
package com.supervision.police.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.police.dto.CaseProcessDTO;
import com.supervision.police.dto.TaskInfoDTO;
import com.supervision.police.vo.CaseProcessReqVO;
import com.supervision.police.vo.TaskInfoReqVO;
import java.util.List;
public interface MroService {
IPage<CaseProcessDTO> queryCaseList(CaseProcessReqVO caseProcessReqVO, Integer page, Integer size);
void analysisCase(List<String> caseIds);
}

@ -12,6 +12,5 @@ public interface NoteRecordService extends IService<NoteRecord> {
void uploadFileToLangChainChat(String caseId);
String saveOrUpdRecord(NoteRecord noteRecord);
}

@ -26,10 +26,19 @@ public interface NoteRecordSplitService extends IService<NoteRecordSplit> {
void delRecords(String id);
NoteRecordSplit saveRecordSplit(NoteRecord record, String fileName, String question, String answer);
NoteRecordSplit saveRecordSplit(NoteRecord record, String fileId, String fileName, String question, String answer);
List<NoteRecordSplit> batchSaveRecordSplit(NoteRecord record, String fileId);
Map<String, Object> queryRecordList(NoteRecordReqVO noteRecord, Integer page, Integer size);
String redoExtract(NoteRecordReqVO records) throws IOException;
List<NoteRecordSplit> queryRecordSplitList(String recordId);
/**
*
* @param splitList
*/
void batchUpdatePronoun(List<NoteRecordSplit> splitList);
}

@ -1,7 +1,7 @@
package com.supervision.police.service;
import com.supervision.police.domain.ModelRecordType;
import com.supervision.police.domain.NoteRecordSplit;
import com.supervision.thread.ReplacePronounTask;
import java.util.List;
@ -9,6 +9,9 @@ public interface RecordSplitProcessService {
void process(List<ModelRecordType> allTypeList, List<NoteRecordSplit> splitList);
void processWithReplacePronoun(List<ModelRecordType> allTypeList, List<NoteRecordSplit> splitList);
/**
*
*
@ -18,4 +21,22 @@ public interface RecordSplitProcessService {
*/
boolean recordProcessTaskStatusCheck(String caseId, String recordId, Integer splitSize);
/**
*
* @param splitList
* @return note:
* @throws InterruptedException
*/
List<NoteRecordSplit> replacePronoun(List<NoteRecordSplit> splitList) throws InterruptedException;
/**
*
*
* @param splitList
* @param index
*/
ReplacePronounTask buildReplacePronounTask(List<NoteRecordSplit> splitList, int index);
}

@ -0,0 +1,28 @@
package com.supervision.police.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.police.domain.ScoringModelInfo;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
import java.util.stream.LongStream;
/**
* @author Administrator
* @description scoring_model_info()Service
* @createDate 2025-02-14 16:27:25
*/
public interface ScoringModelInfoService extends IService<ScoringModelInfo> {
String saveScoringModel(ScoringModelInfo modelInfo);
void deleteScoringModel(String modelId);
void updateScoringModel(ScoringModelInfo modelInfo);
String copyScoringModel(ScoringModelInfo modelInfo);
IPage<ScoringModelInfo> pageList(String modelName, Integer pageNum, Integer pageSize);
String getScoringModelNameById(String modelId, List<ScoringModelInfo> modelInfoList);
}

@ -16,6 +16,9 @@ public interface SystemUserService extends IService<SystemUser> {
UserInfoDTO getCurrentUser();
UserInfoDTO getUserInfo(String account);
String saveUserInfo(UserInfoReqVo userInfoReqVo);
void updateUserInfo(UserInfoReqVo userInfoReqVo);

@ -0,0 +1,40 @@
package com.supervision.police.service;
import com.supervision.police.domain.TaskCaseRecord;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
import java.util.Map;
/**
* @author dxy
* @description task_case_recordService
* @createDate 2024-12-25 09:57:08
*/
public interface TaskCaseRecordService extends IService<TaskCaseRecord> {
/**
*
* @return
*/
List<TaskCaseRecord> queryProcessingTaskList();
List<TaskCaseRecord> queryByTaskId(String taskId);
/**
*
* @param taskCaseRecord
* @return
*/
String getActuallyStatus(TaskCaseRecord taskCaseRecord);
TaskCaseRecord updateStatus(String taskId, String executeId,String promptId,boolean isSuccess);
TaskCaseRecord updateStatus(String taskId, String executeId,String promptId,boolean isSuccess,List<TaskCaseRecord> taskCaseRecordList);
Boolean updateStatus(String taskId,List<String> olderStatus,String nowStatus);
Boolean removeByTaskId(List<String> taskIds);
}

@ -0,0 +1,70 @@
package com.supervision.police.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.supervision.police.domain.NotePrompt;
import com.supervision.police.domain.TaskCaseRecord;
import com.supervision.police.domain.TaskRecord;
import com.supervision.police.dto.TaskInfoDTO;
import com.supervision.police.dto.taskRecord.TaskRecordVo;
import com.supervision.police.vo.TaskInfoReqVO;
import java.util.List;
/**
* @author dxy
* @description task_recordService
* @createDate 2024-12-24 14:44:43
*/
public interface TaskRecordService extends IService<TaskRecord> {
void executePromptExtractTask(TaskRecordVo taskRecordVo);
void executeAllPromptExtractTask();
void graphExtract(NotePrompt prompt, String caseId, String executeId);
/**
*
*
* @param evidenceId id
*/
void structureExtract(String evidenceId);
IPage<TaskInfoDTO> queryTaskList(TaskInfoReqVO taskInfoReqVO, Integer page, Integer size);
/**
*
*
* @param status
* @return true false
*/
Boolean taskStatusCancelEnabled(String status);
/**
*
*
* @param status
* @return true false
*/
Boolean taskStatusDeleteEnabled(String status);
void cancelTask(List<String> taskIds);
void deleteTask(List<String> taskIds);
/**
*
*
* @param taskId id
* @param executeId id
*/
void completeTask(String taskId, String promptId,String executeId, boolean isSuccess);
String determineStatus(List<TaskCaseRecord> taskCaseRecords);
}

@ -1,7 +1,22 @@
package com.supervision.police.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.supervision.police.domain.NotePrompt;
import com.supervision.police.domain.TripleInfo;
import java.util.List;
public interface TripleInfoService extends IService<TripleInfo> {
/**
* id
* @param tripleInfo
* @return
*/
TripleInfo saveOrUpdateByBusiness(TripleInfo tripleInfo);
void updateNeo4jFlag(List<String> ids, String neo4jFlag);
List<TripleInfo> queryByRecordIdAndPrompt(String recordId, NotePrompt notePrompt);
}

@ -0,0 +1,32 @@
package com.supervision.police.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.supervision.police.domain.AuditLog;
import com.supervision.police.dto.AuditLogDTO;
import com.supervision.police.service.AuditLogService;
import com.supervision.police.mapper.AuditLogMapper;
import org.springframework.stereotype.Service;
/**
* @author Administrator
* @description audit_log()Service
* @createDate 2024-12-09 13:19:15
*/
@Service
public class AuditLogServiceImpl extends ServiceImpl<AuditLogMapper, AuditLog>
implements AuditLogService{
@Override
public void saveAuditLog(AuditLogDTO auditLogDTO) {
if (null == auditLogDTO){
return;
}
AuditLog auditLog = auditLogDTO.toAuditLog();
this.save(auditLog);
}
}

@ -268,7 +268,9 @@ public class CaseEvidencePropertyServiceImpl implements CaseEvidencePropertyServ
Field field = beanDesc.getField(StrUtil.toCamelCase(entry.getKey()));
NotePromptExtractAttributesDto attributesDto = new NotePromptExtractAttributesDto();
attributesDto.setAttrName(getFieldDesc(field));
attributesDto.setAttrValue(StrUtil.toString(entry.getValue()));
if (null != entry.getValue()){
attributesDto.setAttrValue(StrUtil.toString(entry.getValue()));
}
attributesDto.setAttrValueType(getFieldType(field));
return attributesDto;
}).filter(a->StrUtil.isNotEmpty(a.getAttrName())).toList();

@ -13,6 +13,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itextpdf.text.DocumentException;
import com.supervision.common.constant.EvidenceConstants;
import com.supervision.common.constant.IndexRuleConstants;
import com.supervision.minio.domain.MinioFile;
@ -23,21 +24,31 @@ import com.supervision.police.mapper.CaseEvidenceMapper;
import com.supervision.police.service.*;
import com.supervision.police.vo.EvidenceDirectoryReqVO;
import com.supervision.police.vo.VerifyEvidenceReqVO;
import com.supervision.utils.UserUtil;
import com.supervision.utils.WatermarkUtil;
import com.supervision.utils.ZipFileUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.supervision.common.constant.XxlJobConstants.TASK_NAME_EVIDENCE_ANALYSIS;
@Slf4j
@Service
@ -45,17 +56,11 @@ import java.util.stream.Stream;
public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, CaseEvidence> implements CaseEvidenceService {
private final EvidenceFileService evidenceFileService;
private final ComDictionaryService comDictionaryService;
private final CaseStatusManageService caseStatusManageService;
private final FileOcrProcessService fileOcrProcessService;
private final MinioService minioService;
private final ModelCaseService modelCaseService;
@Autowired
private LLMExtractService llmExtractService;
@Autowired
@ -69,6 +74,9 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
private final CaseEvidencePropertyService caseEvidencePropertyService;
@Value("${fu-hsi-config.watermark.template}")
private String watermarkTemplate;
@Override
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class)
public String saveEvidence(CaseEvidenceDTO caseEvidenceDTO) {
@ -79,11 +87,11 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
CaseEvidence caseEvidence = caseEvidenceDTO.toCaseEvidence();
super.save(caseEvidence);
if (CollUtil.isNotEmpty(caseEvidence.getProperty())){
if (CollUtil.isNotEmpty(caseEvidence.getProperty())) {
// 同时保存证据属性值
EvidenceDirectoryDTO rootDirectory = new EvidenceDirectoryDTO(evidenceDirectoryService.listDirectoryTree(caseEvidence.getCaseId()));
EvidenceDirectoryDTO directory = rootDirectory.findDirectory(caseEvidence.getDirectoryId());
caseEvidencePropertyService.saveEvidenceProperty(caseEvidence.getId(),directory.getCategoryId(),caseEvidence.getProperty());
caseEvidencePropertyService.saveEvidenceProperty(caseEvidence.getId(), directory.getCategoryId(), caseEvidence.getProperty());
}
@ -121,11 +129,11 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
// 更新证据属性
EvidenceDirectoryDTO rootDirectory = new EvidenceDirectoryDTO(evidenceDirectoryService.listDirectoryTree(caseEvidence.getCaseId()));
EvidenceDirectoryDTO directory = rootDirectory.findDirectory(caseEvidence.getDirectoryId());
if (null != directory && StrUtil.isNotEmpty(directory.getCategoryId())){
if (CollUtil.isNotEmpty(caseEvidence.getProperty())){
caseEvidencePropertyService.updateEvidenceProperty(caseEvidence.getId(),directory.getCategoryId(),caseEvidence.getProperty());
}else {
caseEvidencePropertyService.deleteEvidenceProperty(caseEvidence.getId(),directory.getCategoryId());
if (null != directory && StrUtil.isNotEmpty(directory.getCategoryId())) {
if (CollUtil.isNotEmpty(caseEvidence.getProperty())) {
caseEvidencePropertyService.updateEvidenceProperty(caseEvidence.getId(), directory.getCategoryId(), caseEvidence.getProperty());
} else {
caseEvidencePropertyService.deleteEvidenceProperty(caseEvidence.getId(), directory.getCategoryId());
}
}
@ -178,7 +186,7 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class)
public boolean batchDeleteEvidence(List<EvidenceIdWrapper> wrappers) {
if (CollUtil.isEmpty(wrappers)){
if (CollUtil.isEmpty(wrappers)) {
return true;
}
List<String> evidenceIds = wrappers.stream().map(EvidenceIdWrapper::getEvidenceId).toList();
@ -250,7 +258,7 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
caseEvidenceDetailDTO.setContentTypeValue(recordFileDTOS);
EvidenceDirectoryDTO directory = rootDirectory.findDirectory(caseEvidence.getDirectoryId());
caseEvidenceDetailDTO.setEvidenceFormatValue(directory);
if (null != queryDirectory && queryDirectory.getLevel() == 3 && StrUtil.isNotEmpty(caseEvidence.getFileName())){
if (null != queryDirectory && queryDirectory.getLevel() == 3 && StrUtil.isNotEmpty(caseEvidence.getFileName())) {
caseEvidenceDetailDTO.setEvidenceName(caseEvidence.getFileName().split("\\.")[0]);
}
caseEvidenceDetailDTO.setDirectoryNamePath(StrUtil.join("/", rootDirectory.getDirectoryPath(caseEvidence.getDirectoryId())));
@ -299,12 +307,12 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
CaseEvidence caseEvidence = getById(evidenceId);
if (caseEvidence == null) {
log.error("证据不存在");
return;
throw new IllegalArgumentException("证据不存在");
}
List<EvidenceFileDTO> evidenceFiles = evidenceFileService.listFileInfo(List.of(evidenceId));
if (evidenceFiles.isEmpty()) {
log.error("证据id:【{}】不存在证据文件", evidenceId);
return;
throw new IllegalArgumentException("证据不存在证据文件");
}
try {
// 根据rank升序排序
@ -370,7 +378,7 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
caseEvidence.setProcessStatus(EvidenceConstants.PROCESS_STATUS_SUCCESS);
updateById(caseEvidence);
} catch (Exception e) {
log.error("证据:【{}】解析失败。更新证据处理状态为【处理失败】。",evidenceId, e);
log.error("证据:【{}】解析失败。更新证据处理状态为【处理失败】。", evidenceId, e);
caseEvidence.setProcessStatus(EvidenceConstants.PROCESS_STATUS_FAILED);
updateById(caseEvidence);
} finally {
@ -380,20 +388,21 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
/**
*
*
* @param extract
* @return
*/
private boolean checkExtractAttributes(NotePromptExtractAttributesDto extract){
if (null == extract){
private boolean checkExtractAttributes(NotePromptExtractAttributesDto extract) {
if (null == extract) {
return false;
}
String attrValueType = extract.getAttrValueType();
if (StrUtil.equals(attrValueType, IndexRuleConstants.VALUE_TYPE_DATE)){ // 日期
if (StrUtil.equals(attrValueType, IndexRuleConstants.VALUE_TYPE_DATE)) { // 日期
try {
new SimpleDateFormat("yyyy-MM-dd").parse(extract.getAttrValue());
return true;
} catch (Exception e) {
log.error("属性:{},日期:{}格式错误", extract.getAttrName(),extract.getAttrValue(),e);
log.error("属性:{},日期:{}格式错误", extract.getAttrName(), extract.getAttrValue(), e);
return false;
}
}
@ -406,7 +415,7 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
@Override
public void callEvidenceAnalysis(String evidenceId) {
Assert.notEmpty(evidenceId, "证据ID不能为空");
xxlJobService.executeTaskByJobHandler("evidenceAnalysis", evidenceId);
xxlJobService.executeTaskByJobHandler(TASK_NAME_EVIDENCE_ANALYSIS, evidenceId);
}
@Override
@ -462,7 +471,7 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
List<EvidenceCategoryDTO> evidenceCategoryTree = evidenceCategoryService.listCategoryTree(caseType);
List<EvidenceDirectoryDTO> evidenceDirectoryTree = evidenceDirectoryService.listDirectoryTree(caseId);
initCaseEvidenceDirectory(evidenceCategoryTree,evidenceDirectoryTree,caseId, null);
initCaseEvidenceDirectory(evidenceCategoryTree, evidenceDirectoryTree, caseId, null);
}
@Override
@ -495,17 +504,17 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
((CaseEvidenceService) AopContext.currentProxy()).doReplaceEvidence(modelCase, allEvidence, catagroyMap, allFile);
successCount++;
} catch (Exception e) {
log.error("案件{}的目录初始化失败。案件id:{}", modelCase.getCaseName(), modelCase.getId(),e);
log.error("案件{}的目录初始化失败。案件id:{}", modelCase.getCaseName(), modelCase.getId(), e);
errorCount++;
}
index += 1;
log.info("案件【{}】的目录初始化完成。耗时:{}秒,占总体进度:{}%", modelCase.getCaseName(),interval.intervalSecond(modelCase.getId()),index/(list.size()*1.0)*100);
log.info("案件【{}】的目录初始化完成。耗时:{}秒,占总体进度:{}%", modelCase.getCaseName(), interval.intervalSecond(modelCase.getId()), index / (list.size() * 1.0) * 100);
}
log.info("<<<<=======初始化案件的证据目录完成。案件总条数:{},总耗时:{}秒,成功个数:{},失败个数:{}", list.size(),interval.intervalSecond(),successCount,errorCount);
log.info("<<<<=======初始化案件的证据目录完成。案件总条数:{},总耗时:{}秒,成功个数:{},失败个数:{}", list.size(), interval.intervalSecond(), successCount, errorCount);
}
@Transactional(rollbackFor = Exception.class, transactionManager = "dataSourceTransactionManager",propagation = Propagation.REQUIRES_NEW)
@Transactional(rollbackFor = Exception.class, transactionManager = "dataSourceTransactionManager", propagation = Propagation.REQUIRES_NEW)
public void doReplaceEvidence(ModelCase modelCase, List<CaseEvidence> allEvidence, Map<String, String> catagroyMap, List<EvidenceFile> allFile) {
String caseType = modelCase.getCaseType();
String id = modelCase.getId();
@ -517,28 +526,28 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
log.info("案件{}证据总数:{}", modelCase.getCaseName(), evidenceList.size());
for (CaseEvidence caseEvidence : evidenceList) {
String directoryId = caseEvidence.getDirectoryId();
if (StrUtil.isNotEmpty(directoryId)){
log.warn("证据id{},证据名:{}已经存在目录id:{},不进行目录绑定操作",caseEvidence.getId(),caseEvidence.getEvidenceName(),directoryId);
if (StrUtil.isNotEmpty(directoryId)) {
log.warn("证据id{},证据名:{}已经存在目录id:{},不进行目录绑定操作", caseEvidence.getId(), caseEvidence.getEvidenceName(), directoryId);
continue;
}
if (StrUtil.equalsAny(caseEvidence.getEvidenceType(), "3","6")){
log.warn("证据id{},证据名:{},证据类型为【{}】,清除无用数据",caseEvidence.getId(),caseEvidence.getEvidenceName(),caseEvidence.getEvidenceType());
if (StrUtil.equalsAny(caseEvidence.getEvidenceType(), "3", "6")) {
log.warn("证据id{},证据名:{},证据类型为【{}】,清除无用数据", caseEvidence.getId(), caseEvidence.getEvidenceName(), caseEvidence.getEvidenceType());
super.removeById(caseEvidence.getId());
continue;
}
if (!catagroyMap.containsKey(caseEvidence.getEvidenceType())){
log.warn("证据id{},证据名:{},证据类型为【{}】,没有对应的目录,请检查目录配置",caseEvidence.getId(),caseEvidence.getEvidenceName(),caseEvidence.getEvidenceType());
if (!catagroyMap.containsKey(caseEvidence.getEvidenceType())) {
log.warn("证据id{},证据名:{},证据类型为【{}】,没有对应的目录,请检查目录配置", caseEvidence.getId(), caseEvidence.getEvidenceName(), caseEvidence.getEvidenceType());
continue;
}
if (StrUtil.isEmpty(caseEvidence.getEvidenceType())){
log.warn("证据id{},证据名:{},证据类型不能为空,默认为书证",caseEvidence.getId(),caseEvidence.getEvidenceName());
if (StrUtil.isEmpty(caseEvidence.getEvidenceType())) {
log.warn("证据id{},证据名:{},证据类型不能为空,默认为书证", caseEvidence.getId(), caseEvidence.getEvidenceName());
caseEvidence.setEvidenceType("1");
}
EvidenceDirectoryDTO topDirectory = findTopDirectory(rootDirectory, catagroyMap.get(caseEvidence.getEvidenceType()));
if (null == topDirectory){
log.warn("证据id{},证据名:{},证据类型为【{}】,在根目录下没有对应的目录,请检查目录配置",caseEvidence.getId(),caseEvidence.getEvidenceName(),caseEvidence.getEvidenceType());
if (null == topDirectory) {
log.warn("证据id{},证据名:{},证据类型为【{}】,在根目录下没有对应的目录,请检查目录配置", caseEvidence.getId(), caseEvidence.getEvidenceName(), caseEvidence.getEvidenceType());
continue;
}
caseEvidence.setDirectoryId(topDirectory.getId());
@ -550,24 +559,24 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
for (EvidenceFile file : files) {
evidenceFileService.updateById(file);
MinioFile minioFile = minioFileMap.get(file.getFileId());
if (null == minioFile){
log.warn("证据id{},证据名:{}文件id{}不存在minio上传信息", caseEvidence.getId(),caseEvidence.getEvidenceName(),file.getFileId());
if (null == minioFile) {
log.warn("证据id{},证据名:{}文件id{}不存在minio上传信息", caseEvidence.getId(), caseEvidence.getEvidenceName(), file.getFileId());
continue;
}
fileOcrProcessService.multipleTypeOcrProcess(List.of(file.getFileId()),minioFile.getFileType());
fileOcrProcessService.multipleTypeOcrProcess(List.of(file.getFileId()), minioFile.getFileType());
}
}
}
private EvidenceDirectoryDTO findTopDirectory(EvidenceDirectoryDTO rootDirectory, String categoryId) {
if (StrUtil.equals(rootDirectory.getCategoryId(), categoryId)){
if (StrUtil.equals(rootDirectory.getCategoryId(), categoryId)) {
return rootDirectory;
}
if (CollUtil.isNotEmpty(rootDirectory.getChild())){
if (CollUtil.isNotEmpty(rootDirectory.getChild())) {
for (EvidenceDirectoryDTO child : rootDirectory.getChild()) {
EvidenceDirectoryDTO directory = findTopDirectory(child, categoryId);
if (directory != null){
if (directory != null) {
return directory;
}
}
@ -664,11 +673,11 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
public void syncEvidenceAnalysis(List<CaseEvidenceDetailDTO> evidenceList) {
List<EvidenceFileDTO> ocrFileDTOList = evidenceList.stream().filter(
// 当前证据下不是所有文件都是新增
evidenceDetail-> !evidenceDetail.getFileList().stream().allMatch(file -> StrUtil.equalsAny(file.getUpdateStatus(), "1", "-1"))
// 当前证据下不是所有文件都是新增
evidenceDetail -> !evidenceDetail.getFileList().stream().allMatch(file -> StrUtil.equalsAny(file.getUpdateStatus(), "1", "-1"))
)
.flatMap(evidenceDetailDTO -> evidenceDetailDTO.getFileList().stream().filter(file -> StrUtil.equals(file.getUpdateStatus(), "1"))).toList();
if (CollUtil.isNotEmpty(ocrFileDTOList)){
if (CollUtil.isNotEmpty(ocrFileDTOList)) {
// 在已经存在的目录下追加文件只需要重新及进行ocr识别
log.info("ocrAndExtract:开始只进行文件内容识别...");
Map<String, List<EvidenceFileDTO>> evidenceMap = ocrFileDTOList.stream().collect(Collectors.groupingBy(EvidenceFileDTO::getEvidenceId));
@ -678,17 +687,17 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
// 首先统一更新为正在处理
CaseEvidence one = this.lambdaQuery().eq(CaseEvidence::getId, evidenceId).one();
updateEvidenceAppendProcessingNewTransaction(evidenceId,one.getProcessStatus(),"1");
updateEvidenceAppendProcessingNewTransaction(evidenceId, one.getProcessStatus(), "1");
}
for (Map.Entry<String, List<EvidenceFileDTO>> entry : evidenceMap.entrySet()) {
String evidenceId = entry.getKey();
List<EvidenceFileDTO> value = entry.getValue();
for (EvidenceFileDTO evidenceFileDTO : value) {
fileOcrProcessService.multipleTypeOcrProcess(List.of(evidenceFileDTO.getFileId()),evidenceFileDTO.getFileType());
fileOcrProcessService.multipleTypeOcrProcess(List.of(evidenceFileDTO.getFileId()), evidenceFileDTO.getFileType());
}
log.info("ocrAndExtract:证据:{} 文件内容识别完成", evidenceId);
updateEvidenceAppendProcessingNewTransaction(evidenceId,EvidenceConstants.PROCESS_STATUS_SUCCESS,"0");
updateEvidenceAppendProcessingNewTransaction(evidenceId, EvidenceConstants.PROCESS_STATUS_SUCCESS, "0");
}
}
@ -707,10 +716,10 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
}
@Override
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
public void updateEvidenceAppendProcessingNewTransaction(String evidenceId, String status,String appendProcessing) {
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void updateEvidenceAppendProcessingNewTransaction(String evidenceId, String status, String appendProcessing) {
this.lambdaUpdate().eq(CaseEvidence::getId, evidenceId)
.set(StrUtil.isNotEmpty(status),CaseEvidence::getProcessStatus, status)
.set(StrUtil.isNotEmpty(status), CaseEvidence::getProcessStatus, status)
.set(CaseEvidence::getAppendProcessing, appendProcessing)
.set(CaseEvidence::getUpdateTime, LocalDateTime.now()).update();
}
@ -793,7 +802,7 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
.filter(evidenceDetail -> CollUtil.isNotEmpty(evidenceDetail.getFileList()))
.map(EvidenceProcessDTO::new).collect(Collectors.toList());
List<EvidenceDirectoryDTO> evidenceDirectoryDTOS = evidenceDirectoryService.listDirectoryTree(caseId);
List<EvidenceCategory> categoryList = evidenceCategoryService.lambdaQuery().eq(EvidenceCategory::getCaseType, modelCase.getCaseType()).list();
List<EvidenceCategory> categoryList = evidenceCategoryService.listCategoryByCaseType(modelCase.getCaseType());
for (EvidenceProcessDTO evidenceProcessDTO : processDTOList) {
evidenceProcessDTO.setTemplateInfo(evidenceDirectoryDTOS, categoryList);
evidenceProcessDTO.setEvidenceTypeName(categoryList);
@ -829,10 +838,10 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
// 同时更新证据属性值
String categoryId = rootDirectory.findDirectory(CollUtil.getFirst(value).getDirectoryId()).getCategoryId();
Map<String, List<NotePromptExtractAttributesDto>> map = caseEvidencePropertyService.listEvidenceProperty(categoryId, Collections.singletonList(evidenceId));
if (CollUtil.isEmpty(map.get(categoryId))){
caseEvidencePropertyService.saveEvidenceProperty(evidenceId, categoryId,CollUtil.getFirst(value).getProperties());
}else {
caseEvidencePropertyService.updateEvidenceProperty(evidenceId, categoryId,CollUtil.getFirst(value).getProperties());
if (CollUtil.isEmpty(map.get(evidenceId))) {
caseEvidencePropertyService.saveEvidenceProperty(evidenceId, categoryId, CollUtil.getFirst(value).getProperties());
} else {
caseEvidencePropertyService.updateEvidenceProperty(evidenceId, categoryId, CollUtil.getFirst(value).getProperties());
}
@ -850,7 +859,7 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
if (evidenceDetail != null) {
List<EvidenceFileDTO> fileList = evidenceDetail.getFileList();
int initOrder = 0;
if (StrUtil.isNotEmpty(batchNo) && !CollUtil.isNotEmpty(fileList)){
if (StrUtil.isNotEmpty(batchNo) && !CollUtil.isNotEmpty(fileList)) {
// 如果批次不为空,则只对当前批次的文件进行排序
initOrder = fileList.size();
}
@ -913,7 +922,7 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
rebuildEvidenceProperties(rootDirectory, caseEvidenceList);
List<CategoryPromptDTO> categoryPromptDTOS = evidenceDirectoryService.listCategoryPrompt(caseId);
Map<String, CaseEvidenceDTO> caseEvidenceMap = caseEvidenceList.stream().map(CaseEvidenceDTO::new).peek(e->e.setDirectoryNamePathValue(rootDirectory)).collect(Collectors.toMap(CaseEvidenceDTO::getId, Function.identity()));
Map<String, CaseEvidenceDTO> caseEvidenceMap = caseEvidenceList.stream().map(CaseEvidenceDTO::new).peek(e -> e.setDirectoryNamePathValue(rootDirectory)).collect(Collectors.toMap(CaseEvidenceDTO::getId, Function.identity()));
Map<String, CategoryPromptDTO> categoryPromptMap = categoryPromptDTOS.stream().collect(Collectors.toMap(CategoryPromptDTO::getDirectoryId, k -> k, (v1, v2) -> v1));
Iterator<EvidenceDirectoryDTO> iterator = evidenceDirectoryDTOS.iterator();
@ -936,7 +945,7 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
Map<String, List<String>> categoryMapEvidence = new HashMap<>();
for (CaseEvidence caseEvidence : caseEvidences) {
EvidenceDirectoryDTO directory = rootDirectory.findDirectory(caseEvidence.getDirectoryId());
if (null != directory && StrUtil.isNotEmpty(directory.getCategoryId())){
if (null != directory && StrUtil.isNotEmpty(directory.getCategoryId())) {
List<String> evidenceIds = categoryMapEvidence.getOrDefault(directory.getCategoryId(), new ArrayList<>());
evidenceIds.add(caseEvidence.getId());
categoryMapEvidence.put(directory.getCategoryId(), evidenceIds);
@ -950,15 +959,46 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
for (CaseEvidence caseEvidence : caseEvidences) {
List<NotePromptExtractAttributesDto> attributesDtos = map.get(caseEvidence.getId());
// 兼容老数据
if (CollUtil.isNotEmpty(attributesDtos)){
if (CollUtil.isNotEmpty(attributesDtos)) {
caseEvidence.setProperty(attributesDtos);
}
}
}
@Override
public void downloadEvidence(String evidenceId, HttpServletResponse response) throws IOException, DocumentException {
List<EvidenceFileDTO> evidenceFileDTOList = evidenceFileService.listFileInfo(List.of(evidenceId));
Map<String, InputStream> fileInputStreamMap = new HashMap<>();
for (EvidenceFileDTO evidenceFileDTO : evidenceFileDTOList) {
MinioFile minioFile = minioService.getMinioFile(evidenceFileDTO.getFileId());
if (null != minioFile) {
if (StrUtil.equalsAnyIgnoreCase(minioFile.getFileType(), "pdf")) {
String waterMarkName = StrUtil.format(watermarkTemplate, Map.of("userName", UserUtil.getUser().getUserName()));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
WatermarkUtil.pdfByText(minioService.getObjectInputStream(minioFile), bos, waterMarkName, Map.of());
fileInputStreamMap.put(minioFile.getFilename(), new ByteArrayInputStream(bos.toByteArray()));
} else if (StrUtil.equalsAnyIgnoreCase(minioFile.getFileType(), "jpg", "png", "jpeg", "bmp")) {
String waterMarkName = StrUtil.format(watermarkTemplate, Map.of("userName", UserUtil.getUser().getUserName()));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
WatermarkUtil.imageByText(waterMarkName, minioService.getObjectInputStream(minioFile), bos, Map.of("formatName", minioFile.getFileType()));
fileInputStreamMap.put(minioFile.getFilename(), new ByteArrayInputStream(bos.toByteArray()));
} else {
fileInputStreamMap.put(minioFile.getFilename(), minioService.getObjectInputStream(minioFile));
}
}
}
try {
ZipFileUtil.createZipAndDownload(response, getById(evidenceId).getEvidenceName(), fileInputStreamMap);
} catch (IOException e) {
log.error("下载证据文件失败", e);
}
}
/**
*
* @param rootDirectory
*
* @param rootDirectory
* @param caseEvidenceList
*/
private void rebuildEvidenceProperties(EvidenceDirectoryDTO rootDirectory, List<CaseEvidence> caseEvidenceList) {
@ -966,33 +1006,33 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
Map<String, String> directoryIdMapCategoryId = caseEvidenceList.stream()
.filter(e -> StrUtil.isNotEmpty(e.getDirectoryId()) && null != rootDirectory.findDirectory(e.getDirectoryId()))
.map(CaseEvidence::getDirectoryId).distinct().collect(
Collectors.toMap(directoryId -> directoryId,di-> rootDirectory.findDirectory(di).getCategoryId()));
Collectors.toMap(directoryId -> directoryId, di -> rootDirectory.findDirectory(di).getCategoryId()));
Map<String, List<NotePromptExtractAttributesDto>> categoryIdMapExtractAttributes = new HashMap<>();
for (CaseEvidence caseEvidence : caseEvidenceList) {
EvidenceDirectoryDTO directory = rootDirectory.findDirectory(caseEvidence.getDirectoryId());
if (null == directory || StrUtil.isEmpty(directory.getCategoryId())){
if (null == directory || StrUtil.isEmpty(directory.getCategoryId())) {
continue;
}
String categoryId = directory.getCategoryId();
if (!categoryIdMapExtractAttributes.containsKey(categoryId)){
if (!categoryIdMapExtractAttributes.containsKey(categoryId)) {
categoryIdMapExtractAttributes.put(categoryId, caseEvidencePropertyService.findExtractAttributes(categoryId));
}
}
for (CaseEvidence caseEvidence : caseEvidenceList) {
if (StrUtil.isEmpty(caseEvidence.getDirectoryId())){
if (StrUtil.isEmpty(caseEvidence.getDirectoryId())) {
continue;
}
String categoryId = directoryIdMapCategoryId.get(caseEvidence.getDirectoryId());
if (StrUtil.isEmpty(categoryId)){
if (StrUtil.isEmpty(categoryId)) {
continue;
}
List<NotePromptExtractAttributesDto> merged = mergeExtractAttributes(caseEvidence.getProperty(), categoryIdMapExtractAttributes.get(categoryId));
if (null != merged){
if (null != merged) {
merged = merged.stream().filter(Objects::nonNull).peek(e -> {
if (!checkExtractAttributes(e)) {
e.setAttrValue(null);
@ -1006,13 +1046,13 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
}
private List<NotePromptExtractAttributesDto> mergeExtractAttributes(List<NotePromptExtractAttributesDto> property, List<NotePromptExtractAttributesDto> attributesTemplates) {
if (CollUtil.isEmpty(attributesTemplates) || CollUtil.isEmpty(property)){
if (CollUtil.isEmpty(attributesTemplates) || CollUtil.isEmpty(property)) {
return attributesTemplates;
}
for (NotePromptExtractAttributesDto attributesTemplate : attributesTemplates) {
String attrName = attributesTemplate.getAttrName();
for (NotePromptExtractAttributesDto attributesDto : property) {
if (StrUtil.equals(attributesDto.getAttrName(), attrName)){
if (StrUtil.equals(attributesDto.getAttrName(), attrName)) {
attributesTemplate.setAttrValue(attributesDto.getAttrValue());
break;
}
@ -1184,7 +1224,7 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
/**
*
*
* @param oldEvidenceList
* @param oldEvidenceList
* @param newEvidenceList
* @return
*/
@ -1321,18 +1361,19 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
*/
/**
*
* @param evidenceCategoryTree
* @param evidenceDirectoryTree
* @param caseId id
* @param parentId id
*
* @param evidenceCategoryTree
* @param evidenceDirectoryTree
* @param caseId id
* @param parentId id
*/
private void initCaseEvidenceDirectory(List<EvidenceCategoryDTO> evidenceCategoryTree, List<EvidenceDirectoryDTO> evidenceDirectoryTree,String caseId,String parentId) {
if (null == evidenceDirectoryTree){
private void initCaseEvidenceDirectory(List<EvidenceCategoryDTO> evidenceCategoryTree, List<EvidenceDirectoryDTO> evidenceDirectoryTree, String caseId, String parentId) {
if (null == evidenceDirectoryTree) {
evidenceDirectoryTree = new ArrayList<>(1);
}
for (EvidenceCategoryDTO evidenceCategoryDTO : evidenceCategoryTree) {
List<EvidenceDirectoryDTO> directoryDTOS = evidenceDirectoryTree.stream().filter(evidenceDirectoryDTO -> evidenceDirectoryDTO.getCategoryId().equals(evidenceCategoryDTO.getId())).toList();
if (CollUtil.isEmpty(directoryDTOS)){
if (CollUtil.isEmpty(directoryDTOS)) {
EvidenceDirectory evidenceDirectory = new EvidenceDirectory();
evidenceDirectory.setCaseId(caseId);
evidenceDirectory.setDirectoryName(evidenceCategoryDTO.getCategoryName());
@ -1346,7 +1387,7 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
EvidenceDirectoryDTO parentDTO = CollUtil.getFirst(directoryDTOS);
if (CollUtil.isNotEmpty(evidenceCategoryDTO.getChild())) {
initCaseEvidenceDirectory(evidenceCategoryDTO.getChild(),parentDTO.getChild(),caseId,parentDTO.getId());
initCaseEvidenceDirectory(evidenceCategoryDTO.getChild(), parentDTO.getChild(), caseId, parentDTO.getId());
}
}
}

@ -58,4 +58,9 @@ public class CasePersonServiceImpl extends ServiceImpl<CasePersonMapper, CasePer
return super.getBaseMapper().listByEvidenceId(evidenceId);
}
@Override
public CasePerson getMainActor(String caseId) {
return super.lambdaQuery().eq(CasePerson::getCaseId, caseId).eq(CasePerson::getCaseActorFlag, 1).one();
}
}

@ -1,21 +1,46 @@
package com.supervision.police.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.supervision.chat.client.LangChainChatService;
import com.supervision.chat.client.dto.chat.ChatReqDTO;
import com.supervision.chat.client.dto.chat.ChatResDTO;
import com.supervision.common.domain.R;
import com.supervision.constant.CaseAnalysisStatusEnum;
import com.supervision.police.domain.Conversation;
import com.supervision.police.domain.ConversationQa;
import com.supervision.police.domain.ModelCase;
import com.supervision.police.service.ChatService;
import com.supervision.police.service.ModelCaseService;
import com.supervision.police.domain.ModelIndex;
import com.supervision.police.dto.AnalyseCaseDTO;
import com.supervision.police.dto.IndexDetail;
import com.supervision.police.dto.IndexResultQuery;
import com.supervision.police.service.*;
import com.supervision.police.vo.ChatReqVO;
import com.supervision.police.vo.ChatResVO;
import com.supervision.police.vo.ConversationResVo;
import com.supervision.police.vo.dify.DIFYChatReqInputVO;
import com.supervision.police.vo.dify.DifyChatReqVO;
import com.supervision.police.vo.dify.DifyChatResVO;
import com.supervision.police.vo.dify.KnowledgeBaseSegmentVO;
import com.supervision.utils.DifyApiUtil;
import com.supervision.utils.UserUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import static com.supervision.common.constant.DifyConstants.*;
@Slf4j
@Service
@ -23,9 +48,13 @@ import java.util.List;
public class ChatServiceImpl implements ChatService {
private final LangChainChatService langChainChatService;
private final ModelCaseService modelCaseService;
private final ModelService modelService;
private final ConversationService conversationService;
private final ConversationQaService conversationQaService;
private final ModelIndexService modelIndexService;
private final DifyApiUtil difyApiUtil;
private final ComDictionaryService comDictionaryService;
@Override
@ -43,23 +72,288 @@ public class ChatServiceImpl implements ChatService {
ChatResDTO chat = null;
try {
chat = langChainChatService.chat(
ChatReqDTO.create(chatReqVO.getQuery(), modelCase.getCaseNo(),chatReqVO.getHistory()));
ChatReqDTO.create(chatReqVO.getQuery(), modelCase.getCaseNo(), chatReqVO.getHistory()));
} catch (Exception e) {
log.error("chat: caseNo:{},query{},error:{}", modelCase.getCaseNo(), chatReqVO.getQuery(), e.getMessage(),e);
log.error("chat: caseNo:{},query{},error:{}", modelCase.getCaseNo(), chatReqVO.getQuery(), e.getMessage(), e);
chat = new ChatResDTO();
chat.setAnswer("服务繁忙,请稍后重试!");
}
if (null ==chat){
if (null == chat) {
chat = new ChatResDTO();
}
if (StrUtil.isEmpty(chat.getAnswer())){
if (StrUtil.isEmpty(chat.getAnswer())) {
chat.setAnswer("我暂时还不知道怎么回答,您可以尝试换一种问法!");
chat.setDocs(new ArrayList<>(1));
}
log.info("chat: caseNo:{},query{},answer:{}", modelCase.getCaseNo(), chatReqVO.getQuery(),chat.getAnswer());
log.info("chat: caseNo:{},query{},answer:{}", modelCase.getCaseNo(), chatReqVO.getQuery(), chat.getAnswer());
return new ChatResVO(chat);
}
}
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class)
@Override
public R<ChatResVO> chatNew(ChatReqVO chatReqVO) {
ChatResVO chatResVO = new ChatResVO();
Map<String, Object> answerMap = new HashMap<>();
String query = chatReqVO.getQuery().trim();
String caseId = chatReqVO.getCaseId();
String userId = UserUtil.getUser().getId();
String type = chatReqVO.getType();
String intentType = chatReqVO.getIntentType();
long startTime = System.currentTimeMillis();
if (StringUtils.isEmpty(chatReqVO.getConversationId())) {
Conversation conversation = new Conversation();
conversation.setId(UUID.randomUUID().toString());
conversation.setCaseId(caseId);
conversation.setUserId(userId);
conversationService.save(conversation);
chatReqVO.setConversationId(conversation.getId());
log.info("会话已创建conversationId:{}", conversation.getId());
} else {
Conversation conversation = conversationService.getById(chatReqVO.getConversationId());
conversation.setUpdateTime(new Date());
conversationService.updateById(conversation);
log.info("会话已更新conversationId:{}", conversation.getId());
}
List<ModelIndex> modelIndices = modelIndexService.list(new LambdaQueryWrapper<ModelIndex>().eq(ModelIndex::getDataStatus, "1"));
Map<String, String> indexType = comDictionaryService.getDictionaryMap("index_type");
switch (type) {
case QA_TYPE_DIFY:
if (modelIndices.stream().map(ModelIndex::getName).anyMatch(query::equals)) {
type = QA_TYPE_NX_LLM;
intentType = INTENT_TYPE_INDEX_RESULT;
handleIndexResultQA(modelIndices, query, caseId, answerMap);
} else if (INTENT_TYPE_TEXT_CASE_RESULT.equals(query)) {
type = QA_TYPE_NX_LLM;
intentType = INTENT_TYPE_CASE_RESULT;
ModelCase modelCase = modelCaseService.getById(caseId);
if (modelCase.getTotalScore() == null) {
log.info("案件【{}】尚未执行模型分析,现在开始执行", modelCase.getCaseName());
AnalyseCaseDTO analyseCaseDTO = new AnalyseCaseDTO();
analyseCaseDTO.setCaseId(caseId);
modelService.analyseCaseWrapper(analyseCaseDTO);
}
answerMap = JSON.parseObject(JSON.toJSONString(modelService.caseScoreDetail(caseId)), Map.class);
} else if (INTENT_TYPE_TEXT_CASE_OVERVIEW.equals(query)) {
type = QA_TYPE_NX_LLM;
intentType = INTENT_TYPE_CASE_OVERVIEW;
answerMap.put("answerText", modelCaseService.getById(caseId).getCaseDetail());
} else if (INTENT_TYPE_TEXT_CASE_EVIDENCE_GUIDE.equals(query)) {
type = QA_TYPE_NX_LLM;
intentType = INTENT_TYPE_CASE_EVIDENCE_GUIDE;
answerMap.put("guideDesc", modelService.caseScoreDetail(caseId).getGuideDesc());
} else {
ModelCase modelCase = modelCaseService.getById(caseId);
DifyChatReqVO difyChatReqVO = new DifyChatReqVO();
difyChatReqVO.setUser(userId);
difyChatReqVO.setConversationId(chatReqVO.getConversationId());
difyChatReqVO.setQuery(query);
DIFYChatReqInputVO inputs = new DIFYChatReqInputVO();
inputs.setCase_id(caseId);
inputs.setUser_id(userId);
inputs.setConversation_id(chatReqVO.getConversationId());
inputs.setDataset_id(modelCase.getKnowledgeBaseId());
inputs.setParticipator(modelCase.getLawActor());
inputs.setDialogue_count(chatReqVO.getDialogueCount());
inputs.setIntent_type(intentType);
difyChatReqVO.setInputs(inputs);
DifyChatResVO response = difyApiUtil.chat(difyChatReqVO);
log.info("response:{}", JSON.toJSONString(response));
// 拼装返回对象
JSONObject json = JSON.parseObject(response.getAnswer());
if (json != null) {
intentType = json.getString("intentType");
if (json.getBoolean("isFunctionCalling")) {
answerMap = executeIntent(json.getString("intentType"), caseId, json.getString("query"), answerMap, modelIndices);
} else {
chatResVO.setSegmentList(JSONArray.parseArray(json.getString("quote"), KnowledgeBaseSegmentVO.class));
}
JSONArray adviceList = json.getJSONArray("adviceList");
if (adviceList != null && !adviceList.isEmpty()) {
List<Map<String, String>> adviceMapList = new ArrayList<>();
// 遍历adviceList里的指标名称尝试在modelIndices集合中找到name匹配的指标并根据indexType更新当前指标名称在字符串前插入对应的指标类型
for (int i = 0; i < adviceList.size(); i++) {
String advice = adviceList.getString(i);
for (ModelIndex modelIndex : modelIndices) {
if (advice.equals(modelIndex.getName())) {
Map<String, String> map = new HashMap<>();
map.put("indexType", indexType.get(modelIndex.getIndexType()));
map.put("indexName", modelIndex.getName());
adviceMapList.add(map);
break;
}
}
}
adviceMapList.add(Map.of("indexType", "", "indexName", "以上都不是"));
answerMap.put("adviceList", adviceMapList);
}
chatResVO.setAnswer(json.getString("answerText"));
chatResVO.setDialogueCount(json.getInteger("dialogueCount") == null ? 0 : json.getInteger("dialogueCount"));
} else {
log.error("返回结果格式异常query:【{}】", query);
}
}
break;
case QA_TYPE_NX_LLM:
answerMap = executeIntent(intentType, caseId, query, answerMap, modelIndices);
break;
default:
break;
}
if (StringUtils.isEmpty(chatResVO.getAnswer()) && "{}".equals(JSON.toJSONString(answerMap))) {
log.error("chatNew: 未找到答案query:【{}】", query);
return R.fail("未找到答案");
}
long end = System.currentTimeMillis();
ConversationQa qa = new ConversationQa();
qa.setId(UUID.randomUUID().toString());
qa.setDialogCount(chatResVO.getDialogueCount());
qa.setQuestion(query);
qa.setQuestionTime(new Date(startTime));
qa.setAnswer(chatResVO.getAnswer());
qa.setAnswerMap(JSON.toJSONString(answerMap));
qa.setSegmentList(chatResVO.getSegmentList());
qa.setAnswerTime(new Date(end));
qa.setType(type);
qa.setIntentType(intentType);
qa.setTimeInterval(String.valueOf(end - startTime));
qa.setCaseId(caseId);
qa.setUserId(userId);
qa.setConversationId(chatReqVO.getConversationId());
conversationQaService.save(qa);
log.info("QA已保存qaId:【{}】question【{}】answer【{}】", qa.getId(), query, JSON.toJSONString(answerMap));
chatResVO.setAnswwerMap(answerMap);
chatResVO.setType(type);
chatResVO.setIntentType(intentType);
chatResVO.setConversationId(chatReqVO.getConversationId());
return R.ok(chatResVO);
}
@Override
public IPage<ChatResVO> queryConversationInfoList(String conversationId, int page, int size) {
Assert.notEmpty(conversationId, "会话id不能为空");
IPage<ConversationQa> qaPage = conversationQaService.lambdaQuery().eq(ConversationQa::getConversationId, conversationId)
.orderBy(true, true, ConversationQa::getQuestionTime).page(Page.of(page, size));
return qaPage.convert(ChatResVO::new);
}
@Override
public IPage<ConversationResVo> queryUserConversationList(String userId, int page, int size) {
Assert.notEmpty(userId, "用户id不能为空");
return conversationService.queryUserConversationList(userId, DateUtil.offsetDay(DateUtil.date(), -180), null, new Page<>(page, size));
}
@Override
@Transactional(rollbackFor = Exception.class, transactionManager = "dataSourceTransactionManager")
public void deleteConversation(List<String> conversationIdList) {
if (CollUtil.isEmpty(conversationIdList)) {
return;
}
for (String conversationId : conversationIdList) {
boolean success = conversationService.removeById(conversationId);
if (success) {
conversationQaService.lambdaUpdate().eq(ConversationQa::getConversationId, conversationId).remove();
}
}
}
/**
*
*
* @param modelIndices
* @param query
* @param caseId id
* @param answerMap map
*/
private void handleIndexResultQA(List<ModelIndex> modelIndices, String query, String caseId, Map<String, Object> answerMap) {
//如果案件分析状态不是分析成功,则先执行案件分析
ModelCase modelCase = modelCaseService.getById(caseId);
ModelIndex modelIndex = modelIndices.stream().filter(index -> query.equals(index.getName())).findFirst().get();
IndexResultQuery indexResultQuery = new IndexResultQuery();
indexResultQuery.setCaseId(caseId);
indexResultQuery.setIndexType(modelIndex.getIndexType());
indexResultQuery.setIndexName(modelIndex.getName());
IPage<IndexDetail> indexDetailPage = modelCaseService.getIndexDetail(indexResultQuery, 1, 1);
if (indexDetailPage.getRecords().isEmpty() || (modelCase.getTotalScore() == null && modelCase.getCaseAnalysisStatus() != CaseAnalysisStatusEnum.ANALYZED.getCode())) {
log.info("案件【{}】尚未执行模型分析,现在开始执行", modelCase.getCaseName());
AnalyseCaseDTO analyseCaseDTO = new AnalyseCaseDTO();
analyseCaseDTO.setCaseId(caseId);
modelService.analyseCaseWrapper(analyseCaseDTO);
}
indexDetailPage = modelCaseService.getIndexDetail(indexResultQuery, 1, 1);
if (!indexDetailPage.getRecords().isEmpty()) {
IndexDetail indexDetail = indexDetailPage.getRecords().get(0);
answerMap.put("indexName", modelIndex.getName());
answerMap.put("indexType", modelIndex.getIndexType());
answerMap.put("result", Boolean.parseBoolean(indexDetail.getIndexResult()) ? "符合" : "不符合");
List<Map<String, String>> qaSplitList = new ArrayList<>();
if (CollUtil.isNotEmpty(indexDetail.getChildren())) {
indexDetail.getChildren().forEach(atomicIndexDTO -> {
if (!atomicIndexDTO.getRecordSegmentationList().isEmpty()) {
atomicIndexDTO.getRecordSegmentationList().forEach(split -> {
Map<String, String> qaMap = new HashMap<>();
qaMap.put("question", split.getQuestion());
qaMap.put("answer", split.getAnswer());
qaMap.put("noteRecordId", split.getNoteRecordId());
qaMap.put("splitId", split.getId());
qaMap.put("noteName", split.getNoteName());
qaMap.put("noteFileId", split.getNoteFileId());
qaSplitList.add(qaMap);
});
}
});
}
answerMap.put("qaSplitList", qaSplitList);
List<Map<String, String>> evidenceList = new ArrayList<>();
if (CollUtil.isNotEmpty(indexDetail.getChildren())) {
indexDetail.getChildren().forEach(atomicIndexDTO -> {
if (!atomicIndexDTO.getEvidentResultList().isEmpty()) {
atomicIndexDTO.getEvidentResultList().forEach(evidentIndexResultDTO -> {
Map<String, String> evidenceMap = new HashMap<>();
evidenceMap.put("evidenceName", evidentIndexResultDTO.getEvidenceName());
evidenceMap.put("evidenceId", evidentIndexResultDTO.getEvidenceId());
evidenceList.add(evidenceMap);
});
}
});
}
answerMap.put("evidenceNames", evidenceList);
}
}
private Map<String, Object> executeIntent(String intentType, String caseId, String query, Map<String, Object> answerMap, List<ModelIndex> modelIndices) {
switch (intentType) {
case INTENT_TYPE_INDEX_RESULT:
if (modelIndices.stream().map(ModelIndex::getName).anyMatch(query::equals)) {
handleIndexResultQA(modelIndices, query, caseId, answerMap);
} else {
answerMap.put("answerText", "暂无相关指标信息");
}
break;
case INTENT_TYPE_CASE_RESULT:
ModelCase modelCase = modelCaseService.getById(caseId);
if (modelCase.getTotalScore() == null) {
log.info("案件【{}】尚未执行模型分析,现在开始执行", modelCase.getCaseName());
AnalyseCaseDTO analyseCaseDTO = new AnalyseCaseDTO();
analyseCaseDTO.setCaseId(caseId);
modelService.analyseCaseWrapper(analyseCaseDTO);
}
answerMap = JSON.parseObject(JSON.toJSONString(modelService.caseScoreDetail(caseId)), Map.class);
break;
case INTENT_TYPE_CASE_OVERVIEW:
answerMap.put("answerText", modelCaseService.getById(caseId).getCaseDetail());
break;
case INTENT_TYPE_CASE_EVIDENCE_GUIDE:
answerMap.put("guideDesc", modelService.caseScoreDetail(caseId).getGuideDesc());
break;
default:
break;
}
return answerMap;
}
}

@ -0,0 +1,22 @@
package com.supervision.police.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.supervision.police.domain.ConversationQa;
import com.supervision.police.service.ConversationQaService;
import com.supervision.police.mapper.ConversationQaMapper;
import org.springframework.stereotype.Service;
/**
* @author yaxin
* @description conversation_qaService
* @createDate 2024-11-22 11:37:02
*/
@Service
public class ConversationQaServiceImpl extends ServiceImpl<ConversationQaMapper, ConversationQa>
implements ConversationQaService{
}

@ -0,0 +1,31 @@
package com.supervision.police.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.supervision.police.domain.Conversation;
import com.supervision.police.service.ConversationService;
import com.supervision.police.mapper.ConversationMapper;
import com.supervision.police.vo.ConversationResVo;
import org.springframework.stereotype.Service;
import java.util.Date;
/**
* @author yaxin
* @description conversation()Service
* @createDate 2024-11-25 13:43:52
*/
@Service
public class ConversationServiceImpl extends ServiceImpl<ConversationMapper, Conversation>
implements ConversationService{
@Override
public IPage<ConversationResVo> queryUserConversationList(String userId, Date startTime,Date endTime, Page<ConversationResVo> page) {
return super.getBaseMapper().queryUserConversationList(userId,startTime,endTime, page);
}
}

@ -12,7 +12,6 @@ import com.supervision.police.service.NotePromptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
@ -27,10 +26,15 @@ public class EvidenceCategoryServiceImpl extends ServiceImpl<EvidenceCategoryMap
@Autowired
private NotePromptService notePromptService;
/**
*
* @param caseType
* @return
*/
@Override
public List<EvidenceCategoryDTO> listCategoryTree(String caseType) {
List<EvidenceCategoryDTO> list = super.getBaseMapper().listCategoryDTO(caseType);
List<EvidenceCategoryDTO> list = super.getBaseMapper().listCategoryDTO(null);
List<NotePrompt> notePrompts = notePromptService.list();
for (EvidenceCategoryDTO categoryDTO : list) {
List<EvidenceCategoryDTO> child = list.stream()
@ -47,6 +51,11 @@ public class EvidenceCategoryServiceImpl extends ServiceImpl<EvidenceCategoryMap
}
return list.stream().filter(categoryDTO -> StrUtil.isEmpty(categoryDTO.getParentId())).toList();
}
@Override
public List<EvidenceCategory> listCategoryByCaseType(String caseType) {
return super.lambdaQuery().list();
}
}

@ -1,9 +1,9 @@
package com.supervision.police.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.supervision.neo4j.service.Neo4jService;
import com.supervision.police.domain.CasePerson;
import com.supervision.police.domain.NotePrompt;
import com.supervision.police.domain.NoteRecordSplit;
@ -31,8 +31,6 @@ import java.util.function.Consumer;
@RequiredArgsConstructor
public class ExtractTripleInfoServiceImpl implements ExtractTripleInfoService {
private final CaseTaskRecordService caseTaskRecordService;
private final NotePromptService notePromptService;
private final TripleInfoService tripleInfoService;
@ -44,6 +42,8 @@ public class ExtractTripleInfoServiceImpl implements ExtractTripleInfoService {
@Autowired
private NoteRecordSplitService noteRecordSplitService;
private final Neo4jService neo4jService;
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class)
public void extractTripleInfo(String caseId, String name, String recordSplitId) {
@ -66,10 +66,8 @@ public class ExtractTripleInfoServiceImpl implements ExtractTripleInfoService {
log.warn("extractTripleInfo:笔录片段:{},笔录分类:{} 不属于任何提示词,不进行后续操作...", recordSplit.getId(), recordSplit.getRecordType());
return;
}
QueryWrapper<CasePerson> wrapper = new QueryWrapper<>();
wrapper.eq("case_id", caseId);
wrapper.eq("case_actor_flag", 1);
CasePerson mainActor = casePersonService.getOne(wrapper);
CasePerson mainActor = casePersonService.getMainActor(caseId);
List<TripleExtractTask> taskList = notePromptList.stream()
.filter(prompt -> StrUtil.isNotBlank(prompt.getPrompt()))
@ -84,9 +82,15 @@ public class ExtractTripleInfoServiceImpl implements ExtractTripleInfoService {
return;
}
log.info("extractTripleInfo:笔录片段:{}开始提交三元组抽取任务,任务数量:{}", recordSplit.getId(),taskList.size());
List<TripleInfo> tripleInfos = doTripleExtractTask(taskList);
log.info("extractTripleInfo:笔录片段:{}三元组抽取任务提交结束,抽取三元组个数:{}...", recordSplit.getId(), tripleInfos.size());
}
private List<TripleInfo> doTripleExtractTask(List<TripleExtractTask> taskList) {
List<TripleInfo> tripleInfos = new ArrayList<>();
try {
log.info("extractTripleInfo:笔录片段:{}抽取任务成功提交{}个任务....", recordSplitId, taskList.size());
log.info("doTripleExtractTask:抽取任务成功提交{}个任务....", taskList.size());
List<Future<TripleInfo>> futures = TripleExtractTaskPool.executor.invokeAll(taskList);
for (Future<TripleInfo> future : futures) {
@ -96,22 +100,65 @@ public class ExtractTripleInfoServiceImpl implements ExtractTripleInfoService {
tripleInfos.add(tripleInfo);
}
} catch (ExecutionException e) {
log.error("extractTripleInfo:笔录片段:{}三元组提取任务执行失败...", recordSplitId, e);
log.error("doTripleExtractTask:三元组提取任务执行失败...", e);
}
}
} catch (InterruptedException e) {
log.error("extractTripleInfo:笔录片段:{}三元组提取任务提交失败...", recordSplitId, e);
log.error("doTripleExtractTask:三元组提取任务提交失败...", e);
}
// 如果有提取到三元组信息
if (CollUtil.isNotEmpty(tripleInfos)) {
for (TripleInfo tripleInfo : tripleInfos) {
log.info("extractTripleInfo:笔录片段:{}三元组提取任务执行结束...,三元组信息入库:{}", recordSplitId, JSONUtil.toJsonStr(tripleInfo));
tripleInfoService.save(tripleInfo);
// 三元组入库到neo4j
log.info("doTripleExtractTask:笔录片段:{}三元组提取任务执行结束,开始三元组信息入库",tripleInfo.getRecordSplitId());
neo4jService.saveTripleInfo(tripleInfo);
log.info("doTripleExtractTask:笔录片段:{}三元组提取任务执行结束...,开始三元组信息入库",tripleInfo.getRecordSplitId());
tripleInfo.setAddNeo4j("1");
tripleInfoService.saveOrUpdateByBusiness(tripleInfo);
}
} else {
log.info("extractTripleInfo:笔录片段:{}三元组提取任务执行结束...,未提取到任何三元组信息...", recordSplitId);
}
return tripleInfos;
}
@Override
public List<TripleInfo> extractTripleInfo(NotePrompt notePrompt,CasePerson mainActor,List<NoteRecordSplit> noteRecordSplitList) {
Assert.notEmpty(noteRecordSplitList, "noteRecordSplitList不能为空");
Assert.notNull(notePrompt, "notePrompt不能为空");
List<TripleExtractTask> taskList = noteRecordSplitList.stream().map(
noteRecordSplit ->
new TripleExtractTask(chatClient, notePrompt, noteRecordSplit, postExtractTriple(), mainActor)
).toList();
if (CollUtil.isEmpty(taskList)){
return new ArrayList<>();
}
log.info("extractTripleInfo:提示词:{}开始提交三元组抽取任务,任务数量:{}", notePrompt.getName(),taskList.size());
List<TripleInfo> tripleInfos = doTripleExtractTask(taskList);
log.info("extractTripleInfo:提示词:{}三元组抽取任务提交结束,抽取三元组个数:{}...", notePrompt.getName(), tripleInfos.size());
return tripleInfos;
}
@Override
public List<TripleInfo> extractTripleInfo(NotePrompt notePrompt, String caseId, String recordId) {
Assert.notNull(notePrompt, "notePrompt不能为空");
Assert.notEmpty(recordId, "recordId不能为空");
Assert.notEmpty(caseId, "caseId不能为空");
// 先清除之前的三元组信息
List<TripleInfo> tripleInfos = tripleInfoService.queryByRecordIdAndPrompt(recordId, notePrompt);
log.info("extractTripleInfo:笔录片段:{}清除之前的三元组信息,三元组个数:{}", recordId, tripleInfos.size());
for (TripleInfo tripleInfo : tripleInfos) {
neo4jService.deleteTripleInfo(tripleInfo);
tripleInfoService.removeById(tripleInfo.getId());
}
CasePerson mainActor = casePersonService.getMainActor(caseId);
List<NoteRecordSplit> noteRecordSplits = noteRecordSplitService.queryRecordSplitList(recordId);
return extractTripleInfo(notePrompt, mainActor, noteRecordSplits);
}
private Consumer<NoteRecordSplit> postExtractTriple() {

@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.supervision.constant.DataStatus;
import com.supervision.police.domain.ModelAtomicIndex;
import com.supervision.police.domain.ModelIndex;
import com.supervision.police.dto.AtomicIndexUsedDTO;
import com.supervision.police.dto.JudgeLogic;
import com.supervision.police.dto.ModelIndexDTO;
import com.supervision.police.mapper.ModelAtomicIndexMapper;
@ -81,4 +82,9 @@ public class ModelAtomicIndexServiceImpl extends ServiceImpl<ModelAtomicIndexMap
modelIndexService.lambdaUpdate().eq(ModelIndex::getId, modelIndexDTO.getId()).set(ModelIndex::getJudgeLogic, modelIndexDTO.getJudgeLogic()).update();
});
}
@Override
public List<AtomicIndexUsedDTO> atomicUsed(String atomicIndexId) {
return super.getBaseMapper().atomicUsed(atomicIndexId);
}
}

@ -7,7 +7,20 @@ import com.supervision.police.service.ModelAtomicResultService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
@Slf4j
@Service
public class ModelAtomicResultServiceImpl extends ServiceImpl<ModelAtomicResultMapper, ModelAtomicResult> implements ModelAtomicResultService {
@Override
public List<ModelAtomicResult> queryByCaseIdForUpdate(String caseId) {
return super.getBaseMapper().queryByCaseIdForUpdate(caseId);
}
@Override
public void replaceResultCaseId(String oldCaseId, String newCaseId) {
super.lambdaUpdate().eq(ModelAtomicResult::getCaseId, oldCaseId)
.set(ModelAtomicResult::getCaseId, newCaseId).update();
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save