new-api/web/default/AGENTS.md
Calcium-Ion 8b2b03d276
feat(web/default): unified UI overhaul — Base UI migration, theme presets, rankings dashboard, and table toolbar refactor (#4633)
* 🎨 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>
2026-05-06 12:39:36 +08:00

11 KiB
Vendored
Raw Blame History

前端开发规范

本文档定义前端项目的开发规范与最佳实践,供开发与 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 国际化

  • 页面文本:所有面向用户的文案均需支持 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_MESSAGESERROR_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 代码风格与类型)。
  • 单文件超过约 200 行时考虑拆分子组件或将逻辑抽到自定义 Hooks类型定义可与组件同文件或放在同模块的 types 中。

3.4 性能

  • React:合理使用 useMemouseCallback 减少无效重渲染;避免在渲染路径中创建新对象/数组;必要时使用 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 错误处理)。
  • Axios:使用项目统一的 api 实例(含 baseURLheaderswithCredentials: trueGET 默认请求去重,特殊请求可通过配置关闭;认证与通用错误在拦截器中处理。

3.7 表单

  • 使用 React Hook Form + Zod在功能模块的 lib/ 下定义 schema并用 z.infer 导出表单类型;useForm 配合 @hookform/resolvers/zod 做校验。
  • 提交逻辑放在 onSubmit,展示加载与错误状态;成功后视场景重置表单或关闭弹窗。服务端校验错误映射到对应字段并展示(字段级错误展示方式见 3.9 错误处理)。

3.8 路由

  • 使用 TanStack Router路由文件位于 src/routes/,通过 createFileRoute 定义;搜索参数用 Zod schema + validateSearch 校验。
  • beforeLoad 中做认证与重定向,避免不必要的请求;嵌套结构用布局路由与 _authenticated 等前缀,子路由通过 <Outlet /> 渲染。
  • 导航使用 useNavigateLink,保持类型安全,避免直接操作 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.tstypes.tsconstants.ts、入口组件等。
  • 通用:通用组件放 src/components/,通用工具与类型放 src/lib/;组件文件 PascalCase工具/类型文件 kebab-case 或 types.ts,类型使用 PascalCase 命名并 export type

3.12 可访问性

  • 使用语义化 HTMLheadernavmainfooter),表单用 label 关联输入。
  • 保证键盘可操作与焦点顺序合理;必要时使用 ARIAaria-labelaria-expandedaria-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 依赖管理

  • 使用 Bunbun installbun add <pkg>bun add -d <pkg>bun remove <pkg>bun pm lsbun update 等。
  • 新增依赖前评估维护情况、体积与许可;生产与开发依赖区分清楚,版本用 ^/~ 控制,定期更新以获取安全修复。

3.16 构建与部署

  • 使用 Rsbuild配置见 rsbuild.config.ts;脚本以 package.json 为准(如 bun run devbun run buildbun run typecheckbun run lintbun run format),包管理见 3.15 依赖管理
  • 代码分割与懒加载策略见 3.4 性能;资源使用合适格式与压缩,环境变量用 .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 并修复至无错。