feat(mcp): 新增 MCP 服务基础设施,重构规则文件序号,新增 v1.3.0 工单文档

- 规则重组:全局/ 下 8 个规则合并为 6 个(01+02→01,05+06→04),序号顺延

- 新增项目规则 05-多入口功能同步规范(UI/语音入口覆盖检查)

- 新增 MCP 服务基础设施:Mcp/ 目录(DI 注册、端点扩展、动态工具描述符)、单元测试

- v1.3.0 工单文档:03 系列(会议任务拆分)、04(富文本描述与附件管理)

- MCP 接口与前端集成指南:docs/manual/08、09
This commit is contained in:
ShaoHua
2026-06-16 01:15:40 +08:00
parent aacc56e952
commit 9223ceca50
30 changed files with 3907 additions and 346 deletions
@@ -0,0 +1,341 @@
# 研发工单 v1.3.0 - 03 会议任务拆分
> 术语澄清:本文件中"研发工单"指智能体/开发者执行的**编码工作项**;"任务/待办项/Todo"指 Hua.Todo 业务领域的 **Todo 待办项**(Task 实体),二者请勿混淆。
---
## 一、目标与范围
### 1.1 目标
实现"会议内容 → AI 任务拆分"功能:用户创建一个标记为"会议"类型的 Todo 待办项作为父目录,通过录音或文字输入会议内容,由 AI 分析后生成待办项建议列表,用户确认后批量创建为子任务。
### 1.2 核心流程
```
用户创建"会议"类型父任务(指定标题,如"周一产品评审会")
选择输入方式:
├─ 录音:录制会议音频 → 系统转写为文字
└─ 文字:直接输入/粘贴会议纪要
AI 分析会议内容 → 生成待办项建议列表
(每条建议含:标题、优先级、可选截止日期)
用户审阅建议列表:
├─ 勾选/取消勾选
├─ 编辑建议内容(修改标题、调整优先级)
└─ 手动补充新条目
确认 → 批量创建为父任务的子待办项
```
### 1.3 范围
**包含**
- "会议"类型标记:创建 Todo 时可指定为会议类型,UI 上以图标/标签区分
- 音频录制:前端录音控件,录制会议音频
- 音频转写:将录音发送至后端,调用 STT 服务转为文字
- 文字输入:直接输入/粘贴会议纪要文本
- AI 任务拆分:将会议文字内容发送给 LLM,生成结构化待办项建议
- 建议审阅与确认 UI:用户勾选、编辑、补充建议后批量创建子任务
- 与工单 02 的 LLM 基础设施复用(`LlmClientService`
**不包含**
- 实时语音转写(边录边转,后续版本考虑)
- 多人协作/会议纪要共享
- 音频文件持久存储(录音转写完成后不保留音频,节省空间;如需保留为后续版本需求)
- 会议录音的云同步(后续版本)
---
## 二、前置条件
| 条件 | 说明 | 状态 |
|---|---|---|
| Hua.Todo v1.2.0 | 基础业务能力(Task CRUD、父子任务) | 已完成 |
| 工单 02 LLM 基础设施 | `LlmClientService`、AI 拆分服务 | 待实现 |
| 浏览器 MediaRecorder API | 前端音频录制 | 已就绪(主流浏览器支持) |
| 后端 STT 服务 | 音频转文字(可复用工单 02 的 STT 能力或调用第三方 API) | 待实现 |
---
## 三、子工单拆分
| 子工单 | 标题 | 依赖 | 可并行 |
|---|---|---|---|
| 03-01 | 会议数据模型与 API | 无 | 是 |
| 03-02 | 音频录制与转写 | 03-01(API 契约) | 部分(前端录音 UI 可并行) |
| 03-03 | AI 任务拆分服务 | 03-01、工单 02 LlmClientService | 部分(prompt 设计可并行) |
| 03-04 | 任务建议与确认 UI | 03-01、03-03 | 否(依赖后端 API 就绪) |
### 执行顺序建议
```
03-01(模型与API) ──────┐
├──→ 03-04(确认UI)
03-02(录制与转写) ──────┤
03-03(AI拆分服务) ──────┘
```
03-01、03-02、03-03 可部分并行推进;03-04 需等前三者 API 就绪后开始。
---
## 四、架构设计
### 4.1 整体架构
```
┌──────────────────────────────────────────────────┐
│ Vue 前端 │
│ ┌─────────────┐ ┌─────────────┐ ┌────────────┐ │
│ │ 录音控件 │ │ 文字输入区 │ │ 建议审阅 │ │
│ │ MediaRecorder│ │ Textarea │ │ 确认对话框 │ │
│ └──────┬──────┘ └──────┬──────┘ └─────┬──────┘ │
│ │ │ │ │
│ ▼ ▼ │ │
│ ┌──────────────────────────────┐ │ │
│ │ meetingApi (前端 API 模块) │ │ │
│ └──────────────┬───────────────┘ │ │
└─────────────────┼──────────────────────┼─────────┘
│ HTTP │
▼ │
┌─────────────────────────────────────────┤
│ 后端 (Application 层) │
│ ┌────────────┐ ┌─────────────────┐ │
│ │ Meeting │ │ MeetingAi │ │
│ │ Controller │ │ BreakdownService│ │
│ └─────┬──────┘ └───────┬─────────┘ │
│ │ │ │
│ ┌─────▼──────┐ ┌──────▼─────────┐ │
│ │ Meeting │ │ LlmClient │ │
│ │ Service │ │ Service (复用02)│ │
│ └─────┬──────┘ └────────────────┘ │
│ │ │
│ ┌─────▼──────┐ │
│ │ STT 服务 │ │
│ │ (转写音频) │ │
│ └────────────┘ │
└─────────────────────────────────────────┘
```
### 4.2 数据模型扩展
在现有 `TaskEntity` 上新增 `TaskType` 字段,区分普通待办项与会议:
```csharp
/// <summary>待办项类型枚举</summary>
public enum TaskType
{
/// <summary>普通待办项(默认)</summary>
Normal = 0,
/// <summary>会议(可包含录音、纪要,支持 AI 任务拆分)</summary>
Meeting = 1
}
```
`TaskEntity` 新增字段:
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| `TaskType` | `TaskType` | `Normal` | 待办项类型 |
| `MeetingNotes` | `string?` | null | 会议纪要/转写文字(仅 Meeting 类型有值) |
| `AudioDuration` | `double?` | null | 录音时长(秒),仅 Meeting 类型有值 |
> 注意:音频文件本身不持久存储,转写完成后仅保留文字结果。`AudioDuration` 用于 UI 展示录音时长。
### 4.3 API 设计
#### 4.3.1 创建会议类型待办项
```
POST /api/task
请求体:
{
"title": "周一产品评审会",
"priority": 1,
"taskType": 1 // TaskType.Meeting = 1
}
响应体:
{
"success": true,
"data": {
"id": 42,
"title": "周一产品评审会",
"taskType": 1,
"meetingNotes": null,
"audioDuration": null,
...
}
}
```
#### 4.3.2 上传录音并转写
```
POST /api/meeting/{taskId}/transcribe
Content-Type: multipart/form-data
字段:
- audio: 音频文件(webm/wav/mp3
- format: 音频格式(可选,默认从文件扩展名推断)
响应体:
{
"success": true,
"data": {
"taskId": 42,
"transcript": "今天的产品评审会主要讨论了三个议题:第一...",
"audioDuration": 1830.5
}
}
```
#### 4.3.3 保存会议纪要(文字输入)
```
POST /api/meeting/{taskId}/notes
请求体:
{
"notes": "今天的产品评审会主要讨论了三个议题:第一..."
}
响应体:
{
"success": true,
"data": {
"taskId": 42,
"meetingNotes": "今天的产品评审会主要讨论了三个议题:第一..."
}
}
```
#### 4.3.4 AI 任务拆分建议
```
POST /api/meeting/{taskId}/breakdown
请求体:
{
"notes": "..." // 可选,若不传则使用已保存的 meetingNotes
}
响应体:
{
"success": true,
"data": {
"taskId": 42,
"suggestions": [
{
"title": "整理产品需求文档",
"priority": 2,
"reason": "会议中提到需要在本周五前完成需求文档的整理"
},
{
"title": "安排技术方案评审",
"priority": 1,
"reason": "张三负责在下周三前输出技术方案"
},
{
"title": "跟进客户反馈",
"priority": 0,
"reason": "李四反馈了三个客户问题,需后续跟进"
}
]
}
}
```
#### 4.3.5 确认并批量创建子任务
```
POST /api/meeting/{taskId}/breakdown/confirm
请求体:
{
"subTasks": [
{ "title": "整理产品需求文档", "priority": 2 },
{ "title": "安排技术方案评审", "priority": 1 }
]
}
响应体:
{
"success": true,
"data": {
"createdCount": 2,
"subTasks": [
{ "id": 43, "title": "整理产品需求文档", "priority": 2, "parentTaskId": 42 },
{ "id": 44, "title": "安排技术方案评审", "priority": 1, "parentTaskId": 42 }
]
}
}
```
---
## 五、与工单 02 的边界
| 能力 | 工单 02 | 工单 03 |
|---|---|---|
| LLM 调用 | `LlmClientService` 基础设施 | 复用 `LlmClientService`,新增会议拆分专用 prompt |
| 语音输入 | STT 平台原生能力(语音指令) | 前端 MediaRecorder 录音 → 后端 STT 转写(场景不同) |
| AI 拆分 | 对已有单个任务做拆分(`AI_BREAKDOWN` 意图) | 对会议内容做拆分(输入为长文本,输出为多条建议) |
| 确认流程 | 语音确认/点选候选 | 专门的审阅 UI(勾选、编辑、补充) |
**复用关系**
- `LlmClientService`:03 直接复用 02 的 LLM 调用封装
- `AiBreakdownService`:02 的单任务拆分服务,03 不直接复用(输入形式和输出结构不同),但设计上保持一致的调用模式
---
## 六、验收标准
| 验收项 | 验证方法 | 预期结果 |
|---|---|---|
| 创建会议类型待办项 | 创建 Todo 时选择"会议"类型 | 创建成功,列表中显示会议图标/标签 |
| 录音功能 | 点击录音按钮,录制一段音频 | 录音控件正常工作,显示录音时长 |
| 录音转写 | 录音完成后提交 | 后端返回转写文字,文字内容基本准确 |
| 文字输入纪要 | 在会议待办项中粘贴会议纪要 | 保存成功,再次打开可见纪要内容 |
| AI 拆分建议 | 提交会议内容请求 AI 拆分 | 返回 3-10 条建议,每条含标题+优先级+理由 |
| 建议审阅 | 勾选/取消/编辑建议 | UI 支持勾选、编辑标题和优先级 |
| 批量创建 | 确认勾选的建议 | 子任务批量创建到父任务下 |
| 离线降级 | 离线时请求 AI 拆分 | 提示"离线模式不支持 AI 拆分" |
| 非会议类型 | 普通待办项不显示录音/拆分入口 | 功能入口仅对 Meeting 类型显示 |
---
## 七、风险与回滚
| 风险 | 影响 | 应对策略 |
|---|---|---|
| STT 转写准确率不足 | 会议纪要质量差,影响 AI 拆分效果 | 支持文字输入作为备选;转写后允许用户编辑修正 |
| LLM API 不稳定 | AI 拆分功能不可用 | 功能降级,其他会议功能(录音、纪要)不受影响 |
| 录音文件过大 | 上传超时/存储压力大 | 前端限制录音时长(建议最长 2 小时);压缩音频格式 |
| 浏览器 MediaRecorder 兼容性 | 部分平台录音功能不可用 | 降级提示"当前浏览器不支持录音,请使用文字输入" |
---
## 八、Touch List
| 文件路径 | 修改类型 | 是否共享 | 说明 |
|---|---|---|---|
| `src/Hua.Todo.Core/Entities/TaskType.cs` | 新增 | 否 | TaskType 枚举 |
| `src/Hua.Todo.Core/Entities/TaskEntity.cs` | 修改 | 是 | 新增 TaskType/MeetingNotes/AudioDuration 字段 |
| `src/Hua.Todo.Application/Data/TodoDbContext.cs` | 修改 | 是 | 新增字段映射 + 迁移 |
| `src/Hua.Todo.Application/Models/TaskModels.cs` | 修改 | 是 | DTO 扩展(CreateTaskDto/TaskDto 新增字段) |
| `src/Hua.Todo.Application/Meeting/` | 新增目录 | 否 | 会议相关服务目录 |
| `src/Hua.Todo.Application/Meeting/MeetingController.cs` | 新增 | 否 | 会议 API 端点 |
| `src/Hua.Todo.Application/Meeting/MeetingService.cs` | 新增 | 否 | 会议业务逻辑 |
| `src/Hua.Todo.Application/Meeting/MeetingAiBreakdownService.cs` | 新增 | 否 | 会议 AI 拆分服务 |
| `src/Hua.Todo.Application/Meeting/SttService.cs` | 新增 | 否 | 音频转写服务 |
| `src/Hua.Todo.Application/Meeting/Models/` | 新增 | 否 | 会议相关 DTO |
| `src/Hua.Todo.Web/src/api/meeting.ts` | 新增 | 否 | 前端会议 API 模块 |
| `src/Hua.Todo.Web/src/composables/useAudioRecorder.ts` | 新增 | 否 | 前端录音组合式函数 |
| `src/Hua.Todo.Web/src/components/MeetingBreakdownDialog.vue` | 新增 | 否 | 会议任务拆分审阅对话框 |
| `src/Hua.Todo.Web/src/components/MeetingTaskItem.vue` | 新增 | 否 | 会议类型待办项(含录音/纪要入口) |
| `src/Hua.Todo.Web/src/components/AudioRecorder.vue` | 新增 | 否 | 录音控件 |
| `src/Hua.Todo.Web/src/types/task.ts` | 修改 | 是 | 类型扩展(taskType/meetingNotes |
---
**工单编号**03
**标题**:会议任务拆分
**版本**v1.3.0
**创建日期**2026-06-16