Some checks failed
Build and Deploy (admin.xpcool.com) / build-and-deploy (push) Failing after 4s
新增通知历史记录多维筛选(关键字/分组/类型/事件/渠道/接收人/状态/时间/排序)、统计概览、详情抽屉、批量删除与按天数清空,并补充通知字典选项接口与常量兜底。
211 lines
16 KiB
Markdown
211 lines
16 KiB
Markdown
# 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)已验证的运行方式 —— 直接复制可用
|
||
|
||
```bash
|
||
# 关键: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)
|
||
- **最终生效的修复(启动器层面,推荐)**:本机全局 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)
|
||
```ini
|
||
registry=https://registry.npmmirror.com
|
||
node-linker=hoisted # 避免 symlink 权限问题,走扁平化安装
|
||
store-dir=E:\.pnpm-store # store 与项目同盘(E 盘),走同卷硬链接,快且无需管理员权限
|
||
```
|
||
|
||
## 4. 常用命令
|
||
|
||
```bash
|
||
# 依赖
|
||
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(修复依赖安装)
|
||
1. **问题**:`pnpm install` 装不上,报 `ERR_UNKNOWN_BUILTIN_MODULE: No such built-in module: node:sqlite`
|
||
2. **根因**:pnpm 11.16.0 强依赖 `node:sqlite`,但系统 Node 23.0 / managed Node 22 默认未启用该内置模块(需 `--experimental-sqlite` 标志)
|
||
3. **修复**:设 `NODE_OPTIONS=--experimental-sqlite` 后用 managed node 22.22.2 + corepack 跑 `pnpm install` → 成功(39 workspace 项目,Already up to date)✅
|
||
4. **启动**:`pnpm dev:tdesign` → Vite ready,http://localhost:6000(5999 被占用自动切换)✅ HTTP 200,标题「Vben Admin Tdesign」
|
||
5. **澄清项目结构**:确认项目已精简为**唯一应用 web-tdesign**(非 agents.md 旧记录的 web-antd),同步更新本档案
|
||
6. **残留进程清理**:终止了此前多次失败重试遗留的 pnpm/tsdown/stub 后台进程
|
||
|
||
### 2026-08-24(首次搭建)
|
||
1. **梳理项目**:确认为 Vben Admin 5.7.0 官方模板克隆,无业务定制;主应用 web-antd(端口 5666)
|
||
2. **安装依赖**:
|
||
- 第 1 次失败:NODE_OPTIONS safe-delete shim 拦截 → 解法 `unset NODE_OPTIONS`
|
||
- 第 2 次失败:Windows symlink 权限 → 解法 `.npmrc` 加 `package-import-method=copy`
|
||
- 最终:`pnpm install` 成功(46 workspace 项目,1723 包)✅
|
||
3. **启动开发服务器**:`pnpm dev:antd` → 验证 http://localhost:5666 (状态见下)
|
||
4. **建立本文件 agents.md**:项目上下文档案 + 操作日志机制
|
||
5. **建立工作日志**:`.workbuddy/memory/YYYY-MM-DD.md`(每日记录,跨账号迁移时连同 agents.md 一起拷贝)
|
||
|
||
## 7. 迁移清单(换 WorkBuddy 账号 / 换机器时)
|
||
|
||
1. 拷贝整个项目目录(含 `node_modules` 可不拷,重新 install 即可)
|
||
2. 必拷文件:`agents.md`(本文件)+ `.workbuddy/memory/`(历史工作日志)
|
||
3. 本机环境要点(新机器):
|
||
- Node ≥ 22.18;pnpm ≥ 11(corepack)
|
||
- 跑 pnpm 前设 `NODE_OPTIONS=--experimental-sqlite`(否则报 node:sqlite 缺失)
|
||
- Windows 无开发者模式时保持 `.npmrc` 的 `node-linker=hoisted` 与 `store-dir=E:\.pnpm-store`
|
||
4. 装依赖后先 `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`,后续所有写索引操作全被拒。
|
||
- **处理**:
|
||
1. 先确认**没有进程真在写**(否则删锁会损坏索引):`tasklist | findstr /i git.exe`;要看命令行用 `Get-CimInstance Win32_Process -Filter "Name='git.exe'"`。
|
||
2. 确认无 `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` 同款写法),消除探测超时:
|
||
```bash
|
||
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`** 在本仓库(pnpm `node-linker=hoisted` + workspace 包名 `@vben/*` + 包内 `imports` 别名)下解析代价近乎无界:
|
||
- 单个 10 行的 `apps/web-tdesign/src/main.ts`(仅 3 个 import)跑 **300 秒仍不结束**;
|
||
- 关闭这条规则后同一文件 **1.7s** 完成;关闭整个 `n/` 插件也是 1.7s ⇒ 唯一元凶就是它;
|
||
- 对本次待提交的 7 个文件:修复前卡死 >15 分钟 ⇒ 修复后 **1.9s**。
|
||
- **修复(已完成)**:`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` 后再重建。
|
||
- **可复用的排查方法论(本次靠它一锤定音)**:
|
||
1. `eslint --no-config-lookup --rule no-unused-vars:error <file>` → 0.5s(排除 eslint 本体)
|
||
2. `eslint --print-config <file>` → 2.9s(排除配置加载慢)
|
||
3. 同一文件带完整配置直接 lint → **>300s 不结束** ⇒ 锁定「某条规则执行」阶段
|
||
4. 用「按前缀批量关闭插件规则」的临时探针配置做二分:先关 `n/` → 1.7s,再逐条缩小到 `n/no-extraneous-import`(`TIMING=all` 需跑完才输出,本例跑不完,故用二分更快)
|
||
- **附带优化(已完成,`lefthook.yml`)**:`checkType` 由全量改为增量:
|
||
```yaml
|
||
- 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)。
|
||
|
||
### 环境自检命令(只读,秒级)
|
||
```bash
|
||
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`。
|
||
|
||
1. **中文注释**:写/改代码时,在应有处(函数、复杂逻辑、配置项、非显然分支)加中文注释。
|
||
2. **做记录**:每次请求/变更/修复/文档动作,都在本项目 `.workbuddy/memory/CHANGELOG.md` 顶部追加一条,格式 `YYYY-MM-DD | 类型 | 一句话摘要`(类型:REQ/CHG/FIX/DOC/CFG/DEP)。
|
||
3. **中文优先**:与用户的思考、输出、交流,能中文尽量中文。
|