first commit
This commit is contained in:
+615
@@ -0,0 +1,615 @@
|
|||||||
|
# Nova 项目约定 (Project Conventions)
|
||||||
|
|
||||||
|
> dumi + father 技术栈的 AI-Native 组件库工程规范。
|
||||||
|
> 所有配置在此预先约定,AI 生成代码时按此执行。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、技术栈确认
|
||||||
|
|
||||||
|
| 领域 | 方案 | 版本 |
|
||||||
|
|------|------|------|
|
||||||
|
| 包管理 | pnpm | >= 9 |
|
||||||
|
| Monorepo | pnpm workspace | — |
|
||||||
|
| 文档站点 | dumi | 2.x |
|
||||||
|
| 组件构建 | father | 4.x |
|
||||||
|
| 测试 | Vitest + @testing-library/react | — |
|
||||||
|
| Lint | ESLint + Prettier | — |
|
||||||
|
| Git Hooks | husky + lint-staged | — |
|
||||||
|
| 版本管理 | Changesets | — |
|
||||||
|
| 样式方案 | **CSS Modules** | — |
|
||||||
|
| 语言 | TypeScript (strict) | 5.x |
|
||||||
|
|
||||||
|
### 为什么选 CSS Modules?
|
||||||
|
|
||||||
|
| 方案 | dumi 兼容 | father 兼容 | AI 友好度 | 运行时开销 |
|
||||||
|
|------|:---------:|:-----------:|:---------:|:---------:|
|
||||||
|
| CSS Modules | ✅ 原生 | ✅ 原生 | ★★★ (import styles 清晰) | 0 |
|
||||||
|
| vanilla-extract | ⚠️ 需插件 | ⚠️ 需插件 | ★★ (编译时,调试困难) | 0 |
|
||||||
|
| styled-components | ✅ | ⚠️ 需配置 | ★ (模板字符串 AI 常出错) | 有 |
|
||||||
|
| Tailwind | ✅ | ✅ | ★ (类名太长 AI 难控制) | 0 |
|
||||||
|
|
||||||
|
**结论:CSS Modules 零配置、零运行时、AI 最可控。**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
novaui/
|
||||||
|
├── .husky/
|
||||||
|
│ ├── pre-commit # lint-staged
|
||||||
|
│ └── commit-msg # commitlint
|
||||||
|
├── .github/
|
||||||
|
│ └── workflows/
|
||||||
|
│ ├── ci.yml # lint + test + build
|
||||||
|
│ └── release.yml # 发布 npm
|
||||||
|
├── docs/ # dumi 站点文档
|
||||||
|
│ ├── index.md # 首页
|
||||||
|
│ ├── guide/
|
||||||
|
│ │ ├── getting-started.md
|
||||||
|
│ │ ├── theme.md
|
||||||
|
│ │ └── faq.md
|
||||||
|
│ └── components/ # 组件概览页
|
||||||
|
│ └── index.md
|
||||||
|
├── src/
|
||||||
|
│ ├── components/
|
||||||
|
│ │ ├── Button/
|
||||||
|
│ │ │ ├── index.ts
|
||||||
|
│ │ │ ├── Button.tsx
|
||||||
|
│ │ │ ├── Button.module.css # ← CSS Modules
|
||||||
|
│ │ │ ├── Button.test.tsx
|
||||||
|
│ │ │ └── index.md # ← dumi 文档(关键)
|
||||||
|
│ │ └── ...
|
||||||
|
│ ├── hooks/
|
||||||
|
│ ├── theme/
|
||||||
|
│ │ ├── tokens.ts
|
||||||
|
│ │ ├── dark.css
|
||||||
|
│ │ └── global.css
|
||||||
|
│ ├── charts/ # 可视化组件
|
||||||
|
│ │ ├── LineChart/
|
||||||
|
│ │ └── ...
|
||||||
|
│ └── index.ts # 按需导出不做 barrel export
|
||||||
|
├── .dumirc.ts # dumi 配置
|
||||||
|
├── .fatherrc.ts # father 配置
|
||||||
|
├── vitest.config.ts
|
||||||
|
├── tsconfig.json
|
||||||
|
├── .eslintrc.cjs
|
||||||
|
├── .prettierrc
|
||||||
|
├── .commitlintrc.cjs
|
||||||
|
├── package.json
|
||||||
|
├── pnpm-workspace.yaml
|
||||||
|
├── .npmrc
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、dumi 配置约定
|
||||||
|
|
||||||
|
### 3.1 `.dumirc.ts`
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineConfig } from 'dumi'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
themeConfig: {
|
||||||
|
name: 'Nova',
|
||||||
|
logo: '/logo.png',
|
||||||
|
nav: [
|
||||||
|
{ title: '指南', link: '/guide' },
|
||||||
|
{ title: '组件', link: '/components' },
|
||||||
|
{ title: '图表', link: '/charts' },
|
||||||
|
],
|
||||||
|
socialLinks: {
|
||||||
|
github: 'https://github.com/user/novaui',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 自动 API 表格(必须,AI 生成组件时直接能看到类型)
|
||||||
|
apiParser: {},
|
||||||
|
resolve: {
|
||||||
|
// doc 目录下的 .md 作为文档路由
|
||||||
|
docDirs: ['docs'],
|
||||||
|
// 组件目录下的 index.md 作为组件文档
|
||||||
|
atomDirs: [
|
||||||
|
{ type: 'component', dir: 'src/components' },
|
||||||
|
{ type: 'chart', dir: 'src/charts' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// 约定输出
|
||||||
|
outputPath: 'dist-docs',
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 组件文档 (`index.md`) 模板
|
||||||
|
|
||||||
|
```md
|
||||||
|
---
|
||||||
|
nav: 组件
|
||||||
|
group: 通用
|
||||||
|
title: Button 按钮
|
||||||
|
description: 用于触发操作的按钮组件。
|
||||||
|
---
|
||||||
|
|
||||||
|
## 代码演示
|
||||||
|
|
||||||
|
### 基础用法
|
||||||
|
|
||||||
|
```tsx | pure
|
||||||
|
/**
|
||||||
|
* title: 基础按钮
|
||||||
|
* description: 使用 `variant` 切换按钮风格。
|
||||||
|
*/
|
||||||
|
import { Button } from '@nova/ui/button'
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<Button variant="solid" size="md">
|
||||||
|
确认
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 变体
|
||||||
|
|
||||||
|
```tsx | pure
|
||||||
|
<Button variant="solid">Solid</Button>
|
||||||
|
<Button variant="outline">Outline</Button>
|
||||||
|
<Button variant="ghost">Ghost</Button>
|
||||||
|
<Button variant="glass">Glass</Button>
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
<API id="Button" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 dumi 文档规则
|
||||||
|
|
||||||
|
```
|
||||||
|
1. 每个组件目录必须包含 index.md
|
||||||
|
2. 每个 demo 必须用 ```tsx | pure 声明(禁止用 react,避免 dumi 额外包裹)
|
||||||
|
3. demo 必须有 title,可选 description
|
||||||
|
4. 必须用 <API id="ComponentName" /> 生成 API 表格(依赖 apiParser 插件)
|
||||||
|
5. 组件分类:通用 / 录入 / 展示 / 反馈 / 导航 / 图表
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、father 配置约定
|
||||||
|
|
||||||
|
### 4.1 `.fatherrc.ts`
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineConfig } from 'father'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
// Bundless 模式:保持源码目录结构,每个组件独立产物(Tree-shaking 最佳)
|
||||||
|
cjs: {
|
||||||
|
output: 'dist/cjs',
|
||||||
|
platform: 'browser',
|
||||||
|
},
|
||||||
|
esm: {
|
||||||
|
output: 'dist/esm',
|
||||||
|
platform: 'browser',
|
||||||
|
// 保留 .module.css 作为 CSS Modules
|
||||||
|
extraBabelPlugins: [
|
||||||
|
// 确保 .module.css 被正确处理
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// 自动生成 .d.ts
|
||||||
|
typescript: {},
|
||||||
|
// UMD 构建(可选)
|
||||||
|
umd: {
|
||||||
|
output: 'dist/umd',
|
||||||
|
name: 'NovaUI',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 father 构建规则
|
||||||
|
|
||||||
|
```
|
||||||
|
1. 使用 Bundless 模式(非 Bundle),保持每个组件独立文件
|
||||||
|
→ 用户可 import { Button } from '@nova/ui/button'
|
||||||
|
2. 产物格式:esm + cjs(双格式)
|
||||||
|
3. CSS Modules 文件 (.module.css) 自动保留,build 后生成对应的 .css
|
||||||
|
4. TypeScript 生成 .d.ts 类型定义
|
||||||
|
5. 外部依赖:react、react-dom 标记为 peerDependencies,不打包
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.3 package.json 导出配置
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "@nova/ui",
|
||||||
|
"type": "module",
|
||||||
|
"main": "dist/cjs/index.js",
|
||||||
|
"module": "dist/esm/index.js",
|
||||||
|
"types": "dist/esm/index.d.ts",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"import": "./dist/esm/index.js",
|
||||||
|
"require": "./dist/cjs/index.js"
|
||||||
|
},
|
||||||
|
"./*": {
|
||||||
|
"import": "./dist/esm/*/index.js",
|
||||||
|
"require": "./dist/cjs/*/index.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sideEffects": [
|
||||||
|
"**/*.css"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=18",
|
||||||
|
"react-dom": ">=18"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、CSS Modules 约定
|
||||||
|
|
||||||
|
### 5.1 命名规则
|
||||||
|
|
||||||
|
```css
|
||||||
|
/* Button.module.css */
|
||||||
|
|
||||||
|
/* ✅ 用 camelCase,在 JS 中 import 后直接 styles.xxx */
|
||||||
|
.wrapper { }
|
||||||
|
.iconLeft { }
|
||||||
|
.iconRight { }
|
||||||
|
|
||||||
|
/* ✅ 全局覆盖用 :global */
|
||||||
|
:global(.nv-theme-dark) .wrapper {
|
||||||
|
background: #1a1a3e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ✅ data-* 状态样式 */
|
||||||
|
.wrapper[data-variant='solid'] { }
|
||||||
|
.wrapper[data-variant='outline'] { }
|
||||||
|
.wrapper[data-size='lg'] { }
|
||||||
|
.wrapper[data-loading] { }
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 组件引用
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// ✅ AI 正确用法
|
||||||
|
import styles from './Button.module.css'
|
||||||
|
|
||||||
|
<div className={styles.wrapper}>
|
||||||
|
<span className={styles.iconLeft}>{icon}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
// ❌ 禁止:styles['wrapper'](AI 容易拼错字符串)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.3 全局 CSS
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// theme/global.css — 引入 normalize + CSS 变量
|
||||||
|
// 在 dumi 的 .dumirc.ts 中通过 extraBabelPlugins 或手动 import
|
||||||
|
|
||||||
|
// theme/dark.css — 暗色模式变量
|
||||||
|
// 通过 html[data-theme='dark'] 选择器作用
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、Monorepo 约定
|
||||||
|
|
||||||
|
### 6.1 pnpm-workspace.yaml
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
packages:
|
||||||
|
- 'packages/*'
|
||||||
|
- 'apps/*'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.2 当前是单包,但结构保留扩展性
|
||||||
|
|
||||||
|
```
|
||||||
|
novaui/
|
||||||
|
├── packages/
|
||||||
|
│ ├── core/ # UI 组件(@nova/ui)
|
||||||
|
│ ├── charts/ # 图表组件(@nova/charts)
|
||||||
|
│ ├── theme/ # 主题包(@nova/theme)
|
||||||
|
│ └── utils/ # 工具(@nova/utils)
|
||||||
|
└── apps/
|
||||||
|
└── docs/ # dumi 文档站点
|
||||||
|
```
|
||||||
|
|
||||||
|
> 初期可扁平,但目录名和 npm scope 预先约定好。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、代码质量工具约定
|
||||||
|
|
||||||
|
### 7.1 ESLint + Prettier
|
||||||
|
|
||||||
|
```jsonc
|
||||||
|
// .eslintrc.cjs
|
||||||
|
module.exports = {
|
||||||
|
extends: [
|
||||||
|
'eslint:recommended',
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
'plugin:react/recommended',
|
||||||
|
'plugin:react-hooks/recommended',
|
||||||
|
'prettier', // 关闭冲突规则
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
'react/react-in-jsx-scope': 'off', // React 18+
|
||||||
|
'react/prop-types': 'off', // TypeScript 已覆盖
|
||||||
|
'@typescript-eslint/no-explicit-any': 'error',
|
||||||
|
'@typescript-eslint/consistent-type-definitions': ['error', 'interface'],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```jsonc
|
||||||
|
// .prettierrc
|
||||||
|
{
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "all",
|
||||||
|
"printWidth": 100,
|
||||||
|
"arrowParens": "avoid"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.2 commitlint
|
||||||
|
|
||||||
|
```
|
||||||
|
// .commitlintrc.cjs
|
||||||
|
module.exports = {
|
||||||
|
extends: ['@commitlint/config-conventional'],
|
||||||
|
rules: {
|
||||||
|
'type-enum': [2, 'always', [
|
||||||
|
'feat', 'fix', 'docs', 'style', 'refactor',
|
||||||
|
'test', 'chore', 'ci',
|
||||||
|
]],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式: <type>(<scope>): <subject>
|
||||||
|
// 示例: feat(Button): add glass variant
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.3 lint-staged
|
||||||
|
|
||||||
|
```jsonc
|
||||||
|
// package.json
|
||||||
|
{
|
||||||
|
"lint-staged": {
|
||||||
|
"*.{ts,tsx}": ["eslint --fix", "prettier --write"],
|
||||||
|
"*.{css,json,md}": ["prettier --write"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、测试约定
|
||||||
|
|
||||||
|
### 8.1 vitest.config.ts
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineConfig } from 'vitest/config'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
test: {
|
||||||
|
environment: 'jsdom',
|
||||||
|
globals: true,
|
||||||
|
setupFiles: ['./test-setup.ts'],
|
||||||
|
include: ['src/**/*.test.{ts,tsx}'],
|
||||||
|
coverage: {
|
||||||
|
provider: 'v8',
|
||||||
|
include: ['src/components/**/*.tsx', 'src/charts/**/*.tsx'],
|
||||||
|
thresholds: {
|
||||||
|
functions: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.2 测试规范
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// 每个组件至少覆盖:
|
||||||
|
// 1. 默认渲染
|
||||||
|
import { render, screen } from '@testing-library/react'
|
||||||
|
|
||||||
|
it('renders with default props', () => {
|
||||||
|
render(<Button>Click</Button>)
|
||||||
|
expect(screen.getByRole('button')).toHaveTextContent('Click')
|
||||||
|
})
|
||||||
|
|
||||||
|
// 2. Props 组合
|
||||||
|
it.each(['solid', 'outline', 'ghost'] as const)(
|
||||||
|
'renders variant="%s" correctly',
|
||||||
|
variant => {
|
||||||
|
const { container } = render(<Button variant={variant} />)
|
||||||
|
expect(container.querySelector('button')).toHaveAttribute('data-variant', variant)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// 3. 事件回调
|
||||||
|
it('fires onClick when clicked', () => {
|
||||||
|
const onClick = vi.fn()
|
||||||
|
render(<Button onClick={onClick} />)
|
||||||
|
screen.getByRole('button').click()
|
||||||
|
expect(onClick).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 4. 边界(disabled、loading、空 children)
|
||||||
|
it('does not fire onClick when disabled', () => {
|
||||||
|
const onClick = vi.fn()
|
||||||
|
render(<Button onClick={onClick} disabled />)
|
||||||
|
screen.getByRole('button').click()
|
||||||
|
expect(onClick).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 九、发布流程约定
|
||||||
|
|
||||||
|
### 9.1 Changesets
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 版本变更三步走
|
||||||
|
|
||||||
|
# 1. 开发完,记变更
|
||||||
|
pnpm changeset
|
||||||
|
# → 选择变更类型 (patch / minor / major)
|
||||||
|
# → 填写 changelog 描述
|
||||||
|
|
||||||
|
# 2. 统一版本
|
||||||
|
pnpm changeset version
|
||||||
|
# → 自动更新版本号 + 生成 CHANGELOG.md
|
||||||
|
|
||||||
|
# 3. 发布
|
||||||
|
pnpm changeset publish
|
||||||
|
```
|
||||||
|
|
||||||
|
### 9.2 GitHub Actions
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# .github/workflows/ci.yml
|
||||||
|
name: CI
|
||||||
|
on: [push, pull_request]
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
- run: pnpm install
|
||||||
|
- run: pnpm lint
|
||||||
|
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
- run: pnpm install
|
||||||
|
- run: pnpm test -- --coverage
|
||||||
|
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
- run: pnpm install
|
||||||
|
- run: pnpm build
|
||||||
|
- run: pnpm docs:build
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# .github/workflows/release.yml
|
||||||
|
name: Release
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
- run: pnpm install
|
||||||
|
- run: pnpm build
|
||||||
|
- name: Publish
|
||||||
|
uses: changesets/action@v1
|
||||||
|
with:
|
||||||
|
publish: pnpm changeset publish
|
||||||
|
env:
|
||||||
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 十、Git 分支与工作流
|
||||||
|
|
||||||
|
| 分支 | 用途 |
|
||||||
|
|------|------|
|
||||||
|
| `main` | 稳定版,只接受 PR merge |
|
||||||
|
| `feat/xxx` | 新组件/功能 |
|
||||||
|
| `fix/xxx` | Bug 修复 |
|
||||||
|
| `docs/xxx` | 文档改进 |
|
||||||
|
| `chore/xxx` | 工程配置 |
|
||||||
|
|
||||||
|
```
|
||||||
|
工作流:
|
||||||
|
1. 从 main 创建 feat/xxx
|
||||||
|
2. 开发 + 测试
|
||||||
|
3. PR → main(自动 CI 检查)
|
||||||
|
4. Merge → 触发 changesets → 发布
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 十一、提前准备清单(初始项目搭建步骤)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 初始化项目
|
||||||
|
mkdir novaui && cd novaui
|
||||||
|
pnpm init
|
||||||
|
|
||||||
|
# 2. 安装核心依赖
|
||||||
|
pnpm add -D dumi father vitest @testing-library/react \
|
||||||
|
@testing-library/jest-dom jsdom \
|
||||||
|
eslint prettier eslint-config-prettier \
|
||||||
|
@typescript-eslint/eslint-plugin @typescript-eslint/parser \
|
||||||
|
husky lint-staged @commitlint/cli @commitlint/config-conventional \
|
||||||
|
@changesets/cli
|
||||||
|
|
||||||
|
# 3. 安装运行时依赖
|
||||||
|
pnpm add react react-dom
|
||||||
|
pnpm add -D @types/react @types/react-dom
|
||||||
|
|
||||||
|
# 4. 创建核心配置文件
|
||||||
|
# .dumirc.ts, .fatherrc.ts, vitest.config.ts,
|
||||||
|
# tsconfig.json, .eslintrc.cjs, .prettierrc,
|
||||||
|
# .commitlintrc.cjs, pnpm-workspace.yaml
|
||||||
|
|
||||||
|
# 5. 初始化 git + husky
|
||||||
|
git init
|
||||||
|
pnpm husky init
|
||||||
|
|
||||||
|
# 6. 初始化 changesets
|
||||||
|
pnpm changeset init
|
||||||
|
|
||||||
|
# 7. 创建目录骨架
|
||||||
|
mkdir -p src/components src/theme src/hooks src/shared docs/guide docs/components
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 十二、AI 生成检查清单
|
||||||
|
|
||||||
|
每次 AI 生成代码后,按此检查:
|
||||||
|
|
||||||
|
```
|
||||||
|
[ ] import 路径正确:@nova/ui/组件名(全小写 kebab-case)
|
||||||
|
[ ] 样式引用正确:import styles from './Component.module.css'
|
||||||
|
[ ] 使用 data-* 属性标记状态,而非 class 拼接
|
||||||
|
[ ] 所有 prop 有类型定义(联合类型或 interface)
|
||||||
|
[ ] 所有 prop 有默认值(非必填的)
|
||||||
|
[ ] 测试覆盖渲染 + 事件 + 边界
|
||||||
|
[ ] 文档 index.md 有 demo + API 表格
|
||||||
|
[ ] 无 any 类型
|
||||||
|
[ ] 无 switch-case(代之以对象映射)
|
||||||
|
[ ] 无魔法字符串
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
> **提前约定越细,AI 犯错越少。此文档即 Nova 项目的"宪法",所有代码生成以此为据。**
|
||||||
+464
@@ -0,0 +1,464 @@
|
|||||||
|
# Nova 设计规范
|
||||||
|
|
||||||
|
> AI-Native 组件库:专为大模型代码生成优化的 AntV 类可视化 + UI 组件库。
|
||||||
|
> 核心目标:**让 AI 第一次生成的代码就能跑、就能看、就能用。**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、核心理念
|
||||||
|
|
||||||
|
### 1.1 AI 优先 (AI-First)
|
||||||
|
|
||||||
|
传统组件库(antd)面向人类开发者编写,Nova 面向 AI 编写。这意味着:
|
||||||
|
|
||||||
|
| 原则 | 说明 | 反例 (antd 风格) | 正例 (Nova 风格) |
|
||||||
|
|------|------|-------------------|------------------|
|
||||||
|
| **零歧义** | 每个 prop 名称自解释,无简称、无隐式行为 | `allowClear` | `showClear` |
|
||||||
|
| **零默认假设** | 所有视觉行为显式声明,不靠"常识" | `status` 默认 `undefined` 表示正常 | `status: 'default' \| 'error' \| 'warning' \| 'success'` |
|
||||||
|
| **一致性** | 相同概念用相同 prop 名,跨组件统一 | Table `dataSource` / Select `options` | 统一 `data` |
|
||||||
|
| **扁平化** | 最多一层嵌套,禁止深层 renderProps | `columns[].render()` | `column.renderCell` 函数 prop |
|
||||||
|
| **确定性** | 相同输入始终产生相同输出,无随机行为 | 部分组件默认不带 `key` 警告 | 所有组件强制 `key` 或无状态 |
|
||||||
|
|
||||||
|
### 1.2 可视化 + UI 一体化
|
||||||
|
|
||||||
|
Nova 融合 AntV 的数据可视化能力与 antd 的 UI 能力,两者共享同一套设计 Token、交互模式、主题系统。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、AI 最友好的 API 设计规则
|
||||||
|
|
||||||
|
### 规则 1: 统一数据模型
|
||||||
|
|
||||||
|
所有列表/表格/图表组件遵循同一数据接口:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// ✅ Nova 方式 — 所有数据组件统一
|
||||||
|
<Table data={items} />
|
||||||
|
<List data={items} />
|
||||||
|
<Chart data={items} />
|
||||||
|
<Timeline data={items} />
|
||||||
|
|
||||||
|
// ❌ antd 方式 — 不同名称增加 AI 混淆
|
||||||
|
<Table dataSource={items} /> // dataSource
|
||||||
|
<Select options={items} /> // options
|
||||||
|
<Tree treeData={items} /> // treeData
|
||||||
|
```
|
||||||
|
|
||||||
|
### 规则 2: 统一尺寸体系
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// 所有组件共用 size,无例外
|
||||||
|
size: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
||||||
|
|
||||||
|
// ❌ antd 不一致的尺寸名
|
||||||
|
// Button: large / middle / small
|
||||||
|
// Input: large / middle / small
|
||||||
|
// DatePicker: large / middle / small
|
||||||
|
// Tag: 无尺寸 prop
|
||||||
|
```
|
||||||
|
|
||||||
|
### 规则 3: 统一事件命名
|
||||||
|
|
||||||
|
```
|
||||||
|
// 所有事件回调 = on + 动词 + 名词
|
||||||
|
onClick // ✅
|
||||||
|
onChange // ✅
|
||||||
|
onSelect // ✅
|
||||||
|
onClose // ✅
|
||||||
|
|
||||||
|
// ❌ 避免 on + 名词 + 动词 (增加 AI 推理负担)
|
||||||
|
onMenuClick // ❌ → onClick 即可
|
||||||
|
onPanelChange // ❌ → onChange
|
||||||
|
```
|
||||||
|
|
||||||
|
### 规则 4: 统一布尔 prop 命名
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// ✅ 统一用动词/形容词 + 肯定形式
|
||||||
|
disabled: boolean // 禁用
|
||||||
|
loading: boolean // 加载中
|
||||||
|
readOnly: boolean // 只读
|
||||||
|
showSearch: boolean // 显示搜索
|
||||||
|
showClear: boolean // 显示清除
|
||||||
|
allowMultiple: boolean // 允许多选
|
||||||
|
|
||||||
|
// ❌ 避免 antd 风格的不一致
|
||||||
|
// allowClear / showSearch / bordered / dropdownMatchSelectWidth
|
||||||
|
```
|
||||||
|
|
||||||
|
### 规则 5: 自包含组件 + 确定导入路径
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// ✅ 每个组件独立导入,路径即名字
|
||||||
|
import { Button } from '@nova/ui/button'
|
||||||
|
import { Modal } from '@nova/ui/modal'
|
||||||
|
import { LineChart } from '@nova/ui/line-chart'
|
||||||
|
|
||||||
|
// ❌ 避免 AI 不确定路径
|
||||||
|
// import { Button } from '@nova/ui' // 可能 tree-shake 失败
|
||||||
|
// import { LineChart } from '@nova/charts' // 需要 AI 猜测包名
|
||||||
|
```
|
||||||
|
|
||||||
|
### 规则 6: 类型优先
|
||||||
|
|
||||||
|
所有 prop 使用联合类型字面量而非 boolean,让 AI 看到所有选项:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// ✅ 明确枚举,AI 能看到所有可能性
|
||||||
|
type ButtonVariant = 'solid' | 'outline' | 'ghost' | 'glass'
|
||||||
|
type ButtonSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
||||||
|
type Status = 'default' | 'success' | 'warning' | 'error' | 'info'
|
||||||
|
|
||||||
|
// ❌ boolean 隐藏了其他可能性
|
||||||
|
<Button ghost /> // 为什么不是 outline?
|
||||||
|
<Button primary /> // primary 和 type="primary" 是什么关系?
|
||||||
|
```
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// 每个组件导出完整类型
|
||||||
|
export interface ButtonProps {
|
||||||
|
variant: ButtonVariant
|
||||||
|
size: ButtonSize
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 规则 7: 远离魔法字符串
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// ✅ 枚举/常量,AI 不会拼错
|
||||||
|
<Table scrollBar={{ placement: 'overlay' }} />
|
||||||
|
|
||||||
|
// ❌ 魔法字符串
|
||||||
|
<Input status="error" /> // "error" 还是 "Error"?还有哪些值?
|
||||||
|
```
|
||||||
|
|
||||||
|
### 规则 8: 组件原子化
|
||||||
|
|
||||||
|
一个组件只做一件事,不做"大而全"的上帝组件:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// ✅ 拆分
|
||||||
|
<Table /> // 纯表格
|
||||||
|
<TableFilter /> // 表格筛选
|
||||||
|
<TableSort /> // 表格排序
|
||||||
|
|
||||||
|
// ❌ 不拆分
|
||||||
|
<Table filter sort pagination editable /> // 30+ props 的巨无霸
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、结合 AntV 的可视化组件规范
|
||||||
|
|
||||||
|
### 3.1 图表组件统一接口
|
||||||
|
|
||||||
|
所有图表组件共享以下 props 契约:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
interface ChartBaseProps<T> {
|
||||||
|
data: T[] // 统一数据源
|
||||||
|
xField: keyof T // X 轴字段名
|
||||||
|
yField: keyof T // Y 轴字段名
|
||||||
|
seriesField?: keyof T // 分组/系列字段
|
||||||
|
color?: string | string[] | ((d: T) => string)
|
||||||
|
size?: number | ((d: T) => number)
|
||||||
|
tooltip?: boolean | TooltipConfig
|
||||||
|
legend?: boolean | LegendConfig
|
||||||
|
animation?: boolean | AnimationConfig
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 支持的图表类型
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// 基础图表
|
||||||
|
<LineChart data={data} xField="date" yField="value" />
|
||||||
|
<BarChart data={data} xField="category" yField="count" />
|
||||||
|
<PieChart data={data} angleField="value" colorField="name" />
|
||||||
|
<AreaChart data={data} xField="date" yField="value" />
|
||||||
|
<ScatterChart data={data} xField="age" yField="income" />
|
||||||
|
|
||||||
|
// 组合图表
|
||||||
|
<DualAxesChart data={data} left={{ yField: 'revenue' }} right={{ yField: 'rate' }} />
|
||||||
|
|
||||||
|
// 统计图表
|
||||||
|
<BoxPlot data={data} />
|
||||||
|
<Heatmap data={data} />
|
||||||
|
<RadarChart data={data} />
|
||||||
|
<Treemap data={data} />
|
||||||
|
|
||||||
|
// 地图
|
||||||
|
<MapChart data={geoData} />
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 可视化交互
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// 所有图表支持标准交互
|
||||||
|
interface ChartInteraction {
|
||||||
|
tooltip: boolean | { shared?: boolean; crosshairs?: boolean }
|
||||||
|
zoom: boolean | { type: 'x' | 'y' | 'both' }
|
||||||
|
brush: boolean | { type: 'rect' | 'polygon' }
|
||||||
|
slider: boolean | { start?: number; end?: number }
|
||||||
|
legendFilter: boolean
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.4 Stat 组件(数值 + 迷你图)
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// AI 生成看板时最常用的组件
|
||||||
|
<Stat
|
||||||
|
title="本月收入"
|
||||||
|
value={128000}
|
||||||
|
prefix="¥"
|
||||||
|
trend={12.5} // 正数上升,负数下降
|
||||||
|
trendDirection="up"
|
||||||
|
chart={<MiniLine data={trendData} />}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、可落地的 Token 体系
|
||||||
|
|
||||||
|
所有值用 TypeScript 常量 + CSS 自定义属性双重暴露:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// theme/tokens.ts
|
||||||
|
export const tokens = {
|
||||||
|
color: {
|
||||||
|
primary: '#6C5CE7',
|
||||||
|
primaryHover: '#A29BFE',
|
||||||
|
primaryActive: '#4A3DBF',
|
||||||
|
success: '#00B894',
|
||||||
|
warning: '#FDCB6E',
|
||||||
|
error: '#FF7675',
|
||||||
|
info: '#74B9FF',
|
||||||
|
text: '#1a1a2e',
|
||||||
|
bg: '#ffffff',
|
||||||
|
bgElevated: '#f8f9fa',
|
||||||
|
border: '#e2e8f0',
|
||||||
|
},
|
||||||
|
radius: {
|
||||||
|
xs: '4px',
|
||||||
|
sm: '8px',
|
||||||
|
md: '12px',
|
||||||
|
lg: '16px',
|
||||||
|
xl: '24px',
|
||||||
|
round: '9999px',
|
||||||
|
},
|
||||||
|
space: {
|
||||||
|
xs: '4px',
|
||||||
|
sm: '8px',
|
||||||
|
md: '12px',
|
||||||
|
lg: '16px',
|
||||||
|
xl: '24px',
|
||||||
|
'2xl': '32px',
|
||||||
|
'3xl': '48px',
|
||||||
|
},
|
||||||
|
font: {
|
||||||
|
family: '"Inter", "SF Pro Display", -apple-system, sans-serif',
|
||||||
|
familyMono: '"JetBrains Mono", "SF Mono", monospace',
|
||||||
|
size: { xs: 12, sm: 14, md: 16, lg: 20, xl: 24 },
|
||||||
|
weight: { regular: 400, medium: 500, semibold: 600, bold: 700 },
|
||||||
|
},
|
||||||
|
shadow: {
|
||||||
|
sm: '0 1px 3px rgba(0,0,0,0.08)',
|
||||||
|
md: '0 4px 12px rgba(0,0,0,0.1)',
|
||||||
|
lg: '0 8px 30px rgba(0,0,0,0.12)',
|
||||||
|
xl: '0 20px 60px rgba(0,0,0,0.15)',
|
||||||
|
},
|
||||||
|
motion: {
|
||||||
|
fast: '100ms',
|
||||||
|
normal: '200ms',
|
||||||
|
slow: '350ms',
|
||||||
|
easeOut: 'cubic-bezier(0.23, 1, 0.32, 1)',
|
||||||
|
easeInOut: 'cubic-bezier(0.65, 0, 0.35, 1)',
|
||||||
|
spring: 'cubic-bezier(0.34, 1.56, 0.64, 1)',
|
||||||
|
},
|
||||||
|
} as const
|
||||||
|
```
|
||||||
|
|
||||||
|
CSS 变量注入:
|
||||||
|
|
||||||
|
```css
|
||||||
|
:root {
|
||||||
|
--nv-color-primary: #6C5CE7;
|
||||||
|
--nv-radius-sm: 8px;
|
||||||
|
--nv-space-md: 12px;
|
||||||
|
/* ... 每个 token 对应一个 --nv-* 变量 */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、组件文件脚手架(AI 生成模板)
|
||||||
|
|
||||||
|
每个新组件创建时,AI 按此模板生成:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// Button.tsx — AI 生成的模板示例
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
export interface ButtonProps extends React.ComponentPropsWithoutRef<'button'> {
|
||||||
|
variant?: 'solid' | 'outline' | 'ghost' | 'glass'
|
||||||
|
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
||||||
|
status?: 'default' | 'success' | 'warning' | 'error'
|
||||||
|
loading?: boolean
|
||||||
|
icon?: React.ReactNode
|
||||||
|
iconPosition?: 'left' | 'right'
|
||||||
|
fullWidth?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||||
|
({
|
||||||
|
variant = 'solid',
|
||||||
|
size = 'md',
|
||||||
|
status = 'default',
|
||||||
|
loading = false,
|
||||||
|
icon,
|
||||||
|
iconPosition = 'left',
|
||||||
|
fullWidth = false,
|
||||||
|
children,
|
||||||
|
...rest
|
||||||
|
}, ref) => {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
ref={ref}
|
||||||
|
data-variant={variant}
|
||||||
|
data-size={size}
|
||||||
|
data-status={status}
|
||||||
|
data-loading={loading || undefined}
|
||||||
|
data-full-width={fullWidth || undefined}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
{loading ? <Spinner /> : icon && iconPosition === 'left' && icon}
|
||||||
|
{children}
|
||||||
|
{icon && iconPosition === 'right' && icon}
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
Button.displayName = 'Button'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 每个组件必须包含:
|
||||||
|
|
||||||
|
```
|
||||||
|
Button/
|
||||||
|
├── index.ts # export { Button } from './Button'
|
||||||
|
├── Button.tsx # 组件实现 + Props 类型导出
|
||||||
|
├── Button.style.ts # 样式(vanilla-extract / CSS modules)
|
||||||
|
├── Button.test.tsx # 测试(至少 3 个用例:渲染、交互、边界)
|
||||||
|
└── Button.stories.tsx # Storybook stories(至少展示所有 variant + size 组合)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、AI 友好的代码约束
|
||||||
|
|
||||||
|
### 6.1 Props 声明规范
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// ✅ 正确做法
|
||||||
|
interface ButtonProps {
|
||||||
|
/** 按钮风格变体 */
|
||||||
|
variant?: 'solid' | 'outline' | 'ghost' | 'glass'
|
||||||
|
/** 按钮尺寸 */
|
||||||
|
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
||||||
|
}
|
||||||
|
|
||||||
|
// ❌ 禁止做法
|
||||||
|
interface BadProps {
|
||||||
|
type?: string // string 类型 — AI 不知道可选值
|
||||||
|
mode?: any // any 类型 — 无类型提示
|
||||||
|
[key: string]: any // 透传导致 AI 无法推理
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.2 状态映射(禁止 switch-case 硬编码)
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// ✅ 用对象映射,AI 容易理解
|
||||||
|
const STATUS_MAP = {
|
||||||
|
default: { bg: '#f5f5f5', color: '#333' },
|
||||||
|
success: { bg: '#f0fff4', color: '#00b894' },
|
||||||
|
warning: { bg: '#fffbeb', color: '#fdcb6e' },
|
||||||
|
error: { bg: '#fff5f5', color: '#ff7675' },
|
||||||
|
} as const
|
||||||
|
|
||||||
|
// ❌ switch-case 层层嵌套
|
||||||
|
switch (status) {
|
||||||
|
case 'success': return { bg: '#f0fff4', color: '#00b894' }
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.3 条件渲染
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// ✅ 提前 return / 三元表达式
|
||||||
|
if (!data.length) return <Empty />
|
||||||
|
return <div>{data.map(render)}</div>
|
||||||
|
|
||||||
|
// ❌ 复杂 && 链
|
||||||
|
{!!data && data.length > 0 && data.map(item => item.active && <Item />)}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.4 样式绑定
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// ✅ data-* 属性 + CSS 属性选择器(AI 删改时不易出错)
|
||||||
|
<button data-variant="solid" data-size="lg" />
|
||||||
|
|
||||||
|
// ❌ classnames 动态拼接(AI 难以追踪所有组合)
|
||||||
|
<button className={cn('btn', `btn-${variant}`, `btn-${size}`)} />
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
novaui/
|
||||||
|
├── packages/
|
||||||
|
│ ├── core/ # 核心组件
|
||||||
|
│ │ ├── Button/
|
||||||
|
│ │ ├── Modal/
|
||||||
|
│ │ └── ...
|
||||||
|
│ ├── charts/ # 可视化组件(基于 AntV/G2)
|
||||||
|
│ │ ├── LineChart/
|
||||||
|
│ │ ├── BarChart/
|
||||||
|
│ │ └── ...
|
||||||
|
│ ├── icons/ # 图标库
|
||||||
|
│ ├── theme/ # 主题 Token + 生成器
|
||||||
|
│ └── utils/ # 工具函数
|
||||||
|
├── apps/
|
||||||
|
│ └── docs/ # Storybook
|
||||||
|
├── packages.json # monorepo root
|
||||||
|
└── tsconfig.json
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、总结:Nova 给 AI 的"提示工程"
|
||||||
|
|
||||||
|
当 AI 生成 Nova 组件代码时,应当遵循的心智模型:
|
||||||
|
|
||||||
|
```
|
||||||
|
1. 导入路径 = @nova/ui/组件名(全小写 kebab-case)
|
||||||
|
2. 数据 prop 始终叫 data,没有例外
|
||||||
|
3. 尺寸 prop 始终叫 size,值从 xs-xl 选
|
||||||
|
4. 布尔 prop 用动词开头,如 showSearch、allowMultiple
|
||||||
|
5. 所有 prop 类型用联合类型字面量定义
|
||||||
|
6. 状态样式用 data-* 属性,不用 class 拼接
|
||||||
|
7. 回调命名 = on + 动词 + 名词
|
||||||
|
8. 每个组件独立文件,组件 = 文件夹
|
||||||
|
9. 可视化组件统一 xField / yField / data
|
||||||
|
10. 拒绝魔法字符串、拒绝 any、拒绝深层嵌套
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Nova 的核心竞争力:AI 写的代码,跟人写的一样规范。**
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://opencode.ai/config.json",
|
||||||
|
"autoCompact": true,
|
||||||
|
"performance": {
|
||||||
|
"cache": {
|
||||||
|
"enabled": true,
|
||||||
|
"size": "512MB"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"server": {
|
||||||
|
"concurrency": {
|
||||||
|
"maxSessions": 8,
|
||||||
|
"maxRequestsPerSession": 4,
|
||||||
|
"requestTimeoutMs": 25000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"models": {
|
||||||
|
"deepseek": {
|
||||||
|
"temperature": 0.2,
|
||||||
|
"max_tokens": 2048
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"disabled_providers": ["minimax", "mimo"]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user