Browse Source

docs: add antd lint to CI, improve CLAUDE.md and cheatsheets (#11766)

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
pull/11769/head
Alex Zhu 3 weeks ago
committed by GitHub
parent
commit
1d52ebd090
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 10
      .github/workflows/ci.yml
  2. 22
      CLAUDE.md
  3. 95
      docs/cheatsheet.en-US.md
  4. 95
      docs/cheatsheet.zh-CN.md

10
.github/workflows/ci.yml

@ -6,6 +6,16 @@ permissions:
contents: read
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v5
with:
node-version: 20
- run: npm ci
- run: npx antd lint ./src
build:
runs-on: ${{ matrix.os }}
strategy:

22
CLAUDE.md

@ -90,7 +90,7 @@ Umi Max (`@umijs/max`) is the meta-framework. It wraps the build pipeline and pr
- **@tanstack/react-query** for complex server state (e.g., table-list uses `useMutation` + `useQuery`)
- Most pages use ProTable's built-in `request` prop for data loading
### Styling: Three Systems Coexist
### Styling Systems
1. **Tailwind CSS v4** — entry: `src/tailwind.css`, PostCSS plugin in `postcss.config.js`. Best for layout utilities
2. **antd-style v4** (`createStyles`) — CSS-in-JS with design token access (`{ token }`). Preferred when consuming theme tokens
@ -117,6 +117,12 @@ Each page directory contains its own index.tsx, optional service.ts, _mock.ts, d
`cloudflare-worker/` is a separate deployable (Hono framework, own `package.json`/`tsconfig.json`). Not an npm workspace — manage independently. Provides the production demo API.
```bash
cd cloudflare-worker
npm run dev # Local dev (wrangler dev)
npm run deploy # Deploy to Cloudflare (wrangler deploy)
```
## Ant Design CLI
`@ant-design/cli` (antd) is installed as a dev dependency. It provides offline antd component metadata and project analysis. Run via `npx antd`.
@ -139,7 +145,17 @@ The CLI also supports MCP server mode: `npx antd mcp` (for IDE integrations).
- **TypeScript strict mode** enabled. Path aliases: `@/*``./src/*`, `@@/*``./src/.umi/*`.
- **Node >= 20** required.
- **Markdown as raw strings**: `config/md-raw-loader.cjs` lets `.md` files be imported as strings (used in Welcome/cheatsheet pages with `@ant-design/x-markdown`).
- **Auto-generated code in `src/services/`** is excluded from Biome linting. Never edit manually — regenerate with `npm run openapi`.
- **Auto-generated code in `src/services/`** is excluded from Biome linting
- **Adding a new page**: 1) Create component in `src/pages/` 2) Add route in `config/routes.ts` 3) Add menu translation in `src/locales/` (route `name` maps to `menu.xxx` i18n key)
- **Adding global state**: Create a file in `src/models/` exporting a custom Hook, use `useModel('filename')` in components
- **Access control**: Route-level via `access` field in routes; component-level via `<Access accessible={...}>` or `useAccess()` hook from `@umijs/max`
- **Access control**: Route-level via `access` field in routes; component-level via `<Access accessible={...}>` or `useAccess()` hook from `@umijs/max`
## Gotchas & Troubleshooting
- **`.umi` directory**: Auto-generated by Umi. If dev server behaves unexpectedly, delete `src/.umi` and restart
- **Port 8000 in use**: Kill the process (`lsof -ti:8000 | xargs kill`) or use `PORT=3000 npm start` to change it
- **Mock not updating**: Umi usually auto-discovers `mock/` and `src/pages/**/_mock.ts` changes. If a new file isn't recognized, try restarting the dev server
- **Biome + antd lint**: Both must pass before committing. `npm run lint` runs Biome + tsc; `npx antd lint ./src` runs separately. Do not install ESLint or Prettier — this project uses Biome only
- **`src/services/` is auto-generated**: Never edit manually. Run `npm run openapi` to regenerate
- **`npm run simple` is irreversible**: Always commit or branch before running it
- **Lock file**: Uses `package-lock.json`. If deps break, delete `node_modules` and reinstall

95
docs/cheatsheet.en-US.md

@ -100,6 +100,7 @@ npm install # Update dependencies
**Route config** is in `config/routes.ts`:
```ts
// File: config/routes.ts
export default [
{
path: '/welcome',
@ -143,12 +144,19 @@ const location = useLocation(); // current route info
**ProLayout config** is in `config/defaultSettings.ts`:
```ts
// File: config/defaultSettings.ts
export default {
navTheme: 'light', // nav theme: light / dark
colorPrimary: '#1890ff', // primary color
layout: 'mix', // layout mode: side / top / mix
contentWidth: 'Fluid', // content width: Fluid / Fixed
fixSiderbar: true, // fixed sidebar
navTheme: 'light', // nav theme: light / dark
colorPrimary: '#1890ff', // primary color
layout: 'mix', // layout mode: side / top / mix
contentWidth: 'Fluid', // content width: Fluid / Fixed
fixedHeader: false, // fixed header
fixSiderbar: true, // fixed sidebar
colorWeak: false, // color weak mode
title: 'Ant Design Pro', // site title
logo: 'https://...', // logo URL
iconfontUrl: '', // iconfont URL
token: {}, // ProLayout token for fine-grained style customization
};
```
@ -181,7 +189,7 @@ const Page = () => (
**useModel — lightweight global state:** Create a file in `src/models/` to auto-register:
```ts
// src/models/counter.ts
// File: src/models/counter.ts
import { useState } from 'react';
export default function useCounter() {
@ -229,7 +237,7 @@ const mutation = useMutation({
**Initial state — getInitialState:** Define in `src/app.tsx`, accessible globally:
```tsx
// src/app.tsx
// File: src/app.tsx
export async function getInitialState() {
const currentUser = await fetchUserInfo();
return { currentUser };
@ -249,6 +257,7 @@ const { initialState } = useModel('@@initialState');
**Request config** is in `src/app.tsx`:
```ts
// File: src/app.tsx
export const request: RequestConfig = {
baseURL: 'https://api.example.com',
timeout: 10000,
@ -288,6 +297,7 @@ Auto-generates API calling code under `src/services/` based on `config/oneapi.js
**Define permissions** in `src/access.ts`:
```ts
// File: src/access.ts
export default function access(initialState: { currentUser?: API.CurrentUser }) {
const { currentUser } = initialState;
return {
@ -441,7 +451,7 @@ Test files go next to the component, named `*.test.ts(x)`.
**Mock data:** Create files in `mock/`:
```ts
// mock/user.ts
// File: mock/user.ts
export default {
'GET /api/currentUser': { name: 'Serati Ma', access: 'admin' },
'POST /api/login': (req, res) => { res.end('ok'); },
@ -453,6 +463,7 @@ Umi auto-registers mocks, active in dev mode.
**Proxy config** is in `config/proxy.ts`:
```ts
// File: config/proxy.ts
export default {
dev: {
'/api/': {
@ -488,3 +499,71 @@ Create a file in `src/models/` exporting a custom Hook, then use `useModel('file
1. Configure `openAPI` in `config/config.ts` 2. Run `npm run openapi` 3. Code is auto-generated under `src/services/`
→ See [umi FAQ](https://umijs.org/en-US/docs/introduce/faq)
## Common Tasks
### Add a New Page
```bash
# 1. Create the page component
# File: src/pages/my-page/index.tsx
# 2. Register in route config
# File: config/routes.ts
# { path: '/my-page', name: 'myPage', icon: 'file', component: './my-page' }
# 3. Add i18n translations (for menu display)
# File: src/locales/zh-CN/menu.ts → menu.myPage: '我的页面'
# File: src/locales/en-US/menu.ts → menu.myPage: 'My Page'
```
### Add Global State
```bash
# 1. Create a model file (filename becomes the model key)
# File: src/models/myModel.ts
# Export a custom Hook: export default function useMyModel() { ... }
# 2. Use in components
# import { useModel } from '@umijs/max';
# const { data } = useModel('myModel'); // 'myModel' matches filename
```
### Add a Mock API
```bash
# Global mock: mock/api.ts (applies to all environments)
# Page-level mock: src/pages/my-page/_mock.ts (auto-discovered by Umi)
# Mock format:
# export default { 'GET /api/my-data': { data: [] } }
```
### Generate API Service Code
```bash
# 1. Edit OpenAPI config: config/oneapi.json
# 2. Run generation (overwrites src/services/ant-design-pro/)
npm run openapi
# 3. Never edit generated code manually — modify oneapi.json and regenerate
```
### Switch to Simple Mode
```bash
git add -A && git commit -m "chore: save before simple" # Must commit first
npm run simple # Irreversible
npm install # Update dependencies
```
## Constraints & Gotchas
- **`src/services/ant-design-pro/`** is auto-generated code. Do NOT edit manually. Modify `config/oneapi.json` and run `npm run openapi` to regenerate.
- **`npm run simple` is irreversible**: It deletes demo pages and unused dependencies. Always commit before running.
- **`.umi` temp directory**: `src/.umi` is auto-generated by Umi. Delete it and restart the dev server if you encounter unexpected behavior.
- **Biome over ESLint**: This project uses Biome for linting and formatting. Do not install ESLint or Prettier plugins.
- **Commit convention**: Must follow [Conventional Commits](https://www.conventionalcommits.org/) (e.g., `feat:`, `fix:`, `chore:`).
- **`npx antd lint ./src`**: Must pass with zero errors and warnings before committing.
- **Mock priority**: `mock/` directory for global mocks, `src/pages/**/_mock.ts` for page-level mocks. Both are auto-registered by Umi.
- **Styling priority**: Tailwind (layout) > antd-style (theme tokens) > CSS Modules (component styles) > Less (legacy global styles only).
- **Path aliases**: `@/*``./src/*`, `@@/*``./src/.umi/*`

95
docs/cheatsheet.zh-CN.md

@ -100,6 +100,7 @@ npm install # 更新依赖
**路由配置** 位于 `config/routes.ts`
```ts
// File: config/routes.ts
export default [
{
path: '/welcome',
@ -143,12 +144,19 @@ const location = useLocation(); // 当前路由信息
**ProLayout 配置** 位于 `config/defaultSettings.ts`
```ts
// File: config/defaultSettings.ts
export default {
navTheme: 'light', // 导航主题:light / dark
colorPrimary: '#1890ff', // 主题色
layout: 'mix', // 布局模式:side / top / mix
contentWidth: 'Fluid', // 内容宽度:Fluid / Fixed
fixSiderbar: true, // 固定侧边栏
navTheme: 'light', // 导航主题:light / dark
colorPrimary: '#1890ff', // 主题色
layout: 'mix', // 布局模式:side / top / mix
contentWidth: 'Fluid', // 内容宽度:Fluid / Fixed
fixedHeader: false, // 固定顶部导航
fixSiderbar: true, // 固定侧边栏
colorWeak: false, // 色弱模式
title: 'Ant Design Pro', // 站点标题
logo: 'https://...', // Logo URL
iconfontUrl: '', // 图标字体 URL
token: {}, // ProLayout token,用于细粒度样式定制
};
```
@ -181,7 +189,7 @@ const Page = () => (
**useModel — 轻量全局状态:** 在 `src/models/` 下创建文件即自动注册:
```ts
// src/models/counter.ts
// File: src/models/counter.ts
import { useState } from 'react';
export default function useCounter() {
@ -229,7 +237,7 @@ const mutation = useMutation({
**初始状态 — getInitialState:** 在 `src/app.tsx` 中定义,全局可访问:
```tsx
// src/app.tsx
// File: src/app.tsx
export async function getInitialState() {
const currentUser = await fetchUserInfo();
return { currentUser };
@ -249,6 +257,7 @@ const { initialState } = useModel('@@initialState');
**请求配置** 位于 `src/app.tsx`
```ts
// File: src/app.tsx
export const request: RequestConfig = {
baseURL: 'https://api.example.com',
timeout: 10000,
@ -288,6 +297,7 @@ npm run openapi
**定义权限** 在 `src/access.ts`
```ts
// File: src/access.ts
export default function access(initialState: { currentUser?: API.CurrentUser }) {
const { currentUser } = initialState;
return {
@ -441,7 +451,7 @@ npm run test:update # 更新快照
**Mock 数据:** 在 `mock/` 目录下创建文件:
```ts
// mock/user.ts
// File: mock/user.ts
export default {
'GET /api/currentUser': { name: 'Serati Ma', access: 'admin' },
'POST /api/login': (req, res) => { res.end('ok'); },
@ -453,6 +463,7 @@ Umi 自动注册 mock,开发模式下生效。
**代理配置** 位于 `config/proxy.ts`
```ts
// File: config/proxy.ts
export default {
dev: {
'/api/': {
@ -488,3 +499,71 @@ export default {
1. 在 `config/config.ts` 配置 `openAPI` 2. 运行 `npm run openapi` 3. 自动生成 `src/services/` 下的代码
→ 更多内容见 [umi FAQ](https://umijs.org/docs/introduce/faq)
## 常见任务
### 添加新页面
```bash
# 1. 创建页面组件
# 文件路径:src/pages/my-page/index.tsx
# 2. 在路由配置中注册
# 文件路径:config/routes.ts
# { path: '/my-page', name: 'myPage', icon: 'file', component: './my-page' }
# 3. 添加国际化翻译(如需菜单显示)
# 文件路径:src/locales/zh-CN/menu.ts → menu.myPage: '我的页面'
# 文件路径:src/locales/en-US/menu.ts → menu.myPage: 'My Page'
```
### 添加全局状态
```bash
# 1. 创建 model 文件(文件名即 model key)
# 文件路径:src/models/myModel.ts
# 导出自定义 Hook:export default function useMyModel() { ... }
# 2. 在组件中使用
# import { useModel } from '@umijs/max';
# const { data } = useModel('myModel'); // 'myModel' 对应文件名
```
### 添加 Mock 接口
```bash
# 全局 Mock:mock/api.ts(匹配所有环境)
# 页面级 Mock:src/pages/my-page/_mock.ts(Umi 自动发现)
# Mock 格式:
# export default { 'GET /api/my-data': { data: [] } }
```
### 生成 API 服务代码
```bash
# 1. 编辑 OpenAPI 配置:config/oneapi.json
# 2. 运行生成命令(覆盖 src/services/ant-design-pro/)
npm run openapi
# 3. 不要手动编辑生成代码,改 oneapi.json 重新生成
```
### 切换到精简模式
```bash
git add -A && git commit -m "chore: save before simple" # 必须先提交
npm run simple # 不可逆操作
npm install # 更新依赖
```
## 注意事项
- **`src/services/ant-design-pro/`** 为自动生成代码,禁止手动编辑。修改 `config/oneapi.json` 后执行 `npm run openapi` 重新生成
- **`npm run simple` 不可逆**:会删除示例页面和多余依赖,执行前务必提交代码
- **`.umi` 临时目录**:`src/.umi` 由 Umi 自动生成,遇到异常可删除后重启开发服务器
- **Biome 代替 ESLint**:项目使用 Biome 进行 lint 和格式化,不要安装 ESLint 或 Prettier 插件
- **Commit 规范**:必须遵循 [Conventional Commits](https://www.conventionalcommits.org/),如 `feat:`, `fix:`, `chore:`
- **`npx antd lint ./src`**:提交前必须零错误零警告
- **Mock 优先级**:`mock/` 目录为全局 Mock,`src/pages/**/_mock.ts` 为页面级 Mock,两者都会被 Umi 自动注册
- **样式优先级**:Tailwind(布局)> antd-style(主题 token)> CSS Modules(组件样式)> Less(仅遗留全局样式)
- **路径别名**:`@/*` → `./src/*`,`@@/*` → `./src/.umi/*`

Loading…
Cancel
Save