Files
Hua.Todo/docs/project/研发工单-v1.3.0/03-01-会议数据模型与API.md
ShaoHua 9223ceca50 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
2026-06-16 01:15:40 +08:00

7.4 KiB
Raw Permalink Blame History

研发工单 v1.3.0 - 03-01 会议数据模型与 API

父工单:03-会议任务拆分


一、目标

为"会议任务拆分"功能建立数据模型:扩展 TaskEntity 新增 TaskType 枚举和 MeetingNotes/AudioDuration 字段,定义完整的会议相关 API 端点与 DTO,完成数据库迁移。

二、范围

包含

  • 新增 TaskType 枚举(Normal / Meeting
  • TaskEntity 新增字段:TaskTypeMeetingNotesAudioDuration
  • EF Core 数据库迁移
  • DTO 扩展:CreateTaskDtoUpdateTaskDtoTaskDto 新增对应字段
  • 会议 API 端点骨架:MeetingController + MeetingService
  • API 路径:/api/meeting/{taskId}/transcribe/api/meeting/{taskId}/notes
  • 会议相关 DTO 定义:TranscribeRequestTranscribeResponseMeetingNotesRequest

不包含

  • AI 拆分逻辑(由 03-03 完成)
  • STT 转写实现(由 03-02 完成)
  • 前端组件(由 03-04 完成)

三、前置条件

条件 说明
Hua.Todo v1.2.0 基础 Task CRUD 能力、父子任务、DynamicApi 中间件
ABP 基类迁移(可选) 若工单 09v1.2.0)已完成,TaskEntity 已转为 ABP 基类,字段新增方式不同

四、详细规格

4.1 TaskType 枚举

/// <summary>待办项类型,区分普通待办项与会议</summary>
public enum TaskType
{
    /// <summary>普通待办项(默认)</summary>
    Normal = 0,
    /// <summary>会议:包含录音/纪要,支持 AI 任务拆分</summary>
    Meeting = 1
}

文件位置:src/Hua.Todo.Core/Entities/TaskType.cs

4.2 TaskEntity 新增字段

/// <summary>待办项类型</summary>
public TaskType TaskType { get; set; } = TaskType.Normal;

/// <summary>会议纪要/转写文字(仅 Meeting 类型有值)</summary>
[MaxLength(20000)]
public string? MeetingNotes { get; set; }

/// <summary>录音时长(秒),仅 Meeting 类型有值</summary>
public double? AudioDuration { get; set; }

4.3 EF Core 配置(TodoDbContext.cs

builder.Entity<TaskEntity>(b =>
{
    // ... 现有配置 ...

    b.Property(x => x.TaskType)
        .HasDefaultValue(TaskType.Normal)
        .HasConversion<int>(); // 枚举存为整数

    b.Property(x => x.MeetingNotes)
        .HasMaxLength(20000); // 最多约 20000 字符

    b.Property(x => x.AudioDuration)
        .IsRequired(false);
});

4.4 数据库迁移

dotnet ef migrations add AddMeetingFieldsToTasks

迁移应在 Hua.Todo.Application/Migrations/ 目录生成。

4.5 DTO 扩展

CreateTaskDto 新增:

/// <summary>待办项类型(0=Normal, 1=Meeting),默认 Normal</summary>
public TaskType TaskType { get; set; } = TaskType.Normal;

TaskDto 新增:

/// <summary>待办项类型</summary>
public TaskType TaskType { get; set; }
/// <summary>会议纪要/转写文字</summary>
public string? MeetingNotes { get; set; }
/// <summary>录音时长(秒)</summary>
public double? AudioDuration { get; set; }

4.6 会议 DTO

/// <summary>转写请求</summary>
public class TranscribeRequest
{
    public IFormFile Audio { get; set; } = null!;
    public string? Format { get; set; }
}

/// <summary>转写响应</summary>
public class TranscribeResponse
{
    public int TaskId { get; set; }
    public string Transcript { get; set; } = string.Empty;
    public double AudioDuration { get; set; }
}

/// <summary>保存会议纪要请求</summary>
public class MeetingNotesRequest
{
    public string Notes { get; set; } = string.Empty;
}

/// <summary>会议纪要响应</summary>
public class MeetingNotesResponse
{
    public int TaskId { get; set; }
    public string MeetingNotes { get; set; } = string.Empty;
}

4.7 API 端点

POST /api/meeting/{taskId}/transcribe

  • 接收:multipart/form-data(音频文件)
  • 返回:TranscribeResponse
  • 业务:音频上传后异步转写,结果存回 TaskEntity.MeetingNotes
  • 当前骨架:返回占位文字,具体转写逻辑由 03-02 实现

POST /api/meeting/{taskId}/notes

  • 接收:MeetingNotesRequest
  • 返回:MeetingNotesResponse
  • 业务:保存/更新会议纪要

4.8 MeetingService 骨架

/// <summary>会议业务服务</summary>
public class MeetingService
{
    private readonly ITaskRepository _taskRepo;

    public MeetingService(ITaskRepository taskRepo)
    {
        _taskRepo = taskRepo;
    }

    /// <summary>验证 taskId 对应的待办项存在且为 Meeting 类型</summary>
    public async Task<TaskEntity> GetMeetingTaskOrThrow(int taskId)
    {
        var task = await _taskRepo.GetAsync(taskId);
        if (task == null)
            throw new NotFoundException($"任务 {taskId} 不存在");
        if (task.TaskType != TaskType.Meeting)
            throw new BusinessException($"任务 {taskId} 不是会议类型");
        return task;
    }

    /// <summary>保存会议纪要</summary>
    public async Task<TaskEntity> SaveNotes(int taskId, string notes)
    {
        var task = await GetMeetingTaskOrThrow(taskId);
        task.MeetingNotes = notes;
        task.UpdatedAt = DateTime.UtcNow;
        await _taskRepo.UpdateAsync(task);
        return task;
    }

    /// <summary>保存转写结果与音频时长</summary>
    public async Task<TaskEntity> SaveTranscript(int taskId, string transcript, double audioDuration)
    {
        var task = await GetMeetingTaskOrThrow(taskId);
        task.MeetingNotes = transcript;
        task.AudioDuration = audioDuration;
        task.UpdatedAt = DateTime.UtcNow;
        await _taskRepo.UpdateAsync(task);
        return task;
    }
}

五、验收标准

验收项 验证方法 预期结果
TaskType 枚举可用 编译通过 TaskType.Normal / TaskType.Meeting 可正常赋值
DB 迁移可执行 dotnet ef database update Tasks 表新增 TaskType/MeetingNotes/AudioDuration
创建 Meeting 类型任务 POST /api/tasktaskType:1 返回的 TaskDto 中 taskType=1
保存会议纪要 POST /api/meeting/{id}/notes meetingNotes 字段更新成功
非 Meeting 类型调用会议 API 普通任务调 /api/meeting/{id}/notes 返回业务异常
现有代码兼容 运行所有已有测试 不破坏现有业务

六、风险

风险 影响 应对
TaskEntity 已重构为 ABP 基类 字段新增方式不同 通过 ABP 的 ExtraProperties 或标准字段新增,迁移方式略有调整
字段长度限制 超长会议纪要截断 MeetingNotesMaxLength(20000),前端也做长度限制

七、Touch List

文件路径 修改类型 是否共享
src/Hua.Todo.Core/Entities/TaskType.cs 新增
src/Hua.Todo.Core/Entities/TaskEntity.cs 修改
src/Hua.Todo.Application/Data/TodoDbContext.cs 修改
src/Hua.Todo.Application/Models/TaskModels.cs 修改
src/Hua.Todo.Application/Meeting/MeetingController.cs 新增
src/Hua.Todo.Application/Meeting/MeetingService.cs 新增
src/Hua.Todo.Application/Meeting/Models/MeetingDtos.cs 新增
src/Hua.Todo.Web/src/types/task.ts 修改
Migrations/AddMeetingFieldsToTasks.cs 新增

工单编号03-01 标题:会议数据模型与 API 版本v1.3.0 创建日期2026-06-16