# xpcool.com 工作空间 · 统一规则与项目索引 > 本文件随会话自动加载。保持精简:只放规则与索引,详细历史在各项目 CHANGELOG。 ## 三条铁律(全项目通用) 1. 中文注释:写/改代码时,在应有处(函数、复杂逻辑、配置项、非显然分支)加中文注释。 2. 做记录:每次请求/变更/修复/文档动作,都在对应项目 CHANGELOG.md 顶部追加一条。 3. 中文优先:与用户的思考、输出、交流,能中文尽量中文。 ## 接口设计规范(2026-08-27 起 · 全项目强制) > 用户拍板:新建 HTTP 接口**全部采用 POST**;**URL 中不得带任何参数**(查询参数与路径参数 `{id}` 都禁止);**所有入参一律通过请求体 body(JSON)传递**。 - 路由用静态 path(如 `/recruitment/info/update`),`id` 等也放 body,不用 `/update/{id}`。 - 既适用于 service 后端(g.Meta `method:"post"`),也适用于 admin 前端(`requestClient.post(url, data)`,url 无参)。 - **首个落地模块**:service.xpcool.com 的 `recruitment`(招聘考试聚合),作为规范范本;后续新接口(含 house 之外的模块)一律遵守,存量接口逐步迁移。 ## 界面开发约定(2026-08-26 起) - **admin.xpcool.com 后台界面开发优先使用 TDesign MCP**(`tdesign-mcp-server`,已配置于 `~/.workbuddy/mcp.json`,`npx -y tdesign-mcp-server@latest`;tools:get-component-docs / get-component-list / get-component-changelog / get-component-dom / search-icons)。 - 写/改 tdesign 组件代码前,先通过 MCP 查官方文档,用官方封装属性与推荐用法,避免踩自造轮子/已知坑。 - 树形表格必须用 `t-enhanced-table`(t-table/PrimaryTable 不支持 tree);异步数据后需 `await nextTick()` + `tableRef.value.expandAll()`(defaultExpandAll 只在首次渲染生效)。 ## 工作空间说明(git 管理 · 跨设备同步) - 本工作空间仓库:`workbuddy.xpcool.com`(含本规则、每日日志、README),远程:`https://git.xpcool.com/xpcool/workbuddy.xpcool.com.git` - **布局约定(跨设备必须一致)**:所有项目与工作空间仓库位于同一父目录下: ``` <父目录>/ ├── workbuddy.xpcool.com/ ← 本工作空间(规则+索引+日志) ├── admin.xpcool.com/ ├── service.xpcool.com/ └── tool.xpcool.com/ ``` 换设备时按此布局 clone,索引即全部生效,无需改任何路径。 ## 项目索引(变更记录在各项目 .workbuddy/memory/CHANGELOG.md) | 项目 | 类型 | 相对路径(相对本工作空间) | 远程仓库 | |------|------|--------------------------|---------| | admin.xpcool.com | Vue 管理后台前端 | ../admin.xpcool.com/.workbuddy/memory/CHANGELOG.md | https://git.xpcool.com/xpcool/admin.xpcool.com.git | | service.xpcool.com | Go 后端服务 | ../service.xpcool.com/.workbuddy/memory/CHANGELOG.md | https://git.xpcool.com/xpcool/service.xpcool.com.git | | tool.xpcool.com | 前端工具站 | ../tool.xpcool.com/.workbuddy/memory/CHANGELOG.md | https://git.xpcool.com/xpcool/tool.xpcool.com.git | (新增项目:在此加一行 + 在其 .workbuddy/memory/ 建 CHANGELOG.md + git.xpcool.com 建仓库) ## 记录格式(省 token · 快速命中) - 倒序:最新在上,一行一条 - 模板:`YYYY-MM-DD | 类型 | 一句话摘要` - 类型:REQ 请求 / CHG 变更 / FIX 修复 / DOC 文档 / CFG 配置 / DEP 依赖 - 示例:`2026-08-26 | CHG | 新增用户列表分页接口并补中文注释` ## 命中流程 1. 判断是否涉及某项目(看项目名/路径)。 2. 读该项目 CHANGELOG.md 头部(最新 10–15 条)了解近况。 3. 处理后于 CHANGELOG 顶部追加本次记录。 4. 新增项目时同步更新上方索引表。 ## 生产部署(腾讯云 193.112.118.168,SSH 22025/xxcool,Docker+宿主机 Nginx) - 站点落点:前端静态 → `/data/www/<域名>/`;nginx 配置 → `/data/nginx/conf.d/<域名>.conf`(80→301→443 + 反代/静态);证书 → `/data/nginx/ssl/<域名>/<域名>_bundle.crt|.key`(本地源:`E:\xxcool\ssl\<域名>_nginx/`)。 - service 后端容器:`service.xpcool.com:new`,`127.0.0.1:10100:10100`,网络 `xpcool-net`,env:`GF_GCFG_ENV=prod` + `DB_DSN=mysql:service:xxx@tcp(xpcool-mysql:3306)/service?...`(**必须带 mysql: 类型前缀**)+ `JWT_SECRET`;容器内必须有 `manifest/config/config.yaml`(基础配置),否则 GF 启动报「找不到 config」;构建目录 `/data/deploy/projects/service.xpcool.com/`(main + manifest/config + resource,Dockerfile 用 COPY manifest/config 整体拷贝)。 - DB:`xpcool-mysql` 容器(root 密码见该容器 env),库名 `service`,种子执行顺序 003→004→004b→007(服务器表结构旧,必须先 003 加列;导入用 `sudo sh -c 'docker exec -i xpcool-mysql mysql ... < file'` 宿主机重定向)。 - 权限映射:admin_menu type=2 行的 path 必须匹配实际路由(现为 `POST /api/service/admin/...`,见 manifest/sql/007_menu_permissions_v3.sql)。 - 文件下载站(2026-09-03 上线,当晚迁移):`file.xpcool.com` = **FileBrowser Quantum** 容器 `fbq`(`gtstef/filebrowser:stable` v1.5.5,`127.0.0.1:10881→80`,restart unless-stopped,`/data/share:/srv:ro` **只读挂载**,数据卷 `/data/filebrowser-q`:config.yaml+database.db+tmp,属主=镜像 uid1000)+ nginx 反代。**要点**:初始凭据 **admin/admin**(首登后立即改密);配置走 `config.yaml`(sources/cacheDir),管理走网页 UI;API 与原版不兼容(需用户建 long-live token,/swagger 亦需);镜像默认非 root(uid1000);原版 filebrowser(容器 `filebrowser`/10880/db `/data/filebrowser/database`)已于 2026-09-01 归档、现已停用**保留回滚**;Quantum v2.0 beta 权限模型改 per-source(view/download/modify/create/delete)。改密/建只读账号/临时分享(过期+密码+匿名)均在网页 UI。 - SSH 凭据/密码不入库,需要时询问用户或查对话记忆;远程批量命令用 paramiko 脚本(`%TEMP%\wb_deploy\ssh_exec.py`,支持第 2 参数超时秒数),docker build 用服务器端 nohup+日志轮询防超时。**(2026-09-11 密钥轮换后更新)**:当前登录 = 本地 `~/.ssh/xpcool_ed25519`(ed25519,注释 xpcool-server-20260904)→ `xxcool@193.112.118.168:22025`(root 被拒;密码登录已禁);旧 `CentOS.pem`(RSA,对应服务器公钥 `skey-q6pq6jb3`)**已作废并从 authorized_keys 移除**(因私钥误提交 Gitea 事件而轮换),服务器 authorized_keys 另存 2 把钥(`mcp-server-manager@local`、`xxcoolwork@gmail.com`)为其他用途、保留不动;安全组按出口 IP 限放 22025(本机出口 1.204.105.116 曾因未放行连不上,80/443 可达);本机旧记录 `~/.ssh/id_ed25519` 与 wb_deploy 脚本**在当前设备不存在**。 - **服务器安全加固(2026-08-27 完成)**:firewalld 已启用(放行 22025/80/443/3000/2222;cockpit/rpcbind 已停);fail2ban 保护 sshd(port=22025, maxretry5/bantime1h);监控脚本 `/usr/local/bin/server-monitor.sh` + cron 每 10 分钟(调度在 **xxcool 的 crontab**:`*/10 * * * * sudo /usr/local/bin/server-monitor.sh`;日志 `/var/log/server-monitor.log`,Bark 推送配 `/etc/server-monitor.conf` 的 `BARK_URL`);**fail2ban 封禁告警已去重(2026-09-11)**:状态文件 `/var/lib/server-monitor/banned-ips.state` 存当前封禁 IP 集合,仅对**新增**封禁推送一次;已解封 IP 自动移出状态,日后再被封视为新事件可再提醒(脚本备份 `server-monitor.sh.bak.20260911`);dnf-automatic 每天 06:00 自动安全补丁;SSH 密钥登录已部署(本地 `~/.ssh/id_ed25519`)但用户要求保留密码登录。**坑**:① 腾讯云安全组未放行 3000/2222/8081,Gitea 走 nginx 反代 80/443;② 改 sshd 前必须先 `sshd -t` 预检+备份(曾因脏行导致 SSH 断开);③ EPEL 源需腾讯云镜像(`mirrors.cloud.tencent.com/epel`)且 baseurl 必须手动写全;④ CentOS9 的 fail2ban 在 EPEL。**⑤(2026-09-04 新坑)腾讯云改带宽若切计费模式会触发实例冷重启,重启后 firewalld 自定义端口规则曾丢失致 SSH 22025 失联(80/443 正常)——firewall-cmd 放行务必带 `--permanent`,且实例冷重启后要复查 22025 放行**。另:带宽 3M→5M 已升级(2026-09-04,实测 619KB/s 满速)。 - 本地 pnpm 修复(2026-08-27 升级为 wrapper 方案):根因=本环境 MSYS 路径转换故障,把 `/c/...` 参数转成 `E:\c\...`(多 `E:\c\` 前缀)致 corepack shim 与 node 都找不到 pnpm.js。**已建持久 wrapper**:`~/.workbuddy/binaries/node/bin/pnpm`(内容:`export NODE_OPTIONS=--experimental-sqlite; exec "<托管node.exe>" "C:/Users/ybtdevxxl/.workbuddy/binaries/node/workspace/node_modules/pnpm/bin/pnpm.cjs" "$@"`,关键=给 node 传 Windows 风格路径 `C:/...` 规避 MSYS 转换)。**提交/构建前需 `PATH="~/.workbuddy/binaries/node/bin:$PATH"` 前置**,pre-commit 钩子(lefthook oxlint/oxfmt/eslint/stylelint/checkType)即可正常运行;否则钩子崩 → 只能 --no-verify。已验证 pnpm 11.16.0 + `pnpm exec oxlint` 1.79.0。 ## 日常同步习惯(建议) - 每次工作结束:在各改动项目 `git add + commit`,本工作空间同样提交(规则/日志变化时)。**只 commit、不要 push**(2026-09-01 用户明确:推送由用户自行完成,AI 无需代为 push,避免凭据交互失败)。 - **验证分工(2026-09-01 用户明确)**:AI 能做的验证(类型检查、构建、单元/二进制测试、自动化冒烟)照做;**AI 不方便验证的部分(真实浏览器交互体验、视觉效果、下载弹窗等)直接交给用户手动验证**,不要反复折腾自动化工具。 - 换设备开工前:先 `git pull` 各仓库,保证规则与记录最新。 ## 本机 Windows/PowerShell 工具链坑位(2026-09-10 实测,写脚本必看) - **PowerShell 工具不回显 stdout**:exit code 正常但看不到输出;必须把结果 `Out-File` 落盘,再用 Read 读取。Bash 里调 `powershell.exe` 会被安全策略拒绝。 - **`[byte] -shl 8` 会溢出归零**(结果仍是 byte 宽度)。字节拼 16 位整数必须先 `[int]` 转换,否则高位丢失(剪贴板/协议解析类代码的高频坑)。 - **给 .ps1 加 BOM 绝不能用 `Get-Content -Raw` + `Out-File`**:本机默认按 GBK 解码 UTF-8 文件,中文会被永久破坏且不可逆。正确做法是字节级前置 `EF BB BF`(`[System.IO.File]::WriteAllBytes`)。 - **PATH 被裁剪**:脚本里直接写 `ping` / `netsh` 会报"无法识别",须用 `$env:SystemRoot\System32\xxx.exe` 绝对路径;且不要写 `& $exe args 2>$null | Out-String`(会报"无法在管道中间运行文档"),改用 `$out = & $exe args` 再 `@($out) -join ' '`。 - **PowerShell 变量名不区分大小写**:`$R` 与循环变量 `$r` 是同一个变量,会导致集合被静默覆盖。 - **后台监听的进程可能杀不掉**(Stop-Process / taskkill 均无效),换端口重新起更省事。 - **防火墙规则按可执行文件路径匹配**:一批 node.exe 规则指向已不存在的路径(失效);目前 `C:\Users\xxl\AppData\Roaming\nvm\v23.0.0\node.exe` 有有效的 Public 档「TCP+UDP 任意端口」入站放行规则——需要做**免提权的入站可达性测试**时就用它监听。 - 测入站**不要用 ping**:Windows 默认拦 ICMPv6/ICMP 入站,必须用 TCP 端口测试。 - 国内测速:Cloudflare 端点不可用;用 **Ookla 官方 CLI**(`install.speedtest.net` 可直连下载)。 - 本机网络备注:家里的宽带是**运营商级 NAT(CGNAT,第 2 跳 100.64.0.1)**,无公网 IPv4;但有**公网 IPv6**(`240e:338:263:3600::/64`)。以太网被判定为 Public 网络档。