190 lines
6.2 KiB
Markdown
190 lines
6.2 KiB
Markdown
# Phase 2 遗留功能:挖掘任务管理
|
||
|
||
> 状态:设计已完成,待后续启动开发
|
||
> 记录时间:2026-06-04
|
||
|
||
---
|
||
|
||
## 功能概述
|
||
|
||
当前「会话挖掘」点击"开始挖掘"后没有任何进度反馈,用户处于黑盒等待状态。
|
||
本功能旨在为每次挖掘任务建立完整的生命周期管理:创建 → 执行中 → 完成/失败,并提供实时进度和历史回溯能力。
|
||
|
||
---
|
||
|
||
## 数据库设计
|
||
|
||
### 新增表 `chat_mining_tasks`
|
||
|
||
```sql
|
||
CREATE TABLE chat_mining_tasks (
|
||
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||
task_id VARCHAR(64) NOT NULL COMMENT '任务唯一标识 UUID',
|
||
corp_id VARCHAR(64) NOT NULL COMMENT '企业ID',
|
||
target_type VARCHAR(20) NOT NULL COMMENT '挖掘目标: UTTERANCE/KNOWLEDGE/ALL',
|
||
status VARCHAR(20) NOT NULL COMMENT '状态: PENDING/RUNNING/COMPLETED/FAILED',
|
||
total_sessions INT DEFAULT 0 COMMENT '总会话数',
|
||
processed_sessions INT DEFAULT 0 COMMENT '已处理会话数',
|
||
total_extracted INT DEFAULT 0 COMMENT 'LLM提取总数',
|
||
total_saved INT DEFAULT 0 COMMENT '入库候选数',
|
||
total_duplicates INT DEFAULT 0 COMMENT '去重过滤数',
|
||
min_score INT DEFAULT 6 COMMENT '质量分阈值',
|
||
time_range_start BIGINT COMMENT '时间范围起始(ms)',
|
||
time_range_end BIGINT COMMENT '时间范围结束(ms)',
|
||
error_msg TEXT COMMENT '失败原因',
|
||
started_at TIMESTAMP NULL COMMENT '开始时间',
|
||
completed_at TIMESTAMP NULL COMMENT '完成时间',
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
UNIQUE KEY uk_task_id (task_id),
|
||
INDEX idx_corp_status (corp_id, status),
|
||
INDEX idx_created_at (created_at)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会话挖掘任务记录';
|
||
```
|
||
|
||
---
|
||
|
||
## 后端改动清单
|
||
|
||
### 1. 新增实体 `MiningTask.java`
|
||
|
||
路径:`backend/kb-admin-service/src/main/java/com/artedu/kbadmin/entity/MiningTask.java`
|
||
|
||
字段与上表对应,使用 MyBatis-Plus 注解。
|
||
|
||
### 2. 新增 Mapper `MiningTaskMapper.java`
|
||
|
||
```java
|
||
@Mapper
|
||
public interface MiningTaskMapper extends BaseMapper<MiningTask> {
|
||
}
|
||
```
|
||
|
||
### 3. 修改 `ChatMiningService.startMining()`
|
||
|
||
- 任务开始时:创建 `MiningTask` 记录,状态 `RUNNING`
|
||
- 每处理完一个会话:更新 `processed_sessions`
|
||
- 任务完成:更新状态 `COMPLETED`,记录 `total_extracted`、`total_saved`、`total_duplicates`
|
||
- 任务异常:更新状态 `FAILED`,记录 `error_msg`
|
||
|
||
**关键代码示意:**
|
||
```java
|
||
@Async
|
||
public void startMining(String taskId, String corpId, ...) {
|
||
// 1. 创建任务记录
|
||
MiningTask task = new MiningTask();
|
||
task.setTaskId(taskId);
|
||
task.setStatus("RUNNING");
|
||
task.setStartedAt(LocalDateTime.now());
|
||
miningTaskMapper.insert(task);
|
||
|
||
try {
|
||
List<String> sessionIds = selectQualitySessions(...);
|
||
task.setTotalSessions(sessionIds.size());
|
||
miningTaskMapper.updateById(task);
|
||
|
||
for (String sessionId : sessionIds) {
|
||
// ... 提取逻辑 ...
|
||
task.setProcessedSessions(task.getProcessedSessions() + 1);
|
||
task.setTotalExtracted(task.getTotalExtracted() + extracted);
|
||
task.setTotalSaved(task.getTotalSaved() + saved);
|
||
miningTaskMapper.updateById(task); // 每会话更新进度
|
||
}
|
||
|
||
task.setStatus("COMPLETED");
|
||
task.setCompletedAt(LocalDateTime.now());
|
||
} catch (Exception e) {
|
||
task.setStatus("FAILED");
|
||
task.setErrorMsg(e.getMessage());
|
||
}
|
||
miningTaskMapper.updateById(task);
|
||
}
|
||
```
|
||
|
||
### 4. 修改 `ChatMiningController.startMining()`
|
||
|
||
- 生成 `taskId`(UUID)
|
||
- 异步调用 `chatMiningService.startMining(taskId, corpId, ...)`
|
||
- 立即返回任务 ID:`{"taskId": "xxx", "message": "挖掘任务已启动"}`
|
||
|
||
### 5. 新增接口
|
||
|
||
```java
|
||
// 任务列表(分页)
|
||
@GetMapping("/tasks")
|
||
public Result<PageResult<MiningTask>> listTasks(
|
||
@RequestParam String corpId,
|
||
@RequestParam(defaultValue = "1") int page,
|
||
@RequestParam(defaultValue = "10") int size)
|
||
|
||
// 任务进度查询(前端轮询用)
|
||
@GetMapping("/tasks/{taskId}/progress")
|
||
public Result<Map<String, Object>> getTaskProgress(@PathVariable String taskId)
|
||
```
|
||
|
||
---
|
||
|
||
## 前端改动清单
|
||
|
||
### 1. 启动任务后立即显示任务卡片
|
||
|
||
点击「开始挖掘」后,不再只显示 toast,而是在页面下方新增一个「正在运行」的任务卡片:
|
||
- 任务ID、目标类型、时间范围
|
||
- 进度条:`已处理 N / M 个会话`
|
||
- 前端每 3 秒轮询 `/tasks/{taskId}/progress`
|
||
|
||
### 2. 新增「任务历史」折叠面板
|
||
|
||
在「挖掘任务配置」下方增加可折叠的「任务历史」区域:
|
||
- 表格列:任务ID、目标类型、状态(带颜色标签)、会话数、提取数、保存数、去重数、耗时、操作
|
||
- 状态标签:
|
||
- `RUNNING` → 蓝色 + 进度条
|
||
- `COMPLETED` → 绿色
|
||
- `FAILED` → 红色
|
||
- 操作按钮:查看详情(显示失败原因)
|
||
|
||
### 3. 实时进度组件
|
||
|
||
```tsx
|
||
// 轮询任务进度
|
||
useEffect(() => {
|
||
if (!runningTaskId) return
|
||
const timer = setInterval(async () => {
|
||
const res = await request.get(`/v1/admin/chat-mine/tasks/${runningTaskId}/progress`)
|
||
setTaskProgress(res.data)
|
||
if (res.data.status !== 'RUNNING') {
|
||
clearInterval(timer)
|
||
loadStats()
|
||
loadCandidates(activeTab)
|
||
}
|
||
}, 3000)
|
||
return () => clearInterval(timer)
|
||
}, [runningTaskId])
|
||
```
|
||
|
||
---
|
||
|
||
## 待决策事项
|
||
|
||
| 事项 | 建议方案 | 备注 |
|
||
|------|---------|------|
|
||
| 进度更新频率 | 每处理完1个会话更新DB | 简单可靠,DB压力可控(单次挖掘≤100会话) |
|
||
| 轮询间隔 | 前端3秒轮询 | 平衡实时性和服务器压力 |
|
||
| 历史任务保留 | 保留最近30天 | 可定期清理或归档 |
|
||
| 并发任务 | 同企业只允许1个RUNNING任务 | 避免资源竞争和LLM限流 |
|
||
|
||
---
|
||
|
||
## 关联文件
|
||
|
||
- 后端:`ChatMiningService.java`、`ChatMiningController.java`
|
||
- 前端:`ChatMining.tsx`
|
||
- 数据库:`chat_mining_tasks` 表
|
||
|
||
## 启动条件
|
||
|
||
当运营团队反馈以下痛点时启动开发:
|
||
1. "点击挖掘后不知道跑到哪了,刷新页面也不知道有没有完成"
|
||
2. "想看一下昨天挖了哪些会话、质量怎么样"
|
||
3. "多人同时操作可能会重复挖掘"
|