@qin-ui/antd-vue-pro 2.2.2 → 2.2.4

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 CHANGED
@@ -1,236 +1,164 @@
1
- # @qin-ui/antd-vue-pro — AI Context
1
+ # @qin-ui/antd-vue-pro
2
2
 
3
- > Schema-driven component library wrapping **ant-design-vue v4** (`a-` prefix). Describe UIs as JS objects instead of template tag soup.
3
+ 基于 ant-design-vue v4(`a-` 前缀)封装的 Schema 驱动组件库。
4
+ 用 JS 配置对象描述 UI,不写 `<a-*>` 模板堆叠。ProForm/ProTable 是渲染引擎,所有真实 UI 来自 ant-design-vue。
4
5
 
5
- ---
6
+ ## 安装与使用
6
7
 
7
- ## 1. Architecture
8
-
9
- ### 1.1 Three-layer rendering
10
-
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 ...
8
+ ```bash
9
+ pnpm add @qin-ui/antd-vue-pro # peerDeps: ant-design-vue ^4, vue ^3.5
17
10
  ```
18
11
 
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.
12
+ ```ts
13
+ // 按需引入(推荐)
14
+ import { ProForm, ProTable, useForm, useTable } from '@qin-ui/antd-vue-pro';
15
+ ```
20
16
 
21
- ### 1.2 Component resolution
17
+ ## 核心心智模型
22
18
 
23
- `Field.component` string → `componentMap` → ant-design-vue component.
19
+ **1. 配置驱动**:`useForm(数据, Field[])` / `useTable({ columns, searchFields })` 生成实例,组件接收实例。
24
20
 
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).
21
+ **2. 属性分层透传**(最关键):Field 上的属性被"剥离到不同 DOM 层",不是全塞给输入控件。写错层就失效:
26
22
 
27
- ### 1.3 Built-in component map
23
+ | 属性 | 落到哪一层 | 说明 |
24
+ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------- | :------------- |
25
+ | `span`/`offset`/`push`/`pull`/`flex`/`xs..xxl` | `<a-col>` Grid 层 | 仅 grid 开启时 |
26
+ | `label`/`rules`/`tooltip`/`colon`/`labelAlign`/`labelCol`/`wrapperCol`/`extra`/`help`/`validateFirst`/`validateTrigger`/`valuePropName`/`normalize`/`required`/`formItemClass`/`formItemStyle`/`formItemDataAttrs` | `<a-form-item>` 层 | 表单项 |
27
+ | `disabled`/`placeholder`/`allowClear`/`options`/`mode`/`maxlength`/`componentClass`/`componentStyle`/`componentDataAttrs` + 该控件其余 ant 原生属性 | 输入控件本身(a-input 等) | 其余全部 |
28
+ | `component`/`hidden`/`modelProp`/`valueFormatter`/`fields`/`slots`/`formItemContainer`/`componentContainer`/`extraProps` | ProForm 逻辑消费,**不绑到 DOM** | 框架级 |
28
29
 
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 |
30
+ > 规则:`span` 给 Grid,`label`/`rules` 给 FormItem,其余给输入控件。
48
31
 
49
- > The prop column is illustrative. **Always verify prop names/types against [antdv.com](https://antdv.com).**
32
+ ## 速查
50
33
 
51
- ---
34
+ ### component 映射(Field.component 字符串 -> ant-design-vue 组件)
52
35
 
53
- ## 2. Property layering (core rule)
36
+ `input`->Input · `textarea`->TextArea · `input-password`->InputPassword · `input-search`->InputSearch ·
37
+ `input-number`->InputNumber · `select`->Select · `cascader`->Cascader · `date-picker`->DatePicker ·
38
+ `range-picker`->RangePicker · `time-picker`->TimePicker · `checkbox-group`->CheckboxGroup ·
39
+ `radio-group`->RadioGroup · `switch`->Switch · `slider`->Slider · `tree-select`->TreeSelect ·
40
+ `transfer`->Transfer · `custom`->用户自定义组件
54
41
 
55
- Field props are **stripped in layers** and dispatched to different DOM targets.
42
+ > 写 Field 中输入控件的具体属性前,**属性名/类型以 https://antdv.com 官方文档为准**。
56
43
 
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>
63
- ```
44
+ ### 隐式默认行为(INJECT_CONFIG,易踩坑)
64
45
 
65
- ### 2.1 Layer dispatch
46
+ 由 `ProComponentProvider` 注入,优先级低于 Field 配置。**不写也有这些默认值,需知晓以免行为与预期不符:**
66
47
 
67
- **Grid layer → `<a-col>`** (only when grid is enabled):
68
- `span`, `order`, `offset`, `push`, `pull`, `flex`, `xs`, `sm`, `md`, `lg`, `xl`, `xxl`
48
+ | component | 默认预设 |
49
+ | :--------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
50
+ | `switch` | `{ modelProp: 'checked' }` -> v-model 绑 `checked` 而非 `value` |
51
+ | `input` / `input-password` | `{ maxlength: 100, allowClear: true, placeholder: '请输入' }` |
52
+ | `textarea` | `{ maxlength: 200, autoSize: {minRows:3,maxRows:6}, showCount: true, allowClear: true, placeholder: '请输入' }` |
53
+ | `input-number` | `{ max: 1e15-1, min: -(1e15+1), controls: false, placeholder: '请输入', style:{width:'100%'} }` |
54
+ | `select` / `cascader` | `{ allowClear: true, placeholder: '请选择', getPopupContainer }` |
55
+ | `date-picker` / `range-picker` / `time-picker` | `{ allowClear: true, getPopupContainer, style:{width:'100%'} }` |
56
+ | `pro-form` | `{ grid: { gutter: {xs:8, sm:16, md:16, lg:24} } }` |
57
+ | `pro-form-item` | `{ validateFirst: true, span: 8 }` |
58
+ | `pro-table` | `{ pagination:{showTotal, showSizeChanger, pageSizeOptions:['10','20','30','40','50','100'], showQuickJumper:true}, searchFormConfig:{layout:'grid', expand:{minExpandRows:2, expandStatus:false}}, control:true, addIndexColumn:true }` |
69
59
 
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-*`
60
+ > `modelProp` 控制 v-model 绑定名,默认 `'value'`->`v-model:value`。
61
+ > `date-picker` 支持按 picker 子类型分别预设:`date-picker.date` / `.week` / `.month` / `.year` / `.quarter`,默认值同上。
62
+ > `input-search` / `checkbox-group` / `radio-group` / `slider` / `tree-select` / `transfer` 无预设(`{}`)。
72
63
 
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.
64
+ ### 不支持响应式的属性(不能包 ref/computed)
75
65
 
76
- **Consumed by ProForm logic, not bound to DOM**: `component`, `fields`, `hidden`, `slots`, `modelProp`, `valueFormatter`, `componentContainer`, `extraProps`.
66
+ `component` / `formItemContainer` / `componentContainer` / `valueFormatter` / `fields` / `slots` / `modelProp`。
77
67
 
78
- ### 2.2 modelProp
68
+ ## 实例成员速查
79
69
 
80
- Controls the `v-model:xxx` binding name.
70
+ ### useForm -- 表单实例
81
71
 
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.
72
+ ```ts
73
+ useForm(initFormData, Field[], root = true) // 重载一(常用):初始数据 + 字段配置
74
+ useForm(true | false) // 重载二:仅拿实例(root)
75
+ ```
85
76
 
86
- ---
77
+ 返回 `Form` 实例(**`formData` 是 reactive 对象,不用 `.value`**):
87
78
 
88
- ## 3. Progressive usage
79
+ | 成员 | 说明 |
80
+ | :------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------- |
81
+ | `form.formData` | 响应式数据,可直接读写,支持深层路径 `formData.address.city` |
82
+ | `form.getFormData(path)` | 路径读取;无参返回 `undefined` |
83
+ | `form.setFormData(path, value)` / `setFormData(path, prev=>new)` | 路径写入,支持函数式 |
84
+ | `form.setFormData({...})` / `setFormData(prev => ({...prev, name:'新'}))` | 批量覆盖整个表单,支持函数式(先清空再写入) |
85
+ | `form.fields` | 字段配置数组(Ref) |
86
+ | `form.getField(path)` / `getField(fn)` | 字段查找,支持路径或查找函数;`{all:true}` 返回所有匹配数组 |
87
+ | `form.setField(path, patch)` / `setField(path, prev=>({...}))` | 字段增改查;默认合并,`{updateType:'rewrite'}` 覆盖;支持函数式更新;`{all:true}` 批量更新所有匹配 |
88
+ | `form.deleteField` / `form.appendField` / `form.prependField` / `form.getParentField` | 字段增删查;均支持 `{all:true}`;`appendField(undefined, f)` 末尾追加、`prependField(undefined, f)` 开头插入,入参可为数组 |
89
+ | `form.formRef` | 底层 ant Form 实例引用(Ref),`formRef.value?.validate()` / `.resetFields()` |
89
90
 
90
- ### Level 1: Config-driven (no hand-written a-\* tags)
91
+ ### useTable -- 表格实例
91
92
 
92
93
  ```ts
93
- import { ProForm, useForm } from '@qin-ui/antd-vue-pro';
94
-
95
- const form = useForm({ username: '', password: '' }, [
96
- {
97
- path: 'username',
98
- component: 'input',
99
- label: '用户名',
100
- placeholder: '请输入',
101
- rules: [{ required: true }],
102
- },
103
- {
104
- path: 'password',
105
- component: 'input-password',
106
- label: '密码',
107
- placeholder: '请输入',
108
- rules: [{ required: true }],
109
- },
110
- ]);
94
+ useTable({ columns, dataSource, pageParam, searchParam, searchFields });
111
95
  ```
112
96
 
113
- ```html
114
- <ProForm :form="form" />
115
- ```
97
+ 返回 `Table` 实例:
116
98
 
117
- ### Level 2: Field linkage
99
+ | 成员 | 说明 |
100
+ | :-------------------------------------------------------------------- | :----------------------------------------------------- |
101
+ | `table.columns` / `table.dataSource` | 列配置 / 数据源(Ref) |
102
+ | `table.pageParam` | 分页参数(reactive):`current` / `pageSize` / `total` |
103
+ | `table.searchForm` | 搜索表单实例(Form 类型,所有 useForm 方法可用) |
104
+ | `table.setColumn` / `deleteColumn` / `appendColumn` / `prependColumn` | 列增删改查(用法同 setField,支持 `{all:true}`) |
105
+ | `table.setPageParam(patch)` | 设置分页参数 |
106
+ | `table.resetQueryParams()` | 重置分页到第一页 + 恢复搜索条件到初始值 |
118
107
 
119
- Control props (`disabled`, `hidden`, `rules`, etc.) support three reactivity patterns:
108
+ ## 关键约定
120
109
 
121
- ```ts
122
- // A) computed() — declarative, for linkages known at init (preferred)
123
- disabled: computed(() => !form.formData.enabled),
124
- rules: computed(() => [{ required: form.formData.hasLimit, message: '必填' }]),
110
+ ### 自定义组件
125
111
 
126
- // B) ref() — external shared state
127
- const isDisabled = ref(false);
112
+ `Field.component` 解析优先级(高 -> 低):`teleport 插槽注入` > `ProComponentProvider.componentMap` > `内置 componentMap` > `原始 component 值`。
128
113
 
129
- // C) setField() — imperative, for event-driven changes
130
- form.setField('limitCount', { disabled: true });
131
- ```
114
+ 四种接入方式(完整代码见 skills):
115
+
116
+ - **方式 1** `markRaw(SFC)`:单字段复用 SFC(**必须 markRaw**,否则被 Vue 深度代理触发性能警告)
117
+ - **方式 2** render 函数 `(props, ctx) => VNode`:需动态拼装 props
118
+ - **方式 3** `ProComponentProvider` 注入 `componentMap`:全局复用 / 覆盖内置组件,可追加 `declare module` 声明获强类型
119
+ - **方式 4** 模板 scoped slot:插槽名 = 字段 `path`,`v-bind="scoped"` 转发(teleport 机制,优先级最高)
132
120
 
133
- **Rule: pick the simplest. computed() for init-time, setField() for runtime events, ref() for external state.**
121
+ 约定:默认 v-model 绑 `value`,他 prop 用 `modelProp` 指定;组件会收到 `path` prop;除框架级属性外其余作 attrs 透传。
134
122
 
135
- ### Level 3: Custom component
123
+ ### valueFormatter -- 字段值转换
124
+
125
+ 控制表单值与组件值之间的转换。**在表单数据写入前(computed setter 中)执行**,支持两种形态:
136
126
 
137
127
  ```ts
138
- import { h } from 'vue';
139
- import CustomInput from './CustomInput.vue';
128
+ // 函数形态:(新值, 旧值) => 转换后的值,写回 formData。仅 set(写入)方向生效,读取时不转换
129
+ { path: 'name', valueFormatter: (val, oldVal) => val?.trim() }
140
130
 
141
- // In field config:
142
- { path: 'key', component: (p, ctx) => h(CustomInput, { ...p, ...ctx.attrs }) }
131
+ // 对象形态:get 读出时转换,set 写入时转换(双向)
132
+ { path: 'birthday', component: 'date-picker',
133
+ valueFormatter: { get: v => v ? dayjs(v) : null, set: v => v ? dayjs(v).format('YYYY-MM-DD') : null } }
143
134
  ```
144
135
 
145
- Or via scoped slot in template (all binding params forwarded via `v-bind="scoped"`):
136
+ ### ProTable -- 配置驱动表格
146
137
 
147
- ```html
148
- <ProForm :form="form">
149
- <template #agreement="scoped">
150
- <a-checkbox v-bind="scoped">同意协议</a-checkbox>
151
- </template>
152
- </ProForm>
153
- ```
138
+ 透传所有 ant-design-vue `TableProps`(`& TableProps`),可直接写 `row-key` / `bordered` / `scroll` / `row-selection` 等原生属性;`size`、`loading` 是 v-model。
154
139
 
155
- ---
156
-
157
- ## 4. Anti-patterns
158
-
159
- - **Never hand-write `<a-form-item>` inside `<ProForm>`.** ProForm renders FormItems from Field config automatically.
160
- - **Never guess pass-through prop names.** Verify against [ant-design-vue docs](https://antdv.com).
161
- - **Don't confuse Grid props with input props.** `span` goes to `<a-col>`, not the input.
162
- - **Use `computed()` for reactive Field configs.** Plain values won't track dependencies.
163
- - **Prefer the simplest linkage pattern.** Don't use `setField()` when `computed()` suffices.
164
-
165
- ---
166
-
167
- ## 5. ProComponentProvider — global defaults
168
-
169
- Wrap your app to set defaults for all ProForm/ProTable instances. Merged with priority (highest first):
170
-
171
- 1. **Field-level config** (always wins)
172
- 2. **`componentVars`** passed to ProComponentProvider
173
- 3. **`INJECT_CONFIG`** built-in presets
174
-
175
- ### Built-in presets (INJECT_CONFIG)
176
-
177
- | Component | Preset |
178
- | :--------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------- |
179
- | `switch` | `{ modelProp: 'checked' }` |
180
- | `input` | `{ maxlength: 100, allowClear: true, placeholder: '请输入' }` |
181
- | `textarea` | `{ maxlength: 200, autoSize: {minRows:3,maxRows:6}, showCount: true, allowClear: true, placeholder: '请输入' }` |
182
- | `select` / `cascader` | `{ allowClear: true, placeholder: '请选择', getPopupContainer }` |
183
- | `input-number` | `{ max: 10^15, min: -(10^15), controls: false, placeholder: '请输入', style: {width:'100%'} }` |
184
- | `date-picker` / `range-picker` / `time-picker` | `{ allowClear: true, getPopupContainer, style: {width:'100%'} }` |
185
- | `pro-table` | `{ pagination: {showTotal, showSizeChanger, showQuickJumper}, searchFormConfig: {layout:'grid'}, control: true, addIndexColumn: true }` |
186
- | `pro-form` | `{ grid: { gutter: {xs:8, sm:16, md:16, lg:24} } }` |
187
- | `pro-form-item` | `{ validateFirst: true, span: 8 }` |
188
-
189
- ### Override example
190
-
191
- ```vue
192
- <ProComponentProvider
193
- :component-vars="{
194
- 'pro-form-item': { span: 6 },
195
- input: { maxlength: 200 },
196
- select: { showSearch: true },
197
- 'pro-table': { addIndexColumn: false },
198
- }"
199
- >
200
- <ProForm :form="form" />
201
- <ProTable :table="table" />
202
- </ProComponentProvider>
203
- ```
140
+ 关键 prop:`table`(useTable 实例)、`search`(数据查询方法 `() => Promise`,ProTable 内部调用,非自动触发)、`addIndexColumn`、`immediateSearch`、`control`、`searchFormConfig`(含 `hidden`/`container`/`layout`/`expand`)、`tableContainer`。
204
141
 
205
- ---
142
+ **数据流**:搜索->重置分页到第 1 页->调 `search()`;分页/排序变化->更新 `pageParam`->调 `search()`;重置->`resetQueryParams()`->调 `search()`。
206
143
 
207
- ## 6. ProTable quick reference
144
+ ### Column -- 列配置
208
145
 
209
- ```ts
210
- import { ProTable, useTable } from '@qin-ui/antd-vue-pro';
211
-
212
- const table = useTable<Row>({
213
- columns: [
214
- { title: 'ID', dataIndex: 'id', width: 80 },
215
- { title: 'Name', dataIndex: 'name', width: 120 },
216
- ],
217
- // searchFields uses the same Field[] format as ProForm
218
- searchFields: [
219
- { path: 'name', component: 'input', placeholder: 'Search' },
220
- { path: 'status', component: 'select', options: [...] },
221
- ],
222
- });
223
- // table.searchForm is a ProForm instance — all form methods available
224
- ```
146
+ 继承 ant-design-vue `ColumnType`,所有原生列属性可用。新增:`dataIndex`(列数据路径,主用,支持 `'name'` / `'address.city'` / `['address','city']`)、`key`(辅助标识,优先级更低)、`hidden`(隐藏该列,配合列控制)。
225
147
 
226
- ```html
227
- <ProTable :table="table" :search="fetchData" addIndexColumn immediateSearch />
228
- ```
148
+ ## 反模式
149
+
150
+ - ❌ 在 `<ProForm>` 内手写 `<a-form-item>` -- ProForm 从 Field 配置自动渲染。
151
+ - ❌ 猜透传属性名 -- 先查 antdv.com。
152
+ - ❌ 把 `span` 当输入控件属性。
153
+ - ❌ 传 SFC 给 `component` 不用 `markRaw`。
154
+ - ❌ 在 ProTable 上忘了传 `:search`,或期望它自动请求 -- 查询由你提供并驱动。
229
155
 
230
- ---
156
+ ## 按需深查
231
157
 
232
- ## 7. References
158
+ 完整 API(详细签名、参数表、完整示例、ProTable Slots、ProComponentProvider 用法):
233
159
 
234
- 1. **`node_modules/@qin-ui/antd-vue-pro/api.json`** — Structured API metadata (signatures, types, JSDoc examples)
235
- 2. **`node_modules/@qin-ui/antd-vue-pro/README.md`** — Full usage docs and code examples
236
- 3. **[antdv.com](https://antdv.com)** — ant-design-vue component API reference (always check before writing pass-through props)
160
+ - `.agents/skills/antd-vue-pro/SKILL.md` — skills 入口(速查 + 参考导航)
161
+ - `.agents/skills/antd-vue-pro/references/README.md` — 完整使用文档与进阶示例
162
+ - `.agents/skills/antd-vue-pro/references/api.md` — 结构化 API 元数据
163
+ - `node_modules/@qin-ui/antd-vue-pro/README.md` — 完整用法与进阶示例
164
+ - ant-design-vue 组件属性查阅官方文档:https://antdv.com
package/README.md CHANGED
@@ -38,6 +38,24 @@ pnpm add @qin-ui/antd-vue-pro
38
38
 
39
39
  ---
40
40
 
41
+ ## 🤖 AI 辅助开发
42
+
43
+ 本项目内置 AI 上下文初始化工具。安装后在项目根目录执行:
44
+
45
+ ```bash
46
+ npx @qin-ui/antd-vue-pro init-ai
47
+ ```
48
+
49
+ 将在项目中生成双载体 AI 上下文,使 Cursor / Claude Code / Codex 等 AI 工具深度理解本库的 Schema 驱动用法与属性透传规则:
50
+
51
+ - `AGENTS.md` — 核心使用规则(跨工具开放约定,会话时自动注入,AI 默认加载)
52
+ - `.agents/skills/antd-vue-pro/SKILL.md` — skills 入口(速查 + 参考导航)
53
+ - `.agents/skills/antd-vue-pro/references/` — 完整使用文档与结构化 API 元数据
54
+
55
+ > 生成的 `AGENTS.md` 使用标记区块写入,重复执行 `init-ai` 可安全更新,不影响项目内其他库的指令。建议将生成的文件提交到 Git 仓库,团队共享 AI 上下文。
56
+
57
+ ---
58
+
41
59
  ## 🚀 快速开始
42
60
 
43
61
  ### 1. 全局注册组件(可选)
@@ -119,6 +137,29 @@ const handleSubmit = async () => {
119
137
 
120
138
  ---
121
139
 
140
+ ## 🧱 属性分层透传(核心规则)
141
+
142
+ ProForm/ProTable 是渲染引擎,所有真实 UI 来自 ant-design-vue。**Field 上的属性会被"剥离到不同 DOM 层",不是全塞给输入控件**。写错层就会失效,这是最容易踩的坑:
143
+
144
+ ```
145
+ <a-col :span="8"> ← Grid 层(仅 grid 开启时)
146
+ <a-form-item label="..."> ← FormItem 层
147
+ <a-input placeholder> ← 输入控件层
148
+ </a-form-item>
149
+ </a-col>
150
+ ```
151
+
152
+ | 属性 | 落到哪一层 | 说明 |
153
+ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------- | :------------------- |
154
+ | `span` / `offset` / `push` / `pull` / `flex` / `xs`..`xxl` | `<a-col>` Grid 层 | 仅 `grid` 开启时生效 |
155
+ | `label` / `rules` / `tooltip` / `colon` / `labelCol` / `wrapperCol` / `extra` / `help` / `validateTrigger` / `validateFirst` / `valuePropName` / `normalize` / `formItemStyle` / `formItemClass` / `formItemDataAttrs` | `<a-form-item>` 层 | 表单项相关属性 |
156
+ | `disabled` / `placeholder` / `allowClear` / `options` / `mode` / `maxlength` / `componentStyle` / `componentClass` / `componentDataAttrs` + 该控件其余 ant-design-vue 原生属性 | 输入控件本身(`a-input` 等) | 其余全部 |
157
+ | `component` / `hidden` / `modelProp` / `valueFormatter` / `fields` / `slots` / `formItemContainer` / `componentContainer` / `extraProps` | ProForm 逻辑消费,**不绑到 DOM** | 框架级属性 |
158
+
159
+ > **规则**:`span` 给 Grid,`label`/`rules` 给 FormItem,其余给输入控件。输入控件的具体属性名/类型请以 [ant-design-vue 官方文档](https://antdv.com) 为准。
160
+
161
+ ---
162
+
122
163
  ## 📚 组件 API 说明
123
164
 
124
165
  ### 1. ProComponentProvider
@@ -131,6 +172,24 @@ const handleSubmit = async () => {
131
172
  | :--------------- | :-------------------------------------- | :-------------- | :----- |
132
173
  | `component-vars` | 需要全局 provide 给子组件的默认属性配置 | `ComponentVars` | - |
133
174
 
175
+ #### 内置默认预设(INJECT_CONFIG)
176
+
177
+ ProComponentProvider 内置了一套默认属性预设,**即使不配置 `component-vars` 也会生效**。Field 配置优先级最高,会覆盖这些预设。以下为各组件的内置默认值(写代码时需知晓,避免行为与预期不符):
178
+
179
+ | component | 默认预设 |
180
+ | :--------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
181
+ | `switch` | `{ modelProp: 'checked' }` —— v-model 绑定 `checked` 而非 `value` |
182
+ | `input` / `input-password` | `{ maxlength: 100, allowClear: true, placeholder: '请输入' }` |
183
+ | `textarea` | `{ maxlength: 200, autoSize: { minRows: 3, maxRows: 6 }, showCount: true, allowClear: true, placeholder: '请输入' }` |
184
+ | `input-number` | `{ max: 1e15-1, min: -(1e15+1), controls: false, placeholder: '请输入', style: { width: '100%' } }` |
185
+ | `select` / `cascader` | `{ allowClear: true, placeholder: '请选择', getPopupContainer }` |
186
+ | `date-picker` / `range-picker` / `time-picker` | `{ allowClear: true, getPopupContainer, style: { width: '100%' } }` |
187
+ | `pro-form` | `{ grid: { gutter: { xs: 8, sm: 16, md: 16, lg: 24 } } }` |
188
+ | `pro-form-item` | `{ validateFirst: true, span: 8 }` |
189
+ | `pro-table` | `{ pagination: { showTotal, showSizeChanger, pageSizeOptions: ['10', '20', '30', '40', '50', '100'], showQuickJumper: true }, searchFormConfig: { layout: 'grid', expand: { minExpandRows: 2, expandStatus: false } }, control: true, addIndexColumn: true }` |
190
+
191
+ > `modelProp` 控制 v-model 绑定的属性名,默认 `'value'`(即 `v-model:value`)。`switch` 经预设绑定为 `checked`,通常无需手动设置。
192
+
134
193
  ---
135
194
 
136
195
  ### 2. ProForm
@@ -177,6 +236,32 @@ const handleSubmit = async () => {
177
236
  | `toolbar` | 自定义工具栏区域(位于表格右上方控制按钮旁) |
178
237
  | `table` | 完全自定义渲染表格区域 |
179
238
 
239
+ #### 数据流
240
+
241
+ ProTable 不会自动请求数据,**查询由你提供的 `search` 回调驱动**。内部串联逻辑:
242
+
243
+ ```
244
+ 点击搜索 -> 重置分页到第 1 页 -> 调用 search()
245
+ 分页/排序变化 -> 更新 pageParam -> 调用 search()
246
+ 点击重置 -> resetQueryParams() -> 调用 search()
247
+ 挂载(immediateSearch) -> 立即触发一次 -> 调用 search()
248
+ ```
249
+
250
+ `search` 回调内通常组装查询参数并赋值数据源:
251
+
252
+ ```ts
253
+ const fetchData = async () => {
254
+ const res = await api.list({
255
+ ...table.searchForm.formData, // 搜索条件
256
+ ...table.pageParam, // 分页
257
+ });
258
+ table.dataSource.value = res.data;
259
+ table.setPageParam({ total: res.total });
260
+ };
261
+
262
+ // 重置按钮(ProTable 内部已串联 resetQueryParams -> search,一般无需手动处理)
263
+ ```
264
+
180
265
  ---
181
266
 
182
267
  ## ⚙️ 核心 Hooks 说明
@@ -197,19 +282,19 @@ const form = useForm<D>(initFormData?, initFields?, root?)
197
282
 
198
283
  #### 返回值 (Form 实例)
199
284
 
200
- | 属性/方法 | 说明 | 类型 |
201
- | :----------------------------- | :---------------------------------------------------------------------------------- | :------------------------------- |
202
- | `formData` | 响应式表单数据对象(**2.0+ 中由 reactive 包装**) | `Reactive<D>` |
203
- | `fields` | 响应式表单字段配置数组引用 | `Ref<Field[]>` |
204
- | `formRef` | 底层 Ant Design Vue `a-form` 的 DOM/组件引用实例 | `Ref<FormInstance \| undefined>` |
205
- | `getFormData(path)` | 安全获取指定字段路径(支持深层 'a.b')的数据值 | `(path) => any` |
206
- | `setFormData(path, val)` | 安全更新指定路径的值,支持批量对象或函数式更新 | `(path, val) => void` |
207
- | `getField(path, opts?)` | 获取指定 path 的字段配置,支持查找函数定位,支持配置 `{ all: true }` 获取所有匹配项 | `(path, opts) => Field` |
208
- | `setField(path, patch, opts?)` | 增量更新指定字段的配置参数(如改变 label、hidden 等),支持 merge 或 rewrite 更新 | `(path, patch, opts) => void` |
209
- | `deleteField(path)` | 从当前配置数组中删除特定 path 的表单字段配置 | `(path) => void` |
210
- | `appendField(path, field)` | 在特定的字段 path 后面,动态追加一个新的表单字段配置 | `(path, field) => void` |
211
- | `prependField(path, field)` | 在特定的字段 path 前面,动态插入一个新的表单字段配置 | `(path, field) => void` |
212
- | `getParentField(path)` | 查找获取当前子字段的父级配置项,一级字段返回虚拟根容器 | `(path) => Field` |
285
+ | 属性/方法 | 说明 | 类型 |
286
+ | :----------------------------- | :----------------------------------------------------------------------------------------------------------------------------- | :------------------------------- |
287
+ | `formData` | 响应式表单数据对象(**2.0+ 中由 reactive 包装**) | `Reactive<D>` |
288
+ | `fields` | 响应式表单字段配置数组引用 | `Ref<Field[]>` |
289
+ | `formRef` | 底层 Ant Design Vue `a-form` 的 DOM/组件引用实例 | `Ref<FormInstance \| undefined>` |
290
+ | `getFormData(path)` | 安全获取指定字段路径(支持深层 'a.b')的数据值 | `(path) => any` |
291
+ | `setFormData(path, value)` | 路径写入或函数式更新;传对象(`{...}`)批量覆盖整个表单;传函数 `(prev) => new` 批量更新 | `(path, val) => void` |
292
+ | `getField(path, opts?)` | 获取指定 path 的字段配置,支持查找函数定位,支持配置 `{ all: true }` 获取所有匹配项 | `(path, opts) => Field` |
293
+ | `setField(path, patch, opts?)` | 默认合并更新字段配置;`{updateType:'rewrite'}` 覆盖;支持函数式 `setField(path, prev=>({...}))`;`{all:true}` 批量更新所有匹配 | `(path, patch, opts) => void` |
294
+ | `deleteField(path, opts?)` | 删除字段配置;`{all:true}` 删除所有匹配的字段 | `(path, opts?) => void` |
295
+ | `appendField(path, field)` | 在指定字段后追加新字段(入参可为数组);`undefined` 在末尾追加;`{all:true}` 所有匹配后追加 | `(path, field, opts?) => void` |
296
+ | `prependField(path, field)` | 在指定字段前插入新字段(入参可为数组);`undefined` 在开头插入;`{all:true}` 所有匹配前插入 | `(path, field, opts?) => void` |
297
+ | `getParentField(path, opts?)` | 查找父级字段配置;`{all:true}` 返回所有匹配的父级字段 | `(path, opts?) => Field` |
213
298
 
214
299
  ---
215
300
 
@@ -244,6 +329,16 @@ const table = useTable<D, T>({
244
329
  | `setPageParam(param)` | 增量设置当前分页参数值,支持传入对象或更新函数 | `(param) => void` |
245
330
  | `resetQueryParams()` | 重置搜索参数,并恢复分页至第 1 页 | `() => void` |
246
331
 
332
+ #### 列配置(Column)
333
+
334
+ `columns` 数组中每一项为 `Column<T>` 类型,**继承 ant-design-vue `ColumnType`**,因此所有原生列属性(`title` / `width` / `fixed` / `align` / `customRender` / `ellipsis` 等)均可用。在此基础上新增:
335
+
336
+ | 属性 | 说明 | 类型 | 默认值 |
337
+ | :---------- | :---------------------------------------------------------------------------------------- | :------------------- | :------ |
338
+ | `dataIndex` | 列数据路径(主要字段),类型安全,支持 `'name'` / `'address.city'` / `['address','city']` | `string \| string[]` | - |
339
+ | `key` | 列字段标识(辅助),仅当 `dataIndex` 无法满足时使用,匹配优先级低于 `dataIndex` | `string` | - |
340
+ | `hidden` | 是否隐藏该列(配合列动态控制) | `boolean` | `false` |
341
+
247
342
  ---
248
343
 
249
344
  ## 📄 字段配置(`Field`)详解
@@ -275,6 +370,63 @@ const table = useTable<D, T>({
275
370
  | `fields` | 嵌套子表单项的 Schema 数组配置(用于分组或复杂嵌套表单) | `Field[]` | - |
276
371
  | `grid` | 针对当前嵌套子表单项所使用的网格布局参数(仅当有 `fields` 时有效) | `boolean \| GridProps` | - |
277
372
 
373
+ #### `valueFormatter` 字段值转换
374
+
375
+ 控制表单值与组件值之间的转换(如日期 `dayjs` 与字符串互转)。在表单数据写入前(computed setter 中)执行,支持两种形态。**函数形态仅 set(写入)方向生效,读取时不转换;对象形态 get/set 双向生效:**
376
+
377
+ ```ts
378
+ // 函数形态:(新值, 旧值) => 转换后的值,写回 formData
379
+ { path: 'name', component: 'input', valueFormatter: (val, oldVal) => val?.trim() }
380
+
381
+ // 对象形态:get 读出时转换,set 写入时转换
382
+ {
383
+ path: 'birthday',
384
+ component: 'date-picker',
385
+ valueFormatter: {
386
+ get: (val) => (val ? dayjs(val) : null), // formData -> 组件显示
387
+ set: (val) => (val ? dayjs(val).format('YYYY-MM-DD') : null), // 组件 -> formData
388
+ },
389
+ }
390
+ ```
391
+
392
+ > ⚠️ `valueFormatter` 不支持响应式(不能包 `ref`/`computed`),与 `component` / `fields` / `slots` / `modelProp` 等同属不支持响应式的属性。
393
+
394
+ ---
395
+
396
+ ### 🔄 响应式联动
397
+
398
+ 控制类属性(`disabled` / `hidden` / `rules` 等)支持三种响应式模式,按场景选最简的:
399
+
400
+ ```ts
401
+ // A. computed() 声明式 -- 初始化时已知的联动(首选)
402
+ disabled: computed(() => !form.formData.enabled),
403
+ rules: computed(() => form.formData.hasLimit ? [{ required: true, message: '必填' }] : []),
404
+
405
+ // B. ref() -- 外部共享状态
406
+ const isDisabled = ref(false);
407
+ disabled: isDisabled,
408
+
409
+ // C. setField() 命令式 -- 事件驱动的运行时变更
410
+ form.setField('limitCount', { disabled: true });
411
+ ```
412
+
413
+ > **规则**:初始化时已知的联动用 `computed()`,运行时事件触发的用 `setField()`,外部共享状态用 `ref()`。能用 `computed()` 解决就不要用 `setField()`。
414
+
415
+ #### 不支持响应式的属性
416
+
417
+ 以下属性不能包 `ref`/`computed`(会失效或引发渲染异常),只能传静态值:
418
+
419
+ | 属性 | 原因 |
420
+ | :----------------------------------------- | :-------------------------------------------------- |
421
+ | `component` | 组件对象/函数,响应式代理会破坏渲染(需 `markRaw`) |
422
+ | `valueFormatter` | 纯转换函数,无需响应式 |
423
+ | `fields` | 嵌套字段数组结构,响应式代理会干扰内部解析 |
424
+ | `slots` | 插槽内容,响应式代理会破坏渲染 |
425
+ | `modelProp` | 字符串标识,无需响应式 |
426
+ | `formItemContainer` / `componentContainer` | 容器组件,需 `markRaw` |
427
+
428
+ > 动态切换 `component` 或 `slots` 时,用 `setField()` 命令式更新,而非包 `computed`。
429
+
278
430
  ---
279
431
 
280
432
  ### 内置组件映射(`component` 可选值)
@@ -303,9 +455,45 @@ const table = useTable<D, T>({
303
455
 
304
456
  ---
305
457
 
306
- ### 🧩 扩充注册您的自定义组件
458
+ ### 🧩 自定义组件(4 种方式)
307
459
 
308
- #### 步骤 1:利用 ComponentProvider 全局注册
460
+ `Field.component` 的解析优先级(高 -> 低):
461
+
462
+ `teleport 插槽注入` > `ProComponentProvider.componentMap` > `内置 componentMap` > `原始 component 值`
463
+
464
+ #### 方式 1:传入 SFC 单文件组件对象(推荐,单字段最常用)
465
+
466
+ `component` 直接传组件对象,**必须用 `markRaw` 包裹**:
467
+
468
+ ```ts
469
+ import { markRaw } from 'vue';
470
+ import MyInput from './MyInput.vue';
471
+
472
+ const fields = [{ path: 'code', label: '验证码', component: markRaw(MyInput) }];
473
+ ```
474
+
475
+ > ⚠️ **必须 `markRaw`**:不包会被 Vue 当成响应式对象深度代理,触发性能警告甚至渲染异常。类型上 `component` 接受 `RenderComponentType | Raw<RenderComponentType>`,`Raw<T>` 即 markRaw 的类型标记。此字段不支持响应式(不能包 `ref`/`computed`)。
476
+
477
+ #### 方式 2:传入 render 函数(单字段,需动态拼装 props 时)
478
+
479
+ `component` 传 `(props, ctx) => VNode`。`props` 含 v-model 绑定值与 path,`ctx.attrs` 含透传属性:
480
+
481
+ ```ts
482
+ import { h } from 'vue';
483
+ import MyInput from './MyInput.vue';
484
+
485
+ const fields = [
486
+ {
487
+ path: 'code',
488
+ label: '验证码',
489
+ component: (p, ctx) => h(MyInput, { ...p, ...ctx.attrs }),
490
+ },
491
+ ];
492
+ ```
493
+
494
+ #### 方式 3:ProComponentProvider 注入 componentMap(全局复用,推荐多字段场景)
495
+
496
+ 在根用 `componentMap` 注册,Field 里用字符串引用。**可覆盖内置组件**(如 `input: MyInput` 替换全局 `input`)。
309
497
 
310
498
  ```vue
311
499
  <script setup lang="ts">
@@ -324,9 +512,7 @@ const componentMap = {
324
512
  </template>
325
513
  ```
326
514
 
327
- #### 步骤 2:追加 TypeScript 全局声明获取强类型补全
328
-
329
- 在项目任意 `.d.ts` 类型文件中写入以下代码:
515
+ 追加 TypeScript 全局声明获取强类型补全(项目任意 `.d.ts`):
330
516
 
331
517
  ```ts
332
518
  declare module '@qin-ui/antd-vue-pro' {
@@ -336,7 +522,34 @@ declare module '@qin-ui/antd-vue-pro' {
336
522
  }
337
523
  ```
338
524
 
339
- 现在,您在表单配置中写入 `component: 'rich-editor'` 时,将自动获得精准的属性类型联想与校验!
525
+ 之后 `component: 'rich-editor'` 即获精准属性类型联想与校验。
526
+
527
+ #### 方式 4:模板 scoped slot(声明式,简单替换)
528
+
529
+ 插槽名 = 字段 `path`,绑定参数通过 `v-bind="scoped"` 转发(teleport 机制,优先级最高):
530
+
531
+ ```vue
532
+ <ProForm :form="form">
533
+ <template #agreement="scoped">
534
+ <a-checkbox v-bind="scoped">同意协议</a-checkbox>
535
+ </template>
536
+ </ProForm>
537
+ ```
538
+
539
+ #### 选择建议
540
+
541
+ | 场景 | 推荐方式 |
542
+ | :--------------------------- | :-------------------------------- |
543
+ | 单字段复用一个 SFC | 方式 1(`markRaw(SFC)`) |
544
+ | 单字段、需动态拼装 props | 方式 2(render 函数) |
545
+ | 多处复用 / 替换内置组件 | 方式 3(componentMap + 声明扩充) |
546
+ | 简单声明式替换、不想写 `h()` | 方式 4(scoped slot) |
547
+
548
+ #### 自定义组件需遵守的约定
549
+
550
+ - **v-model**:默认绑 `value`(`v-model:value`)。若组件用别的 prop(如 Switch 用 `checked`),通过字段 `modelProp` 指定,或在 `componentVars` 预设 `modelProp`。
551
+ - **接收 path**:组件会收到 `path` prop(字段路径),可用于透传或标识。
552
+ - **属性透传**:Field 上除框架级属性外(`component` / `hidden` / `modelProp` / `valueFormatter` / `fields` / `slots` / `formItemContainer` / `componentContainer` / `extraProps` 等),其余作为 attrs 透传给自定义组件。
340
553
 
341
554
  ---
342
555
 
package/api.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "generatedAt": "2026-07-13T08:00:52.657Z",
2
+ "generatedAt": "2026-08-05T02:02:12.968Z",
3
3
  "name": "@qin-ui/antd-vue-pro",
4
4
  "api": [
5
5
  {
@@ -8,6 +8,20 @@
8
8
  "package": "@qin-ui/antd-vue-pro",
9
9
  "signature": "<ProComponentProvider>",
10
10
  "description": "@qin-ui/antd-vue-pro 全局配置提供者组件\n用于在组件树的顶层配置所有子组件的全局默认属性。\n支持配置 ProForm、ProTable、ProFormItem 以及所有内置组件的默认属性。",
11
+ "params": [
12
+ {
13
+ "name": "componentVars",
14
+ "type": "ComponentVars",
15
+ "optional": true,
16
+ "description": "组件全局配置变量"
17
+ },
18
+ {
19
+ "name": "componentMap",
20
+ "type": "Record<ComponentName, any>",
21
+ "optional": true,
22
+ "description": "自定义组件映射,用于替换或扩展内置组件"
23
+ }
24
+ ],
11
25
  "examples": [
12
26
  "```vue\n<template>\n<ProComponentProvider\n:componentVars=\"{\n'pro-form': { labelCol: { span: 4 } },\n'input': { placeholder: '请输入', maxlength: 200 },\n'select': { placeholder: '请选择' },\n}\"\n>\n<ProForm :form=\"form\" />\n</ProComponentProvider>\n</template>\n```"
13
27
  ]
@@ -32,6 +46,26 @@
32
46
  "package": "@qin-ui/antd-vue-pro",
33
47
  "signature": "<ProForm>",
34
48
  "description": "@qin-ui/antd-vue-pro 配置驱动表单组件\n架构设计说明 (Architecture Overview)\n[ 数据层 (Core) ] => [ 绑定层 (ProForm) ] => [ 渲染层 (BaseFormItem / BaseField) ]\n1. 数据隔离:ProForm 本身不负责存储和管理表单状态,所有核心状态(formData, fields, 校验规则)\n均交由底层的 `useForm`(@qin-ui/pro-components-core)驱动。\n2. 上下文透传:通过 `provide` 将核心状态下发给子组件,避免了深层嵌套的 Props 传递。\n3. 递归渲染:网格布局和具体字段的解析交由 `<BaseFormItem>` 递归完成,实现了 UI 布局与表单逻辑的解耦。\n通过配置驱动的方式快速构建表单,支持:\n- 字段联动(通过 setField、watch 等实现)\n- 嵌套字段(通过 fields 递归配置)\n- 自定义组件(通过 component 属性和 custom 类型)\n- 网格布局(通过 grid 属性)\n- 动态插槽(以字段 path 命名的插槽)\n- 全局配置注入(通过 ProComponentProvider)",
49
+ "params": [
50
+ {
51
+ "name": "form",
52
+ "type": "F",
53
+ "optional": true,
54
+ "description": "useForm 返回的表单实例"
55
+ },
56
+ {
57
+ "name": "grid",
58
+ "type": "boolean | GridProps",
59
+ "optional": true,
60
+ "description": "是否启用网格布局 (默认 false)"
61
+ },
62
+ {
63
+ "name": "...attrs",
64
+ "type": "...FormProps",
65
+ "optional": false,
66
+ "description": "Ant Design Vue Form 组件的其他属性"
67
+ }
68
+ ],
35
69
  "typeParams": [
36
70
  {
37
71
  "name": "F"
@@ -74,6 +108,14 @@
74
108
  "package": "@qin-ui/antd-vue-pro",
75
109
  "signature": "export const useFormData = <D extends Data = Data>(\n initFormData?: ExtendWithAny<DeepPartial<D>>\n): UseFormDataReturn<D> =>",
76
110
  "description": "表单数据处理 Hook\n提供响应式表单数据的管理能力,支持:\n- 响应式数据存储(基于 Vue reactive)\n- 深层路径读写(支持点号分隔,如 'address.city')\n- 类型安全的路径提示(传入泛型 D 后,path 参数可获得类型推导)\n- 父子表单自动注入(非根表单会从注入中获取数据)",
111
+ "params": [
112
+ {
113
+ "name": "initFormData",
114
+ "type": "ExtendWithAny<DeepPartial<D>>",
115
+ "optional": true,
116
+ "description": "初始表单数据"
117
+ }
118
+ ],
77
119
  "returns": "{UseFormDataReturn<D>} 表单数据操作对象",
78
120
  "typeParams": [
79
121
  {
@@ -90,6 +132,14 @@
90
132
  "package": "@qin-ui/antd-vue-pro",
91
133
  "signature": "export function useFields<D extends Data = Data>(\n initFields?: Fields<D>\n): UseFieldsReturn<D, Field<ComponentName, D>, FormItemInstance>;",
92
134
  "description": "字段配置管理 Hook\n基于 `@qin-ui/pro-components-core` 的 `useFields`,将泛型参数绑定为 Ant Design Vue 的本地类型:\n- 字段类型 F -> `Field<ComponentName, D>`(支持 Ant Design Vue 组件类型推导)\n- FormItem 实例 -> Ant Design Vue 的 `FormItemInstance`\n提供对字段配置数组的增删改查操作,支持:\n- 通过路径字符串或查找函数定位字段\n- 深层嵌套字段的遍历和匹配\n- 字段配置的合并/覆盖更新\n- 字段的添加、插入、删除\n- 父级字段查找\n- `fields` - 字段配置数组(响应式 Ref\\<F[]\\>)\n- `getField(path)` - 获取字段配置,支持路径字符串或查找函数\n- `setField(path, field, options?)` - 更新字段配置,默认合并模式\n- `deleteField(path, options?)` - 删除字段配置\n- `appendField(path, field, options?)` - 在指定字段后追加\n- `prependField(path, field, options?)` - 在指定字段前插入\n- `getParentField(path, options?)` - 获取父级字段配置",
135
+ "params": [
136
+ {
137
+ "name": "initFields",
138
+ "type": "Fields<D>",
139
+ "optional": true,
140
+ "description": "初始字段配置数组"
141
+ }
142
+ ],
93
143
  "returns": "字段操作对象,包含以下属性:",
94
144
  "typeParams": [
95
145
  {
@@ -131,6 +181,26 @@
131
181
  "package": "@qin-ui/antd-vue-pro",
132
182
  "signature": "export function useForm<D extends Data = Data>(\n initFormData?: ExtendWithAny<DeepPartial<D>>,\n initFields?: Field<ComponentName, D>[],\n root?: boolean\n): Form<D, Field<ComponentName, D>>;",
133
183
  "description": "创建表单实例的 Hook\n基于 `@qin-ui/pro-components-core` 的 `useForm`,将泛型参数绑定为 Ant Design Vue 的本地类型:\n- 字段类型 F -> `Field<ComponentName, D>`(支持 Ant Design Vue 所有内置组件类型推导)\n- 表单实例 -> Ant Design Vue 的 `FormInstance`(使 formRef 获得完整的类型提示)\n表单实例组合了三个子模块的能力:\n- **useFormData**:表单数据管理(响应式数据、读写、批量更新)\n- **useFields**:字段配置管理(增删改查字段配置,支持嵌套)\n- **useFormRef**:底层 Form 组件实例引用",
184
+ "params": [
185
+ {
186
+ "name": "initFormData",
187
+ "type": "ExtendWithAny<DeepPartial<D>>",
188
+ "optional": true,
189
+ "description": "初始表单数据"
190
+ },
191
+ {
192
+ "name": "initFields",
193
+ "type": "Field<ComponentName, D>[]",
194
+ "optional": true,
195
+ "description": "初始字段配置数组"
196
+ },
197
+ {
198
+ "name": "root",
199
+ "type": "boolean",
200
+ "optional": true,
201
+ "description": "是否为根表单。设为 `false` 时尝试从父组件注入获取表单实例 (默认 true)"
202
+ }
203
+ ],
134
204
  "returns": "{Form<D>} 表单实例,包含数据操作、字段操作和 ref 操作",
135
205
  "typeParams": [
136
206
  {
@@ -206,6 +276,36 @@
206
276
  "type": "object",
207
277
  "optional": false,
208
278
  "description": "表格配置参数"
279
+ },
280
+ {
281
+ "name": "params.columns",
282
+ "type": "Columns<T>",
283
+ "optional": true,
284
+ "description": "初始列配置数组"
285
+ },
286
+ {
287
+ "name": "params.dataSource",
288
+ "type": "T[]",
289
+ "optional": true,
290
+ "description": "初始数据源"
291
+ },
292
+ {
293
+ "name": "params.pageParam",
294
+ "type": "PageParam",
295
+ "optional": true,
296
+ "description": "初始分页参数,默认 `{ current: 1, pageSize: 10, total: 0 }`"
297
+ },
298
+ {
299
+ "name": "params.searchParam",
300
+ "type": "ExtendWithAny<DeepPartial<D>>",
301
+ "optional": true,
302
+ "description": "初始搜索参数"
303
+ },
304
+ {
305
+ "name": "params.searchFields",
306
+ "type": "Fields<D>",
307
+ "optional": true,
308
+ "description": "搜索表单字段配置"
209
309
  }
210
310
  ],
211
311
  "returns": "{Table<D, T>} 表格实例",
package/bin/init-ai.mjs CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
+ /* global process -- Node.js CLI 脚本 */
2
3
 
3
4
  /**
4
5
  * @qin-ui/antd-vue-pro AI 上下文初始化 CLI 工具
5
6
  *
6
- * 在消费方项目中生成分层 AI 上下文文件,使 AI 工具能够:
7
- * 1. 理解 @qin-ui/antd-vue-pro 的 Schema 驱动架构
8
- * 2. 掌握属性透传规则(何时查阅 ant-design-vue 文档)
9
- * 3. 快速获取完整 API 参考
7
+ * 在消费方项目中生成双载体 AI 上下文:
8
+ * 1. 根目录 AGENTS.md -- 核心使用规则,跨工具自动注入(主载体)
9
+ * 2. .agents/skills/{pkg}/SKILL.md + references/ -- 分层参考文档,支持 skills 发现的工具按需逐层调取(参考载体)
10
10
  *
11
11
  * 用法:
12
12
  * npx @qin-ui/antd-vue-pro init-ai
@@ -28,6 +28,10 @@ const PKG_JSON = JSON.parse(
28
28
  const PKG_NAME = PKG_JSON.name;
29
29
  const PKG_SHORT = PKG_NAME.replace(/^@qin-ui\//, '');
30
30
 
31
+ // AGENTS.md 智能合并区块标记(支持多库共存,幂等更新)
32
+ const BEGIN_MARKER = `<!-- BEGIN ${PKG_NAME} -->`;
33
+ const END_MARKER = `<!-- END ${PKG_NAME} -->`;
34
+
31
35
  // ==================== 终端颜色 ====================
32
36
 
33
37
  const green = s => `\x1b[32m${s}\x1b[0m`;
@@ -47,7 +51,10 @@ function readPackageFile(filename) {
47
51
  }
48
52
 
49
53
  function getAiContextContent() {
50
- return readPackageFile('AI-CONTEXT.md') || `# ${PKG_NAME}\n\n> 基于 Vue 3 的配置驱动组件库。`;
54
+ return (
55
+ readPackageFile('AI-CONTEXT.md') ||
56
+ `# ${PKG_NAME}\n\n> 基于 Vue 3 的配置驱动组件库。`
57
+ );
51
58
  }
52
59
 
53
60
  function getReadmeContent() {
@@ -64,76 +71,157 @@ function getApiJsonContent() {
64
71
  }
65
72
  }
66
73
 
67
- // ==================== 内容生成 ====================
74
+ // ==================== 工具函数 ====================
75
+
76
+ function escapeRegExp(s) {
77
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
78
+ }
79
+
80
+ function ensureDir(dirPath) {
81
+ if (!fs.existsSync(dirPath)) {
82
+ fs.mkdirSync(dirPath, { recursive: true });
83
+ }
84
+ }
85
+
86
+ function writeFileWithLog(filePath, content, label) {
87
+ const dir = path.dirname(filePath);
88
+ ensureDir(dir);
89
+ const existed = fs.existsSync(filePath);
90
+ fs.writeFileSync(filePath, content, 'utf-8');
91
+ const status = existed ? yellow('[更新]') : green('[创建]');
92
+ console.log(` ${status} ${cyan(label)}`);
93
+ }
94
+
95
+ // ==================== AGENTS.md(主载体,自动注入)====================
68
96
 
69
97
  /**
70
- * 生成 rules 文件内容(Instructions 层)
71
- * 包含:架构关系、透传规则、反模式、ant-design-vue 资源链接
98
+ * 生成 AGENTS.md 区块内容
99
+ * = AI-CONTEXT.md 全文(核心使用规则,AI 必然读到)
72
100
  */
73
- function getRulesContent() {
101
+ function getAgentsBlock() {
102
+ return getAiContextContent();
103
+ }
104
+
105
+ /**
106
+ * 智能合并 AGENTS.md:
107
+ * - 文件不存在 -> 创建,内容 = 标记区块
108
+ * - 已有本库区块 -> 幂等替换区块内容(支持升级后更新)
109
+ * - 已有其他内容但无本库区块 -> 末尾追加区块(多库共存不冲突)
110
+ */
111
+ function writeAgentsMd(cwd) {
112
+ const agentsPath = path.join(cwd, 'AGENTS.md');
113
+ const blockContent = getAgentsBlock();
114
+ const newBlock = `${BEGIN_MARKER}\n${blockContent}\n${END_MARKER}`;
115
+
116
+ let existing = '';
117
+ if (fs.existsSync(agentsPath)) {
118
+ existing = fs.readFileSync(agentsPath, 'utf-8');
119
+ }
120
+
121
+ let result;
122
+ const hasBlock =
123
+ existing.includes(BEGIN_MARKER) && existing.includes(END_MARKER);
124
+
125
+ if (hasBlock) {
126
+ // 幂等替换已有区块
127
+ const blockRegex = new RegExp(
128
+ `${escapeRegExp(BEGIN_MARKER)}[\\s\\S]*?${escapeRegExp(END_MARKER)}`,
129
+ 'g'
130
+ );
131
+ result = existing.replace(blockRegex, newBlock);
132
+ } else if (existing.trim()) {
133
+ // 已有其他内容,追加区块
134
+ result = `${existing.trimEnd()}\n\n${newBlock}\n`;
135
+ } else {
136
+ // 文件不存在或空
137
+ result = `${newBlock}\n`;
138
+ }
139
+
140
+ const existed = fs.existsSync(agentsPath);
141
+ fs.writeFileSync(agentsPath, result, 'utf-8');
142
+ const status = existed ? yellow('[更新]') : green('[创建]');
143
+ console.log(` ${status} ${cyan('AGENTS.md')}`);
144
+ }
145
+
146
+ // ==================== Skills(参考载体,按需调取)====================
147
+
148
+ /**
149
+ * 生成 SKILL.md 内容
150
+ * = skill frontmatter + AI-CONTEXT.md 速查内容 + references 导航
151
+ * 供支持 skills 发现的工具按需调取,精准定位后查阅 references
152
+ */
153
+ function getSkillMainContent() {
74
154
  const aiContext = getAiContextContent();
155
+ const sections = [];
156
+
157
+ // skill frontmatter
158
+ sections.push('---');
159
+ sections.push(`name: ${PKG_SHORT}`);
160
+ sections.push(
161
+ `description: ${PKG_NAME} 使用指南 - 组件、Hooks、类型、Field/Column 配置。Schema 驱动的配置式组件库。当需要组件映射、默认预设、属性透传规则或完整用法时按需调取。`
162
+ );
163
+ sections.push('---');
164
+ sections.push('');
165
+
166
+ // AI-CONTEXT.md 速查内容(与 AGENTS.md 主载体同源,确保一致)
167
+ sections.push(aiContext);
168
+ sections.push('');
169
+
170
+ // references 导航
171
+ sections.push('---');
172
+ sections.push('');
173
+ sections.push('## 参考文档');
174
+ sections.push('');
175
+ sections.push(
176
+ `以下文件位于 \`.agents/skills/${PKG_SHORT}/references/\`,可在需要精确细节时进一步查阅:`
177
+ );
178
+ sections.push('');
179
+ sections.push(
180
+ `- [references/README.md](references/README.md) — 完整使用文档与进阶示例`
181
+ );
182
+ sections.push(
183
+ `- [references/api.md](references/api.md) — 结构化 API 元数据(函数签名、参数类型、返回值,提取自源码 JSDoc)`
184
+ );
185
+ sections.push(`- 底层组件属性查阅 ant-design-vue 官方文档:https://antdv.com`);
186
+ sections.push('');
75
187
 
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');
188
+ return sections.join('\n');
101
189
  }
102
190
 
103
191
  /**
104
- * 生成 API 文档内容(Resources 层)
105
- * 从 README.md + api.json 合并提取完整 API 参考
192
+ * 生成 references/api.md 内容(结构化 API 元数据 + skill frontmatter)
193
+ * 从 api.json 提取 @public 标记的 JSDoc,含签名、参数、返回值、示例
106
194
  */
107
- function getApiDocContent() {
108
- const readme = getReadmeContent();
195
+ function getSkillApiContent() {
109
196
  const apiJson = getApiJsonContent();
110
-
111
197
  const sections = [];
112
198
 
113
- sections.push(`# ${PKG_NAME} — 完整 API 参考`, '');
114
- sections.push(`> 自动生成自 README.md 和 api.json。版本: ${PKG_JSON.version}`, '');
199
+ // skill frontmatter
200
+ sections.push('---');
201
+ sections.push(`name: ${PKG_SHORT}-api`);
202
+ sections.push(
203
+ `description: ${PKG_NAME} 结构化 API 元数据 - 函数签名、参数类型、返回值、示例。从源码 JSDoc(@public 标记)自动提取。`
204
+ );
205
+ sections.push('---');
206
+ sections.push('');
115
207
 
116
- // README 内容(已包含完整的使用文档)
117
- if (readme) {
118
- sections.push(readme);
119
- sections.push('');
120
- }
208
+ sections.push(`# ${PKG_NAME} - 结构化 API 元数据`, '');
209
+ sections.push(
210
+ `> 自动提取自源码 JSDoc(\`@public\` 标记)。版本: ${PKG_JSON.version}`,
211
+ ''
212
+ );
121
213
 
122
214
  // 结构化 API 元数据
123
215
  if (apiJson && apiJson.api && apiJson.api.length > 0) {
124
- sections.push('---');
125
- sections.push('');
126
- sections.push('## 结构化 API 元数据(自动提取自源码 JSDoc)');
127
- sections.push('');
128
-
129
216
  for (const item of apiJson.api) {
130
- const typeLabel = {
131
- component: '组件',
132
- function: '函数/Hook',
133
- type: '类型',
134
- interface: '接口',
135
- constant: '常量',
136
- }[item.type] || '';
217
+ const typeLabel =
218
+ {
219
+ component: '组件',
220
+ function: '函数/Hook',
221
+ type: '类型',
222
+ interface: '接口',
223
+ constant: '常量',
224
+ }[item.type] || '';
137
225
 
138
226
  sections.push(`### ${typeLabel} \`${item.name}\``);
139
227
  sections.push('');
@@ -168,7 +256,9 @@ function getApiDocContent() {
168
256
  sections.push('| 参数名 | 类型 | 可选 | 描述 |');
169
257
  sections.push('| :--- | :--- | :--- | :--- |');
170
258
  for (const p of item.params) {
171
- sections.push(`| \`${p.name}\` | \`${p.type}\` | ${p.optional ? '是' : '否'} | ${p.description} |`);
259
+ sections.push(
260
+ `| \`${p.name}\` | \`${p.type}\` | ${p.optional ? '是' : '否'} | ${p.description} |`
261
+ );
172
262
  }
173
263
  }
174
264
 
@@ -195,41 +285,30 @@ function getApiDocContent() {
195
285
  return sections.join('\n');
196
286
  }
197
287
 
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
288
  // ==================== CLI 入口 ====================
216
289
 
217
290
  function printHelp() {
218
291
  console.log(`
219
- ${bold(`${PKG_NAME} CLI — AI 上下文初始化`)}
292
+ ${bold(`${PKG_NAME} CLI - AI 上下文初始化`)}
220
293
 
221
294
  ${bold('用法:')}
222
295
  npx ${PKG_NAME} init-ai
223
296
 
224
297
  ${bold('说明:')}
225
- 在项目中生成分层 AI 上下文文件,使 AI 工具能够深度理解和规范使用 ${PKG_NAME}。
298
+ 在项目中生成双载体 AI 上下文,使 AI 工具能够深度理解和规范使用 ${PKG_NAME}。
226
299
 
227
300
  生成的文件结构:
301
+ AGENTS.md 核心使用规则(跨工具自动注入)
228
302
  .agents/
229
- rules/
230
- ${PKG_SHORT}.md 规则文件(架构、透传规则、反模式)
231
- docs/
232
- ${PKG_SHORT}-api.md API 参考(完整文档 + 结构化元数据)
303
+ skills/
304
+ ${PKG_SHORT}/
305
+ SKILL.md skills 入口(速查 + 导航)
306
+ references/
307
+ README.md 完整使用文档
308
+ api.md 结构化 API 元数据
309
+
310
+ ${dim('AGENTS.md 是跨工具开放约定,Codex / Claude Code / Cursor 等会话时自动注入。')}
311
+ ${dim('.agents/skills/ 供支持 skills 发现的工具按需逐层调取。')}
233
312
 
234
313
  ${bold('选项:')}
235
314
  --help 显示帮助信息
@@ -253,49 +332,83 @@ function main() {
253
332
  }
254
333
 
255
334
  console.log('');
256
- console.log(bold(`📦 ${PKG_NAME} — AI 上下文初始化 v${PKG_JSON.version}`));
335
+ console.log(bold(`📦 ${PKG_NAME} - AI 上下文初始化 v${PKG_JSON.version}`));
257
336
  console.log(dim(` 基于 ant-design-vue 的 Schema 驱动组件库`));
258
337
  console.log('');
259
338
 
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`
339
+ // 1. 生成 AGENTS.md(主载体)
340
+ console.log(bold('📋 主载体:AGENTS.md(自动注入)'));
341
+ writeAgentsMd(process.cwd());
342
+ console.log(
343
+ dim(' -> 核心使用规则,Codex/Claude Code/Cursor 等会话自动加载')
267
344
  );
268
- console.log(dim(' → 架构概览、属性透传决策树、渐进用法、反模式'));
269
345
  console.log('');
270
346
 
271
- // 2. 生成 API 文档
272
- console.log(bold('📖 参考层 (Docs)'));
273
- const apiDocContent = getApiDocContent();
347
+ // 2. 生成 Skills(标准结构:SKILL.md + references/)
348
+ console.log(bold('📖 参考载体:.agents/skills/(按需调取)'));
349
+ const skillDir = path.join(process.cwd(), '.agents/skills', PKG_SHORT);
350
+ const skillRefsDir = path.join(skillDir, 'references');
351
+
352
+ // SKILL.md(入口:frontmatter + 速查内容 + 参考导航)
274
353
  writeFileWithLog(
275
- path.join(process.cwd(), '.agents/docs', `${PKG_SHORT}-api.md`),
276
- apiDocContent,
277
- `.agents/docs/${PKG_SHORT}-api.md`
354
+ path.join(skillDir, 'SKILL.md'),
355
+ getSkillMainContent(),
356
+ `.agents/skills/${PKG_SHORT}/SKILL.md`
357
+ );
358
+
359
+ // references/README.md(完整使用文档)
360
+ const readme = getReadmeContent();
361
+ if (readme) {
362
+ writeFileWithLog(
363
+ path.join(skillRefsDir, 'README.md'),
364
+ readme,
365
+ `.agents/skills/${PKG_SHORT}/references/README.md`
366
+ );
367
+ }
368
+
369
+ // references/api.md(结构化 API 元数据)
370
+ const apiJson = getApiJsonContent();
371
+ if (apiJson && apiJson.api && apiJson.api.length > 0) {
372
+ writeFileWithLog(
373
+ path.join(skillRefsDir, 'api.md'),
374
+ getSkillApiContent(),
375
+ `.agents/skills/${PKG_SHORT}/references/api.md`
376
+ );
377
+ }
378
+
379
+ console.log(
380
+ dim(' -> SKILL.md 入口 + references/ 完整文档,skills 工具按需逐层调取')
278
381
  );
279
- console.log(dim(' → 完整 README 文档 + 结构化 API 元数据'));
280
382
  console.log('');
281
383
 
282
384
  // 3. 完成提示
283
- console.log(green('✅ 完成!已生成分层 AI 上下文文件。'));
385
+ console.log(green('✅ 完成!已生成双载体 AI 上下文文件。'));
284
386
  console.log('');
285
387
  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 参考')}`);
388
+ console.log(
389
+ ` ${cyan('AGENTS.md')} ${dim('← 核心规则(AI 自动读取)')}`
390
+ );
391
+ console.log(` ${cyan('.agents/skills/' + PKG_SHORT + '/')}`);
392
+ console.log(
393
+ ` ├── ${cyan('SKILL.md')} ${dim('← skills 入口(速查 + 导航)')}`
394
+ );
395
+ console.log(` └── ${cyan('references/')}`);
396
+ console.log(
397
+ ` ├── ${cyan('README.md')} ${dim('← 完整使用文档')}`
398
+ );
399
+ if (apiJson && apiJson.api && apiJson.api.length > 0) {
400
+ console.log(
401
+ ` └── ${cyan('api.md')} ${dim('← 结构化 API 元数据')}`
402
+ );
403
+ }
291
404
  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`)}`);
405
+ console.log(`${bold('🔄 说明:')}`);
406
+ console.log(
407
+ ` - AGENTS.md 已用标记区块写入,重复执行 init-ai 可安全更新(不破坏其他库的指令)`
408
+ );
409
+ console.log(
410
+ ` - 编写 Field 中输入控件属性前,查阅 ant-design-vue 官方文档:${cyan('https://antdv.com')}`
411
+ );
299
412
  console.log('');
300
413
  }
301
414
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qin-ui/antd-vue-pro",
3
- "version": "2.2.2",
3
+ "version": "2.2.4",
4
4
  "description": "二次封装antd vue组件",
5
5
  "bin": {
6
6
  "antd-vue-pro": "./bin/init-ai.mjs"
@@ -42,11 +42,11 @@
42
42
  },
43
43
  "dependencies": {
44
44
  "scroll-into-view-if-needed": "^3.1.0",
45
- "@qin-ui/pro-components-core": "^1.0.2"
45
+ "vue-component-type-helpers": "^3.2.5",
46
+ "@qin-ui/pro-components-core": "^1.0.4"
46
47
  },
47
48
  "devDependencies": {
48
- "ant-design-vue": "^4",
49
- "vue-component-type-helpers": "^3.2.5"
49
+ "ant-design-vue": "^4"
50
50
  },
51
51
  "sideEffects": [
52
52
  "**/*.css",
@@ -72,7 +72,7 @@
72
72
  "pro-table"
73
73
  ],
74
74
  "scripts": {
75
- "prebuild": "tsx ../../scripts/generate-api-json.ts antd-vue-pro",
75
+ "prebuild": "tsx ../../scripts/generate-api-json.ts antd-vue-pro && tsx ../../scripts/generate-init-ai.ts antd-vue-pro",
76
76
  "build": "vue-tsc --noEmit && vite build"
77
77
  }
78
78
  }