tool.xpcool.com/docs/PROJECT_STATE.md
夏犀麟 dd38aeaf38
All checks were successful
Build and Deploy (tool.xpcool.com) / build-and-deploy (push) Successful in 1m10s
feat(theme): 改版为清晰蓝卡片工作台并接管 UI 库尺度
主色青玉改宝石蓝,字号整体放大一档(正文 16px),
通过 --td-comp-* 与 --td-font-* 接管 TDesign 控件高度与文字,
修复 theme-mode 选择器权重不足导致深色变量被 UI 库覆盖的问题。
2026-09-14 23:54:53 +08:00

191 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# PROJECT_STATE.md — 项目状态与交接文档
> **本文件是项目的「单点真相」Source of Truth任何 AI 账号 / 开发者接手项目时,请先读本文件,再读 `CHANGELOG.md` 与 `docs/api-contract.md`,即可无缝接续工作。**
>
> **维护规则(重要)**:每次对本项目做任何实质变更(新增/修改工具、改架构、改契约、修坑),必须同步更新:
> 1. `docs/CHANGELOG.md` —— 追加一条变更记录(倒序,最新在上)
> 2. 本文档 —— 更新工具清单、状态、待办与技术约定
> 3. `.workbuddy/memory/YYYY-MM-DD.md` —— 工作日志
---
## 1. 项目快照
- **名称**tool.xpcool.com在线工具箱
- **形态**:纯前端 SPA无自建 mock。计算与文件处理在浏览器本地完成「服务端工具」分类的工具调用自建后端见第 5 节)。
- **技术栈**Vite 6 + Vue 3`<script setup>`+ Pinia + TypeScriptstrict+ UnoCSS + TDesign Vue Next + **vue-i18n 11** + pnpm**禁止换 npm/yarn**
- **国际化**:中(基线 zh-CN/ 英 / 日 / 韩 四语言,详见第 3 节
- **主题**:浅色 / 深色 / 跟随系统 三态
- **常用命令**`pnpm dev`(开发)/ `pnpm build`vue-tsc + vite 构建)/ `pnpm type-check`
- **客户端**PC + 移动端 H5 响应式(`<768px` 侧边栏变抽屉
- **构建注意**`pnpm build` 前若 dist 目录文件过多会触发安全删除保护阈值 50 / `mv dist dist.bak-<ts>` 再构建构建后把备份移走
## 2. 当前全貌(截至 2026-09-14共 6 分类 58 个工具)
> ⚠️ **分类在本次改造中从 9 个精简为 6 个**:原 health / study / travel 三个分类下没有任何工具,
> 却仍然渲染出空区块与空标题,属既有缺陷。现 `groupedTools()` 会过滤空分组,分类与工具一一对应。
> 第 4 节待办里的「批次 A/B/C」若要推进需先重新加入对应分类定义。
| 分类 | 数量 | 说明 | 工具path |
| --- | --- | --- | --- |
| work 工作效率 | 19 | 开发编程办公文本与文件处理 | image-compress / image-to-ico / json-format / timestamp / base64 / jwt-parse / cron / radix-convert / hash / url-parse / translate / ocr / uuid / regex-test / case-convert / color-convert / yaml-json / word-count / zh-convert |
| dev 开发进阶 | 14 | 格式化对比转换与代码工具 | sql-format / text-diff / json-to-code / regex-visual / markdown-table / api-builder / gitignore-gen / code-to-image / color-namer / indent-convert / code-stats / hello-world / json-diff / env-parse |
| design 创意设计 | 3 | 渐变占位图与字符画 | gradient-generator / placeholder-image / ascii-art |
| life 生活助手 | 13 | 日常计算查询与决策 | image-cropper / qrcode / idcard / address-parse / unit-convert / rmb-upper / date-calc / password-gen / bmi / mortgage / bill-split / random-decision / pomodoro |
| fun 趣味娱乐 | 1 | 摩斯电码等小玩具 | morse-code |
| online 服务端工具 | 8 | 依赖后端接口**全部标记 `needsNetwork`** | api-status / random-string / ip-info / network-test / speed-test / exchange-rate / express-query / phone-locate |
> 说明:
> - `online` 分类 8 个工具中,`ip-info`(客户端 IP、`random-string`(随机字符串)、`api-status`(连通性自检)已真正对接后端。
> - 另有 3 个**不属于 online 分类**的工具也接入了服务端能力,以「本机 / 服务端」双模式呈现:
> `hash`(服务端 MD5 两端口径对比)、`timestamp`(服务端时钟 + 时钟偏移)、`uuid`(服务端唯一 ID
> 它们默认走本机计算,不自动打网络请求。
> - 剩余 5 个后端接口尚未实现,页面用 `BackendPending` 如实标注。
## 3. 架构与关键机制(新增工具前必读)
### 3.1 工具注册
- **工具注册表** `src/router/tools.ts` 是全站唯一数据源分类 `toolCategories` + 工具 `tools` 数组侧边导航/首页/路由/命令面板全部自动生成新增工具 = 建页面 + 加一条配置path/name/desc/icon/category/component 懒加载**禁止手改路由文件**。
- `ToolItem.needsNetwork` 标记需联网工具侧栏圆点 + 首页服务端工具专区)。
- `groupedTools()` / `networkTools()` / `searchTools()` 供首页服务端专区命令面板使用
### 3.2 视觉体系(令牌 → TDesign 桥接 + UI 库主题控制)
- **唯一真相源**`src/assets/styles/tokens.scss` 定义全部 `--tk-*` 令牌颜色/圆角/间距/字号/z-index/动效/字体栈)。
- **桥接层 + UI 库主题控制**`src/assets/styles/tdesign-theme.scss` 除了把 `--tk-*` 映射到 `--td-*`
还接管两件UI 库自身的事
1. **组件尺度**`--td-comp-size-*`控件高度阶梯)、`--td-comp-paddingTB/LR-*`、`--td-font-size-*`、
`--td-line-height-*`。**TDesign 的输入框 / 按钮 / 下拉 / 日期选择器高度全部取自这些变量**
例如 `.t-input.t-size-l { height: var(--td-comp-size-xl) }`所以放大控件只需改这一处
**不要再给单个组件写死高度或字号**
2. **色阶**品牌 / 中性 / 语义的 10 级色板注意深色下的中性色阶是**反向**1 最深 14 最浅
且必须显式覆盖否则组件会退回 TDesign 自带的冷灰
**改主题 = 改 tokens.scss配色/字号/圆角/间距)+ tdesign-theme.scssUI 库尺度与色阶)两处**
60+ 个未改动的工具页自动继承 —— 这是低风险全站改造的关键机制
- **硬规则**自定义样式一律引用 `--tk-*` `--td-*`**禁止硬编码色值/圆角/阴影/字号**否则昼夜切换会花掉
- **形状一致性**全站只用 tokens 里那一套圆角xs5/sm7/md10/lg12/xl16/2xl22/pill999)。
- **单一强调色**宝石蓝 `#2563eb`。**全站已无任何渐变**品牌图标为实色圆角方块)。
强调色只出现在需要指向的地方hover 的条目活动导航项服务端专区底纹正文链接
- **设计方向2026-09-14 第二次改版清晰蓝 · 卡片工作台**。四条硬规则
1. **字号整体放大一档**正文 16px 说明文字不低于 13px上一版 12/13/14 的密度在 1080p 屏上偏小
2. **控件大于内容**输入框 / 按钮 / 下拉默认 40px 16px 文字可点区域永远比正文更」;
3. **容器有边界**卡片用白底 + 细描边`--tk-border`)」与页面底`--tk-bg`拉开层次不再追求无框纸面
4. **主色单一**全站只有一个强调色
- **发丝线 `--tk-hairline`**只用于**列表条目之间的分隔线**历史列表首页索引行
内容容器边界与功能控件输入框/按钮/下拉一律用 `--tk-border`
- **留白节奏**分区之间用 `--tk-space-9`68px分隔**不画横线** —— 留白本身就是分隔符
窄屏按断点阶梯式收回`≤1279px` `≤1023px` `≤767px`不要一档切到底
- **排版令牌必须成对使用**大字号配负字距 + 紧行高`--tk-track-display/-title` +
`--tk-leading-display/-body`小字号配正字距 + 松行高混用大字号配松行高会让层级立刻垮掉
- **首页是目录不是卡片墙**58 个工具用索引行呈现发丝线分隔不做 58 个描边盒子
图标常态中性灰主色只在 hover 时出现58 个图标全染主色会把主色的含义稀释掉
服务端工具专区用整块底纹 + 卡片与其它分区区分
- **动效档位**克制上浮淡入 + 颜色过渡`prefers-reduced-motion` 下全部降为 0ms
- `v-reveal` 指令`src/directives/reveal.ts`做滚动进入传数字错峰
### 3.3 国际化
- 基础设施 `src/i18n/index.ts``SUPPORTED_LOCALES` / `normalizeLocale()` / `resolveInitialLocale()` /
`applyLocaleToDocument()` / `setAppLocale()``src/i18n/helpers.ts` 提供**带中文兜底**的取词助手
`toolName/toolDesc/categoryLabel/tOr`缺词时回落中文而不是显示 key
- 语言包 `src/i18n/locales/{zh-CN,en-US,ja-JP,ko-KR}.ts`zh-CN 为基线命名空间
`app / nav / palette / theme / locale / home / category / tool / page / pending / common`
- **新增页面必须补齐四语言的 `page.<path>.*`**只补中文会导致切到其他语言时显示中文
- 组件内取词统一用 `const { t } = useI18n()`非组件上下文用 helpers
- **防闪烁**`index.html` 内联同步脚本、`stores/theme.ts`、`src/i18n/index.ts` **三处逻辑必须同步修改**
### 3.4 主题
- `stores/theme.ts`**preference用户偏好 light/dark/auto mode实际生效 light/dark分离**。
三态切换localStorage 持久化`tool-theme`)、监听 `prefers-color-scheme` 变化
- `html[theme-mode='light'|'dark']` 驱动整套 CSS 变量
### 3.5 后端请求
- 统一走 `src/api/client.ts``api.post/get`响应契约 `{ code, message, data }`
`BASE_URL` 回落到 `https://service.xpcool.com`**不建 `.env` 也能用**默认超时 10sAbortController)。
- 已实现的 5 个接口封装在 `src/api/openTools.ts`元数据 `OPEN_TOOL_ENDPOINTS` 同时供接口状态页探测
### 3.6 其他约定
- **历史记录**`useHistory(key)`key 约定等于路由 pathlocalStorage 持久化`tool-history:<key>`),上限 10 条。
- **公共组件**`CopyButton` / `DownloadButton` / `ErrorAlert` / `HistoryPanel` / `UploadDrop` / `AppImageViewer` / `BackendPending`,新页面必须复用。
- **页面样式**`.page-wrap / .page-title / .page-desc / .tool-section / .form-label / .form-actions / .mono-num / .hint-text / .panel / .code-block` 全局已定义,优先复用。
- **站点级常量**`src/config.ts`(目前是备案号 `SITE.icp` 与核验地址)。备案号必须与主站 `xpcool.com``src/config.ts` 保持一致。
## 4. 待办(按批推进,见 docs/tool-ideas.md 第三部分)
- **批次 A 健康生活12**:睡眠周期计算 / 喝水提醒 / 体脂率估算 / 卡路里估算 / 预产期计算 / 房贷提前还款 / 生理周期记录 / 运动配速计算 / BMI 对比表 / 热量平衡 / 理想体重 / 步数时长换算
- **批次 B 学习办公10**汉字拼音标注pinyin-pro 已依赖)/ 单词记忆卡 / 随机口算题 / 乘法表练习 / 请假条生成器 / 会议纪要模板 / 邮件模板 / 公文格式助手 / 学习计划表 / 名言摘抄本
- **批次 C 旅行出行6**:行李清单 / 机票折扣速算 / 签证材料清单 / 地图距离估算Haversine/ 时差换算 / 小费计算器
- **批次 D 创意设计补全9**:阴影生成器 / 圆角生成器 / 调色板生成 / 颜色对比度检查 / 像素画编辑器 / 纹理生成器 / 文字效果生成 / Emoji 放大镜 / 图片九宫格切图
- **批次 E 趣味娱乐补全14**:加密暗号机 / Emoji 密文 / 藏头诗生成 / 绕口令生成器 / 塔罗牌占卜 / 星座运势 / 名字评分 / 电子木鱼 / 猜成语小游戏 / 音效合成器 / 节日倒计时 / 情侣默契问答 / 名言警句生成 / 骰子塔
## 5. 后端契约service.xpcool.com
- **契约文档**`docs/api-contract.md`2026-09-14 **已按线上实际部署重写**,旧版 `/api/tools/*` 是待实现清单,与实际不符)。
- **实际前缀**`/api/service/open/tools/*`**一律 POST、URL 不带参数、入参全走 JSON body**(本项目 2026-08-27 起的强制接口规范)。
- **已实现且实测可用5 个)**`ip` / `time` / `uuid` / `md5` / `random`2026-09-14 `curl` 直连全部 HTTP 200
- **未实现5 个)**exchange-rate / express-query / phone-locate / network-test / speed-test。
对应页面用 `BackendPending` 组件如实说明现状,后端实现后改开关即可生效。
- **接入方式**`BASE_URL` 已回落到 `https://service.xpcool.com`**不建 `.env` 也能正常调用**
仅在需要指向本地/测试后端时才覆盖 `VITE_API_BASE`
- **新增接口的完整流程**:① 在 `src/api/openTools.ts``OpenEndpoint` 元数据 + 调用函数
(元数据与路径共用一份定义,「接口状态」页与首页计数会自动同步);② 在工具页接入;
③ 补四语言 `page.*` 文案;④ 本文件与 `api-contract.md` 同步更新。
## 6. 技术约定与坑(跨会话必须记住)
### 6.1 通用
- **TDesign 图标**:引用前先在 `node_modules/tdesign-icons-vue-next/esm/components/` 确认存在(如 `PaletteIcon` 不存在,只有 `Palette1Icon``GlobeIcon` / `BulbIcon` / `FontIcon` 也**不存在**,可用 `TranslateIcon` / `ServerIcon` / `TextboxIcon`)。
- **Vue 模板 attribute**:内嵌字符串不能直接写 `\"`HTML 解析器会把 `"` 当属性结束符导致编译错误),字符串常量移到 `<script>` 定义。
- **`in` 运算符**`k in obj` 中 obj 需先断言为 `Record<string, unknown>`,否则 strict 模式 TS2638/TS18048。
- **构建安全删除保护**`pnpm build` 清理 dist 会触发沙箱批量删除拦截(>50 文件),先 `mv dist dist.bak-<ts>` 再构建。
- **备份目录同样删不掉**`dist.bak-*` 的递归删除也会被 bulk guard 拦(`SAFE_DELETE_BULK_GUARD_ERROR`
因此多次构建会堆积若干 `dist.bak-*`,属正常现象;需要清理时逐个目录删,或交由人手动处理。
- **大整数**:进制转换等工具禁用 `parseInt/Number`,用 BigInt 逐位解析(现有 radix-convert 已实现)。
- **pnpm 调用方式**`corepack` 的 `pnpm` shell wrapper 在 Git Bash 下会把 `/c/...` 误算成 `E:\c\...`
(报 `Cannot find module 'E:\c\...\corepack\dist\pnpm.js'`)。绕过 wrapper显式调用
```bash
"C:/Users/xxl/.workbuddy/binaries/node/versions/22.22.2-3/node.exe" \
"C:/Users/xxl/.workbuddy/binaries/node/versions/22.22.2-3/node_modules/corepack/dist/pnpm.js" build
```
### 6.2 样式与主题
- **禁止硬编码色值**:一律用 `--tk-*`(自定义样式)或 `--td-*`TDesign 组件覆盖)。
- **UnoCSS `panel` 快捷类自带内边距**`p-5 md:p-7`,编辑感改版后放大一档)且描边为发丝线。
页面 scoped 样式(如 `.block[data-v-*]`)权重更高,需要单独覆盖 padding 时照常写即可。
- **卡片内边距的覆盖写法**`.t-card .t-card__body`(两个类)比 TDesign 自身的 `.t-card__body` 高一级,
能稳定覆盖;只写一个类会被 TDesign 的规则压掉。窄屏需在 `@media (max-width: 767px)` 里收回。
- **`--td-radius-*` 刻意不跟随主题**(浅深共用),改圆角请改 `tokens.scss``--tk-radius-*`
- **canvas 绘制**:注意主题切换,尽量用令牌色或中性色,不要写死黑白。
- **头号坑:`theme-mode` 选择器必须写 `:root[theme-mode='dark']`,不能写 `html[theme-mode='dark']`**。
TDesign 自己的浅/深色变量声明用的是 `:root[theme-mode=...]`(权重 0,2,0
`html[theme-mode=...]` 只有 (0,1,1) —— **生产构建里我们的 CSS 虽然排在 vendor CSS 之后,仍会被 UI 库盖掉**
表现:深色下组件用回 TDesign 自带灰(卡片 `#242424`、描边 `#ddd`),只有少量手写规则生效。
新增主题变量时请放进 tokens.scss / tdesign-theme.scss 里那两个 `:root[theme-mode=...]` 块。
- **验证主题是否真的生效**:切完 `theme-mode` 后**不要**只看 `getComputedStyle(document.body).backgroundColor`
它可能命中浏览器的计算值缓存、读出「上一次主题」的颜色。可靠做法:插入探针元素读
`div.style.backgroundColor = 'var(--tk-bg)'` 后读 computed或**刷新页面后再读**。
- **控件尺度统一由 `--td-comp-size-*` 控制**:放大/缩小按钮、输入框、下拉请改 `tdesign-theme.scss` 的尺度段,
不要给单个组件写死 `height`(会与 UI 库其它组件脱节)。
### 6.3 国际化
- **`html` 的 `lang` 属性写的是完整标签**`ja-JP` / `ko-KR`),因此 `tokens.scss` 里的字体栈选择器
必须用前缀匹配 `html[lang^='ja']`**不能用等值匹配**,否则不生效。
- **防闪烁三处同步**`index.html` 内联脚本、`stores/theme.ts`、`src/i18n/index.ts` 三处逻辑必须一起改。
- **取词助手带中文兜底**`src/i18n/helpers.ts` 在缺词时回落中文而不是显示 key因此漏补翻译不会显示成
`page.xxx.yyy`,但会静默显示中文 —— **新增页面仍必须补齐四语言**
## 7. 给下一个 AI 的接手清单
1. 读本文件(状态全貌)→ `.workbuddy/memory/CHANGELOG.md`(最近的变更)→ `docs/api-contract.md`(后端契约)
2. 运行 `pnpm build` 确认基线(含 `vue-tsc --noEmit` 类型检查)
3. 如需继续实现工具:从第 4 节待办批次挑一批,按 `docs/tool-ideas.md` 的工具描述实现;
⚠️ 批次 A/B/C 需先在 `toolCategories` 里重新加回 health / study / travel 分类定义
4. 完成后:更新 `.workbuddy/memory/CHANGELOG.md` + 本文件 + `.workbuddy/memory/YYYY-MM-DD.md`
## 8. 已知未完成项2026-09-14 遗留)
- **存量工具页的页内文案仍是中文硬编码**。本次已完成多语言的页面:全站外壳(导航/首页/分类/工具名与描述/
主题/语言切换/待接入提示)+ 新建与改造的 6 个页面ip-info / uuid / random-string / api-status / hash / timestamp
其余约 50 个存量工具页的**页内标签文字**(如按钮名、字段名)尚未迁移到 i18n
切换语言时会出现「外壳英文、页内中文」的混排。机制已就绪helpers 有中文兜底),补 key 即可,属机械工作。
- 汇率/快递/手机号归属地/网络测试/网络测速 5 个工具等待后端接口实现。
- home.xpcool.com 子站尚未展示备案号tool 站已于本次补齐)。