# 需求:后台标准件公司化：Vben-模板收编进-pdgen，正本版本化＋外包交付-vendor

状态: accepted(2026-10-14 boss 10-14 直派「记录规则+开始推进」,并拍定则:外包/外部=Go 后台+Vben 模板+uni-app H5,与内部只做协议统一(正本 docs/工程规范/OUTSOURCE-STACK-STANDARD.md);M0 发包需 boss 批,顺序按 M2→M1→M3)
归属: 公司运营
来源: boss 直投(会话)
日期: 2026-10-14
建议: 做,两个入口（pdgen 与 admin-cli）并存导致新项目漏检现成后台模板，已在早点干饭造成一次返工；收编成单一入口＋版本化正本后，每接一个后台项目省一次重写

## 现状

**触发事实（2026-10-14，外包项目 zaodian_order「早点干饭」）**

该项目后台界面被自研了一个 350 行单页（`apps/api-go/internal/api/web/admin.html`，go:embed 挂 `/admin/`），老板否掉：公司有现成 Vben 后台栈。

复盘归因——问题不在"模板不好"，在"没查到就定案"：找模板只走了两个入口，`pdgen list`（六个 init 模板：cf-site / cli-tool / go-service / tauri-app / web-app / worker，**没有后台模板**）与档案记录的 mac 同族仓 `villagesage-ui-admin`（本机不存在）。两处都没有即判定"公司没有现成的"，未量差集就动手，并事后补了三条理由写进交付文档（`zaodian_order/docs/后台集成方案.md` §6），其中"你的单页口径与独立工程冲突"一条**不成立**（Vben 本身就是左导航 SPA）。

**公司侧实际有什么（本机实测，非印象）**

| 资产 | 位置 / 版本 | 状态 |
|---|---|---|
| 后台前端正本 | `D:/code/work/lin/Admin_Template/frontend/packages/admin-core` → npm `@admin-template/admin-core@0.1.3`（Vben5 + Element Plus） | alpha，消费方需 postinstall 打补丁 |
| 后台后端正本 | Go module `github.com/linxianqinwork/Admin_Template/backend/core/v2@v2.0.0-alpha.16`（Gin + GORM + JWT + Redis） | alpha.16 |
| 生成器 | `Admin_Template/cli`＝`npx admin-cli create <proj>`（复制 `backend/starter-app/` ＋ `examples/external-admin-web/`） | **与 pdgen 并存，两个入口** |
| 内网源 | Verdaccio `http://111.229.223.148:40087`、Gitea `:13000` | 实测 HTTP 200 可达（本机） |
| 已集成先例 | `D:/code/work/lin/shgxw/apps/admin-web`（`@admin-template/admin-core ^0.1.1` ＋ `postinstall: scripts/patch-admin-core.mjs`）、`shgxw/apps/api-go`（gin ＋ core alpha.16 ＋ gorm） | 补丁未回收进正本 |
| 开箱契约 | admin-core 前端实际要打：`/auth/login`、`/auth/me`、`/auth/logout`、`/system/auth/refresh`、`/system/auth/codes`、`/menu/add|tree|router|user-tree`、`/user/add|list`、`/messages/*`（约 20 条），base 走 `VITE_GLOB_API_URL=/api` | 这就是"接进去要多少工"的真实大小 |

**三条结构性问题**

1. **入口分裂**：新项目"出生"有两个 CLI——pdgen 管六类骨架、admin-cli 管后台，没有任何一处告诉前者之外还有后者，检索必然漏（本票就是证据）。
2. **正本未定型**：core 在 alpha，消费方靠 postinstall 补丁续命，补丁不回灌＝正本没在长，第二个项目会打第二份补丁。
3. **交付形态未定**：外包客户拿不到内网源，"能不能用"取决于有没有 vendor 这一步，现在没有任何文档写过。

## 方案

判据（公司视角四条，用来否决花哨方案）：复用边际成本趋零／升级一处收敛／外包交付可落地／发现成本＝一条命令。

**分层职责**

- **L1 正本** ＝ `admin-core` ＋ `backend/core/v2`。通用能力（登录、菜单、权限、表格、站内信、主题）只在此长。业务项目**不许复制标准件源码**进仓。
- **L2 入口** ＝ `pdgen` 收编：新增 `pdgen init admin-web <name>`，内部转调 `admin-cli create`，只生成**薄壳**（业务 app 包目录 ＋ 配置 ＋ 端口登记 ＋ `.pdgen.json` 版本声明），不生成整套后台代码。`pdgen check` 加一类对账：项目声明的 `admin-core` / `backend/core` 版本 vs 正本最新发布版，落后即报（照 ui_kit sync ＋ `SYNC.json` 那套已验证机制抄）。
- **L3 交付适配** ＝ 外包项目多出一步 `vendor`：把 npm 包与 Go module 拉平成仓内目录，或写清客户自建同源要求。**开发期禁 vendor**（否则又变成 N 份副本），只在出包时拉平。
- **L4 最小契约** ＝ 给"不想上 Redis/GORM"的轻量项目（外包单店这类）一份 **auth/menu 最小后端契约**（约 10~15 条：login/me/logout/refresh ＋ 固定菜单树 ＋ 用户列表），照它实现就能挂 Vben 壳。**这条是决定成败的**——缺它，小项目接不动，就会再出现"干脆自研"。

**里程碑与工量（可分派，互不阻塞）**

| # | 事项 | 仓 | 工量 | 前置 |
|---|---|---|---|---|
| M0 | core 定 1.0 边界：冻结对外契约（接口/事件/组件 props），把 shgxw 的 `patch-admin-core.mjs` 收编进包并发版 | Admin_Template | 0.5~1 天 | 无 |
| M1 | `pdgen init admin-web` 薄壳收编 ＋ `pdgen check` 版本对账 | pdgen | 0.5 天 | M0 定版号（可并行开工） |
| M2 | L4 最小契约文档（清单以浏览器网络账本实测为准，不按印象写） | Admin_Template/docs | 0.5 天 | 无 |
| M3 | 早点干饭试点迁移：后台页换 Vben 壳，23 条业务接口与真库判据零改动，按 M2 补 auth/menu | zaodian_order | 1~2 天 | M0 ＋ M2 |
| M4 | vendor 固化进外包交付清单与出包脚本 | company/ops ＋ 模板 docs | 0.5 天 | M3 出真实依赖清单 |

**分工边界**：按 2026-09-17 定则，pdgen 模板与 Admin_Template 正本不由本项目会话修改，本票只出方案；M3 属早点干饭项目，可直接做。待老板拍两件事：① M0/M1/M2 派给谁；② M3 是现在就切，还是先交付当前自研版、Vben 版作第二版。

**进展（2026-10-14 当日，M2＋M1 已闭环）**

- **M2 落纸** = `Admin_Template/docs/ADMIN-CORE-CONTRACT.md`（已进该仓 README 文档索引）。两条口径被实测推翻：①**框架启动必发只有 4 条**（login/me/menu-router/logout，`starter-app` 全有现成实现），其余是 `index.mjs` 的**导出面**不是调用面——「开箱约 20 条」这个数就是这么来的，也正是把人推回自研的伪前提；②**0.1.3 从未发布**：Verdaccio `dist-tags.latest=0.1.1`（2026-06-24 停更），`npm i @admin-template/admin-core@0.1.3` 实跑 **ETARGET 装不到**，且 0.1.1 用 `/user/list`·`/menu/add`、0.1.3 改 RESTful `/system/users`·`/system/menus`，两版路径不是一套。**M0 的必要性由此从抽象风险变成硬证据：正本没发出去，第二个项目就照未发布的版本号写适配层。**
- **M1 落地** = pdgen 新模板 `init/admin-web`（薄壳 19 文件，对齐 `examples/external-admin-web`，不复制后台源码）＋ `src/check.js::auditPins` 版本对账（`template.json` 的 `pins` 是正本版本唯一记录处，现钉 0.1.1）。实跑：`pdgen list` 出现 admin-web → `npm install`(407 包)/`vitest`(3 passed)/`vite build`(dist 出成) 全绿 → `pdgen check --drift` rc=0 → 反向注入降版（npm 与 go.mod 各一例）`pdgen check` 报 `[pin]` rc=2。pdgen 全量 `npm test` 65 passed。端口按 `ops/ports.py` 登记制，未登记 `npm run dev` 直接报错（不回落默认端口）。
- **M3 已换壳（同日，boss「开始推进 M3」）**：zaodian_order 后台由 `pdgen init admin-web` 生成的 Vben 壳承载，旧 456 行手写单页 `internal/api/web/admin.html` **已删除，不留两个入口**。后端只加协议层：`internal/api/admin_auth.go` 出契约 4 条 + `withBearerAdminKey` 把 Bearer 翻译回原口令门，**23 条业务 handler 一行未动**（`go test ./...` 七包全绿，新用例含错口令/篡改/过期/无凭据直通等负向断言）。8 个视图（5 个同构模块共用 `resource.vue`+`configs.ts`），build 产物经 `scripts/export-go-dist.mjs` 走 go:embed 随 exe 交付。浏览器实测：登录 → 左导航 8 条由 `/menu/router` 下发 → 概览挂载。**M3 未打勾的原因**（当日 14:3x 记）：票面要求「真库下 23 条接口零改动 + H5 58 页走查缺口 0」，当时判定「本机没有可连的 Postgres」。**这条判定后来被推翻**：容器一直在跑，且「空表」另有真因（baseURL 相拼成 404），详见下面 15:3x 那条。
- **M0 的必要性再加一条硬证据**：干净项目 `npm install` 拿到的 **0.1.1 发布物直接白屏**（`mergeLocaleMessage` 抛 `Invalid value`，包没带 app locale 兜底；且不转发 `pageMap`，后端菜单解析不到组件）。shgxw 是靠 `scripts/patch-admin-core.mjs` 的 **30 余处 postinstall 补丁**跑起来的——那份脚本就是本票要消灭的东西。仓内 0.1.3 已含这两处修复但**从未发布**，用它一次跑通。现况：`package.json` 仍钉 0.1.1（不钉装不到的版本号），验证用 `npm i --no-save file:...admin-core` 引仓内版，实况与「M0 发包后删掉这行」写进 `apps/admin-web/README.md`。
- **新登记的口径缺陷（M0 一并处置）**：后端信封 `{code,msg,data,error}` 与 admin-core 拦截器读的 `error`/`message` 不重合，界面拿不到我方写的中文解释；0.1.3 仍无条件轮询 `/messages/*`。
- **安全级缺陷（登记未擅改，建议排在 M0 收编补丁之前）**：`getAccessCodesApi` 在 `return ["super"]` 之后才发请求（0.1.1/0.1.3 两版都有，`dist/api/auth.mjs:16-17`），权限码恒为 `["super"]`，按钮级鉴权形同虚设。


- **M0 发包完成（同日，boss「按你推荐的推进」）**：正本收编 5 处修复后发布 **`@admin-template/admin-core@0.1.5`**（`dist-tags.latest=0.1.5`），并补发工作区有、源上没有的 `@vben-core/design@5.5.5` / `@vben/styles@5.5.5`。**通道教训**：`npm publish` 会把 `catalog:`/`workspace:*` 原样发出去 → 干净项目 `EUNSUPPORTEDPROTOCOL` 装不动（0.1.4 即废版，已 `npm deprecate` 指向 0.1.5，不做 unpublish）；必须 `pnpm publish`。验证两条都过：干净目录 `npm i @admin-template/admin-core@0.1.5` = 209 包 rc=0；zaodian 壳切回发布物后 `check`/`build` 全绿、`/admin/` 200。pdgen pin 同步 0.1.5（`npm test` 65 passed）。**M0 未打勾的两条**：①前端只到 0.1.5，不是去 alpha 的 1.0 边界版，后端 `backend/core/v2` 仍 alpha.16 未定版；②shgxw 的 `patch-admin-core.mjs` 现已多余但没动（别家仓构建链，改前先对齐时机）。**0.1.5 的浏览器挂载复验**：Qoder browser 通道超时未做成，同日 15:3x 改走 weave 真 Chromium 补完（四证齐全，见 M3 复验那条）。

- **仍欠（按优先级）**：①~~0.1.5 的浏览器挂载复验~~（**已做**，见下条）＋真库下 H5 58 页走查重跑——我改的是 router 注册层，得确认没伤 C 端；但 3232 上跑的是别的会话起的**旧二进制**（exe 11:30 编译，改动 15:36），在它上面重跑等于测改动前，接管 3232 要先协调；②M0 的「1.0 边界版」——前端 0.1.5→1.0、后端 `backend/core/v2` alpha.16→定版，并冻结对外契约表（`docs/core-boundary.md`）；③M4 vendor 固化（前端已走 go:embed 随 exe 交付，Go module 侧出包拉平仍要走一遍）；④shgxw 补丁脚本退役（0.1.5 之后它已多余）。`pdgen report` 的 admin-web 零使用告警在 M3 结掉后自然清零，不做豁免。

- **M3 数据面带真库复验（同日 15:3x，boss「按你推荐的推进」之后）**：①**当日 14:3x 记的「本机无可连 Postgres」是错的**——`zaodian-postgres` 容器一直健康跑在 127.0.0.1:3237，`deploy/.env` 里 `ZD_PG_*` 全套都在；带库跑 `migrate -check`（8 个迁移文件 0 待执行）+ `go test -count=1 ./...` 七包全绿（含 `pgstore` 那组 12 子例，「后台写完顾客端立刻看到新值」即 C 端读同一份库的口径）。②**带库复验抓出一个真缺陷**：壳的 `requestClient` baseURL=`/api`（契约）与业务层 `BASE='/app-api/zaodian/admin'` 相拼 → 实发 `/api/app-api/...`＝**404**，页面只显「暂无数据」，与「库里真没数据」同形——14:3x 那轮浏览器实测的「无库所以空表」结论其实是这个 404。修法落在**注册层**：`shellAdminAlias` 给管理端 23 条并 `/api/zaodian/admin/*` 别名（handler 零改动，两个前缀挂同一个 `withBearerAdminKey`+`guard` 包装），前端 `BASE` 改回相对 baseURL 的 `/zaodian/admin`；C 端一律不并（多一前缀=多一面攻击面）。判据 `TestAdminRoutesAlsoServedUnderShellPrefix` 先红（503 vs 404）后绿，断两前缀同状态码同 error + C 端 404 + 无库时两前缀同判据。③**0.1.5 挂载复验做成**：Qoder 浏览器通道全灭（连 `list_pages` 都超时），改走公司 weave（自带 Chromium，`weave shell --headless --console`）实证四证——`#app` 有子节点、登录表单可见、登录后 8 条后端下发菜单逐条对上、订单页渲染出真组件（表头 8 列 + 状态页签）；console 无未捕获异常，0.1.1 那类 `mergeLocaleMessage` 崩溃不再出现。④口径落纸：`ADMIN-CORE-CONTRACT.md` **§9「baseURL 会和业务前缀相拼」**＋ pdgen 模板 README 的同位置警告（`pdgen npm test` 65 passed）。教训进全局错题集（空态把 404 洗成空库 = 「空集合不构成通过」同族）。



## 验收标准

- [ ] M0：`admin-core` 与 `backend/core` 各有一个去掉 alpha 后缀的边界版本；shgxw 删除 `postinstall` 补丁后仍能构建（补丁回收为证据）。
- [x] M1：`pdgen list` 出现 `admin-web`；`pdgen init admin-web demo && cd demo && npm install && npm run build` 退出码 0；故意把副本里的版本号降一档，`pdgen check` 报 drift（判据要能红）。
- [x] M2：契约文档逐条对上 admin-core 实际发起的请求（拿浏览器网络账本核，不是照 README 抄），并标出"最少实现集"与"可先 501 的集"。
- [ ] M3：早点干饭后台由 Vben 壳承载；23 条业务接口零改动；`go test -count=1 ./...` 带库全绿；H5 全量走查 58 页缺口仍为 0；旧自研页要么下线要么显式标注为降级备份，**不留两个入口**。
- [ ] M4：外包交付清单里 vendor 是一条可执行命令（不是散文段落），并在没有内网源的干净机器上实测装起来一次。
- [ ] 反判据（出现即方案失败）：任何业务仓出现 `admin-core` 源码副本；或新项目仍需"有人恰好知道"才能发现后台模板。
