Files
zentao-flow/workspace/specs/ai-sop-20260723-1024/04_design/interfaces.md
T

18 KiB
Raw Blame History

AI 交互接口文档 —— 禅道 AI SOP 改造(二期)

版本:v1.0 | 日期:2026-08-06 | 关联改动:CHG-039 ~ CHG-070(鉴权落地 CHG-061) 验证状态:✅ 已验证(全部字段/分支/错误文案均取自运行代码实证,非推测) 证据位置:见文末「证据映射表」;单测 24 绿、8086 三×三鉴权矩阵实测通过(dev_log CHG-061) 适用范围:AI 框架通道(demand-assessor / pmassist / tgassist 等技能脚本)与 zentao 后端的全部交互接口


1. 通用约定

1.1 Base URL

环境 Base URL 说明
本地测试 http://127.0.0.1:8085/zentao 框架脚本(submit_assessment.py / upload_md.py)默认地址(CHG-061 拍板"别用正线的 url")
测试库直连验证 192.168.1.161:3306/zentao_dev DB 回读校验用,非接口地址
生产 http://192.168.1.105:8015/zentao ⚠️ [ASSUMPTION] 端口 8015 见 dev_log CHG-070"发布 8015 即可生效";主机地址以部署实为准
  • 所有路径均含上下文根 /zentao(部署于域名根路径)。
  • 字符集 UTF-8;JSON 接口 produces = application/json; charset=UTF-8。

1.2 鉴权(CHG-061 落地)

  • 请求头:Authorization: {token}(JWT,由 JwtAuthenticationFilter 解析,写入 RiskUserThreadLocal)。
  • token 获取(人工/调试用):
    POST /zentao/zt-user/login
    Content-Type: application/json
    {"account":"admin","password":"<md5(密码)>"}
    → 响应 data 即 token
    
  • AI 通道使用 ai 账户永久 token(生成于 .claude/ai_token.txt,框架两脚本自动携带,无需手工管理)。
  • token 缺失或无效:过滤器直接返回 {"code":-1,"message":"请登录"},不进入业务层。

接口级权限矩阵:

接口 权限要求 越权响应
/zt-story-expand/saveOrUpdate 仅 ai 账户 token code:-1 "该接口仅AI框架通道可用(需ai账户token)"
/zt-task/aiBatchAdd 仅 ai 账户 token code:-1 "aiBatchAdd仅AI框架通道可用(需ai账户token)"
/common/uploadBind 任意登录态(AI 带 ai token;UI 带用户 token) code:-1 "请登录(上传需携带有效token)"

1.3 统一响应结构

{ "code": 0, "message": "成功", "data": { } }
code 含义 触发
0 成功 正常返回(data 可为 null)
-1 失败 业务校验失败(BusinessException,message 为具体原因);文件为空;未登录
-2 重复添加 框架保留码,本三接口未使用
401 请登录 框架保留码;实际未登录返回 -1 + "请登录"(过滤器写死)

1.4 AI 框架典型调用时序

sequenceDiagram
    participant Skill as AI 技能脚本<br/>(demand-assessor/tgassist)
    participant ZT as zentao 后端
    participant DB as MySQL (zt_*)

    Note over Skill: .claude/ai_token.txt<br/>自动读 ai 永久 token
    Skill->>ZT: ① POST /zt-story-expand/saveOrUpdate<br/>(W 指标 + 验收标准 MD)
    ZT->>DB: upsert zt_story_expand(按 story_id)
    Skill->>ZT: ② POST /zt-task/aiBatchAdd<br/>(拆分 devel/test 任务)
    ZT->>DB: insert zt_task × N(跳过重复)<br/>+ zt_action 留痕(任务级+需求级)
    Skill->>ZT: ③ POST /common/uploadBind<br/>(PRD/审查报告/日志等 MD 文件)
    ZT->>DB: 刷新主表 url 字段 → 插 zt_file<br/>+ zt_action 动态
    ZT-->>Skill: {"code":0,"data":zt_file 记录}

2. 接口一览

# 接口 方法 路径 Content-Type 鉴权 用途 关联 FR
1 AI 评估指标与验收标准提交 POST /zentao/zt-story-expand/saveOrUpdate application/json 仅 ai token 七步评估结果(S/B/F(T)/G(A)/W)+ 验收标准 MD 落库 FR-004
2 AI 批量拆分任务 POST /zentao/zt-task/aiBatchAdd application/json 仅 ai token 按任务清单批量建 devel/test 任务,防重跳过 FR-006
3 文件上传并绑定业务对象 POST /zentao/common/uploadBind multipart/form-data 任意登录态 上传 MD 等文件,同步刷新主表 url 字段 FR-002/005/008/010/011

3. 接口 1:AI 评估指标与验收标准提交

POST /zentao/zt-story-expand/saveOrUpdate
Content-Type: application/json
Authorization: {ai token}

用途:demand-assessor 七步评估完成后,将工作量指标与 AI 框架验收标准写入 zt_story_expand(按 story_id upsert)。生产侧由 submit_assessment.py 调用。

3.1 请求体字段(ZtStoryExpand)

字段 类型 必填 说明
storyId Integer ✅ 需求 ID(zt_story.id)。为空时服务端静默返回成功、不处理(见 3.2 分支②)
numberUnits Integer 评估时✅ 单元数量 S
unitBusinessComplexity String 评估时✅ 单元业务复杂度 B(如 "2.2")
technicalComplexityCoefficient String 评估时✅ 技术复杂度系数 F(T)(如 "1.4")
aiEfficiencyCoefficient String 评估时✅ AI 效率系数 G(A)(如 "0.55")
evaluationTime BigDecimal 评估时✅ 评估工时 W(人日,如 5.1)
workloadIndex String 否 工作量指数(finished 结算时优先取库内已有值)
aiParticipationRate String 否 AI 参与率(只存不算,口径待定)
requirementStatus String 否 inProgress(默认)/ finished;finished 触发月度工作量结算
requirementCompletionDegree String 否 需求完成度 "0"~"100";finished 时被强制置 "100"
acceptanceCriteria String 否 AI 框架验收指标(Given/When/Then,MD 文本)。与老验收标准 zt_storyspec.verify 互不干扰(CHG-022)
productPerson / developPerson / testPerson String 否 产品/开发/测试人员(中文名)
id / createTime / updateTime / createUser / updateUser — 无需传 服务端维护(id 自增,时间戳自动写)
storyTitle / createUserNickname / month / monthEvaluationTime — 无需传 非数据库字段(查询展示/内部结算用)

3.2 业务规则与分支

# 分支 行为
① token 非 ai 账户 拒绝:-1 "该接口仅AI框架通道可用(需ai账户token)"
② storyId 为空 静默返回 code:0,不建不改(注意:不等于参数报错)
③ 该 storyId 无记录 insert;requirementStatus 未传时默认 inProgress;create/updateTime=now
④ 已有记录且其状态为 finished 拒绝:"该需求已完成,不可再修改"(守卫:定稿后不可覆写)
⑤ 已有记录(非 finished) update by id,updateTime=now
⑥ 本次提交 requirementStatus=finished 强制完成度 "100";写当月 zt_story_month_workload:增量 = 100 − 历史最高完成度;折算工时 = 工作量指数 × 增量 ÷ 100(2 位小数 HALF_UP);增量 ≤ 0 记 0
⑦ 幂等性 同 storyId 重复提交 = 覆盖更新,不产生重复行

3.3 报文示例

{
  "storyId": 9130,
  "numberUnits": 3,
  "unitBusinessComplexity": "2.2",
  "technicalComplexityCoefficient": "1.4",
  "aiEfficiencyCoefficient": "0.55",
  "evaluationTime": 5.1,
  "workloadIndex": "5.1",
  "developPerson": "魏冬霞",
  "testPerson": "罗勇",
  "acceptanceCriteria": "## AC-001\n- Given ...\n- When ...\n- Then ..."
}

3.4 响应

{ "code": 0, "message": "成功", "data": null }

失败:{ "code": -1, "message": "该接口仅AI框架通道可用(需ai账户token)" } / { "code": -1, "message": "该需求已完成,不可再修改" }


4. 接口 2:AI 批量拆分任务

POST /zentao/zt-task/aiBatchAdd
Content-Type: application/json
Authorization: {ai token}

用途:按任务清单为指定需求批量创建研发/测试任务;同需求下重名同类型任务自动跳过。生产侧由任务拆分流程(tasks.md → zentao)调用。

4.1 请求体字段(ZtTaskAiBatchDTO)

字段 类型 必填 说明
storyId Integer ✅ 需求 ID;不存在则整批拒绝
tasks Array ✅ 非空 任务项列表
tasks[].name String ✅ 任务名称(空则整批拒绝)
tasks[].type String ✅ 仅 devel(开发)/ test(测试);其他值整批拒绝
tasks[].assignedTo String 否 指派人账号(zt_user.account);留痕时转中文昵称显示
tasks[].aiEvaluationTime Float 否 AI 评估工时 → 同时写入 estimate 与 left,consumed=0
tasks[].planStartDate String 否 预计开始 yyyy-MM-dd → estStarted
tasks[].deadline String 否 预计完成 yyyy-MM-dd → deadline,并写 deadlineTime(秒级时间戳)

4.2 业务规则与分支

# 分支 行为
① token 非 ai 账户 拒绝:-1 "aiBatchAdd仅AI框架通道可用(需ai账户token)"
② storyId 空 / 需求不存在 / tasks 空 / 任一 name 空 / 任一 type 非 devel|test / 日期格式错 整批拒绝(BusinessException,事务回滚,一个都不建)
③ 防重 同需求下已存在 name#type(未删除)→ 跳过并记入 skipped;批内重复同样防重(建过的 key 即时入集合)
④ 创建字段 status=wait、openedby=ai(token 身份)、openeddate=now、estimate=left=aiEvaluationTime
⑤ 留痕(CHG-059/060/062) 任务级:zt_action(RW+XJ)每任务一条,与手工建任务同形状;需求级:一批合并一条(XQ+BJ),文案含个数、序号、各任务名称/类型/工时/指派中文名、跳过数
⑥ 日期格式 非法日期整批拒绝:"日期格式错误,应为yyyy-MM-dd:{任务名}"

4.3 报文示例

{
  "storyId": 9130,
  "tasks": [
    {"name": "二期 DDL×3 + 自测", "type": "devel", "assignedTo": "guoqibing",
     "aiEvaluationTime": 8, "planStartDate": "2026-08-10", "deadline": "2026-08-11"},
    {"name": "后端接口测试:uploadBind/aiBatchAdd", "type": "test", "assignedTo": "zhangfubin",
     "aiEvaluationTime": 8, "planStartDate": "2026-08-12", "deadline": "2026-08-12"}
  ]
}

4.4 响应

{
  "code": 0,
  "message": "成功",
  "data": {
    "created": 2,
    "taskIds": [18565, 18566],
    "skipped": ["二期 DDL×3 + 自测"]
  }
}
  • created:本次实际新建数;taskIds:新建任务 ID 列表;skipped:因重名同类型跳过的任务名列表。
  • 全部重复时:created:0、taskIds:[]、skipped 全量 —— 仍返回 code:0(跳过不算失败)。

5. 接口 3:文件上传并绑定业务对象

POST /zentao/common/uploadBind
Content-Type: multipart/form-data
Authorization: {任意登录态 token}

用途:上传文件(AI 框架场景为 MD 文档)并一步绑定到业务对象:写磁盘 + 插 zt_file + 按 objectType 刷新主表访问链接字段 + 写动态留痕。生产侧由 upload_md.py 调用(默认本地 8085、自动带 ai token)。

5.1 表单字段(UploadDTO)

字段 类型 必填 说明
file File ✅ 上传文件(空文件拒绝);服务端仅保留原扩展名,文件名为 yyyyMMddHHmmss + UUID
objectType String ✅ 业务对象类型,白名单 9 类(见 5.2);不在白名单整体拒绝
objectId Integer ✅ 主表记录 ID(需求/会议);记录不存在则拒绝
title String 否 文件标题;缺省取原始文件名(中文标题落库正确,CHG-061 已验证)
reviewResult String 否 仅 objectType=aiCodeReview 有效:pass / reject,非空时同步写 zt_story.code_review_status

5.2 objectType → 主表字段刷新映射(白名单)

objectType 含义 刷新主表字段 动态留痕
story PRD/需求文档 zt_story.prd_url XQ+BJ
aiCodeReview 代码审查报告 zt_story.code_review_url(+code_review_status,若传 reviewResult) XQ+BJ
aiWorkLog 工作日志 zt_story.work_log_url XQ+BJ
aiDocUpdate AI 项目文档更新记录 zt_story.ai_doc_update_url XQ+BJ
testCase 测试用例 zt_story.test_case_url XQ+BJ
testReport 测试报告模版 zt_story.test_report_download_url XQ+BJ
testReportSubmit 测试报告提交 zt_story.test_report_submit_url XQ+BJ
testOther 其他测试文档 zt_story.test_other_url XQ+BJ
meeting 会议纪要 zt_meeting.url MEET+BJ

FileTypes 枚举另有 task/bug/userStory 等 6 个 code,但 uploadBind 不支持——传入会拒绝:"uploadBind不支持的objectType:{type}"。

5.3 业务规则与分支

# 分支 行为
① 无登录态 -1 "请登录(上传需携带有效token)"
② file 为空 -1 "失败"
③ objectType/objectId 为空 -1 "objectType/objectId不能为空"
④ objectType 非枚举值 "不支持的objectType:{type}";是枚举但非白名单 → "uploadBind不支持的objectType:{type}"
⑤ objectId 记录不存在 "需求不存在:{id}" / "会议不存在:{id}"
⑥ 执行顺序(事务) 先校验并刷新主表 → 失败整体回滚不落盘;再写磁盘 → 插 zt_file → 写 zt_action(文案含完整可访问 URL)
⑦ 落库字段 zt_file.addedby = token 身份;pathname/url = 相对路径 /zentao/img/{文件名}(经前端源/代理可达,规避跨域);size 字节数;extension 原扩展名
⑧ 多文件 同一 (objectType, objectId) 可多次上传,形成多份列表;主表 url 字段记录最新一份,前端列表取 zt_file 全集

5.4 调用示例

curl -X POST "http://127.0.0.1:8085/zentao/common/uploadBind" \
  -H "Authorization: {ai token}" \
  -F "file=@代码审查报告.md" \
  -F "objectType=aiCodeReview" \
  -F "objectId=9130" \
  -F "title=代码审查报告-v1" \
  -F "reviewResult=pass"

5.5 响应

{
  "code": 0,
  "message": "成功",
  "data": {
    "id": 1234,
    "title": "代码审查报告-v1",
    "extension": ".md",
    "size": 5321,
    "pathname": "/zentao/img/20260806170215a1b2c3....md",
    "url": "/zentao/img/20260806170215a1b2c3....md",
    "objecttype": "aiCodeReview",
    "objectid": 9130,
    "addedby": "ai",
    "addeddate": "2026-08-06 17:02:15",
    "deleted": "0"
  }
}

6. 失败分支汇总(排障速查)

现象 code message 排查
未带 token / token 失效 -1 请登录 检查 Authorization 头;ai token 见 .claude/ai_token.txt
用人工 token 调 saveOrUpdate / aiBatchAdd -1 仅AI框架通道可用(需ai账户token) 换 ai token;这是设计守卫,非缺陷
需求已 finished 再提交指标 -1 该需求已完成,不可再修改 生产 itsm 已有 finished 记录被此守卫拒绝(summary 2026-08-06),属按设计拦截
saveOrUpdate 返回 0 但库里没数据 0 成功 检查是否漏传 storyId(分支 3.2② 静默成功)
aiBatchAdd 一个任务都没建 -1 (任一校验消息) 整批拒绝机制:任一任务非法全部回滚;先修非法项
aiBatchAdd 成功但 created=0 0 成功 全部命中防重,看 skipped
uploadBind 报类型不支持 -1 (uploadBind)不支持的objectType 对照 5.2 白名单(9 类)
uploadBind 成功但页面看不到 0 成功 前端列表读 zt_file;检查 objectType/objectId 是否传对、前端是否按类型渲染

7. 证据映射表

章节 关键结论 证据来源
1.2 鉴权 Authorization 头 JWT 解析、越权文案 [CODE:codes/zentao/src/main/java/com/sa/zentao/conf/JwtAuthenticationFilter.java:41-66] [CODE:ZtStoryExpandServiceImpl.java:41-45] [CODE:ZtTaskServiceImpl.java:1360-1364] [CODE:CommonsController.java:129-132]
1.3 响应结构 Result/Code 枚举值 [CODE:codes/zentao/src/main/java/com/sa/zentao/dao/Result.java] [CODE:codes/zentao/src/main/java/com/sa/zentao/dao/Code.java] [CODE:conf/GlobalExceptionHandler.java:28-32]
3. 接口1 字段集/upsert/finished 守卫与结算 [CODE:entity/ZtStoryExpand.java] [CODE:ZtStoryExpandServiceImpl.java:40-79,120-150]
4. 接口2 字段/整批拒绝/防重/留痕形状 [CODE:dao/ZtTaskAiBatchDTO.java] [CODE:ZtTaskServiceImpl.java:1357-1470]
5. 接口3 白名单映射/事务顺序/落库字段 [CODE:CommonsController.java:120-187] [CODE:ZtFileServiceImpl.java:74-154] [CODE:enums/FileTypes.java] [CODE:dao/UploadDTO.java]
1.1/运行实证 8085 默认地址、token 自动携带、中文标题正确 [RUNTIME:dev_log CHG-061 闭环记录] [RUNTIME:summary.md 2026-08-06]

8. 假设与缺口

项 状态 说明
生产 Base URL ⚠️ [ASSUMPTION] 8015 端口见于 dev_log CHG-070;生产主机/域名以部署实为准,发布时确认
evaluationTime 单位 ✅ 已确认 人日(demand-assessor W 定义,summary 附录口径一致)
deadlineTime 精度 ✅ 已验证 秒级时间戳(ZtTaskServiceImpl.java:1425)
ai 永久 token 过期策略 ✅ 已确认 永久 token(CHG-061 决策,存 .claude/ai_token.txt)

下一步(Check):本文档与 outputs/dev_plan.md、06_test_docs/test_cases.md §0 环境约定一致;如发现不一致以运行代码为准修正本文档(Runtime 事实优先)。