All checks were successful
Build and Deploy (tool.xpcool.com) / build-and-deploy (push) Successful in 1m10s
主色青玉改宝石蓝,字号整体放大一档(正文 16px), 通过 --td-comp-* 与 --td-font-* 接管 TDesign 控件高度与文字, 修复 theme-mode 选择器权重不足导致深色变量被 UI 库覆盖的问题。
191 lines
18 KiB
Markdown
191 lines
18 KiB
Markdown
# 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 + TypeScript(strict)+ 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.scss(UI 库尺度与色阶)两处**,
|
||
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` 也能用**;默认超时 10s(AbortController)。
|
||
- 已实现的 5 个接口封装在 `src/api/openTools.ts`,元数据 `OPEN_TOOL_ENDPOINTS` 同时供「接口状态」页探测。
|
||
|
||
### 3.6 其他约定
|
||
- **历史记录**:`useHistory(key)`,key 约定等于路由 path,localStorage 持久化(`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 站已于本次补齐)。
|