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 获取(人工/调试用):
- 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 |
成功 |
正常返回(data 可为 null) |
-1 |
失败 |
业务校验失败(BusinessException,message 为具体原因);文件为空;未登录 |
-2 |
重复添加 |
框架保留码,本三接口未使用 |
401 |
请登录 |
框架保留码;实际未登录返回 -1 + "请登录"(过滤器写死) |
1.4 AI 框架典型调用时序
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 评估指标与验收标准提交
用途: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 报文示例
3.4 响应
失败:{ "code": -1, "message": "该接口仅AI框架通道可用(需ai账户token)" } / { "code": -1, "message": "该需求已完成,不可再修改" }
4. 接口 2:AI 批量拆分任务
用途:按任务清单为指定需求批量创建研发/测试任务;同需求下重名同类型任务自动跳过。生产侧由任务拆分流程(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 报文示例
4.4 响应
created:本次实际新建数;taskIds:新建任务 ID 列表;skipped:因重名同类型跳过的任务名列表。
- 全部重复时:
created:0、taskIds:[]、skipped 全量 —— 仍返回 code:0(跳过不算失败)。
5. 接口 3:文件上传并绑定业务对象
用途:上传文件(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 调用示例
5.5 响应
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 事实优先)。