@qin-ui/antd-vue-pro 2.1.13 → 2.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AI-CONTEXT.md +194 -95
- package/api.json +1 -1
- package/bin/init-ai.mjs +302 -0
- package/es/antd-vue-pro.css +3 -3
- package/es/table/index.js +1 -1
- package/package.json +5 -1
package/AI-CONTEXT.md
CHANGED
|
@@ -1,123 +1,222 @@
|
|
|
1
|
-
# @qin-ui/antd-vue-pro
|
|
1
|
+
# @qin-ui/antd-vue-pro — AI Context
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Schema-driven component library wrapping **ant-design-vue v4** (`a-` prefix). Describe UIs as JS objects instead of template tag soup.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Architecture
|
|
8
|
+
|
|
9
|
+
### 1.1 Three-layer rendering
|
|
6
10
|
|
|
7
|
-
```bash
|
|
8
|
-
npm install @qin-ui/antd-vue-pro ant-design-vue vue
|
|
9
11
|
```
|
|
12
|
+
Field[] config layer { path:'name', component:'input', span:8, label:'Name', placeholder:'...' }
|
|
13
|
+
│
|
|
14
|
+
@qin-ui/antd-vue-pro Schema parser — strips props layer by layer
|
|
15
|
+
│
|
|
16
|
+
ant-design-vue v4 a-input / a-select / a-table / a-form-item / a-col ...
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
ProForm/ProTable are **rendering engines**, not a component library. All actual UI comes from ant-design-vue. Field props are peeled off and dispatched to different DOM layers.
|
|
20
|
+
|
|
21
|
+
### 1.2 Component resolution
|
|
22
|
+
|
|
23
|
+
`Field.component` string → `componentMap` → ant-design-vue component.
|
|
24
|
+
|
|
25
|
+
If not found in the built-in map, the string is resolved against `ProComponentProvider` injected components; a Vue component object is rendered directly (used by `'custom'` internally).
|
|
10
26
|
|
|
11
|
-
|
|
27
|
+
### 1.3 Built-in component map
|
|
12
28
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
29
|
+
| Field `component` | ant-design-vue component | Key pass-through props (verify against https://antdv.com) |
|
|
30
|
+
| :--------------------- | :----------------------- | :------------------------------------------------------------------ |
|
|
31
|
+
| `'input'` | Input | placeholder, maxlength, allowClear, addonBefore, addonAfter, prefix, suffix, showCount |
|
|
32
|
+
| `'textarea'` | TextArea | rows, maxlength, showCount, autoSize |
|
|
33
|
+
| `'input-password'` | InputPassword | placeholder, maxlength, visibilityToggle |
|
|
34
|
+
| `'input-search'` | InputSearch | placeholder, loading, onSearch |
|
|
35
|
+
| `'input-number'` | InputNumber | min, max, step, precision, formatter, parser |
|
|
36
|
+
| `'select'` | Select | **options**, mode, showSearch, filterOption, allowClear, loading |
|
|
37
|
+
| `'cascader'` | Cascader | **options**, fieldNames, showSearch, allowClear |
|
|
38
|
+
| `'date-picker'` | DatePicker | picker, format, showTime, disabledDate, valueFormat |
|
|
39
|
+
| `'range-picker'` | RangePicker | format, showTime, disabledDate, allowClear |
|
|
40
|
+
| `'time-picker'` | TimePicker | format, showSecond, hourStep, minuteStep |
|
|
41
|
+
| `'checkbox-group'` | CheckboxGroup | **options**, direction |
|
|
42
|
+
| `'radio-group'` | RadioGroup | **options**, direction, buttonStyle |
|
|
43
|
+
| `'switch'` | Switch | checkedChildren, unCheckedChildren, loading |
|
|
44
|
+
| `'slider'` | Slider | min, max, step, marks, range, tooltip |
|
|
45
|
+
| `'tree-select'` | TreeSelect | **treeData**, showSearch, treeCheckable, fieldNames |
|
|
46
|
+
| `'transfer'` | Transfer | **dataSource**, **titles**, **targetKeys**, showSearch, render |
|
|
47
|
+
| `'custom'` | (user-supplied) | component receives a Vue component or `h()` render function |
|
|
48
|
+
|
|
49
|
+
> The prop column is illustrative. **Always verify prop names/types against [antdv.com](https://antdv.com).**
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 2. Property layering (core rule)
|
|
54
|
+
|
|
55
|
+
Field props are **stripped in layers** and dispatched to different DOM targets.
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
<a-col :span="8"> ← Grid layer
|
|
59
|
+
<a-form-item label="City"> ← FormItem layer
|
|
60
|
+
<a-select placeholder="..." /> ← Input-control layer
|
|
61
|
+
</a-form-item>
|
|
62
|
+
</a-col>
|
|
16
63
|
```
|
|
17
64
|
|
|
18
|
-
|
|
65
|
+
### 2.1 Layer dispatch
|
|
19
66
|
|
|
20
|
-
|
|
67
|
+
**Grid layer → `<a-col>`** (only when grid is enabled):
|
|
68
|
+
`span`, `order`, `offset`, `push`, `pull`, `flex`, `xs`, `sm`, `md`, `lg`, `xl`, `xxl`
|
|
21
69
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
| `ProForm` | 配置驱动表单组件 |
|
|
25
|
-
| `ProTable` | 配置驱动表格组件 |
|
|
26
|
-
| `ProComponentProvider` | 全局配置提供者 |
|
|
70
|
+
**FormItem layer → `<a-form-item>`**:
|
|
71
|
+
`label`, `rules`, `colon`, `labelAlign`, `labelCol`, `wrapperCol`, `tooltip`, `extra`, `help`, `validateFirst`, `validateTrigger`, `valuePropName`, `normalize`, `formItemClass`→`class`, `formItemStyle`→`style`, `formItemContainer`, `formItemDataAttrs`→`data-*`
|
|
27
72
|
|
|
28
|
-
|
|
73
|
+
**Input-control layer → the input component** (everything else):
|
|
74
|
+
`disabled`, `placeholder`, `allowClear`, `options`, `showSearch`, `maxlength`, `mode`, `componentClass`→`class`, `componentStyle`→`style`, `componentDataAttrs`→`data-*`, and any ant-design-vue props for that component.
|
|
29
75
|
|
|
30
|
-
|
|
31
|
-
| ------------------ | ------------ |
|
|
32
|
-
| `useForm<D>()` | 创建表单实例 |
|
|
33
|
-
| `useFields<D>()` | 字段配置管理 |
|
|
34
|
-
| `useFormRef()` | 表单组件引用 |
|
|
35
|
-
| `useTable<D, T>()` | 创建表格实例 |
|
|
76
|
+
**Consumed by ProForm logic, not bound to DOM**: `component`, `fields`, `hidden`, `slots`, `modelProp`, `valueFormatter`, `componentContainer`, `extraProps`.
|
|
36
77
|
|
|
37
|
-
|
|
78
|
+
### 2.2 modelProp
|
|
38
79
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const form = useForm
|
|
55
|
-
{ path: '
|
|
56
|
-
{ path: '
|
|
80
|
+
Controls the `v-model:xxx` binding name.
|
|
81
|
+
|
|
82
|
+
- Default: `modelProp: 'value'` → `v-model:value`
|
|
83
|
+
- Switch uses `checked` — **ProComponentProvider presets `modelProp: 'checked'` for `'switch'`** so you rarely set it manually.
|
|
84
|
+
- Override per-field when using a custom component that expects a different v-model prop.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 3. Progressive usage
|
|
89
|
+
|
|
90
|
+
### Level 1: Config-driven (no hand-written a-* tags)
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
import { ProForm, useForm } from '@qin-ui/antd-vue-pro';
|
|
94
|
+
|
|
95
|
+
const form = useForm({ username: '', password: '' }, [
|
|
96
|
+
{ path: 'username', component: 'input', label: '用户名', placeholder: '请输入', rules: [{ required: true }] },
|
|
97
|
+
{ path: 'password', component: 'input-password', label: '密码', placeholder: '请输入', rules: [{ required: true }] },
|
|
57
98
|
]);
|
|
58
|
-
</script>
|
|
59
99
|
```
|
|
60
100
|
|
|
61
|
-
|
|
101
|
+
```html
|
|
102
|
+
<ProForm :form="form" />
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Level 2: Field linkage
|
|
106
|
+
|
|
107
|
+
Control props (`disabled`, `hidden`, `rules`, etc.) support three reactivity patterns:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
// A) computed() — declarative, for linkages known at init (preferred)
|
|
111
|
+
disabled: computed(() => !form.formData.enabled),
|
|
112
|
+
rules: computed(() => [{ required: form.formData.hasLimit, message: '必填' }]),
|
|
113
|
+
|
|
114
|
+
// B) ref() — external shared state
|
|
115
|
+
const isDisabled = ref(false);
|
|
116
|
+
|
|
117
|
+
// C) setField() — imperative, for event-driven changes
|
|
118
|
+
form.setField('limitCount', { disabled: true });
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**Rule: pick the simplest. computed() for init-time, setField() for runtime events, ref() for external state.**
|
|
122
|
+
|
|
123
|
+
### Level 3: Custom component
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
import { h } from 'vue';
|
|
127
|
+
import CustomInput from './CustomInput.vue';
|
|
128
|
+
|
|
129
|
+
// In field config:
|
|
130
|
+
{ path: 'key', component: (p, ctx) => h(CustomInput, { ...p, ...ctx.attrs }) }
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Or via scoped slot in template (all binding params forwarded via `v-bind="scoped"`):
|
|
134
|
+
|
|
135
|
+
```html
|
|
136
|
+
<ProForm :form="form">
|
|
137
|
+
<template #agreement="scoped">
|
|
138
|
+
<a-checkbox v-bind="scoped">同意协议</a-checkbox>
|
|
139
|
+
</template>
|
|
140
|
+
</ProForm>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## 4. Anti-patterns
|
|
146
|
+
|
|
147
|
+
- **Never hand-write `<a-form-item>` inside `<ProForm>`.** ProForm renders FormItems from Field config automatically.
|
|
148
|
+
- **Never guess pass-through prop names.** Verify against [ant-design-vue docs](https://antdv.com).
|
|
149
|
+
- **Don't confuse Grid props with input props.** `span` goes to `<a-col>`, not the input.
|
|
150
|
+
- **Use `computed()` for reactive Field configs.** Plain values won't track dependencies.
|
|
151
|
+
- **Prefer the simplest linkage pattern.** Don't use `setField()` when `computed()` suffices.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## 5. ProComponentProvider — global defaults
|
|
156
|
+
|
|
157
|
+
Wrap your app to set defaults for all ProForm/ProTable instances. Merged with priority (highest first):
|
|
158
|
+
|
|
159
|
+
1. **Field-level config** (always wins)
|
|
160
|
+
2. **`componentVars`** passed to ProComponentProvider
|
|
161
|
+
3. **`INJECT_CONFIG`** built-in presets
|
|
162
|
+
|
|
163
|
+
### Built-in presets (INJECT_CONFIG)
|
|
164
|
+
|
|
165
|
+
| Component | Preset |
|
|
166
|
+
| :--------------------------------------------- | :----------------------------------------------------------------------------- |
|
|
167
|
+
| `switch` | `{ modelProp: 'checked' }` |
|
|
168
|
+
| `input` | `{ maxlength: 100, allowClear: true, placeholder: '请输入' }` |
|
|
169
|
+
| `textarea` | `{ maxlength: 200, autoSize: {minRows:3,maxRows:6}, showCount: true, allowClear: true, placeholder: '请输入' }` |
|
|
170
|
+
| `select` / `cascader` | `{ allowClear: true, placeholder: '请选择', getPopupContainer }` |
|
|
171
|
+
| `input-number` | `{ max: 10^15, min: -(10^15), controls: false, placeholder: '请输入', style: {width:'100%'} }` |
|
|
172
|
+
| `date-picker` / `range-picker` / `time-picker` | `{ allowClear: true, getPopupContainer, style: {width:'100%'} }` |
|
|
173
|
+
| `pro-table` | `{ pagination: {showTotal, showSizeChanger, showQuickJumper}, searchFormConfig: {layout:'grid'}, control: true, addIndexColumn: true }` |
|
|
174
|
+
| `pro-form` | `{ grid: { gutter: {xs:8, sm:16, md:16, lg:24} } }` |
|
|
175
|
+
| `pro-form-item` | `{ validateFirst: true, span: 8 }` |
|
|
176
|
+
|
|
177
|
+
### Override example
|
|
62
178
|
|
|
63
179
|
```vue
|
|
64
|
-
<
|
|
180
|
+
<ProComponentProvider :component-vars="{
|
|
181
|
+
'pro-form-item': { span: 6 },
|
|
182
|
+
input: { maxlength: 200 },
|
|
183
|
+
select: { showSearch: true },
|
|
184
|
+
'pro-table': { addIndexColumn: false },
|
|
185
|
+
}">
|
|
186
|
+
<ProForm :form="form" />
|
|
65
187
|
<ProTable :table="table" />
|
|
66
|
-
</
|
|
188
|
+
</ProComponentProvider>
|
|
189
|
+
```
|
|
67
190
|
|
|
68
|
-
|
|
69
|
-
interface User {
|
|
70
|
-
name: string;
|
|
71
|
-
age: number;
|
|
72
|
-
}
|
|
191
|
+
---
|
|
73
192
|
|
|
74
|
-
|
|
193
|
+
## 6. ProTable quick reference
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
import { ProTable, useTable } from '@qin-ui/antd-vue-pro';
|
|
197
|
+
|
|
198
|
+
const table = useTable<Row>({
|
|
75
199
|
columns: [
|
|
76
|
-
{
|
|
77
|
-
{
|
|
200
|
+
{ title: 'ID', dataIndex: 'id', width: 80 },
|
|
201
|
+
{ title: 'Name', dataIndex: 'name', width: 120 },
|
|
202
|
+
],
|
|
203
|
+
// searchFields uses the same Field[] format as ProForm
|
|
204
|
+
searchFields: [
|
|
205
|
+
{ path: 'name', component: 'input', placeholder: 'Search' },
|
|
206
|
+
{ path: 'status', component: 'select', options: [...] },
|
|
78
207
|
],
|
|
79
|
-
dataSource: [],
|
|
80
208
|
});
|
|
81
|
-
|
|
209
|
+
// table.searchForm is a ProForm instance — all form methods available
|
|
82
210
|
```
|
|
83
211
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
每个字段支持以下属性:
|
|
87
|
-
|
|
88
|
-
- `path` - 数据路径(类型安全)
|
|
89
|
-
- `label` - 字段标签
|
|
90
|
-
- `component` - 组件名(内置支持: input, select, date-picker, cascader 等)
|
|
91
|
-
- `hidden` - 是否隐藏
|
|
92
|
-
- `disabled` - 是否禁用
|
|
93
|
-
- `rules` - 校验规则
|
|
94
|
-
- `valueFormatter` - 值格式化函数
|
|
95
|
-
- `fields` - 嵌套子字段
|
|
96
|
-
- `grid` - 网格布局
|
|
97
|
-
- `slots` - FormItem 插槽配置
|
|
98
|
-
- `componentStyle/componentClass` - 组件样式
|
|
99
|
-
- `componentContainer` - 组件容器包装
|
|
100
|
-
- `formItemStyle/formItemClass` - FormItem 样式
|
|
101
|
-
- `formItemContainer` - FormItem 容器包装
|
|
102
|
-
- `modelProp` - v-model 绑定属性名
|
|
103
|
-
|
|
104
|
-
完整类型定义见 `Field<ComponentName, D>`。
|
|
105
|
-
|
|
106
|
-
## 表格列配置(Column)
|
|
107
|
-
|
|
108
|
-
每列支持以下属性:
|
|
109
|
-
|
|
110
|
-
- `dataIndex` - 数据路径(优先使用)
|
|
111
|
-
- `key` - 列标识(dataIndex 不满足时使用)
|
|
112
|
-
- `hidden` - 是否隐藏
|
|
113
|
-
- 所有 ant-design-vue ColumnType 属性(title, width, fixed, align 等)
|
|
114
|
-
|
|
115
|
-
## 类型扩展
|
|
116
|
-
|
|
117
|
-
```typescript
|
|
118
|
-
declare module '@qin-ui/antd-vue-pro' {
|
|
119
|
-
interface ComponentMap {
|
|
120
|
-
'my-custom-component': typeof MyComponent;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
212
|
+
```html
|
|
213
|
+
<ProTable :table="table" :search="fetchData" addIndexColumn immediateSearch />
|
|
123
214
|
```
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## 7. References
|
|
219
|
+
|
|
220
|
+
1. **`node_modules/@qin-ui/antd-vue-pro/api.json`** — Structured API metadata (signatures, types, JSDoc examples)
|
|
221
|
+
2. **`node_modules/@qin-ui/antd-vue-pro/README.md`** — Full usage docs and code examples
|
|
222
|
+
3. **[antdv.com](https://antdv.com)** — ant-design-vue component API reference (always check before writing pass-through props)
|
package/api.json
CHANGED
package/bin/init-ai.mjs
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @qin-ui/antd-vue-pro AI 上下文初始化 CLI 工具
|
|
5
|
+
*
|
|
6
|
+
* 在消费方项目中生成分层 AI 上下文文件,使 AI 工具能够:
|
|
7
|
+
* 1. 理解 @qin-ui/antd-vue-pro 的 Schema 驱动架构
|
|
8
|
+
* 2. 掌握属性透传规则(何时查阅 ant-design-vue 文档)
|
|
9
|
+
* 3. 快速获取完整 API 参考
|
|
10
|
+
*
|
|
11
|
+
* 用法:
|
|
12
|
+
* npx @qin-ui/antd-vue-pro init-ai
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import fs from 'node:fs';
|
|
16
|
+
import path from 'node:path';
|
|
17
|
+
import { fileURLToPath } from 'node:url';
|
|
18
|
+
|
|
19
|
+
// ==================== 常量 ====================
|
|
20
|
+
|
|
21
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
22
|
+
const __dirname = path.dirname(__filename);
|
|
23
|
+
const PKG_ROOT = path.resolve(__dirname, '..');
|
|
24
|
+
|
|
25
|
+
const PKG_JSON = JSON.parse(
|
|
26
|
+
fs.readFileSync(path.join(PKG_ROOT, 'package.json'), 'utf-8')
|
|
27
|
+
);
|
|
28
|
+
const PKG_NAME = PKG_JSON.name;
|
|
29
|
+
const PKG_SHORT = PKG_NAME.replace(/^@qin-ui\//, '');
|
|
30
|
+
|
|
31
|
+
// ==================== 终端颜色 ====================
|
|
32
|
+
|
|
33
|
+
const green = s => `\x1b[32m${s}\x1b[0m`;
|
|
34
|
+
const cyan = s => `\x1b[36m${s}\x1b[0m`;
|
|
35
|
+
const bold = s => `\x1b[1m${s}\x1b[0m`;
|
|
36
|
+
const yellow = s => `\x1b[33m${s}\x1b[0m`;
|
|
37
|
+
const dim = s => `\x1b[2m${s}\x1b[0m`;
|
|
38
|
+
|
|
39
|
+
// ==================== 内容读取 ====================
|
|
40
|
+
|
|
41
|
+
function readPackageFile(filename) {
|
|
42
|
+
const filePath = path.join(PKG_ROOT, filename);
|
|
43
|
+
if (fs.existsSync(filePath)) {
|
|
44
|
+
return fs.readFileSync(filePath, 'utf-8').trim();
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function getAiContextContent() {
|
|
50
|
+
return readPackageFile('AI-CONTEXT.md') || `# ${PKG_NAME}\n\n> 基于 Vue 3 的配置驱动组件库。`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function getReadmeContent() {
|
|
54
|
+
return readPackageFile('README.md') || '';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function getApiJsonContent() {
|
|
58
|
+
try {
|
|
59
|
+
const raw = readPackageFile('api.json');
|
|
60
|
+
if (!raw) return null;
|
|
61
|
+
return JSON.parse(raw);
|
|
62
|
+
} catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ==================== 内容生成 ====================
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* 生成 rules 文件内容(Instructions 层)
|
|
71
|
+
* 包含:架构关系、透传规则、反模式、ant-design-vue 资源链接
|
|
72
|
+
*/
|
|
73
|
+
function getRulesContent() {
|
|
74
|
+
const aiContext = getAiContextContent();
|
|
75
|
+
|
|
76
|
+
return [
|
|
77
|
+
'---',
|
|
78
|
+
`description: "${PKG_NAME} 组件库使用规范 — Schema 驱动、属性透传规则"`,
|
|
79
|
+
'globs: ["**/*.vue", "**/*.ts", "**/*.tsx"]',
|
|
80
|
+
'alwaysApply: false',
|
|
81
|
+
'---',
|
|
82
|
+
'',
|
|
83
|
+
aiContext,
|
|
84
|
+
'',
|
|
85
|
+
'---',
|
|
86
|
+
'',
|
|
87
|
+
'## 本地参考文件',
|
|
88
|
+
'',
|
|
89
|
+
'本规则文件提供了核心架构和用法指南。需要完整 API 参考或底层组件文档时,请阅读以下资源:',
|
|
90
|
+
'',
|
|
91
|
+
`- **\`.agents/docs/${PKG_SHORT}-api.md\`** — 完整 API 文档(组件、Hooks、类型、Field 配置参考)`,
|
|
92
|
+
`- **\`node_modules/${PKG_NAME}/api.json\`** — 结构化 API 元数据(函数签名、类型定义)`,
|
|
93
|
+
'',
|
|
94
|
+
'## 底层组件文档',
|
|
95
|
+
'',
|
|
96
|
+
`${PKG_NAME} 基于 **ant-design-vue**(v4,\`a-\` 前缀)封装。编写 Field 中的输入控件属性前,请查阅 ant-design-vue 官方文档确认属性名和类型:`,
|
|
97
|
+
'',
|
|
98
|
+
'- **[ant-design-vue 官方文档](https://antdv.com)** — 组件 API 参考(中文)',
|
|
99
|
+
'',
|
|
100
|
+
].join('\n');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* 生成 API 文档内容(Resources 层)
|
|
105
|
+
* 从 README.md + api.json 合并提取完整 API 参考
|
|
106
|
+
*/
|
|
107
|
+
function getApiDocContent() {
|
|
108
|
+
const readme = getReadmeContent();
|
|
109
|
+
const apiJson = getApiJsonContent();
|
|
110
|
+
|
|
111
|
+
const sections = [];
|
|
112
|
+
|
|
113
|
+
sections.push(`# ${PKG_NAME} — 完整 API 参考`, '');
|
|
114
|
+
sections.push(`> 自动生成自 README.md 和 api.json。版本: ${PKG_JSON.version}`, '');
|
|
115
|
+
|
|
116
|
+
// README 内容(已包含完整的使用文档)
|
|
117
|
+
if (readme) {
|
|
118
|
+
sections.push(readme);
|
|
119
|
+
sections.push('');
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// 结构化 API 元数据
|
|
123
|
+
if (apiJson && apiJson.api && apiJson.api.length > 0) {
|
|
124
|
+
sections.push('---');
|
|
125
|
+
sections.push('');
|
|
126
|
+
sections.push('## 结构化 API 元数据(自动提取自源码 JSDoc)');
|
|
127
|
+
sections.push('');
|
|
128
|
+
|
|
129
|
+
for (const item of apiJson.api) {
|
|
130
|
+
const typeLabel = {
|
|
131
|
+
component: '组件',
|
|
132
|
+
function: '函数/Hook',
|
|
133
|
+
type: '类型',
|
|
134
|
+
interface: '接口',
|
|
135
|
+
constant: '常量',
|
|
136
|
+
}[item.type] || '';
|
|
137
|
+
|
|
138
|
+
sections.push(`### ${typeLabel} \`${item.name}\``);
|
|
139
|
+
sections.push('');
|
|
140
|
+
sections.push(`**类型:** ${item.type}`);
|
|
141
|
+
if (item.signature) {
|
|
142
|
+
sections.push('');
|
|
143
|
+
sections.push('```typescript');
|
|
144
|
+
sections.push(item.signature);
|
|
145
|
+
sections.push('```');
|
|
146
|
+
}
|
|
147
|
+
if (item.description) {
|
|
148
|
+
sections.push('');
|
|
149
|
+
sections.push(item.description);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (item.typeParams && item.typeParams.length > 0) {
|
|
153
|
+
sections.push('');
|
|
154
|
+
sections.push('**泛型参数:**');
|
|
155
|
+
for (const tp of item.typeParams) {
|
|
156
|
+
const extras = [];
|
|
157
|
+
if (tp.extends) extras.push(`extends ${tp.extends}`);
|
|
158
|
+
if (tp.default) extras.push(`默认 ${tp.default}`);
|
|
159
|
+
const extra = extras.length ? ` (${extras.join(', ')})` : '';
|
|
160
|
+
sections.push(`- \`${tp.name}\`${extra}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (item.params && item.params.length > 0) {
|
|
165
|
+
sections.push('');
|
|
166
|
+
sections.push('**参数:**');
|
|
167
|
+
sections.push('');
|
|
168
|
+
sections.push('| 参数名 | 类型 | 可选 | 描述 |');
|
|
169
|
+
sections.push('| :--- | :--- | :--- | :--- |');
|
|
170
|
+
for (const p of item.params) {
|
|
171
|
+
sections.push(`| \`${p.name}\` | \`${p.type}\` | ${p.optional ? '是' : '否'} | ${p.description} |`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (item.returns) {
|
|
176
|
+
sections.push('');
|
|
177
|
+
sections.push(`**返回值:** ${item.returns}`);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (item.examples && item.examples.length > 0) {
|
|
181
|
+
sections.push('');
|
|
182
|
+
sections.push('**示例:**');
|
|
183
|
+
for (const ex of item.examples) {
|
|
184
|
+
sections.push('');
|
|
185
|
+
sections.push(ex);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
sections.push('');
|
|
190
|
+
sections.push('---');
|
|
191
|
+
sections.push('');
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return sections.join('\n');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// ==================== 文件写入 ====================
|
|
199
|
+
|
|
200
|
+
function ensureDir(dirPath) {
|
|
201
|
+
if (!fs.existsSync(dirPath)) {
|
|
202
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function writeFileWithLog(filePath, content, label) {
|
|
207
|
+
const dir = path.dirname(filePath);
|
|
208
|
+
ensureDir(dir);
|
|
209
|
+
const existed = fs.existsSync(filePath);
|
|
210
|
+
fs.writeFileSync(filePath, content, 'utf-8');
|
|
211
|
+
const status = existed ? yellow('[更新]') : green('[创建]');
|
|
212
|
+
console.log(` ${status} ${cyan(label)}`);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// ==================== CLI 入口 ====================
|
|
216
|
+
|
|
217
|
+
function printHelp() {
|
|
218
|
+
console.log(`
|
|
219
|
+
${bold(`${PKG_NAME} CLI — AI 上下文初始化`)}
|
|
220
|
+
|
|
221
|
+
${bold('用法:')}
|
|
222
|
+
npx ${PKG_NAME} init-ai
|
|
223
|
+
|
|
224
|
+
${bold('说明:')}
|
|
225
|
+
在项目中生成分层 AI 上下文文件,使 AI 工具能够深度理解和规范使用 ${PKG_NAME}。
|
|
226
|
+
|
|
227
|
+
生成的文件结构:
|
|
228
|
+
.agents/
|
|
229
|
+
rules/
|
|
230
|
+
${PKG_SHORT}.md 规则文件(架构、透传规则、反模式)
|
|
231
|
+
docs/
|
|
232
|
+
${PKG_SHORT}-api.md API 参考(完整文档 + 结构化元数据)
|
|
233
|
+
|
|
234
|
+
${bold('选项:')}
|
|
235
|
+
--help 显示帮助信息
|
|
236
|
+
`);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function main() {
|
|
240
|
+
const args = process.argv.slice(2);
|
|
241
|
+
const subcommand = args.find(a => !a.startsWith('-'));
|
|
242
|
+
const flags = args.filter(a => a.startsWith('-'));
|
|
243
|
+
|
|
244
|
+
if (!subcommand || flags.includes('--help') || flags.includes('-h')) {
|
|
245
|
+
printHelp();
|
|
246
|
+
process.exit(0);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (subcommand !== 'init-ai') {
|
|
250
|
+
console.error(`\n ❌ 未知命令: ${subcommand}\n`);
|
|
251
|
+
printHelp();
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
console.log('');
|
|
256
|
+
console.log(bold(`📦 ${PKG_NAME} — AI 上下文初始化 v${PKG_JSON.version}`));
|
|
257
|
+
console.log(dim(` 基于 ant-design-vue 的 Schema 驱动组件库`));
|
|
258
|
+
console.log('');
|
|
259
|
+
|
|
260
|
+
// 1. 生成 Rules 文件
|
|
261
|
+
console.log(bold('📋 规则层 (Rules)'));
|
|
262
|
+
const rulesContent = getRulesContent();
|
|
263
|
+
writeFileWithLog(
|
|
264
|
+
path.join(process.cwd(), '.agents/rules', `${PKG_SHORT}.md`),
|
|
265
|
+
rulesContent,
|
|
266
|
+
`.agents/rules/${PKG_SHORT}.md`
|
|
267
|
+
);
|
|
268
|
+
console.log(dim(' → 架构概览、属性透传决策树、渐进用法、反模式'));
|
|
269
|
+
console.log('');
|
|
270
|
+
|
|
271
|
+
// 2. 生成 API 文档
|
|
272
|
+
console.log(bold('📖 参考层 (Docs)'));
|
|
273
|
+
const apiDocContent = getApiDocContent();
|
|
274
|
+
writeFileWithLog(
|
|
275
|
+
path.join(process.cwd(), '.agents/docs', `${PKG_SHORT}-api.md`),
|
|
276
|
+
apiDocContent,
|
|
277
|
+
`.agents/docs/${PKG_SHORT}-api.md`
|
|
278
|
+
);
|
|
279
|
+
console.log(dim(' → 完整 README 文档 + 结构化 API 元数据'));
|
|
280
|
+
console.log('');
|
|
281
|
+
|
|
282
|
+
// 3. 完成提示
|
|
283
|
+
console.log(green('✅ 完成!已生成分层 AI 上下文文件。'));
|
|
284
|
+
console.log('');
|
|
285
|
+
console.log(`${bold('📂 生成的文件:')}`);
|
|
286
|
+
console.log(` ${cyan('.agents/')}`);
|
|
287
|
+
console.log(` ├── ${cyan('rules/')}`);
|
|
288
|
+
console.log(` │ └── ${cyan(PKG_SHORT + '.md')} ${dim('← 核心规则(AI 优先读取)')}`);
|
|
289
|
+
console.log(` └── ${cyan('docs/')}`);
|
|
290
|
+
console.log(` └── ${cyan(PKG_SHORT + '-api.md')} ${dim('← 完整 API 参考')}`);
|
|
291
|
+
console.log('');
|
|
292
|
+
|
|
293
|
+
console.log(`${bold('🔄 建议的下一步:')}`);
|
|
294
|
+
console.log(` 1. 提交 ${cyan('.agents/')} 目录到 Git 仓库,团队共享`);
|
|
295
|
+
console.log(` 2. 编写 Field 配置中的输入控件属性前,查阅 ant-design-vue 官方文档:`);
|
|
296
|
+
console.log(` ${cyan('https://antdv.com')}`);
|
|
297
|
+
console.log(` 3. ${dim('(可选)查看完整 API 参考:')}`);
|
|
298
|
+
console.log(` ${dim(`cat .agents/docs/${PKG_SHORT}-api.md`)}`);
|
|
299
|
+
console.log('');
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
main();
|
package/es/antd-vue-pro.css
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
.pro-table_search-form[data-v-
|
|
1
|
+
.pro-table_search-form[data-v-b023c914] [class*='-form-item'] {
|
|
2
2
|
margin: 0;
|
|
3
3
|
}
|
|
4
|
-
.pro-table_search-form_expand-toggle-button[data-v-
|
|
4
|
+
.pro-table_search-form_expand-toggle-button[data-v-b023c914] {
|
|
5
5
|
display: flex;
|
|
6
6
|
align-items: center;
|
|
7
7
|
padding: 0;
|
|
8
8
|
padding-left: 4px;
|
|
9
9
|
}
|
|
10
|
-
.pro-table_search-form .transition[data-v-
|
|
10
|
+
.pro-table_search-form .transition[data-v-b023c914] {
|
|
11
11
|
transition: all 0.25s;
|
|
12
12
|
}
|
|
13
13
|
.pro-table_search-form-container[data-v-c385cd54] {
|
package/es/table/index.js
CHANGED
|
@@ -230,7 +230,7 @@ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
|
|
|
230
230
|
};
|
|
231
231
|
}
|
|
232
232
|
});
|
|
233
|
-
const SearchForm = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-
|
|
233
|
+
const SearchForm = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-b023c914"]]);
|
|
234
234
|
const _sfc_main$6 = /* @__PURE__ */ defineComponent({
|
|
235
235
|
__name: "DefaultSearchFormContainer",
|
|
236
236
|
setup(__props) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qin-ui/antd-vue-pro",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.15",
|
|
4
4
|
"description": "二次封装antd vue组件",
|
|
5
|
+
"bin": {
|
|
6
|
+
"antd-vue-pro": "./bin/init-ai.mjs"
|
|
7
|
+
},
|
|
5
8
|
"type": "module",
|
|
6
9
|
"module": "es/index.js",
|
|
7
10
|
"types": "es/index.d.ts",
|
|
@@ -14,6 +17,7 @@
|
|
|
14
17
|
},
|
|
15
18
|
"files": [
|
|
16
19
|
"es",
|
|
20
|
+
"bin",
|
|
17
21
|
"README.md",
|
|
18
22
|
"LICENSE",
|
|
19
23
|
"api.json",
|