1. 先解决 Codex 跑长任务时的通道中断问题
用 Codex 搭建“我的工作数据工作台”这件事,本身并不复杂:后端接 MenuViewSet.mywork_router 返回个人菜单树,前端用 MyWorkWorkWorkbenche.vue 做分组、搜索、最近使用和路由跳转。真正让人卡住的是会话一长,默认通道的额度就开始闹脾气。Codex 执行 PDD、SOP、前后端补全这类任务时,经常是文档写到一半、后端代码刚生成,调用就中断了,一中断整个上下文就要重新来。这个问题和代码逻辑无关,纯粹是模型 API 通道不稳定。
我的做法很简单:让 Codex 走的模型通道换成 TaoToken。TaoToken 是一个统一 API 兼容通道,官网在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end ,先去那里注册并创建 API Key,然后把 Codex 的 Base URL 指到 https://taotoken.net/api(注意末尾没有 /v1)。这样 Codex 在跑“我的工作数据工作台”这种长会话任务时,就不会因为 Key 或 Base URL 的兼容问题中断,能一口气把 PDD、SOP、后端接口和前端组件全部生成完。
这篇文章会把整个流程展开讲:从拿到 Key、配置 Codex,到把我整理好的工作台搭建 Prompt 原样发给 Codex,再到验证生成的代码是否符合验收标准。你只要按步骤走,就能复现一套完整的“个人工作入口聚合页”。
2. 把“我的工作数据工作台”拆成 Codex 能执行的任务
2.1 模块定位:不是 CRUD,是个人菜单聚合
“我的工作数据工作台”不能用普通 CRUD 页面的思路去理解。它没有独立业务表,后端入口是 server_backend/dvadmin/system/views/menu.py 里的 mywork_router,这个接口读取当前用户可见的菜单树,优先返回名称为“我的功能”的节点;如果这个节点不存在,再回退到“我的工作”。前端入口是 server_vue3/src/views/system/Workbenches/MyWork/index.vue,实际渲染逻辑在 server_vue3/src/views/system/Workbenches/components/MyWorkWorkWorkbenche.vue。
交给 Codex 时,需要把它定义成“个人菜单工作台”,而不是页面堆砌。后端负责按角色权限返回菜单树,前端负责把树形菜单压平成可点击的模块卡片,提供分类 tab、关键词搜索、最近使用记录和路由跳转。关键约束是:最近使用和激活 tab 保存在 localStorage,属于页面状态回显,不能写成后端业务字段。如果这几个边界不讲清楚,Codex 很容易自作主张建一张 my_work_workbench 表,那就偏离了原系统的设计。
2.2 准备材料:Key、Base URL、源码路径
开始之前,先把材料备齐。你需要:
- TaoToken API Key:打开 TaoToken 注册并创建 API Key,创建后复制下来,后面填到 Codex 配置里。
- Codex 工具本身:已经安装并可以正常调用命令行。
- 教育管理系统源码:重点涉及以下文件的本地路径:
server_backend/dvadmin/system/views/menu.pyserver_vue3/src/views/system/Workbenches/MyWork/index.vueserver_vue3/src/views/system/Workbenches/components/MyWorkWorkWorkbenche.vueserver_vue3/src/components/commonWorkbenches/api.ts
2.3 把 Codex 的 Base URL 指到 TaoToken
Codex 的配置文件在 ~/.codex/config.toml。用编辑器打开这个文件,在 model_provider 下加一个 provider,把 Base URL 指向 TaoToken。
model_provider = "taotoken"
[model_providers.taotoken]
name = "TaoToken"
base_url = "https://taotoken.net/api"
env_key = "TAOTOKEN_API_KEY"
wire_api = "responses"
然后在同一个文件的顶部设置默认模型。注意这里不要写死具体模型 ID,以 TaoToken 官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 的模型广场为准,选择 Codex 兼容的模型后,把 ID 填到 model 字段:
model = "你从模型广场复制的模型ID"
model_provider = "taotoken"
设置环境变量 TAOTOKEN_API_KEY 的值就是刚才复制的 Key:
export TAOTOKEN_API_KEY=YOUR_API_KEY
Key 从 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 创建。之后 Codex 发起的每次模型调用都会通过 TaoToken 的兼容通道转发。这样做的直接收益是:Codex 执行几十轮的长会话任务时,不会再因为默认通道限额中断,生成 PDD、SOP 和前后端代码的连续性有了保障。
3. 后端设计:mywork_router 的权限过滤与树形返回
3.1 后端设计重点:不新增模型,只返回菜单树
后端设计最忌讳新增“我的工作”业务模型。mywork_router 这个方法的核心逻辑是:调用 _get_role_filtered_menu_queryset(request.user) 获取按角色过滤后的菜单查询集,再通过 WebRouterSerializer 序列化,最后用 _build_tree 构造成树形结构。整个过程中,接口优先查找名称为“我的功能”的节点;找不到时,再去找“我的工作”节点。
这个设计的好处是,工作台入口完全受菜单权限控制,后端只返回用户可访问的树,前端不需要额外判断角色,也不需要在工作台里写死“消息中心”或“下载中心”。Codex 补齐这个接口时,要重点检查四件事:空树处理、无权限情况、菜单名称变化、树形序列化字段是否稳定。
3.2 后端 Prompt:让 Codex 校准接口实现
在 Codex 里输入下面的 Prompt 前,先确认 TAOTOKEN_API_KEY 环境变量已经生效。如果配置正确,Codex 在跑这段任务时不会因为模型通道问题中途断掉。
请 Codex 按“我的工作数据工作台”业务从零设计或补齐后端代码。
后端源码范围:
server_backend/dvadmin/system/views/menu.py
必须遵守的现有结构:
1. 接口为 MenuViewSet 的 mywork_router action。
2. 接口路径为 GET /api/system/menu/mywork_router/。
3. 菜单数据来自当前用户角色过滤后的 Menu 查询集。
4. 序列化使用 WebRouterSerializer。
5. 返回节点优先为“我的功能”,没有时回退“我的工作”。
需要实现或校准:
1. 保持角色权限过滤。
2. 保持树形菜单 children、path、name、image、component 字段。
3. 找不到目标节点时返回空数组,不报 500。
4. 返回 total 和 msg,便于前端处理空状态。
5. 不新增我的工作业务模型。
输出涉及文件、接口返回结构、权限规则、空状态处理和测试建议。
Codex 按这个要求生成后端代码时,会先读取 menu.py 的现有结构,再比对 mywork_router 的实现差异。如果接口原本就存在,它会做校准和补全;如果不存在,它会按约束从头生成。这里最容易出问题的地方是“找不到目标节点时返回空数组,不报 500”——默认情况下查不到节点容易抛异常,Codex 会补上防御性判断。
3.3 后端返回结构对照
为了让 Codex 生成的后端代码和前端展示逻辑保持一致,接口返回结构可以参考这个标准:
| 字段 | 类型 | 说明 |
|---|---|---|
data | List | 包含一个根节点树,根节点 children 为分组数据 |
total | int | 根节点数量,前端可据此判断空状态 |
msg | str | 请求状态说明 |
Codex 生成代码时,需要让它明确 data=[target_tree] 而不是把整个菜单列表平铺返回。前端 toMyWorkGroups 是按根节点 children 转换分组的,如果结构不对,后面所有分组和搜索逻辑都会跑偏。
4. 前端设计:从菜单树到可搜索的工作台
4.1 组件职责边界
前端设计不是做静态卡片,而是把菜单树转换成完整的工作台状态。MyWork/index.vue 只负责挂载 MyWorkWorkWorkbenche,业务逻辑全部在 components/MyWorkWorkWorkbenche.vue 里。组件内部使用 GetList(API_URL) 请求 /api/system/menu/mywork_router/,拿到数据后通过 toMyWorkGroups 把根节点 children 转成工作台分组。
组件需要维护四个关键状态:
systemList:工作台分组数据activeName:当前激活的 tab,记录在 localStoragekeyword:搜索关键词,只过滤当前展示范围的模块名称recentIds:最近使用的菜单 ID,同样存在 localStorage,上限 8 条
flattenGroupChildren 负责递归压平分组下的叶子菜单,保证深层菜单能变成可点击卡片。handleOpen 在点击卡片时先写入最近使用,再执行 router.push({ path })。
4.2 前端 Prompt:让 Codex 补齐页面状态
请 Codex 按“我的工作数据工作台”业务生成或补齐前端页面代码。
前端源码范围:
server_vue3/src/views/system/Workbenches/MyWork/index.vue
server_vue3/src/views/system/Workbenches/components/MyWorkWorkWorkbenche.vue
server_vue3/src/components/commonWorkbenches/api.ts
页面现状:
1. MyWork/index.vue 挂载 MyWorkWorkWorkbenche。
2. MyWorkWorkWorkbenche 请求 /api/system/menu/mywork_router/。
3. toMyWorkGroups 将菜单树转换成工作台分组。
4. keyword 支持模块名称搜索。
5. recentIds 记录最近使用,使用 localStorage 持久化。
6. activeName 记录当前 tab,使用 localStorage 持久化。
7. handleOpen 负责写入最近使用并 router.push 跳转。
需要生成或修正:
1. 保持菜单树转换和叶子节点提取。
2. 保持最近使用去重和数量限制。
3. 保持激活 tab 本地记忆,保存的 tab 不存在时回退第一组。
4. 搜索结果为空时要有明确状态。
5. 图片缺失时使用图标回退。
6. 不新增源码中不存在的后端字段或业务接口。
输出页面结构、接口调用、状态管理、搜索过滤、最近使用、路由跳转和验收步骤。
这个 Prompt 的核心价值在最后一条:不新增源码中不存在的后端字段或业务接口。很多 Codex 生成前端代码时会顺手造一个 getRecentList() 接口,但实际系统里最近使用是通过 localStorage 实现的。把这条约束放进 Prompt,能避免前端代码产生对不存在接口的依赖。
4.3 数据联动的字段边界
搜索、分组、最近使用、路由跳转之间是环环相扣的。Codex 生成代码时,要明确每个字段的职责:
id:用于最近使用记录name:用于搜索匹配和卡片展示path:用于路由跳转image:用于卡片图片,缺失时用图标回退children:有嵌套层级时必须递归压平
可以把这个表格直接粘到 Prompt 后面的补充说明里,帮助 Codex 理解哪些字段参与搜索、哪些字段决定跳转。字段边界一旦混淆,最常见的问题就是搜索时把 path 也拿去匹配,导致点进一个不存在的路由。
5. 扩展能力:数据联动与本地状态回显
5.1 数据联动:菜单树到卡片列表的数据流
“我的工作数据工作台”比静态导航页强的地方在于:后端菜单树、角色权限、前端搜索、最近使用和激活 tab 都参与同一个数据流。完整链路是:
mywork_router返回当前用户可见的菜单树toMyWorkGroups把根节点 children 转换成分组flattenGroupChildren递归提取叶子菜单,压平成卡片keyword过滤当前分组下的卡片- 点击卡片时,
handleOpen写入最近使用并执行路由跳转
任何一个环节字段缺失,都会导致卡片无法显示或无法跳转。Codex 生成和校验代码时,要按这个数据流逐项检查,而不是只盯着单个函数对不对。
5.2 本地状态回显:不绕过权限的缓存策略
本地状态回显包含两个部分:my_work_workbench_recent 保存最近点击过的菜单 ID,my_work_workbench_active_tab 保存当前激活的分组。页面加载时先读取本地状态,再请求菜单数据;如果本地保存的分组在菜单接口返回的数据中已经不存在,要回退到第一组。
Codex 生成时还需要处理“localStorage 读写异常”的情况。比如用户禁用了本地存储,或者缓存数据被其他页面塞入了非法格式,页面必须能正常加载,不能因为解析报错导致白屏。这个边界可以用一个 try-catch 包住缓存读写逻辑来解决。
6. Codex 开发标准:SOP 与 PDD 双约束
6.1 SOP 标准:先定目录,再写代码
使用 Codex 开发这个模块时,不要一上来就让它写代码。先让它输出目录结构和开发阶段,确认模块边界后再动手。推荐目录约束如下:
docs/modules/我的工作数据工作台/
├── pdd.md
├── api.md
├── test-cases.md
└── codex-sop.md
server_backend/dvadmin/system/views/
└── menu.py
server_vue3/src/views/system/Workbenches/MyWork/
└── index.vue
server_vue3/src/views/system/Workbenches/components/
└── MyWorkWorkWorkbenche.vue
server_vue3/src/components/commonWorkbenches/
└── api.ts
对应的 SOP 撰写 Prompt:
请 Codex 按教育管理系统模块开发 SOP,从零实现或补齐“我的工作数据工作台”模块。
执行要求:
1. 先输出目录结构,不要直接写代码。
2. 先生成 docs/modules/我的工作数据工作台/pdd.md、api.md、test-cases.md 和 codex-sop.md。
3. 文档确认模块边界后,再根据文档生成或修正项目代码。
4. 后端范围限定在 dvadmin/system/views/menu.py 的 mywork_router。
5. 前端范围限定在 MyWork/index.vue、MyWorkWorkWorkbenche.vue 和 commonWorkbenches/api.ts。
6. 后端需要覆盖菜单权限过滤、目标节点选择、树形返回和空状态。
7. 前端需要覆盖分组转换、搜索过滤、最近使用、激活 tab、图片回退和路由跳转。
8. 不生成源码中不存在的扩展能力。
输出目录结构、开发阶段表、后端任务清单、前端任务清单、状态回显清单和验收修复清单。
Codex 在处理这类任务时,会先读取 menu.py 和 MyWorkWorkWorkbenche.vue 的现有代码上下文,再基于真实结构输出文档,而不是凭空生成一套与源码无关的设计稿。这一步能显著减少后续返工。
6.2 PDD 标准:可验证的验收维度
PDD 的价值是让 Codex 知道自己写出来的代码要满足什么标准。可以把验收维度直接放进 Prompt:
| 验收维度 | 验收标准 | 需要检查的文件 |
|---|---|---|
| 业务目标 | 模块能按权限聚合个人工作入口 | pdd.md、menu.py、MyWorkWorkWorkbenche.vue |
| 页面结构 | 包含分组、搜索、最近使用、卡片、图片回退、空状态 | MyWork/index.vue、MyWorkWorkWorkbenche.vue |
| 数据模型 | 不新增业务模型,菜单数据来自系统菜单树 | menu.py |
| 接口规则 | /api/system/menu/mywork_router/ 返回“我的功能”或“我的工作”树 | menu.py、api.md |
| 权限控制 | 普通用户只看到角色授权菜单 | menu.py、test-cases.md |
| 本地状态回显 | 缓存损坏、tab 不存在、菜单变更都有处理 | MyWorkWorkWorkbenche.vue |
PDD 验收 Prompt:
请 Codex 根据 docs/modules/我的工作数据工作台/pdd.md 对“我的工作数据工作台”模块进行验收。
验收范围:
server_backend/dvadmin/system/views/menu.py
server_vue3/src/views/system/Workbenches/MyWork/index.vue
server_vue3/src/views/system/Workbenches/components/MyWorkWorkWorkbenche.vue
server_vue3/src/components/commonWorkbenches/api.ts
docs/modules/我的工作数据工作台/api.md
docs/modules/我的工作数据工作台/test-cases.md
验收维度:
1. 业务目标:是否能聚合个人工作入口。
2. 页面结构:是否包含分组、搜索、最近使用和卡片跳转。
3. 数据模型:是否未误建业务模型。
4. 接口规则:mywork_router 返回结构是否符合前端转换。
5. 权限控制:是否只展示授权菜单。
6. 数据联动:菜单树、搜索、最近使用和 router.push 是否一致。
7. 本地状态回显:缓存损坏、tab 不存在、菜单变更是否处理。
8. 测试用例:是否覆盖成功路径和失败路径。
输出验收结果表,标记通过、未通过和需要修复的文件位置。不要只给结论,需要指出具体问题、影响范围和修复建议。
Codex 完成验收后,如果发现某个维度未通过,它会给出具体文件和修复建议。这一步结束,整个工作台模块的代码才算真正符合 PDD 标准。
7. 验证与排障:TeaToken 通道的关键检查点
7.1 验证一次完整调用
配置完成后,进入 server_vue3 目录启动前端项目,在浏览器打开工作台页面。正常情况下能看到“消息中心”“下载中心”“问题反馈”等入口卡片。点击任意卡片,确认路由跳转生效;然后刷新页面,确认最近使用和激活 tab 能正确回显。
这一步如果出现问题,优先检查 Codex 生成的接口返回结构是否被前端正确解析。可以在浏览器开发者工具的 Network 面板里查看 /api/system/menu/mywork_router/ 的响应,确认 data 是一个根节点树且 children 包含完整分组数据。
7.2 常见报错对照
| 报错现象 | 可能原因 | 处理方式 |
|---|---|---|
401 Unauthorized | API Key 填错或未设置环境变量 | 重新从 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 创建 Key,检查 TAOTOKEN_API_KEY |
404 Not Found | Base URL 多加了 /v1 或路径错误 | 确认填的是 https://taotoken.net/api,末尾不要加 /v1 |
model_not_found | Codex 配置的模型 ID 不在模型广场 | 去模型广场复制正确的模型 ID,更新 config.toml 的 model 字段 |
Codex 跑长会话时如果中途断流,多半是某个中间步骤报错打断了上下文。此时不要急着重跑整个 Prompt,先把报错信息贴回给 Codex,让它基于现有上下文修复。TaoToken 的兼容通道保证的是调用稳定性,但代码层面的逻辑错误还是需要按普通开发流程排查。
8. 最后一步:把工作台跑通并记录一次真实调用
到这里,整套“我的工作数据工作台”已经从后端菜单权限过滤、树形返回,到前端分组转换、搜索、最近使用、本地状态回显全部跑通了。Codex 生成的代码分布在 menu.py、MyWorkWorkWorkbenche.vue、index.vue 和 api.ts 里,文档落在 docs/modules/我的工作数据工作台/ 目录下。
整个过程中,TaoToken 承担的是模型 API 通道的稳定供给。Codex 在生成 PDD、编写 SOP、校准后端接口、补全前端组件这几个阶段之间来回切换,每一步都需要重新发起模型调用。如果通道不稳定,任何一个节点中断都会导致上下文丢失,前面生成的文档和后端代码全要重来。用 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 上创建 Key,把 Base URL 填成 https://taotoken.net/api 之后,这种中断基本不会再出现。
建议你现在打开 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 注册并创建 API Key,完成一次真实调用。然后回到 Codex 里,把刚才那段工作台搭建的 Prompt 跑一遍。等到 /api/system/menu/mywork_router/ 返回的树形结构正确渲染成卡片,搜索、跳转、最近使用都符合 PDD 验收标准时,这套工作台模块就算真正交付了。




被折叠的 条评论
为什么被折叠?



