Files
Neo-ZQYY/.kiro/specs/rns1-chat-integration/requirements.md

18 KiB
Raw Blame History

需求文档 — RNS1.4CHAT 对齐与联调收尾

简介

RNS1.4 是 NS1 小程序后端 API 补全项目的最后一个子 spec负责 CHAT 模块路径迁移和功能补全、FDW 端到端验证、以及全量前后端联调。本 spec 依赖 RNS1.0-1.3 全部完成,是整个 RNS1 系列的收尾阶段,确保 13 个页面全部连接真实后端运行,无 mock 数据残留。

依赖

  • RNS1.0(基础设施与契约重写)— 全局响应包装中间件、camelCase 转换、重写后的 API 契约
  • RNS1.1(任务与绩效接口)— TASK-1/2、PERF-1/2、PIN 接口已实现
  • RNS1.2(客户与助教接口)— CUST-1/2、COACH-1 接口已实现
  • RNS1.3(三看板接口)— BOARD-1/2/3、CONFIG-1 接口已实现
  • 后端已有 xcx_ai.py(现有 /api/ai/* 路由,需迁移)
  • 前端已有 chat.ts 和 chat-history.ts 页面P5.2 交付),当前使用 mock 数据和模拟流式输出

来源文档

  • docs/prd/Neo_Specs/RNS1-split-plan.md — 拆分计划主文档
  • docs/miniprogram-dev/API-contract.md — API 契约RNS1.0 T0-5 重写后版本)
  • docs/prd/Neo_Specs/storyboard-walkthrough-assistant-view.md — 助教视角走查报告GAP-45~51

术语表

  • BackendFastAPI 后端应用,位于 apps/backend/
  • Miniprogram:微信小程序前端应用,位于 apps/miniprogram/
  • CHAT_1_API:对话历史列表接口 GET /api/xcx/chat/history,返回分页的对话列表
  • CHAT_2_API:对话消息接口 GET /api/xcx/chat/{chatId}/messagesGET /api/xcx/chat/messages?customerId={customerId},返回指定对话的消息列表
  • CHAT_3_API:发送消息接口 POST /api/xcx/chat/{chatId}/messages,发送用户消息并获取 AI 同步回复
  • CHAT_4_SSESSE 流式端点 POST /api/xcx/chat/stream,通过 Server-Sent Events 逐 token 返回 AI 回复
  • SSEServer-Sent Events服务端推送事件协议用于 AI 流式回复的逐 token 输出
  • referenceCard:引用卡片,消息中附带的结构化上下文数据(类型/标题/摘要/键值对),用于展示客户概览等信息
  • FDWPostgreSQL Foreign Data Wrapper用于从业务库 zqyy_app 访问 ETL 库 etl_feiqiu 的数据
  • chat_sessions:业务库 zqyy_app 中的对话会话表,存储对话元数据
  • chat_messages:业务库 zqyy_app 中的消息表,存储对话消息内容
  • Response_WrapperRNS1.0 实现的全局响应包装中间件,text/event-stream 响应自动跳过包装
  • items_sumDWD-DOC 强制使用的消费金额口径
  • 联调:前后端联合调试,验证所有页面使用真实后端数据正常运行

需求

需求 1CHAT 路径迁移T4-1

用户故事: 作为前后端开发者,我希望 CHAT 模块的 API 路径从 /api/ai/* 统一迁移到 /api/xcx/chat/*,以便与其他小程序接口保持一致的路径命名规范。

验收标准

  1. THE Backend SHALL 将现有 /api/ai/* 路由全部迁移到 /api/xcx/chat/* 路径下,包括同步端点和 SSE 流式端点
  2. THE Backend SHALL 在迁移后移除原 /api/ai/* 路径,不保留旧路径的兼容映射
  3. THE Backend SHALL 将迁移后的路由注册到 xcx_chat router或等效命名与其他 xcx_* 路由模块保持一致的组织结构
  4. THE Miniprogram SHALL 更新 services/api.ts 中所有 CHAT 相关的 API 调用路径,从 /api/ai/* 改为 /api/xcx/chat/*
  5. WHEN CHAT_4_SSE 端点迁移到 /api/xcx/chat/streamTHE Response_Wrapper SHALL 继续对 text/event-stream 响应跳过包装RNS1.0 已实现的行为不受路径变更影响)

需求 2实现 CHAT-1 对话历史列表T4-2 历史列表部分)

用户故事: 作为助教,我希望在对话历史页面看到所有对话记录(含对话标题和最后消息摘要),以便快速找到并继续之前的对话。

验收标准

  1. THE CHAT_1_API SHALL 实现 GET /api/xcx/chat/history 端点,接受 page(默认 1pageSize(默认 20查询参数返回分页的对话历史列表
  2. THE CHAT_1_API SHALL 为每条对话记录返回以下字段:id(对话 IDtitle(对话标题)、customerName(关联客户姓名,可选)、lastMessage(最后一条消息摘要)、timestamp最后消息时间ISO 8601 格式)、unreadCount(未读消息数)
  3. THE CHAT_1_API SHALL 从 zqyy_app.chat_sessions 查询对话列表,按最后消息时间倒序排列
  4. THE CHAT_1_API SHALL 为 title 字段生成对话标题:优先使用对话会话中存储的自定义标题,若无自定义标题则使用关联客户姓名,若均无则使用首条消息内容的前 20 个字符作为标题
  5. THE CHAT_1_API SHALL 返回标准分页字段:total(总记录数)、page(当前页码)、pageSize(每页条数)
  6. THE CHAT_1_API SHALL 通过当前登录用户的身份过滤对话列表,确保每位助教只能看到自己的对话记录

需求 3实现 CHAT-2 对话消息查看T4-2 消息查看部分)

用户故事: 作为助教,我希望查看指定对话的消息列表,以便回顾与 AI 助手的对话内容。

验收标准

  1. THE CHAT_2_API SHALL 实现两个等效的消息查询端点:GET /api/xcx/chat/{chatId}/messages(通过对话 ID 查询)和 GET /api/xcx/chat/messages?contextType={type}&contextId={id}(通过上下文类型和 ID 查询)
  2. THE CHAT_2_API SHALL 接受 page(默认 1pageSize(默认 50查询参数返回分页的消息列表
  3. THE CHAT_2_API SHALL 为每条消息返回以下字段:id(消息 IDroleuserassistant)、content(消息内容)、createdAt创建时间ISO 8601 格式)、referenceCard(引用卡片,可选)
  4. THE CHAT_2_API SHALL 统一使用 createdAt 作为消息时间字段名(替代前端使用的 timestamp 和旧契约的 created_at,遵循 camelCase 规范)
  5. THE CHAT_2_API SHALL 从 zqyy_app.chat_messages 查询消息列表,按 createdAt 正序排列(最早的消息在前)
  6. THE CHAT_2_API SHALL 在响应中返回 chatId 字段,供前端后续发送消息时使用(尤其是通过上下文入口时,前端需要获取对应的 chatId
  7. THE CHAT_2_API SHALL 返回标准分页字段:total(总记录数)、page(当前页码)、pageSize(每页条数)

3.2 上下文对话复用规则

  1. WHEN 通过 contextTypecontextId 查询参数调用消息端点时THE CHAT_2_API SHALL 按以下规则查找或创建对话:
    • contextType='task':查找同一用户、同一 contextIdtaskId的已有对话找到则复用无时限找不到则新建
    • contextType='customer'contextType='coach':查找同一用户、同一 contextId 的已有对话,若最后消息时间 ≤ 3 天则复用,> 3 天或不存在则新建
    • contextType='general':始终新建对话
  2. THE CHAT_2_API SHALL 在 ai_conversations 中记录 context_typecontext_id 字段,用于后续对话查找
  3. THE CHAT_2_API SHALL 确保对话复用查找基于 (user_id, site_id, context_type, context_id) 组合,不同用户的对话互不影响

需求 4CHAT referenceCard 支持T4-3

用户故事: 作为助教,我希望在与 AI 助手对话时,消息中能附带客户概览卡片(含余额、消费、到店频次等键值对数据),以便在对话上下文中快速查看客户关键信息。

验收标准

  1. THE CHAT_2_API SHALL 为消息返回可选的 referenceCard 字段,结构包含:type(引用类型,customerrecord 枚举)、title(卡片标题,如 "张伟 — 消费概览")、summary(摘要文字)、dataRecord<string, string> 键值对详情,如 { "近30天消费": "¥2,380", "到店次数": "8次" }
  2. WHEN AI 助手回复消息涉及特定客户时THE Backend SHALL 从 FDW 查询该客户的关键指标(余额、近期消费、到店频次等),组装为 referenceCard 附加到 AI 回复消息中
  3. THE Backend SHALL 将 referenceCard 数据持久化存储到 chat_messages 表中(作为 JSON 字段),以便历史消息查看时仍能展示引用卡片
  4. THE Miniprogram SHALL 在 chat 页面的消息列表中,检测消息的 referenceCard 字段,若存在则渲染为结构化卡片组件(标题 + 摘要 + 键值对列表)

4.2 多入口参数路由GAP-50

  1. THE Miniprogram SHALL 在 chat 页面的 onLoad(options) 中实现多入口参数路由逻辑,按以下优先级处理入口参数:
    • options.historyId 存在(从 chat-history 跳转),使用 historyId 作为 chatId 直接加载历史消息
    • options.taskId 存在(从 task-detail 跳转),使用 contextType=task + contextId=taskId 调用 CHAT_2_API由后端查找同一任务的已有对话始终复用无时限
    • options.customerId 存在(从 customer-detail 跳转),使用 contextType=customer + contextId=customerId 调用 CHAT_2_API由后端按 3 天时限判断复用或新建
    • options.coachId 存在(从 coach-detail 跳转),使用 contextType=coach + contextId=coachId 调用 CHAT_2_API由后端按 3 天时限判断复用或新建
  2. WHEN 通过上下文入口进入对话后THE Miniprogram SHALL 将后端返回的 chatId 缓存到页面 data 中,后续发送消息和 SSE 流式请求均使用该 chatId
  3. IF chat 页面未收到任何入口参数(historyId/taskId/customerId/coachId 均为空THEN THE Miniprogram SHALL 使用 contextType=general 调用 CHAT_2_API 创建一个通用对话

需求 5CHAT-3 发送消息T4-2 发送部分)

用户故事: 作为助教,我希望在对话页面发送消息后能立即收到 AI 的同步回复,以便在不支持 SSE 的场景下也能正常使用 AI 助手。

验收标准

  1. THE CHAT_3_API SHALL 实现 POST /api/xcx/chat/{chatId}/messages 端点,接受请求体 { content: string }
  2. THE CHAT_3_API SHALL 将用户消息存入 chat_messages 表,调用 AI 服务获取回复,将 AI 回复也存入 chat_messages
  3. THE CHAT_3_API SHALL 返回包含用户消息和 AI 回复的响应:userMessage(含 id/content/createdAt)和 aiReply(含 id/content/createdAt
  4. THE CHAT_3_API SHALL 在发送消息后更新 chat_sessions 表的 lastMessage 和最后消息时间字段
  5. IF AI 服务调用失败或超时THEN THE CHAT_3_API SHALL 仍保存用户消息,并返回 AI 回复为错误提示消息(如 { content: "抱歉AI 助手暂时无法回复,请稍后重试" }HTTP 状态码保持 200
  6. THE CHAT_3_API SHALL 验证请求的 chatId 属于当前登录助教,不属于时返回 HTTP 403

需求 6CHAT-4 SSE 流式端点T4-1 SSE 部分)

用户故事: 作为助教,我希望 AI 助手的回复能以流式方式逐字显示,以便获得更自然的对话体验,减少等待感。

验收标准

  1. THE CHAT_4_SSE SHALL 实现 POST /api/xcx/chat/stream 端点,接受请求体 { chatId: string, content: string },响应内容类型为 text/event-stream
  2. THE CHAT_4_SSE SHALL 发送以下三种 SSE 事件类型:
    • event: message — 逐 token 输出,data{"token": "<文本片段>"}
    • event: done — 流结束,data{"messageId": "<完整消息ID>", "createdAt": "<ISO 8601>"}
    • event: error — 错误,data{"message": "<错误描述>"}
  3. THE CHAT_4_SSE SHALL 在流开始前将用户消息存入 chat_messages 表,在流结束后将完整的 AI 回复存入 chat_messages
  4. THE CHAT_4_SSE SHALL 在流结束后更新 chat_sessions 表的 lastMessage 和最后消息时间字段
  5. THE Response_Wrapper SHALL 对 text/event-stream 响应跳过全局包装,直接透传 SSE 事件流RNS1.0 已实现)
  6. THE CHAT_4_SSE SHALL 验证请求的 chatId 属于当前登录助教,不属于时返回 HTTP 403此时响应为普通 JSON 错误,非 SSE
  7. THE Miniprogram SHALL 将 chat 页面现有的 simulateStreamOutput()(模拟逐字输出)替换为真实的 SSE 连接,通过 wx.request 或兼容方案接收 text/event-stream 响应

需求 7FDW 端到端验证T4-4

用户故事: 作为后端开发者,我希望验证所有 FDW 查询在测试环境链路(test_zqyy_apptest_etl_feiqiu)上正常工作,以便确保 RNS1.1-1.3 实现的所有接口在真实数据链路上不会因 FDW 连接、权限或性能问题而失败。

验收标准

  1. THE Backend SHALL 验证所有 fdw_etl.* 视图在 test_zqyy_app 数据库中可正常访问,包括但不限于:v_dws_assistant_salary_calcv_dwd_assistant_service_logv_dim_memberv_dim_assistantv_dws_member_consumption_summaryv_dws_member_assistant_relation_indexv_dws_finance_* 系列视图
  2. THE Backend SHALL 验证每个 FDW 视图的查询响应时间在可接受范围内(单次查询不超过 3 秒),对超时的查询记录慢查询日志并评估是否需要添加索引
  3. THE Backend SHALL 验证 FDW 查询在带有典型过滤条件(如 assistant_idmember_id、日期范围)时能正确返回数据,且结果集与直接查询 test_etl_feiqiu 的结果一致
  4. IF 某个 FDW 视图不存在或权限不足THEN THE Backend SHALL 记录具体的错误信息(视图名、错误类型),并在验证报告中标注需要 DBA 介入修复
  5. THE Backend SHALL 检查 FDW 链路上的关键索引是否存在:chat_sessions 表的 (assistant_id, customer_id) 索引、chat_messages 表的 (session_id, created_at) 索引

需求 8前端联调修复 — notes 页触底加载T4-5 F11

用户故事: 作为助教,我希望在备注列表页面滚动到底部时自动加载更多备注,以便查看全部备注记录而不需要手动翻页。

验收标准

  1. THE Miniprogram SHALL 在 notes 页面实现 onReachBottom() 生命周期函数,当用户滚动到页面底部时自动请求下一页备注数据
  2. WHEN 触底加载触发时THE Miniprogram SHALL 将 page 参数加 1调用 fetchNotes({ page, pageSize }) 接口,将返回的备注追加到已有列表末尾
  3. WHEN 后端返回的 hasMorefalse 或返回的备注数量小于 pageSizeTHE Miniprogram SHALL 停止触底加载,显示"没有更多了"提示
  4. THE Miniprogram SHALL 在触底加载过程中显示加载状态指示器,防止重复触发请求

需求 9前端联调修复 — customer-service-records 按月请求T4-5 F10

用户故事: 作为助教,我希望客户服务记录页面在切换月份时向后端请求对应月份的数据,以便在数据量大时页面仍能快速响应,而不是全量加载后本地过滤。

验收标准

  1. THE Miniprogram SHALL 修改 customer-service-records 页面的月份切换逻辑,从当前的"全量加载后本地过滤"改为"按月请求 API"
  2. WHEN 用户切换月份时THE Miniprogram SHALL 使用新的 year/month 参数调用 fetchCustomerRecords({ customerId, year, month }) 接口,加载对应月份的服务记录
  3. THE Miniprogram SHALL 在月份切换时清空已有记录列表,显示加载状态,待新数据返回后渲染
  4. THE Miniprogram SHALL 在首次加载时默认请求当前月份的数据,而非全量数据
  5. THE Backend SHALL 确保 CUST-2 接口支持 yearmonth 查询参数仅返回指定月份的服务记录RNS1.2 T2-4 已实现按月查询能力)

需求 10全量前后端联调T4-5 联调部分)

用户故事: 作为开发团队,我们希望 13 个小程序页面全部连接真实后端运行,无 mock 数据残留,以便确认整个应用在真实数据环境下功能完整、交互正常。

验收标准

  1. THE Miniprogram SHALL 移除所有页面中的内联 mock 数据和 mock 数据导入(import { mockXxx } from '../../utils/mock-data'),全部替换为真实 API 调用
  2. THE Miniprogram SHALL 确保以下 13 个页面均能使用真实后端数据正常渲染:task-listtask-detailnotesperformanceperformance-recordscustomer-detailcustomer-service-recordscoach-detailboard-coachboard-customerboard-financechat-historychat
  3. WHEN 某个页面的 API 调用失败时THE Miniprogram SHALL 显示友好的错误提示(如 Toast 或空状态占位),不出现白屏或未捕获异常
  4. THE Miniprogram SHALL 验证所有页面间的跳转参数传递正确RNS1.0 T0-6 已修复的跨页面参数),确保目标页面能正确加载对应数据
  5. THE Miniprogram SHALL 验证 chat 页面从 4 个入口task-detail、customer-detail、coach-detail、chat-history进入时均能正确关联上下文并加载对应对话
  6. IF 联调过程中发现新的 Bug 或数据不一致问题THEN THE Miniprogram 和 Backend SHALL 在本 spec 范围内修复,修复内容记录到联调问题清单中

需求 11全局约束与权限控制

用户故事: 作为系统管理员,我希望所有 CHAT 接口遵循统一的权限控制和数据隔离规则,以确保每位助教只能访问自己的对话数据。

验收标准

  1. THE Backend SHALL 对所有 RNS1.4 CHAT 接口CHAT-1、CHAT-2、CHAT-3、CHAT-4执行 require_approved() 权限检查,确保用户状态为 approved
  2. THE Backend SHALL 通过当前登录用户的身份信息过滤对话数据,确保每位助教只能访问自己创建的或与自己关联的对话
  3. IF 当前用户未通过审核(状态非 approvedTHEN THE Backend SHALL 返回 HTTP 403 { code: 403, message: "用户未通过审核,无法访问此资源" }
  4. THE Backend SHALL 对所有 CHAT 接口的响应字段名统一使用 camelCase 格式(与 RNS1.0 的 CamelCase_Converter 一致)
  5. THE Backend SHALL 确保 CHAT 模块的错误响应格式与全局异常处理器一致:{ code: <HTTP状态码>, message: <错误详情> }
  6. WHEN CHAT 模块查询 FDW 数据(如为 referenceCard 获取客户指标THE Backend SHALL 遵循 DWD-DOC 强制规则:金额使用 items_sum 口径,会员信息通过 member_id JOIN dim_member 获取