* 🎨 feat(web/default): add shadcn-style theme presets, radius prefs, and fix selection badges Integrate the qn-platform–style OKLCH color system into the default frontend while keeping the existing blue-tinted dark tokens for the default theme. Add [data-theme-preset] palettes for seven named presets plus the default zinc-like scale, define [data-theme-radius] overrides so user radius beats preset --radius, and align the Tailwind @custom-variant dark helper with .dark usage. Introduce ThemeCustomizationProvider to own preset and radius state, persist choices in cookies (theme-preset, theme-radius), and sync data-theme-preset / data-theme-radius on <html>. Wrap the tree in main.tsx. Extend ConfigDrawer with theme preset swatches (scoped data-theme-preset) and radius previews wired to context; refactor swatch/card markup so selected CircleCheck badges sit outside clipped rows (remove outer overflow-hidden that hid the centered checkmark). Add i18n keys for preset names, radius, and accessibility labels across en, zh, fr, ja, ru, vi. * 🎨 fix(web): align segmented controls with theme radius tokens - Replace hard-coded inner pill radii (rounded-[5px]) on dashboard chart toolbars with radius-md so the active state follows --radius when users change Radius in Theme Settings. - Use nested radii consistent with TabsList/TabsTrigger: outer rounded-lg (var(--radius)) and inner rounded-md (calc(var(--radius) - 2px)) so the track and active thumb stay concentric at small scales (e.g. 0.3rem) instead of a squared “focus” block inside a rounded shell. - Apply the same pattern to pricing SegmentedControl and the segmented groups in consumption-distribution-chart, model-charts, and user-charts. Verified: bun run typecheck (web/default) * ✨ feat(pricing): enrich model details with uptime sparkline and API documentation Add a compact 30-day uptime sparkline (OpenRouter-style bars + aggregate %) with per-day tooltips, surface it in a status row under quick stats and in the per-group performance table, and extend mock data so uptime series are stable and optionally scoped by group. Introduce an API tab with Shiki-highlighted code samples (cURL, Python, TypeScript, JavaScript), endpoint-type switching, authentication guidance, a supported-parameters table, and mock per-group RPM/TPM/RPD limits. Infer vendor, tokenizer, license, and data-retention hints for a provider & data privacy card on the Overview tab (capabilities/modalities stay with model identity; rate limits stay with the API tab). Update i18n for all new user-facing strings across en, zh, fr, ja, ru, and vi. * 🏆 feat(rankings): add comprehensive rankings dashboard Add a mock-data powered rankings experience with period tabs, model, app, and vendor leaderboards, market share and history charts, movers, new releases, and per-category sections while backend analytics are pending. Link ranked models to pricing details and ranked vendors to filtered pricing results, and include localized copy for all supported frontend locales. * fix(theme): correct theme preset selection state - update Base UI Radio selectors to use data-checked/data-unchecked states. - fix unchecked theme options still showing selected indicators. - isolate the default theme preview tokens to prevent preset changes from leaking into it. * fix(setup): correct usage mode radio state - use Base UI data-checked/data-unchecked states for RadioGroup styling. - hide radio indicators when options are unchecked to avoid setup page display issues. - drive usage mode card and icon selection styles from Base UI state. * fix(auth): submit sign-in and sign-up forms * 🎨 refactor: Align default theme with shadcn Base Nova and prune legacy customization Migrate shadcn UI to Base UI primitives via CLI (`base-nova` / `components.json`) and reinstall full component registry with `--overwrite`, including Hugeicons-backed widgets and newly added registry components. - Remove custom multi-preset/theme-radius system (`ThemeCustomizationProvider`, cookies, preset UI from config drawer); rely on official semantic CSS tokens + light/dark only. - Replace `theme.css` with shadcn’s documented neutral `:root`/`.dark` palette and `@theme inline` mappings (plus skeleton token vars for existing shimmer usage). - Update global styles for Base UI: collapsible animation uses `--collapsible-panel-height`; clarify scroll-lock override comment. Application compatibility: - Keep minimal shims where app code diverged from official APIs (popover collision props, combobox legacy `options` callers, Spinner prop typing). - Switch interactive styling from Radix-era `data-state` / `--radix-*` selectors to Base UI semantics (`data-open`, `data-popup-open`, `data-panel-open`, `--anchor-width`, etc.) Tooling / docs / build: - Rename Rsbuild vendor chunk grouping to `@base-ui` + transitive `@radix-ui`. - Refresh AGENTS.md / CLAUDE.md / classic→default sync skill for Base UI stack. - Bump `package.json` / lockfile for shadcn-postinstall deps (Hugeicons, chart stack, themes, etc.) Verified: `bun run typecheck` passes. Note: `bun run lint` still reports pre-existing hooks rule violations elsewhere; not addressed in this change. * 🎨 chore(web/default): unify table toolbar, relocate usage stats, refine filters - Refactor DataTableToolbar to a single wrapping flex row with a right-aligned action cluster (Reset / Search / View / Expand) for a cleaner Ant Design Pro–style filter bar; remove the dedicated stats row and the toolbar `stats` prop. - Move Common Logs summary badges (Usage / RPM / TPM) and the sensitive- data visibility toggle into the page header via CommonLogsHeaderActions and SectionPageLayout.Actions so the toolbar stays focused on filters. - Slim CommonLogsFilterBar props (no stats / preActions eye control). - Improve CompactDateTimeRangePicker: show minute-precision labels on the trigger (seconds omitted; aligns with datetime-local inputs); widen the trigger on sm+ breakpoints so the full range is visible without truncation; apply the same width in task logs filters. - Simplify DataTableViewOptions: text-only “View” trigger, no sliders icon. - Earlier layout tweak: extra top padding on SectionPageLayout scroll content so control focus rings are not clipped by overflow. * feat(web/default): Base UI migration and component foundation Migrate from Radix UI to Base UI, rewrite core UI primitives, update dependencies (recharts, date-fns, next-themes), add shadcn agent skill documentation, and refresh AI element components. This is the foundational work from the v2/localmain lineage that was not covered by the individual feature commits above. --------- Co-authored-by: t0ng7u <dev@aiass.cc> Co-authored-by: QuentinHsu <xuquentinyang@gmail.com>
176 lines
11 KiB
Markdown
Vendored
176 lines
11 KiB
Markdown
Vendored
# 前端开发规范
|
||
|
||
本文档定义前端项目的开发规范与最佳实践,供开发与 AI 助手共同遵循。具体依赖与脚本以 `package.json` 为准。
|
||
|
||
---
|
||
|
||
## 一、项目概览
|
||
|
||
### 技术栈
|
||
|
||
| 类别 | 技术 |
|
||
|----------|------|
|
||
| 包管理 | Bun |
|
||
| 框架 | React 19、TypeScript |
|
||
| 数据与请求 | @tanstack/react-query、axios、Zustand |
|
||
| 路由 | @tanstack/react-router |
|
||
| 表格与列表 | @tanstack/react-table、@tanstack/react-virtual |
|
||
| 国际化 | i18next、react-i18next、i18next-browser-languagedetector |
|
||
| 日期 | Day.js |
|
||
| UI 与样式 | Base UI、Hugeicons、Tailwind CSS、clsx / class-variance-authority |
|
||
| 表单 | React Hook Form、Zod |
|
||
| 图表 | @visactor/vchart、@visactor/react-vchart |
|
||
| 工具 | qrcode.react、prettier、eslint、vitest(可选)|
|
||
|
||
优先选用成熟、维护良好的开源库;仅在现有库无法满足或需特殊适配时自行实现,并评估可维护性与通用性。
|
||
|
||
---
|
||
|
||
## 二、目录
|
||
|
||
- [一、项目概览](#一项目概览)
|
||
- [二、目录](#二目录)
|
||
- [三、开发规范](#三开发规范)
|
||
- [3.1 国际化](#31-国际化)
|
||
- [3.2 代码风格与类型](#32-代码风格与类型)
|
||
- [3.3 组件](#33-组件)
|
||
- [3.4 性能](#34-性能)
|
||
- [3.5 状态管理](#35-状态管理)
|
||
- [3.6 API 请求](#36-api-请求)
|
||
- [3.7 表单](#37-表单)
|
||
- [3.8 路由](#38-路由)
|
||
- [3.9 错误处理](#39-错误处理)
|
||
- [3.10 样式](#310-样式)
|
||
- [3.11 文件组织](#311-文件组织)
|
||
- [3.12 可访问性](#312-可访问性)
|
||
- [3.13 安全](#313-安全)
|
||
- [3.14 测试](#314-测试)
|
||
- [3.15 依赖管理](#315-依赖管理)
|
||
- [3.16 构建与部署](#316-构建与部署)
|
||
- [四、协作与提交](#四协作与提交)
|
||
- [更新日志](#更新日志)
|
||
|
||
---
|
||
|
||
## 三、开发规范
|
||
|
||
### 3.1 国际化
|
||
|
||
- **页面文本**:所有面向用户的文案均需支持 i18n,使用 `useTranslation()` 的 `t()` 进行翻译。
|
||
- **使用场景**
|
||
- **React 组件**:必须使用 `const { t } = useTranslation()`,以保证语言切换时组件会重新渲染。
|
||
- **非 React 环境**(工具函数、常量、类方法):可使用 `import { t } from 'i18next'`;此类用法不会随语言切换自动更新,仅在不依赖响应式更新的场景使用。
|
||
- 即使父组件已使用 `useTranslation()`,子组件仍应自行使用,以保证独立性。
|
||
- **专有名词**:品牌、产品、技术术语等可保留英文(如 API、React、TypeScript);若有约定俗成的译法则使用翻译。
|
||
- **翻译键**:使用有层级、语义清晰的键名,如 `dashboard.overview.title`,并保持命名一致。
|
||
|
||
- **枚举与文案(常量中的 i18n)**
|
||
各 feature 的 `constants.ts` 中常出现「枚举/状态 + 展示文案」或「成功/错误消息」,须统一约定以免遗漏 i18n、用法混乱:
|
||
- **成功/错误/提示类消息**(如 `SUCCESS_MESSAGES`、`ERROR_MESSAGES`):常量值仅表示 **i18n 键**(与英文 fallback 同字面量)。展示时**必须**通过 `t()` 使用,例如 `toast.success(t(SUCCESS_MESSAGES.API_KEY_CREATED))`、`toast.error(t(ERROR_MESSAGES.UNEXPECTED))`,**禁止**直接 `toast.success(SUCCESS_MESSAGES.xxx)` 当作最终文案。
|
||
- **状态/选项的 label**:在常量中统一用 **labelKey**(字符串,即 i18n 键),组件中通过 `t(config.labelKey)` 渲染;或约定用 `label` 存与 en 一致的 key 字符串,组件用 `t(config.label)`。同一 feature 内只采用一种方式,避免混用。
|
||
- **新增此类常量时**:同步在 `src/i18n/static-keys.ts` 中登记对应 key(若项目用其做提取),或确保文案以 `t('...')` 字面量形式出现以便扫描,避免遗漏翻译。
|
||
|
||
### 3.2 代码风格与类型
|
||
|
||
- **表达式**:禁止 2 层及以上嵌套三元表达式;改用 `if-else`、提前返回或抽取函数。单层三元可保留,但需简洁。
|
||
- **可读性**:控制函数圈复杂度,复杂逻辑拆成小函数;变量与函数命名需有意义,遵循驼峰等常规约定。
|
||
- **TypeScript**:避免 `any`,优先具体类型或 `unknown`;为参数与返回值显式标注类型;仅类型用途的导入使用 `import type { X } from '...'`。
|
||
- **类型检查**:每次改动 TypeScript 或 TSX 代码后都要执行类型检查(如 `bun run typecheck`);若出现类型错误,须修复至无错误为止,不得遗留。
|
||
- **解构**:对象非必要不要进行解构,特别是组件的 props;直接使用 `props.xxx` 更清晰,避免不必要的解构增加代码复杂度。
|
||
|
||
### 3.3 组件
|
||
|
||
- 使用函数式组件与 Hooks,单一职责;组件 props 须有明确类型(接口或类型别名)。
|
||
- **Props 使用**:组件 props 非必要不要解构,直接使用 `props.xxx` 访问属性,保持代码清晰(详见 [3.2 代码风格与类型](#32-代码风格与类型))。
|
||
- 单文件超过约 200 行时考虑拆分子组件或将逻辑抽到自定义 Hooks;类型定义可与组件同文件或放在同模块的 `types` 中。
|
||
|
||
### 3.4 性能
|
||
|
||
- **React**:合理使用 `useMemo`、`useCallback` 减少无效重渲染;避免在渲染路径中创建新对象/数组;必要时使用 `React.memo`。
|
||
- **代码分割**:使用 `React.lazy` 与动态 `import` 做按需加载,控制首屏与路由体积。
|
||
- **资源**:图片选用合适格式与尺寸,大列表考虑虚拟滚动(如 @tanstack/react-virtual),大量图片考虑懒加载。
|
||
|
||
### 3.5 状态管理
|
||
|
||
- 使用 Zustand 的 `create` 定义 store,并为 state 与 actions 定义清晰类型。
|
||
- 组件内优先用选择器订阅,避免整 store 订阅导致多余渲染,例如:`const user = useAuthStore((s) => s.auth.user)`。
|
||
- 需持久化的状态在 store 内读写 localStorage,并在初始化时恢复。
|
||
- Store 按功能放在 `src/stores/`,单文件职责清晰,命名表意明确。
|
||
|
||
### 3.6 API 请求
|
||
|
||
- **React Query**:数据获取用 `useQuery`,变更用 `useMutation`;为每个查询配置唯一 `queryKey`(建议数组形式、层级一致);在 `onSuccess` 中对相关 query 做 `invalidateQueries`,可配合乐观更新。服务端错误统一通过 `handleServerError` 处理(详见 [3.9 错误处理](#39-错误处理))。
|
||
- **Axios**:使用项目统一的 `api` 实例(含 `baseURL`、`headers`、`withCredentials: true`);GET 默认请求去重,特殊请求可通过配置关闭;认证与通用错误在拦截器中处理。
|
||
|
||
### 3.7 表单
|
||
|
||
- 使用 React Hook Form + Zod:在功能模块的 `lib/` 下定义 schema,并用 `z.infer` 导出表单类型;`useForm` 配合 `@hookform/resolvers/zod` 做校验。
|
||
- 提交逻辑放在 `onSubmit`,展示加载与错误状态;成功后视场景重置表单或关闭弹窗。服务端校验错误映射到对应字段并展示(字段级错误展示方式见 [3.9 错误处理](#39-错误处理))。
|
||
|
||
### 3.8 路由
|
||
|
||
- 使用 TanStack Router,路由文件位于 `src/routes/`,通过 `createFileRoute` 定义;搜索参数用 Zod schema + `validateSearch` 校验。
|
||
- 在 `beforeLoad` 中做认证与重定向,避免不必要的请求;嵌套结构用布局路由与 `_authenticated` 等前缀,子路由通过 `<Outlet />` 渲染。
|
||
- 导航使用 `useNavigate` 或 `Link`,保持类型安全,避免直接操作 `window.location`。
|
||
|
||
### 3.9 错误处理
|
||
|
||
- **服务端错误**:统一使用 `handleServerError`,在 React Query 全局配置与拦截器中接入;按 HTTP 状态码给出合适提示,文案使用 i18n。
|
||
- **展示**:使用 `toast.error` 等统一方式;路由级错误由 `errorComponent` 承接,提供友好错误页并记录便于排查的信息。
|
||
- **表单**:校验与服务端错误映射到字段后,在字段下方展示;使用 `form.setError` 等与表单库一致的方式。
|
||
|
||
### 3.10 样式
|
||
|
||
- 以 Tailwind 工具类为主,动态类名用 `cn()` 合并;非动态场景避免内联样式。
|
||
- 响应式采用移动优先与 Tailwind 断点(`sm:`、`md:`、`lg:` 等);主题与暗色用 CSS 变量与 `dark:`,自定义样式集中在 `src/styles/`,组件内尽量少写自定义 CSS。
|
||
|
||
### 3.11 文件组织
|
||
|
||
- **功能模块**:置于 `src/features/<feature>/`,内含 `components/`、`lib/`、`hooks/`,以及按需的 `api.ts`、`types.ts`、`constants.ts`、入口组件等。
|
||
- **通用**:通用组件放 `src/components/`,通用工具与类型放 `src/lib/`;组件文件 PascalCase,工具/类型文件 kebab-case 或 `types.ts`,类型使用 PascalCase 命名并 `export type`。
|
||
|
||
### 3.12 可访问性
|
||
|
||
- 使用语义化 HTML(如 `header`、`nav`、`main`、`footer`),表单用 `label` 关联输入。
|
||
- 保证键盘可操作与焦点顺序合理;必要时使用 ARIA(如 `aria-label`、`aria-expanded`、`aria-hidden`);装饰性图标加 `aria-hidden="true"`,重要信息提供文本等价。
|
||
- 对比度满足 WCAG 2.1 AA(正文至少 4.5:1)。
|
||
|
||
### 3.13 安全
|
||
|
||
- 认证与权限在路由与接口层校验;敏感操作增加二次确认等。
|
||
- 前后端均做数据校验(如 Zod),不信任仅前端校验;敏感信息不落前端存储,配置用环境变量,禁止硬编码密钥。
|
||
- 依赖 React 默认转义,慎用 `dangerouslySetInnerHTML`;跨域与 Cookie 使用 `withCredentials` 并按后端要求处理 CSRF。
|
||
|
||
### 3.14 测试
|
||
|
||
- 工具函数与纯逻辑优先单元测试(Vitest),测试文件 `*.test.ts`;组件用 React Testing Library 测交互与行为,避免测实现细节。
|
||
- 关键流程补充集成与 E2E(如 MSW 模拟 API、Playwright/Cypress);核心功能目标覆盖率 80% 以上,关注业务路径与关键分支。
|
||
|
||
### 3.15 依赖管理
|
||
|
||
- 使用 **Bun**:`bun install`、`bun add <pkg>`、`bun add -d <pkg>`、`bun remove <pkg>`、`bun pm ls`、`bun update` 等。
|
||
- 新增依赖前评估维护情况、体积与许可;生产与开发依赖区分清楚,版本用 `^`/`~` 控制,定期更新以获取安全修复。
|
||
|
||
### 3.16 构建与部署
|
||
|
||
- 使用 Rsbuild,配置见 `rsbuild.config.ts`;脚本以 `package.json` 为准(如 `bun run dev`、`bun run build`、`bun run typecheck`、`bun run lint`、`bun run format`),包管理见 [3.15 依赖管理](#315-依赖管理)。
|
||
- 代码分割与懒加载策略见 [3.4 性能](#34-性能);资源使用合适格式与压缩,环境变量用 `.env` 且以 `VITE_` 前缀,不在代码中硬编码。
|
||
- **发布前**:执行 typecheck、lint、format 检查,完成生产构建并检查产物体积与环境变量配置。
|
||
|
||
---
|
||
|
||
## 四、协作与提交
|
||
|
||
- 提交信息清晰、符合项目约定,描述变更内容与原因,中英文统一即可。
|
||
- 变更需经过代码审查,符合本文档规范,并关注质量、性能与安全。
|
||
- 重大功能或规范变更时更新相关文档与 `AGENTS.md`。
|
||
|
||
---
|
||
|
||
## 更新日志
|
||
|
||
- **2026-01-28**:初始版本(国际化、代码、组件、类型等基础规范)。
|
||
- **2026-01-28**:补充状态管理、API、表单、路由、错误处理、样式、文件组织、可访问性、安全、测试、依赖与构建部署规范。
|
||
- **2026-01-29**:重组文档结构,合并重复内容,明确主次与交叉引用。
|
||
- **2026-01-31**:在 3.2 中补充「类型检查」要求:改动 TS/TSX 后须执行 typecheck 并修复至无错。
|