1
0

chore: 合并 dev-code-format-frontend 到 master

This commit is contained in:
2026-04-24 18:21:27 +08:00
64 changed files with 2456 additions and 1707 deletions

View File

@@ -0,0 +1,140 @@
# 前端 Lint 规则
## Purpose
TBD - 定义前端 ESLint 规则配置、构建集成 lint 检查、以及自定义规则
## Requirements
### Requirement: ESLint 规则配置
前端 SHALL 在 `eslint.config.js` 中配置以下规则:
- `@tanstack/query/exhaustive-deps`: `error` — queryFn 中使用的变量 SHALL 出现在 queryKey 中
- `@tanstack/query/no-void-query-fn`: `error` — queryFn SHALL 有返回值
- `@tanstack/query/stable-query-client`: `error` — QueryClient SHALL NOT 在组件渲染中创建
- `@tanstack/query/no-unstable-deps`: `error` — query 选项中 SHALL NOT 有不稳定引用
- `@tanstack/query/infinite-query-property-order`: `error` — infinite query 属性顺序 SHALL 规范
- `@tanstack/query/mutation-property-order`: `error` — mutation 回调顺序 SHALL 规范
- `@tanstack/query/no-rest-destructuring`: `warn` — query 结果 SHALL NOT 使用 rest 解构
- `no-console`: `['error', { allow: ['warn', 'error'] }]` — 代码中 SHALL NOT 使用 `console.log``console.info``console.debug` 等,仅允许 `console.warn``console.error`
- `@typescript-eslint/consistent-type-imports`: `['error', { prefer: 'type-imports', fixStyle: 'inline-type-imports' }]` — type import SHALL 使用内联风格 `import { type Foo }`
- `@typescript-eslint/no-non-null-assertion`: `error` — 代码中 SHALL NOT 使用 `foo!` 非空断言
#### Scenario: TanStack Query 规则未启用时构建失败
- **WHEN** `eslint.config.js` 中未配置 TanStack Query 的 `flat/recommended` 规则
- **THEN** 前端构建 SHALL 失败
#### Scenario: 使用 console.log 时构建失败
- **WHEN** 源代码中出现 `console.log(...)` 调用
- **THEN** ESLint SHALL 报告错误
- **THEN** 前端构建 SHALL 失败
#### Scenario: 使用 console.warn 时不报错
- **WHEN** 源代码中出现 `console.warn(...)` 调用
- **THEN** ESLint SHALL NOT 报告错误
#### Scenario: 使用独立 type import 时自动修复
- **WHEN** 源代码中出现 `import type { Foo } from 'module'`
- **THEN** `eslint --fix` SHALL 自动修复为 `import { type Foo } from 'module'`
#### Scenario: 使用非空断言时构建失败
- **WHEN** 源代码中出现 `foo!.bar` 非空断言
- **THEN** ESLint SHALL 报告错误
### Requirement: 构建集成 lint 检查
前端 SHALL 在 `build` 命令中集成 ESLint 检查和 Prettier 格式检查。
#### Scenario: 构建时执行 lint 和格式检查
- **WHEN** 执行 `bun run build`
- **THEN** 构建 SHALL 依次执行 `tsc -b``bun run check``vite build`
- **THEN** `bun run check` SHALL 执行 `bun run lint && bun run format:check`
- **THEN** 若 `eslint .` 报告任何错误,构建 SHALL 中断
- **THEN** 若 `prettier --check .` 报告任何格式问题,构建 SHALL 中断
#### Scenario: lint 警告不中断构建
- **WHEN** `eslint .` 仅报告警告(无错误)
- **THEN** 构建 SHALL 继续执行格式检查和 `vite build`
#### Scenario: 单独执行 lint
- **WHEN** 执行 `bun run lint`
- **THEN** SHALL 运行 `eslint .`
#### Scenario: 自动修复 lint 问题
- **WHEN** 执行 `bun run lint:fix`
- **THEN** SHALL 运行 `eslint . --fix`
#### Scenario: 统一检查命令
- **WHEN** 执行 `bun run check`
- **THEN** SHALL 运行 `bun run lint && bun run format:check`
- **THEN** lint 错误和格式问题 SHALL 都被检查
#### Scenario: 统一修复命令
- **WHEN** 执行 `bun run fix`
- **THEN** SHALL 运行 `bun run lint:fix && bun run format`
- **THEN** lint 问题 SHALL 被修复
- **THEN** 文件 SHALL 被格式化
### Requirement: 自定义规则禁止硬编码颜色
前端 SHALL 提供自定义 ESLint 规则 `no-hardcoded-color-in-style`,检测 JSX style 属性中的硬编码颜色值。
#### Scenario: 检测十六进制颜色
- **WHEN** JSX style 属性值匹配 `#xxx``#xxxxxx` 格式
- **THEN** 规则 SHALL 报告警告
- **THEN** 警告消息 SHALL 提示使用 `var(--td-*)` CSS Token
#### Scenario: 检测 rgb/rgba/hsl 颜色函数
- **WHEN** JSX style 属性值匹配 `rgb()``rgba()``hsl()` 格式
- **THEN** 规则 SHALL 报告警告
#### Scenario: 允许 CSS Token 引用
- **WHEN** JSX style 属性值为 `var(--td-*)` 格式
- **THEN** 规则 SHALL NOT 报告
#### Scenario: 允许特殊颜色关键字
- **WHEN** JSX style 属性值为 `inherit``transparent``currentColor``none``unset``initial`
- **THEN** 规则 SHALL NOT 报告
#### Scenario: 允许数字值
- **WHEN** JSX style 属性值为数字(如 `0``16`
- **THEN** 规则 SHALL NOT 报告
### Requirement: 自定义规则存放位置
自定义 ESLint 规则 SHALL 存放在 `frontend/eslint-rules/` 目录中。
#### Scenario: 自定义规则目录结构
- **WHEN** 添加自定义 ESLint 规则
- **THEN** 规则文件 SHALL 放置在 `frontend/eslint-rules/` 目录下
- **THEN** `eslint.config.js` SHALL 通过相对路径引用本地插件
- **THEN** 自定义规则 SHALL NOT 作为 npm 包发布
### Requirement: ESLint 与 Prettier 集成配置
前端 SHALL 在 `eslint.config.js` 中集成 `eslint-config-prettier`,确保 ESLint 和 Prettier 职责分离且不冲突。
#### Scenario: 职责分离
- **WHEN** 检查代码
- **THEN** ESLint SHALL 负责代码质量检查(如未使用变量、语法错误)
- **THEN** Prettier SHALL 负责代码格式化(如缩进、引号、分号)
- **THEN** 两者 SHALL NOT 重复检查同一规则

View File

@@ -482,6 +482,9 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
- **THEN** TypeScript 配置 SHALL 开启 noUncheckedIndexedAccess
- **THEN** 所有代码 SHALL NOT 使用 any 类型
- **THEN** tsconfig SHALL 合并为单文件(不使用 project references
- **THEN** type import SHALL 使用内联风格 `import { type Foo }`
- **THEN** 代码 SHALL NOT 使用非空断言 `foo!`
- **THEN** 代码 SHALL NOT 使用 `console.log``console.info``console.debug`(仅允许 `console.warn``console.error`
#### Scenario: React 函数组件
@@ -505,6 +508,30 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
- **THEN** Vite SHALL 对业务代码执行混淆处理
- **THEN** 混淆 SHALL 仅应用于 src 目录下的业务代码
- **THEN** 混淆 SHALL NOT 应用于 node_modules 中的第三方库
- **THEN** 构建流程 SHALL 在 vite build 之前执行 ESLint 检查和 Prettier 格式检查
- **THEN** ESLint 检查失败 SHALL 中断构建
- **THEN** Prettier 格式检查失败 SHALL 中断构建
### Requirement: 开发环境格式化工具
前端 SHALL 配置开发环境格式化工具,确保开发者保存时自动格式化代码。
#### Scenario: VS Code 保存时自动格式化
- **WHEN** 开发者在 VS Code 中保存文件
- **THEN** 文件 SHALL 自动使用 Prettier 格式化
- **THEN** ESLint 可修复的问题 SHALL 自动修复
#### Scenario: 编辑器统一配置
- **WHEN** 开发者在编辑器中打开项目
- **THEN** 编辑器 SHALL 自动应用 `.editorconfig` 配置
- **THEN** 编辑器 SHALL 使用 2 空格缩进、UTF-8 编码、Unix 换行符
#### Scenario: VS Code 推荐安装扩展
- **WHEN** 开发者使用 VS Code 打开项目
- **THEN** VS Code SHALL 提示安装 Prettier 和 ESLint 扩展
### Requirement: 与后端 API 通信

View File

@@ -0,0 +1,232 @@
# Prettier 代码格式化
## Purpose
定义前端代码格式化规则、工具集成、编辑器配置,确保多人协作时代码风格一致。
## Requirements
### Requirement: Prettier 核心配置
前端 SHALL 在 `.prettierrc` 文件中配置以下格式化规则:
- `semi`: `false` — 语句末尾 SHALL NOT 使用分号
- `singleQuote`: `true` — 字符串 SHALL 使用单引号
- `jsxSingleQuote`: `true` — JSX 属性 SHALL 使用单引号
- `tabWidth`: `2` — 缩进 SHALL 使用 2 个空格
- `useTabs`: `false` — 缩进 SHALL NOT 使用制表符
- `trailingComma`: `"es5"` — 多行结构末尾 SHALL 使用 ES5 兼容的尾随逗号
- `printWidth`: `120` — 每行最大字符数 SHALL 为 120
- `bracketSpacing`: `true` — 对象字面量花括号内 SHALL 有空格
- `arrowParens`: `"always"` — 箭头函数参数 SHALL 始终使用括号
- `endOfLine`: `"lf"` — 换行符 SHALL 使用 Unix 风格 (LF)
- `proseWrap`: `"preserve"` — Markdown 文本换行 SHALL 保持原样
- `htmlWhitespaceSensitivity`: `"css"` — HTML 空白处理 SHALL 根据 CSS display 属性
- `embeddedLanguageFormatting`: `"auto"` — 嵌入语言(如 Markdown 中的代码块SHALL 自动格式化
- `singleAttributePerLine`: `false` — JSX 多属性 SHALL NOT 强制每行一个
#### Scenario: 格式化 JavaScript 代码
- **WHEN** 运行 `prettier --write` 格式化 JavaScript 文件
- **THEN** 代码 SHALL 使用单引号、无分号、2 空格缩进
- **THEN** 行宽超过 120 字符时 SHALL 自动换行
#### Scenario: 格式化 TypeScript 代码
- **WHEN** 运行 `prettier --write` 格式化 TypeScript 文件
- **THEN** 代码 SHALL 使用单引号、无分号、2 空格缩进
- **THEN** type import SHALL 保持内联风格 `import { type Foo }`
#### Scenario: 格式化 JSX 代码
- **WHEN** 运行 `prettier --write` 格式化 JSX 文件
- **THEN** JSX 属性 SHALL 使用单引号
- **THEN** 多属性 SHALL 根据行宽自动换行
#### Scenario: 格式化 SCSS 代码
- **WHEN** 运行 `prettier --write` 格式化 SCSS 文件
- **THEN** 代码 SHALL 使用 2 空格缩进
- **THEN** CSS 规则 SHALL 保持一致的格式
#### Scenario: 格式化 JSON 文件
- **WHEN** 运行 `prettier --write` 格式化 JSON 文件
- **THEN** JSON SHALL 使用 2 空格缩进
- **THEN** JSON SHALL 保持尾随换行
#### Scenario: 格式化 Markdown 文件
- **WHEN** 运行 `prettier --write` 格式化 Markdown 文件
- **THEN** 文本换行 SHALL 保持原样
- **THEN** 代码块 SHALL 自动格式化
### Requirement: Prettier 忽略文件配置
前端 SHALL 在 `.prettierignore` 文件中配置以下忽略规则:
- `node_modules` — 依赖目录 SHALL NOT 格式化
- `dist` — 构建输出 SHALL NOT 格式化
- `dist-ssr` — SSR 构建输出 SHALL NOT 格式化
- `bun.lock` — Bun 锁文件 SHALL NOT 格式化
- `package-lock.json` — npm 锁文件 SHALL NOT 格式化
- `yarn.lock` — Yarn 锁文件 SHALL NOT 格式化
- `pnpm-lock.yaml` — pnpm 锁文件 SHALL NOT 格式化
- `.env.*` — 环境变量文件 SHALL NOT 格式化
- `*.local` — 本地配置文件 SHALL NOT 格式化
- `coverage` — 测试覆盖率报告 SHALL NOT 格式化
- `**/*.snap` — Jest snapshot 文件 SHALL NOT 格式化
- `**/__snapshots__/**` — Jest snapshot 目录 SHALL NOT 格式化
- `*.svg` — SVG 文件 SHALL NOT 格式化
- `*.min.js` — 压缩的 JS 文件 SHALL NOT 格式化
- `*.min.css` — 压缩的 CSS 文件 SHALL NOT 格式化
- `openspec/changes/archive/` — 已归档的变更 SHALL NOT 格式化
#### Scenario: 不格式化依赖目录
- **WHEN** 运行 `prettier --write .`
- **THEN** `node_modules` 目录 SHALL NOT 被格式化
#### Scenario: 不格式化锁文件
- **WHEN** 运行 `prettier --write .`
- **THEN** `bun.lock` 文件 SHALL NOT 被格式化
#### Scenario: 不格式化测试快照
- **WHEN** 运行 `prettier --write .`
- **THEN** `**/*.snap` 文件 SHALL NOT 被格式化
- **THEN** `**/__snapshots__/**` 目录 SHALL NOT 被格式化
#### Scenario: 不格式化 SVG 文件
- **WHEN** 运行 `prettier --write .`
- **THEN** `*.svg` 文件 SHALL NOT 被格式化
### Requirement: EditorConfig 配置
前端 SHALL 在 `.editorconfig` 文件中配置以下编辑器设置:
- `root = true` — 声明为根配置文件
- `[*]` `charset = utf-8` — 所有文件 SHALL 使用 UTF-8 编码
- `[*]` `indent_style = space` — 所有文件 SHALL 使用空格缩进
- `[*]` `indent_size = 2` — 所有文件 SHALL 使用 2 空格缩进
- `[*]` `end_of_line = lf` — 所有文件 SHALL 使用 Unix 换行符
- `[*]` `insert_final_newline = true` — 所有文件 SHALL 在末尾插入空行
- `[*]` `trim_trailing_whitespace = true` — 所有文件 SHALL 删除行尾空白
- `[*.md]` `trim_trailing_whitespace = false` — Markdown 文件 SHALL NOT 删除行尾空白Markdown 语法需要)
#### Scenario: 编辑器使用统一缩进
- **WHEN** 开发者在编辑器中打开项目
- **THEN** 编辑器 SHALL 自动使用 2 空格缩进
- **THEN** 编辑器 SHALL NOT 使用制表符缩进
#### Scenario: 编辑器使用统一换行符
- **WHEN** 开发者在编辑器中创建新文件
- **THEN** 编辑器 SHALL 使用 Unix 换行符 (LF)
- **THEN** 编辑器 SHALL NOT 使用 Windows 换行符 (CRLF)
#### Scenario: 编辑器使用统一编码
- **WHEN** 开发者在编辑器中保存文件
- **THEN** 文件 SHALL 使用 UTF-8 编码保存
### Requirement: VS Code 扩展推荐
前端 SHALL 在 `.vscode/extensions.json` 文件中推荐以下扩展:
- `esbenp.prettier-vscode` — Prettier 格式化扩展
- `dbaeumer.vscode-eslint` — ESLint 检查扩展
#### Scenario: VS Code 提示安装扩展
- **WHEN** 开发者使用 VS Code 打开项目
- **THEN** VS Code SHALL 提示安装推荐的扩展
- **THEN** 推荐列表 SHALL 包含 Prettier 和 ESLint 扩展
### Requirement: VS Code 格式化设置
前端 SHALL 在 `.vscode/settings.json` 文件中配置以下设置:
- `editor.formatOnSave = true` — 保存时 SHALL 自动格式化
- `editor.defaultFormatter = "esbenp.prettier-vscode"` — 默认格式化器 SHALL 为 Prettier
- `editor.codeActionsOnSave.source.fixAll.eslint = "explicit"` — 保存时 SHALL 自动修复 ESLint 问题
#### Scenario: 保存时自动格式化
- **WHEN** 开发者在 VS Code 中保存文件
- **THEN** 文件 SHALL 自动使用 Prettier 格式化
- **THEN** ESLint 可修复的问题 SHALL 自动修复
#### Scenario: 使用 Prettier 作为默认格式化器
- **WHEN** 开发者在 VS Code 中使用格式化命令
- **THEN** SHALL 使用 Prettier 进行格式化
- **THEN** SHALL NOT 使用其他格式化器
### Requirement: Prettier 与 ESLint 集成
前端 SHALL 在 `eslint.config.js` 中导入 `eslint-config-prettier` 配置,关闭与 Prettier 冲突的 ESLint 规则。
#### Scenario: ESLint 配置集成 Prettier
- **WHEN** 配置 `eslint.config.js`
- **THEN** SHALL 导入 `eslint-config-prettier`
- **THEN** `eslint-config-prettier` SHALL 放在配置数组的最后
- **THEN** 与 Prettier 冲突的 ESLint 规则 SHALL 被关闭
#### Scenario: ESLint 与 Prettier 不冲突
- **WHEN** 运行 `eslint .``prettier --check .`
- **THEN** ESLint 检查和 Prettier 格式化 SHALL NOT 产生冲突
- **THEN** 同一文件 SHALL NOT 同时报告 ESLint 错误和 Prettier 格式问题
### Requirement: 格式化脚本配置
前端 SHALL 在 `package.json` 中配置以下脚本:
- `format = "prettier --write ."` — 格式化所有文件
- `format:check = "prettier --check ."` — 检查文件格式
- `check = "bun run lint && bun run format:check"` — 检查 lint 和格式
- `fix = "bun run lint:fix && bun run format"` — 修复 lint 问题并格式化
#### Scenario: 运行格式化命令
- **WHEN** 执行 `bun run format`
- **THEN** SHALL 运行 `prettier --write .`
- **THEN** 所有文件 SHALL 被格式化
#### Scenario: 运行格式检查命令
- **WHEN** 执行 `bun run format:check`
- **THEN** SHALL 运行 `prettier --check .`
- **THEN** 未格式化的文件 SHALL 报告错误
#### Scenario: 运行统一检查命令
- **WHEN** 执行 `bun run check`
- **THEN** SHALL 运行 `bun run lint && bun run format:check`
- **THEN** lint 错误和格式问题 SHALL 都被检查
#### Scenario: 运行统一修复命令
- **WHEN** 执行 `bun run fix`
- **THEN** SHALL 运行 `bun run lint:fix && bun run format`
- **THEN** lint 问题 SHALL 被修复
- **THEN** 文件 SHALL 被格式化
### Requirement: Prettier 依赖安装
前端 SHALL 安装以下依赖:
- `prettier` — Prettier 核心库
- `eslint-config-prettier` — 关闭与 Prettier 冲突的 ESLint 规则
#### Scenario: 安装 Prettier 依赖
- **WHEN** 执行 `bun install`
- **THEN** `prettier` SHALL 被安装
- **THEN** `eslint-config-prettier` SHALL 被安装
- **THEN** 依赖版本 SHALL 在 `package.json` 中声明