188 lines
8.2 KiB
Markdown
188 lines
8.2 KiB
Markdown
# 前端开发规范
|
||
|
||
## 技术栈
|
||
|
||
Next.js + TypeScript + React + Tailwind CSS + Zustand/Jotai + pnpm
|
||
|
||
### 核心依赖
|
||
|
||
- **实时通信**: SSE / WebSocket
|
||
- **可视化**: Mermaid + 图谱可视化库
|
||
- **测试**: Vitest + Testing Library
|
||
- **代码质量**: ESLint (flat config) + Prettier + Husky + lint-staged
|
||
|
||
## 开发命令
|
||
|
||
```bash
|
||
pnpm install # 安装依赖
|
||
pnpm add <pkg> # 添加依赖
|
||
pnpm remove <pkg> # 移除依赖
|
||
|
||
pnpm dev # 启动开发服务器 (默认端口 3000)
|
||
pnpm build # 构建生产版本
|
||
pnpm start # 启动生产服务器
|
||
|
||
pnpm lint # 运行 ESLint 检查
|
||
pnpm type-check # TypeScript 类型检查
|
||
|
||
# 代码格式化(Prettier)
|
||
pnpm format # 格式化全部文件
|
||
pnpm format:check # 检查格式是否合规(CI / 提交钩子使用)
|
||
|
||
# 测试(Vitest)
|
||
pnpm test # 运行全部测试(单次)
|
||
pnpm test:watch # 监听模式
|
||
pnpm test:coverage # 运行测试并生成覆盖率报告
|
||
```
|
||
|
||
## 代码规范
|
||
|
||
### 页面设计
|
||
|
||
图标:统一使用 Lucide 图标,界面全程禁止使用表情符号。
|
||
设计标准:对标 Awwwards 顶级网站水准,达到 Awwwards、FWA、CSS Design Awards 每日最佳网站同等设计品质。
|
||
创意自由度:将浏览器视作交互式艺术画布,跳出传统布局框架,追求先锋视觉风格、实验性排版、流畅物理动效、极具冲击力的文字版式。
|
||
沉浸式体验:融合代码、高级渲染逻辑、图片素材,打造统一完整的精品页面,做出突破常规 UI 认知、令人惊艳的数字交互体验。
|
||
|
||
### 通用规范
|
||
|
||
- 遵循 ESLint + Prettier 配置,提交前必须通过 lint 与格式检查
|
||
- 使用 TypeScript 严格模式 (`strict: true`),禁止使用 `any` 类型
|
||
- 组件使用函数式组件 + Hooks,优先使用 Server Components,必要时使用 `'use client'`
|
||
- 文件命名: 组件使用 PascalCase (`UserProfile.tsx`),工具函数使用 camelCase (`formatDate.ts`)
|
||
- 使用 `path` 别名 (`@/*`) 导入模块,避免相对路径层级过深
|
||
- 状态管理: 全局状态使用 Zustand/Jotai,局部状态使用 React useState/useReducer
|
||
|
||
### CSS 变量引用
|
||
|
||
CSS 变量引用遵循 **三层递进规则**,优先级由上至下。
|
||
|
||
#### 规则
|
||
|
||
```text
|
||
Tailwind 映射类 → 优先使用
|
||
Tailwind 任意值 [var(--)] → 仅当变量不在 @theme 映射表中时使用
|
||
内联 style → 仅限复合值 / 动态运行时值
|
||
```
|
||
|
||
#### 具体对照
|
||
|
||
`globals.css` 的 `@theme inline {}` 块已映射的部分,直接用 Tailwind 类:
|
||
|
||
```tsx
|
||
// ✅ 正确:变量在 @theme inline {} 中有 --color-X 映射 → 用 Tailwind 类
|
||
<div className="bg-patina text-fg-dim border-rule" />
|
||
<span className="text-cinnabar" />
|
||
<div className="bg-night-bronze text-fg" />
|
||
<div className="bg-surface" />
|
||
<button className="border-gilt text-gilt" />
|
||
<div className="bg-btn-primary-bg" /> {/* Layer 2 组件 token 同理 */}
|
||
|
||
// ✅ 正确:变量未映射到 @theme inline {} → 用 Tailwind 任意值
|
||
<div className="bg-[var(--patina-wash)]" />
|
||
<span className="text-[var(--fg-faint)]" />
|
||
<div className="border-[var(--gilt-dim)]" />
|
||
<div className="bg-[var(--cinnabar-wash)]" />
|
||
```
|
||
|
||
> `bg-[var(--x)]` 是 Tailwind v4 的合法任意值语法(非 hack),属于 Tailwind 体系内,**不是** style 违规。`--patina-wash`、`--patina-dim`、`--gilt-faint`、`--gilt-dim`、`--cinnabar-wash`、`--cinnabar-dim` 当前均未直接映射,使用任意值是正确做法。
|
||
|
||
```tsx
|
||
// ❌ 禁止:变量已在 @theme inline {} 中有映射,却用任意值
|
||
// 不要用 bg-[var(--patina)] —— 应写 bg-patina(已映射)
|
||
// 不要用 text-[var(--cinnabar)] —— 应写 text-cinnabar(已映射)
|
||
// 不要用 border-[var(--rule)] —— 应写 border-rule(已映射)
|
||
// 不要用 text-[var(--fg-dim)] —— 应写 text-fg-dim(已映射)
|
||
|
||
// ❌ 禁止:用内联 style 表达单值 CSS 变量
|
||
// 不要写 style={{ color: "var(--patina)" }}
|
||
// 不要写 style={{ background: "var(--surface)" }}
|
||
|
||
// ✅ 正确:渐变色/复合 CSS 用内联 style(Tailwind 无法表达)
|
||
<div style={{
|
||
background: "linear-gradient(180deg, var(--patina-wash), var(--surface))",
|
||
boxShadow: "inset 0 1px 0 var(--face-in-top), var(--shadow)",
|
||
}} />
|
||
|
||
// ✅ 正确:动态运行时值用内联 style
|
||
<div style={{ color: health === "ok" ? "var(--patina)" : "var(--cinnabar)" }} />
|
||
|
||
// ✅ 正确:SVG 属性用内联 style 或 className
|
||
<circle style={{ fill: "var(--patina)", stroke: "var(--gilt)" }} />
|
||
```
|
||
|
||
#### 映射速查
|
||
|
||
当前 `@theme inline {}` 中已映射的 铜镜鉴心 变量(查阅 `globals.css` 确认完整列表):
|
||
|
||
| CSS 变量 | Tailwind 类前缀 | 示例 |
|
||
| ---------- | ---------------- | ------ |
|
||
| `--patina` | `patina` | `bg-patina` `text-patina` `border-patina` |
|
||
| `--patina-bright` | `patina-bright` | `bg-patina-bright` |
|
||
| `--gilt` | `gilt` | `bg-gilt` `text-gilt` |
|
||
| `--cinnabar` | `cinnabar` | `bg-cinnabar` `text-cinnabar` |
|
||
| `--ink` | `ink` | `bg-ink` |
|
||
| `--night-bronze` | `night-bronze` | `bg-night-bronze` |
|
||
| `--fg` | `fg` | `text-fg` |
|
||
| `--fg-dim` | `fg-dim` | `text-fg-dim` |
|
||
| `--fg-faint` | `fg-faint` | `text-fg-faint` |
|
||
| `--rule` | `rule` | `border-rule` `bg-rule` |
|
||
| `--surface` | `surface` | `bg-surface` |
|
||
| `--surface-hi` | `surface-hi` | `bg-surface-hi` |
|
||
| `--patina-wash` | `patina-wash` | `bg-patina-wash` |
|
||
| `--patina-dim` | `patina-dim` | `border-patina-dim` `bg-patina-dim` |
|
||
| `--gilt-dim` | `gilt-dim` | `border-gilt-dim` `text-gilt-dim` `bg-gilt-dim` |
|
||
| `--gilt-faint` | `gilt-faint` | `bg-gilt-faint` |
|
||
| `--cinnabar-wash` | `cinnabar-wash` | `bg-cinnabar-wash` |
|
||
| `--cinnabar-dim` | `cinnabar-dim` | `border-cinnabar-dim` |
|
||
| `--glass` | `glass` | `bg-glass` |
|
||
| `--glass-border` | `glass-border` | `border-glass-border` |
|
||
| `--overlay-hover` | `overlay-hover` | `bg-overlay-hover` |
|
||
|
||
**未映射**(用 `bg-[var(--x)]`):`--face-sheen` `--sweep-gradient` `--face-in-top` `--face-in-bot` `--shadow` `--aurora-*` `--code-*` 以及 SVG 特有的 `--raw-*`
|
||
|
||
#### 例外清单
|
||
|
||
以下变量是复合 CSS 值或动画属性,**必须**用内联 style,不能抽象为 Tailwind 类:
|
||
|
||
- 渐变/光照效果:`--face-sheen` `--sweep-gradient` `--face-in-top` `--face-in-bot`
|
||
- 阴影:`--shadow`
|
||
- 背景光晕:`--aurora-*`
|
||
- 动态 `color-mix()` 表达式
|
||
|
||
> 规则生效日:此约定写入后,新代码必须遵守。存量代码暂不回溯,待 P0/P1 功能补齐后再做 codemod 迁移。
|
||
|
||
- 统一通过 `lib/api`(`client.ts` 出口)调用后端,禁止在组件内散落 fetch
|
||
- SSE 连接封装在 `lib/sse-client.ts`,不在组件内直接实例化 EventSource
|
||
- 所有 API 调用必须有 TypeScript 类型定义和错误处理(`ApiError` 统一承载 code/trace_id)
|
||
|
||
## 可视化规范
|
||
|
||
- 图谱可视化使用专用图谱库,Mermaid 用于流程图/时序图等
|
||
- 可视化组件必须支持响应式和主题切换 (暗色/亮色)
|
||
|
||
## 代码审查
|
||
|
||
```bash
|
||
pnpm lint # ESLint 检查
|
||
pnpm type-check # TypeScript 类型检查
|
||
pnpm format:check # Prettier 格式检查
|
||
pnpm test # Vitest 测试
|
||
```
|
||
|
||
- 必须同时通过 lint、type-check 与格式检查才能提交
|
||
- Husky + lint-staged 已配置 `pre-commit` 钩子:对暂存文件自动跑 ESLint --fix + Prettier,再整体 type-check;不通过则阻止提交(临时跳过用 `git commit --no-verify`)
|
||
- 注:本仓库 git 根在父目录(monorepo),`prepare` 脚本以 `cd .. && husky frontend/.husky` 安装钩子,`core.hooksPath` 指向 `frontend/.husky/_`
|
||
|
||
## 绝对禁止事项
|
||
|
||
- 直接修改 `package.json` 或 `pnpm-lock.yaml`(依赖必须用 `pnpm add/remove`;scripts 字段可用 `pnpm pkg set`,注意带冒号的键需用方括号语法 `scripts["name"]`)
|
||
- 在客户端代码中硬编码敏感信息 (密钥、Token等)
|
||
- 使用 `any` 类型 (除非经过团队评审)
|
||
- 忽略 TypeScript 或 ESLint 错误强制提交
|
||
- 在 Server Component 中直接使用 `useState`、`useEffect` 等客户端 Hooks
|
||
- 使用 CSS-in-JS 方案 (统一使用 Tailwind CSS)
|
||
- 在 Client Component 中直接调用数据库
|
||
- 在 useEffect 中做页面初始数据请求
|
||
- 创建 Class 组件
|