Some checks failed
Build and Deploy (admin.xpcool.com) / build-and-deploy (push) Failing after 4s
新增通知历史记录多维筛选(关键字/分组/类型/事件/渠道/接收人/状态/时间/排序)、统计概览、详情抽屉、批量删除与按天数清空,并补充通知字典选项接口与常量兜底。
16 KiB
16 KiB
agents.md — 项目上下文档案(跨账号迁移单一事实源)
用途:让任何 AI 助手(WorkBuddy 其他账号 / 其他 AI 工具)接手本项目时,无需重新摸索即可无缝衔接。 维护约定:每次操作(改代码 / 跑命令 / 决策 / 踩坑)后,更新下方「操作日志」章节;环境与架构变化同步更新对应章节。 首次建立:2026-08-24
1. 项目概况
| 项 | 值 |
|---|---|
| 业务名 | admin.xpcool.com |
| 工作目录 | E:\xxcool\project\admin.xpcool.com |
| 基础框架 | Vue Vben Admin 5.7.0(官方 monorepo 模板) |
| 技术栈 | Vue 3 + TypeScript + Vite + pnpm 11 + turbo(monorepo)+ TDesign |
| 代码来源 | 官方仓库 vbenjs/vue-vben-admin 克隆(remote 为 ghproxy 镜像:https://ghproxy.net/https://github.com/vbenjs/vue-vben-admin.git) |
| 当前基线 | 已精简为单一应用 web-tdesign,并开始业务定制(apps/web-tdesign/src/views/_core/authentication/login.vue 已修改) |
| git 分支 | main(仅 origin/main) |
2. 应用清单(apps/)
| 应用 | 包名 | UI 库 | dev 端口 | 启动命令 |
|---|---|---|---|---|
| web-tdesign | @vben/web-tdesign |
TDesign | 5999(被占用自动切 6000) | pnpm dev:tdesign |
本业务唯一主应用为 web-tdesign(
.env.development设VITE_PORT=5999)。项目已从官方多应用模板精简,仅保留此应用。
3. 环境要求与本机踩坑记录(重要)
版本要求(package.json engines)
- Node
^22.18.0 || ^24.12.0 - pnpm
>=11.0.0(packageManager: pnpm@11.16.0)
本机(Windows)已验证的运行方式 —— 直接复制可用
# 关键:pnpm 11.16.0 用到 node:sqlite,必须给 NODE_OPTIONS 加 --experimental-sqlite(Node 22 需 flag)
export NODE_OPTIONS="--experimental-sqlite"
# 建议:把 managed node 22.22.2 放到 PATH 最前(避免系统 node 23 引擎不匹配告警)
export PATH="/c/Users/ybtdevxxl/.workbuddy/binaries/node/versions/22.22.2:$PATH"
# 用 managed node 的 corepack 驱动 pnpm
CORE="/c/Users/ybtdevxxl/.workbuddy/binaries/node/versions/22.22.2/corepack.cmd"
"$CORE" pnpm install # 安装依赖
"$CORE" pnpm dev:tdesign # 启动开发服务器
坑 1:node:sqlite 模块缺失(2026-08-26 实际遇到,本次修复根因)
- 现象:
pnpm --version/pnpm install报ERR_UNKNOWN_BUILTIN_MODULE: No such built-in module: node:sqlite(at ../store/index/lib/index.js) - 原因:pnpm 11.16.0 在解析包元数据时强依赖
node:sqlite,而系统 Node 23.0 / managed Node 22 默认未启用该内置模块(22.5+ 起在--experimental-sqlite标志后可用,23.4 才默认开) - 解法:
NODE_OPTIONS=--experimental-sqlite后再跑 pnpm(本次直接沿用该法装依赖、起服务均成功) - 持久化修复(2026-09-14,机器
C:\Users\xxl):注意 IDE 终端会进程级注入NODE_OPTIONS=--require=...node-language-shim.cjs,用户级环境变量会被它覆盖,所以必须写进 shell 启动脚本做「幂等追加」(不能覆盖):- PowerShell:
C:\Users\xxl\Documents\WindowsPowerShell\profile.ps1(AllHosts;Microsoft.PowerShell_profile.ps1在该机被误建成目录,故不用) - Git Bash:
~/.bashrc - 兜底:
setx NODE_OPTIONS "--experimental-sqlite" - 根治:把 Node 升到 24.12+(既满足 engines,node:sqlite 也已默认启用,无需任何 flag)
- PowerShell:
- 最终生效的修复(启动器层面,推荐):本机全局 pnpm 是 10.26.2(自身 0 处
node:sqlite),但它检测到packageManager: pnpm@11.16.0会另起 node 子进程运行 11.16.0(含 12 处node:sqlite),子进程用process.execPath启动 → 命令行 flag 传不过去,只有NODE_OPTIONS环境变量会被继承。故直接改C:\Program Files\nodejs\三个启动器(pnpm.cmd/pnpm.ps1/pnpm):既给 node 命令行加--experimental-sqlite,也注入/追加NODE_OPTIONS。备份在C:\Users\xxl\pnpm-shim-backup-20260914;⚠️ 重装 Node / 重装全局 pnpm 会覆盖,需重做- 自检命令(只读):
cmd /c C:\PROGRA~1\nodejs\pnpm.cmd --version→ 应输出11.16.0
- 自检命令(只读):
坑 2:NODE_OPTIONS 污染 / shim
- 现象:
pnpm install报[ERROR] [safe-delete] 操作失败 ... Some operations were aborted(WorkBuddy 注入--require=...genie-safe-delete.cjs --use-system-ca) - 原因:该 shim 会拦截 pnpm 的删除/符号链接操作
- 解法:在写死
NODE_OPTIONS=--experimental-sqlite时已同时覆盖掉 shim;如要保留 shim,则先unset NODE_OPTIONS再补 flag
坑 3:Windows 符号链接权限
- 现象:
pnpm install报UNKNOWN: unknown error, symlink ...,hoist 阶段失败 - 原因:本机未开「开发者模式/无管理员权限」,pnpm 默认 symlink 创建失败
- 解法:项目
.npmrc已改用node-linker=hoisted(扁平化)方案规避,见下
镜像与链接配置(.npmrc)
registry=https://registry.npmmirror.com
node-linker=hoisted # 避免 symlink 权限问题,走扁平化安装
store-dir=E:\.pnpm-store # store 与项目同盘(E 盘),走同卷硬链接,快且无需管理员权限
4. 常用命令
# 依赖
pnpm install # 装依赖(preinstall 会校验必须用 pnpm;postinstall 跑 stub)
pnpm reinstall # 清 lock 重装(= clean --del-lock && install)
# 开发
pnpm dev:tdesign # 启动 web-tdesign(默认 http://localhost:5999,被占用自动切 6000)
pnpm dev # turbo 并行起所有 app
# 构建 / 检查
pnpm build:tdesign # 构建 web-tdesign
pnpm check:type # 类型检查(turbo run typecheck)
pnpm lint # 代码检查
pnpm test:unit # 单元测试(vitest)
5. 架构速览(Vben Admin 5 monorepo)
apps/ 应用层:web-tdesign(唯一主应用)
internal/ 内部工具:vite-config、tsconfig、eslint/stylelint/oxlint 配置、tailwind-config、turbo-run
packages/ 共享包:@core(核心 UI/布局)、effects(请求/权限/hooks/插件)、stores、locales、
preferences(偏好设置)、icons、constants、utils、styles、types
- 主应用源码入口:
apps/web-tdesign/src/- 路由:
src/router/routes/modules/(dashboard.ts / demos.ts / vben.ts) - 页面:
src/views/ - API:
src/api/request.ts(封装requestClient)、src/api/core/ - 偏好:
src/preferences.ts(defineOverridesPreferences,官方默认 + 少量扩展字段)
- 路由:
- 环境变量:
apps/web-tdesign/.env.development(VITE_PORT=5999) - 路径别名:
#/*→./src/*(package.json imports)
关键开发约定(Vben 5 特有)
- 权限:
preferences.ts的app.accessMode(frontend/backend/mixed);按钮级用<AccessControl :codes>/hasAccessByRoles/v-access:code - API 请求:
requestClient.get/post<Type>(url),代理在vite.config.ts - 国际化:
$t(),语言包在packages/locales - 主题:CSS 变量覆盖(
:root { --primary: ... }),偏好里theme.builtinType/colorPrimary - 详细参考:本机已装 vben skill(
C:\Users\ybtdevxxl\.workbuddy\skills\vben,含 20+ references)
6. 操作日志
倒序(最新在上)。每条:日期 / 操作 / 结果 / 备注
2026-08-26(修复依赖安装)
- 问题:
pnpm install装不上,报ERR_UNKNOWN_BUILTIN_MODULE: No such built-in module: node:sqlite - 根因:pnpm 11.16.0 强依赖
node:sqlite,但系统 Node 23.0 / managed Node 22 默认未启用该内置模块(需--experimental-sqlite标志) - 修复:设
NODE_OPTIONS=--experimental-sqlite后用 managed node 22.22.2 + corepack 跑pnpm install→ 成功(39 workspace 项目,Already up to date)✅ - 启动:
pnpm dev:tdesign→ Vite ready,http://localhost:6000(5999 被占用自动切换)✅ HTTP 200,标题「Vben Admin Tdesign」 - 澄清项目结构:确认项目已精简为唯一应用 web-tdesign(非 agents.md 旧记录的 web-antd),同步更新本档案
- 残留进程清理:终止了此前多次失败重试遗留的 pnpm/tsdown/stub 后台进程
2026-08-24(首次搭建)
- 梳理项目:确认为 Vben Admin 5.7.0 官方模板克隆,无业务定制;主应用 web-antd(端口 5666)
- 安装依赖:
- 第 1 次失败:NODE_OPTIONS safe-delete shim 拦截 → 解法
unset NODE_OPTIONS - 第 2 次失败:Windows symlink 权限 → 解法
.npmrc加package-import-method=copy - 最终:
pnpm install成功(46 workspace 项目,1723 包)✅
- 第 1 次失败:NODE_OPTIONS safe-delete shim 拦截 → 解法
- 启动开发服务器:
pnpm dev:antd→ 验证 http://localhost:5666 (状态见下) - 建立本文件 agents.md:项目上下文档案 + 操作日志机制
- 建立工作日志:
.workbuddy/memory/YYYY-MM-DD.md(每日记录,跨账号迁移时连同 agents.md 一起拷贝)
7. 迁移清单(换 WorkBuddy 账号 / 换机器时)
- 拷贝整个项目目录(含
node_modules可不拷,重新 install 即可) - 必拷文件:
agents.md(本文件)+.workbuddy/memory/(历史工作日志) - 本机环境要点(新机器):
- Node ≥ 22.18;pnpm ≥ 11(corepack)
- 跑 pnpm 前设
NODE_OPTIONS=--experimental-sqlite(否则报 node:sqlite 缺失) - Windows 无开发者模式时保持
.npmrc的node-linker=hoisted与store-dir=E:\.pnpm-store
- 装依赖后先
pnpm dev:tdesign验证 5999/6000 端口
8. Git 提交 / 推送排障(2026-09-14 实遇三连坑)
三个现象互相独立,都会让 IDE 里点「提交/推送」看起来"坏了"或"卡死"。
现象 A:fatal: Unable to create '.git/index.lock': File exists
- 原因:上一次 Git 操作(IDE 状态栏
git add/ 被杀掉的提交)中断,残留.git/index.lock,后续所有写索引操作全被拒。 - 处理:
- 先确认没有进程真在写(否则删锁会损坏索引):
tasklist | findstr /i git.exe;要看命令行用Get-CimInstance Win32_Process -Filter "Name='git.exe'"。 - 确认无
git进程持有后删锁:Remove-Item .git\index.lock -Force,再git status验证。
- 先确认没有进程真在写(否则删锁会损坏索引):
- ⚠️ 不要在有活跃 git 进程时直接删锁。
现象 B:git push 长时间挂起(无报错、不动)
- 原因 1(凭证缺失):系统级
credential.helper=manager(GCM 2.6.1)里没有git.xpcool.com的凭证(凭据管理器只有admin.git.ybtdev.com),GCM 于是走交互/GUI 流程,在非交互终端里就表现为挂死。 - 原因 2(探测超时):GCM 对自建 Gitea 域名会尝试自动探测 host provider,实测
warning: auto-detection of host provider took too long (>2000ms),每次 push 先卡 2 秒以上。 - 修复(已完成):全局加
credential.https://git.xpcool.com.provider=generic(与已有admin.git.ybtdev.com同款写法),消除探测超时:git config --global credential.https://git.xpcool.com.provider generic - 仍需人工做一步:凭证本身要首次在有交互的终端里输一次账号/密码(或在 IDE 里点一次推送的输入框),之后 GCM 存入 Windows 凭据管理器(
cmdkey /list可见LegacyGeneric:target=git:https://git.xpcool.com),后续免输。 - 排查技巧:
GIT_TERMINAL_PROMPT=0 GCM_INTERACTIVE=never git push --dry-run origin main—— 禁用交互可立刻暴露「到底是凭证问题还是网络问题」(会直接报could not read Username而不是挂住)。
现象 C:git commit 长时间无响应(钩子"卡死")—— 真凶是 eslint 规则,不是类型检查
- 症状:在 IDE 里提交后长时间无输出;进程链为
git.exe commit→sh .git/hooks/pre-commit→lefthook.exe→node .../eslint.js,其中 eslint 进程累计吃满 900~1400 秒 CPU 仍在跑(是满核计算,不是等待,故不会自己恢复;实测卡了 23 分钟)。 - 根因:
eslint-plugin-n的n/no-extraneous-import在本仓库(pnpmnode-linker=hoisted+ workspace 包名@vben/*+ 包内imports别名)下解析代价近乎无界:- 单个 10 行的
apps/web-tdesign/src/main.ts(仅 3 个 import)跑 300 秒仍不结束; - 关闭这条规则后同一文件 1.7s 完成;关闭整个
n/插件也是 1.7s ⇒ 唯一元凶就是它; - 对本次待提交的 7 个文件:修复前卡死 >15 分钟 ⇒ 修复后 1.9s。
- 单个 10 行的
- 修复(已完成):
internal/lint-configs/eslint-config/src/configs/node.ts里把n/no-extraneous-import置为'off'(含中文注释说明原因)。未声明依赖的兜底改由 pnpm 严格依赖结构 + CI 的 install/build 承担。- ⚠️ 该包经
dist/分发(main: ./dist/index.mjs,且dist被gitignore、未被 git 跟踪):改完src必须重建才生效。 - ⚠️ 本机重建当前不可用:
pnpm --filter @vben/eslint-config run stub(tsdown)报Failed to import module "unrun"——unrun是 tsdown 的可选依赖,hoisted 安装下未落地(node_modules与pnpm-lock.yaml里都没有)。应急做法:手工同步dist/index.mjs(本地派生物,不进仓库);根治可pnpm add -D unrun -w后再重建。
- ⚠️ 该包经
- 可复用的排查方法论(本次靠它一锤定音):
eslint --no-config-lookup --rule no-unused-vars:error <file>→ 0.5s(排除 eslint 本体)eslint --print-config <file>→ 2.9s(排除配置加载慢)- 同一文件带完整配置直接 lint → >300s 不结束 ⇒ 锁定「某条规则执行」阶段
- 用「按前缀批量关闭插件规则」的临时探针配置做二分:先关
n/→ 1.7s,再逐条缩小到n/no-extraneous-import(TIMING=all需跑完才输出,本例跑不完,故用二分更快)
- 附带优化(已完成,
lefthook.yml):checkType由全量改为增量:- name: checkType run: pnpm exec turbo run typecheck --filter=...[HEAD] --concurrency=4--filter=...[HEAD]只校验「自 HEAD 起有改动的包 + 依赖它们的包」→ 实测 38 → 10 个任务;--concurrency=4限制并发峰值。注意:这不是卡死根因,只是缩时优化。 - 应急跳过钩子:
LEFTHOOK=0 git commit ...(本次提交完全不跑钩子,仅用于纯文档/配置类提交)。 - 提示:跑提交前先停掉
pnpm dev,钩子会更快。 - 若再次卡死:先按进程链确认卡在哪个 job(
Get-CimInstance Win32_Process | Where-Object { $_.ParentProcessId -eq <lefthook PID> }),再决定终止:只杀 叶子 进程(eslint 等)后,务必确认.git/index.lock是否残留(见现象 A)。
环境自检命令(只读,秒级)
pnpm exec oxlint --version # 应 < 1s 返回 Version: x.y.z
pnpm exec turbo run typecheck --dry=json | findstr /c:"\"taskId\"" # 看本次会跑多少任务
cmd /c C:\PROGRA~1\nodejs\pnpm.cmd --version # 应为 11.16.0
"C:\Program Files\Git\bin\bash.exe" -lc "cd /e/Project/admin.xpcool.com && pnpm --version" # 钩子执行环境(Git Bash)自检
统一工作约定(xpcool.com 中央规则)
与中央
../workbuddy.xpcool.com/.workbuddy/memory/MEMORY.md保持一致;本项目变更流水在.workbuddy/memory/CHANGELOG.md。
- 中文注释:写/改代码时,在应有处(函数、复杂逻辑、配置项、非显然分支)加中文注释。
- 做记录:每次请求/变更/修复/文档动作,都在本项目
.workbuddy/memory/CHANGELOG.md顶部追加一条,格式YYYY-MM-DD | 类型 | 一句话摘要(类型:REQ/CHG/FIX/DOC/CFG/DEP)。 - 中文优先:与用户的思考、输出、交流,能中文尽量中文。