2026-08-16 · 建站运维
禅道(zentao.1dao.cc)上线当天,我用 API 把待办事项批量录入了产品/项目/迭代/任务结构。这篇把过程中摸清的东西整理出来——基于禅道开源版 22.4 源码,全部实战验证过。
基本结构
- 入口:
https://zentao.1dao.cc/api.php - 版本:URL 第二段是版本号,如
/api.php/v1/...。v1 是实际可用的(130 个资源端点);v2 路由配置存在但 entries 目录为空,未启用 - 风格:REST(资源 + HTTP 方法),返回 JSON
认证机制
登录拿 token,后续每次请求带 Token 请求头。token 本质是 PHP session_id:
POST /api.php/v1/tokens
{"account": "admin", "password": "***"}
→ {"token": "..."}
# 后续请求
Token: b192df...
几个要点:
- token 就是服务端 session(请求头 HTTP_TOKEN → restartSession),等价于浏览器 Cookie 登录态
- 也支持
authKey方式(免密,IM/客户端用) - 失败锁定:登录失败计数,超过 5 次锁 30 分钟,剩余 ≤3 次会警告——别拿脚本乱试密码
URL 路由规则
config/apiv1.php 定义路由表,匹配 api/v1/entries/ 下的端点文件,HTTP 方法映射到 get/post/put/delete:
/tokens → tokens.php 登录
/tasks → tasks.php 任务集合
/tasks/:id → task.php 单任务
/executions/:id/tasks → tasks.php 某迭代下的任务
/executions?project=N → executions.php 某项目的迭代
/projects → projects.php 项目
/products → products.php 产品
实战示例
# 建产品(body 传参)
POST /api.php/v1/products
{"name":"主站 1dao.cc","code":"1daocc-web","type":"normal"}
# 建项目(body 传参)
POST /api.php/v1/projects
{"name":"主站 1dao.cc","type":"scrum","begin":"...","end":"...","days":100,"products":[1]}
# 建迭代(project 必须走 query,不走 body!)
POST /api.php/v1/executions?project=4
{"name":"迭代1:内容与运营","begin":"...","end":"...","days":45}
# 建任务(必须挂在迭代下)
POST /api.php/v1/executions/16/tasks
{"name":"恢复 /backups/ basic auth","type":"devel","pri":1,
"estimate":2,"assignedTo":"admin","estStarted":"2026-08-17","deadline":"2026-08-31"}
# 更新任务状态
PUT /api.php/v1/tasks/27
{"status":"done","consumed":"1","left":"0"}
踩坑记录
| 坑 | 原因 | 解法 |
|---|---|---|
| POST /tasks/16 报 500「taskEntry 无 post 方法」 | 路由 /tasks/:id 匹配到单数 task.php,它只有 put/delete 没有 post | 创建走 /executions/:id/tasks |
| 建迭代报「所属项目不能为空」 | executions.php 的 post 从 URL 参数取 project | ?project=N 放 query |
| 建任务报「预计开始不能为空」 | 必填 5 字段:name/assignedTo/type/estStarted/deadline | 全带上 |
| 标 done 报「总消耗不能为空」 | done 状态校验 consumed | consumed + left 一起传 |
| 任务必须属于 execution | task 表强关联 execution | 先建项目→迭代,再挂任务 |
权限与数据
checkAccess()按对象映射表(product/project/task/bug/user...)查可见性;admin 全放行- 写入类接口(POST/PUT/DELETE)在 v1 不强制 checkAccess,但 assignedTo 必须指向真实用户
Web 端接口(文档等无 API 的模块)
文档模块没有 API 端点(docs.php 只有 get),得走原生表单。这里有个大坑:
1. 先 GET /index.php?m=user&f=login 拿 zentaosid cookie
2. POST /index.php?m=user&f=login&t=json
# 必须带 Referer 头!否则 CSRF 检查清空 $_POST 导致登录失败
3. 带 cookie POST /index.php?m=doc&f=create&objectType=mine&objectID=0&libID=24
# title/lib/type/content/contentType/uid 字段
实用提示
- 调试开关:
config/my.php里$config->debug = true,错误+SQL 写到tmp/log/php.*.log(排查完记得恢复 false) - 登录页验证码仅当
config->safe->loginCaptcha开启时强制;json 视图可绕过密码强度校验 - 禅道文档「禅道 API 详解」已发布在禅道我的空间(docID=1),本篇为博客版
本文同步收录于禅道文档库。
文章导出
生成预览中...