@qin-ui/vant-pro 1.0.4 → 1.0.5
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 +150 -23
- package/api.json +1 -1
- package/bin/init-ai.mjs +242 -52
- package/package.json +1 -1
package/AI-CONTEXT.md
CHANGED
|
@@ -1,38 +1,165 @@
|
|
|
1
|
-
# @qin-ui/vant-pro
|
|
1
|
+
# @qin-ui/vant-pro — AI 上下文
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Schema-driven高级表单组件库,基于 **vant v4**(Vue 3 移动端UI,`van-` 前缀)。
|
|
4
|
+
> 核心思想:用 JS 对象描述 UI,而非在模板中堆砌组件标签。
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
---
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
## 1. 三层架构
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
Field[] 配置层(用户编写的 JS 对象)
|
|
12
|
+
{ path:'city', component:'picker', label:'城市', columns:[...], popup:true }
|
|
13
|
+
↓
|
|
14
|
+
@qin-ui/vant-pro(Schema 解析 + 属性分层剥离)
|
|
15
|
+
van-field 属性 → <van-field> / 其余属性 → 内部输入控件
|
|
16
|
+
↓
|
|
17
|
+
vant v4(Vue 3 移动端组件库)
|
|
18
|
+
van-field / van-picker / van-switch / van-stepper / ...
|
|
9
19
|
```
|
|
10
20
|
|
|
11
|
-
|
|
21
|
+
ProForm 是**渲染引擎**,不是组件库。所有 UI 来自 vant。Field 配置的属性被**逐层剥离**,分发到 `van-field`(容器)和内部控件。
|
|
22
|
+
|
|
23
|
+
### 组件映射表(componentMap,15 个内置组件)
|
|
24
|
+
|
|
25
|
+
| Field `component` | 渲染的 vant 组件 | 备注 |
|
|
26
|
+
| :------------------- | :--------------- | :--- |
|
|
27
|
+
| `'field'` | Field | **特殊:直接渲染 van-field,无内部控件包裹** |
|
|
28
|
+
| `'switch'` | Switch | v-model 绑定 `modelValue`(vant 默认约定) |
|
|
29
|
+
| `'stepper'` | Stepper | |
|
|
30
|
+
| `'rate'` | Rate | |
|
|
31
|
+
| `'slider'` | Slider | |
|
|
32
|
+
| `'uploader'` | Uploader | |
|
|
33
|
+
| `'checkbox-group'` | CheckboxGroup | |
|
|
34
|
+
| `'radio-group'` | RadioGroup | |
|
|
35
|
+
| `'picker'` | Picker | 常用 popup 模式(底部弹出) |
|
|
36
|
+
| `'date-picker'` | DatePicker | 常用 popup 模式 |
|
|
37
|
+
| `'time-picker'` | TimePicker | 常用 popup 模式 |
|
|
38
|
+
| `'cascader'` | Cascader | 常用 popup 模式 |
|
|
39
|
+
| `'area'` | Area | 常用 popup 模式 |
|
|
40
|
+
| `'signature'` | Signature | 常用 popup 模式 |
|
|
41
|
+
| `'button'` | Button | |
|
|
42
|
+
| `'custom'` | 自定义 | 传入 Vue 组件或 h() 渲染函数 |
|
|
43
|
+
|
|
44
|
+
> **编写任何输入控件属性前,必须查阅 [vant v4 官方文档](https://vant-ui.com/) 确认属性名和类型。**
|
|
45
|
+
|
|
46
|
+
---
|
|
12
47
|
|
|
13
|
-
|
|
48
|
+
## 2. 属性分层传递机制
|
|
14
49
|
|
|
15
|
-
|
|
16
|
-
- `ProComponentProvider` - 全局配置提供者
|
|
50
|
+
Field 配置的属性**逐层剥离**,分发到两个目标:
|
|
17
51
|
|
|
18
|
-
|
|
52
|
+
**van-field 容器层(fieldAttrs):**
|
|
53
|
+
`label`, `rules`, `required`, `clearable`, `inputAlign`, `errorMessageAlign`, `colon`, `readonly`, `clickable`, `isLink`, `labelWidth`, `labelAlign`, `labelClass`, `error`, `center`, `border`, `autosize`, `type`, `maxlength`, `placeholder`, `rows`,以及所有 `on*` 事件回调。`fieldClass`/`fieldStyle` → `class`/`style` 绑定到 van-field。
|
|
19
54
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
- `useFormRef()` - 表单组件引用
|
|
55
|
+
**内部控件层(bindAttrs):**
|
|
56
|
+
除上述外的其余属性(`columns`, `options`, `activeValue`, `min`, `max`, `step`, `count`, `size`, `direction`, `disabled` 等)。`componentClass`/`componentStyle` → 内部组件的 `class`/`style`。
|
|
23
57
|
|
|
24
|
-
|
|
58
|
+
**剥离逻辑:**
|
|
59
|
+
- 第一阶段(GroupedFieldAttrs):解构 `path`, `fields`, `hidden`, `extraProps` → 剩余 → `componentProps` → BaseField
|
|
60
|
+
- 第二阶段(BaseField):解构 `valueFormatter`, `displayFormatter`, `modelProp`, `slots`, `popup` 等 → 匹配 vant Field.props 的属性 + `on*` → `fieldAttrs` → van-field;其余 → `bindAttrs` → 内部控件
|
|
25
61
|
|
|
26
|
-
|
|
62
|
+
**`'field'` 特殊:** `component: 'field'` 直接渲染 van-field,无内部控件包裹,所有属性绑定到 van-field。
|
|
27
63
|
|
|
28
|
-
|
|
64
|
+
### modelProp
|
|
29
65
|
|
|
30
|
-
|
|
66
|
+
默认 `modelProp: 'modelValue'` → `v-model:modelValue`(vant 组件统一使用 `modelValue` 作为 v-model 绑定属性名)。
|
|
31
67
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 3. 渐进式用法
|
|
71
|
+
|
|
72
|
+
### 3.1 基础渲染
|
|
73
|
+
|
|
74
|
+
完全依赖 Field 配置,**禁止手写 `<van-field>` 或 `<van-switch>`**。
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import { ProForm, useForm } from '@qin-ui/vant-pro';
|
|
78
|
+
const form = useForm({ username: '', password: '' }, [
|
|
79
|
+
{ path: 'username', component: 'field', label: '用户名', placeholder: '请输入用户名', rules: [{ required: true }] },
|
|
80
|
+
{ path: 'password', component: 'field', label: '密码', type: 'password', rules: [{ required: true }] },
|
|
81
|
+
]);
|
|
38
82
|
```
|
|
83
|
+
|
|
84
|
+
```html
|
|
85
|
+
<template><ProForm :form="form" /></template>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 3.2 字段联动
|
|
89
|
+
|
|
90
|
+
初始化联动用 `computed()`,运行时联动用 `setField()`,外部状态用 `ref()`。**越简单越好:**
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
// computed() — 初始化时已确定的联动
|
|
94
|
+
disabled: computed(() => !form.formData.enabled)
|
|
95
|
+
|
|
96
|
+
// setField() — 事件触发时动态修改
|
|
97
|
+
form.setField('limitCount', { disabled: true })
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### 3.3 自定义组件
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
// h() 挂载或插槽接管
|
|
104
|
+
component: (p, ctx) => h(CustomPicker, { ...p, ...ctx.attrs }),
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
```html
|
|
108
|
+
<ProForm :form="form">
|
|
109
|
+
<template #city="scoped"><CustomPicker v-bind="scoped" /></template>
|
|
110
|
+
</ProForm>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 3.4 Popup 弹窗模式
|
|
114
|
+
|
|
115
|
+
Field 配置 `popup: true` 时:表单项以只读 van-field 展示,点击后底部弹出 Popup,内部控件在 Popup 中渲染。确认提交值,取消丢弃修改。`displayFormatter` 控制只读展示文本。
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
{ path: 'city', component: 'picker', label: '城市', columns: ['北京','上海'], popup: true, displayFormatter: (v) => v || '请选择' }
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 4. 反模式
|
|
124
|
+
|
|
125
|
+
- **禁止手写 van-field**:所有表单项通过 Field 配置驱动,ProForm 自动渲染 van-field
|
|
126
|
+
- **禁止猜测属性名**:编写组件属性前必须查 [vant 文档](https://vant-ui.com/),vant 不使用 `allowClear`/`mode:'multiple'` 等第三方库命名
|
|
127
|
+
- **联动选简单方式**:初始化联动用 `computed()`,运行时用 `setField()`,避免过度设计
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 5. ProComponentProvider 全局默认配置
|
|
132
|
+
|
|
133
|
+
通过 `ProComponentProvider` 在应用顶层统一配置默认属性,避免重复。属性优先级:Field 级别 > componentVars > INJECT_CONFIG 预设。
|
|
134
|
+
|
|
135
|
+
### INJECT_CONFIG 预设默认值
|
|
136
|
+
|
|
137
|
+
| 组件 | 预设默认值 |
|
|
138
|
+
| :--------- | :--- |
|
|
139
|
+
| `pro-form` | `{ inputAlign: 'right', errorMessageAlign: 'right', required: 'auto', scrollToError: true, scrollToErrorPosition: 'nearest' }` |
|
|
140
|
+
| `field` | `{ clearable: true, placeholder: '请输入' }` |
|
|
141
|
+
| 其余所有组件 | `{}`(无预设,直接使用 vant 默认值) |
|
|
142
|
+
|
|
143
|
+
### componentVars 额外配置键
|
|
144
|
+
|
|
145
|
+
`valueFormatter`, `displayFormatter`, `componentContainer`, `modelProp`, `popup` — 可通过 ProComponentProvider 全局统一配置。
|
|
146
|
+
|
|
147
|
+
```vue
|
|
148
|
+
<ProComponentProvider :component-vars="{
|
|
149
|
+
'pro-form': { inputAlign: 'left' },
|
|
150
|
+
field: { clearable: false, placeholder: '请输入内容' },
|
|
151
|
+
switch: { activeColor: '#07c160' },
|
|
152
|
+
stepper: { integer: true, min: 0 },
|
|
153
|
+
}">
|
|
154
|
+
<ProForm :form="form" />
|
|
155
|
+
</ProComponentProvider>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 6. 关键参考文件
|
|
161
|
+
|
|
162
|
+
1. **`node_modules/@qin-ui/vant-pro/api.json`** — 结构化 API 元数据(函数签名、类型定义、JSDoc)
|
|
163
|
+
2. **`node_modules/@qin-ui/vant-pro/README.md`** — 完整使用文档和代码示例
|
|
164
|
+
3. **`https://vant-ui.com/`** — vant v4 官方文档(确认组件属性时必查)
|
|
165
|
+
4. 源码类型定义 — `src/components/form/types/index.ts`(Field 类型)、`src/components/form/constants/index.ts`(componentMap)、`src/components/component-provider/constants/index.ts`(INJECT_CONFIG)
|
package/api.json
CHANGED
package/bin/init-ai.mjs
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @qin-ui
|
|
4
|
+
* @qin-ui/vant-pro AI 上下文初始化 CLI 工具
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* 在消费方项目中生成分层 AI 上下文文件,使 AI 工具能够:
|
|
7
|
+
* 1. 理解 @qin-ui/vant-pro 的 Schema 驱动架构
|
|
8
|
+
* 2. 掌握属性透传规则(van-field 作为表单项容器,属性分流到 Field 层 vs 输入控件层)
|
|
9
|
+
* 3. 快速获取完整 API 参考和 vant 官方文档查阅指南
|
|
8
10
|
*
|
|
9
11
|
* 用法:
|
|
10
12
|
* npx @qin-ui/vant-pro init-ai
|
|
@@ -28,46 +30,202 @@ const PKG_SHORT = PKG_NAME.replace(/^@qin-ui\//, '');
|
|
|
28
30
|
|
|
29
31
|
// ==================== 终端颜色 ====================
|
|
30
32
|
|
|
31
|
-
const green =
|
|
32
|
-
const cyan =
|
|
33
|
-
const bold =
|
|
34
|
-
const
|
|
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`;
|
|
35
38
|
|
|
36
|
-
// ====================
|
|
39
|
+
// ==================== 内容读取 ====================
|
|
37
40
|
|
|
38
|
-
function
|
|
39
|
-
const filePath = path.join(PKG_ROOT,
|
|
41
|
+
function readPackageFile(filename) {
|
|
42
|
+
const filePath = path.join(PKG_ROOT, filename);
|
|
40
43
|
if (fs.existsSync(filePath)) {
|
|
41
44
|
return fs.readFileSync(filePath, 'utf-8').trim();
|
|
42
45
|
}
|
|
43
|
-
return
|
|
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') || '';
|
|
44
55
|
}
|
|
45
56
|
|
|
46
|
-
function
|
|
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
|
+
* 包含:架构关系、透传规则、反模式、Popup 模式、vant 参考链接
|
|
72
|
+
*/
|
|
73
|
+
function getRulesContent() {
|
|
47
74
|
const aiContext = getAiContextContent();
|
|
48
|
-
const core = [
|
|
49
|
-
aiContext,
|
|
50
|
-
'',
|
|
51
|
-
'## 完整 API 参考',
|
|
52
|
-
'',
|
|
53
|
-
`使用 \`${PKG_NAME}\` 时,请阅读以下文件获取完整的 API 定义、类型签名和使用示例:`,
|
|
54
|
-
`- \`node_modules/${PKG_NAME}/README.md\` — 详细使用文档和代码示例`,
|
|
55
|
-
`- \`node_modules/${PKG_NAME}/api.json\` — 结构化 API 元数据(组件、Hook、类型的签名和 JSDoc 示例)`,
|
|
56
|
-
'',
|
|
57
|
-
].join('\n');
|
|
58
75
|
|
|
59
|
-
// 包含兼容性的 Frontmatter(如 Cursor 支持的 globs 等)
|
|
60
76
|
return [
|
|
61
77
|
'---',
|
|
62
|
-
`description: "${PKG_NAME} 组件库使用规范"`,
|
|
78
|
+
`description: "${PKG_NAME} 组件库使用规范 — Schema 驱动、van-field 属性分层"`,
|
|
63
79
|
'globs: ["**/*.vue", "**/*.ts", "**/*.tsx"]',
|
|
64
80
|
'alwaysApply: false',
|
|
65
81
|
'---',
|
|
66
82
|
'',
|
|
67
|
-
|
|
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
|
+
'- **[vant v4 官方文档](https://vant-ui.com/)** — vant 全部组件 API 文档(编写 Field 配置中透传属性前必查)',
|
|
97
|
+
'',
|
|
68
98
|
].join('\n');
|
|
69
99
|
}
|
|
70
100
|
|
|
101
|
+
/**
|
|
102
|
+
* 生成 API 文档内容(Resources 层)
|
|
103
|
+
* 从 README.md + api.json 合并提取完整 API 参考
|
|
104
|
+
*/
|
|
105
|
+
function getApiDocContent() {
|
|
106
|
+
const readme = getReadmeContent();
|
|
107
|
+
const apiJson = getApiJsonContent();
|
|
108
|
+
|
|
109
|
+
const sections = [];
|
|
110
|
+
|
|
111
|
+
sections.push(`# ${PKG_NAME} — 完整 API 参考`, '');
|
|
112
|
+
sections.push(`> 自动生成自 README.md 和 api.json。版本: ${PKG_JSON.version}`, '');
|
|
113
|
+
|
|
114
|
+
// README 内容(已包含完整的使用文档)
|
|
115
|
+
if (readme) {
|
|
116
|
+
sections.push(readme);
|
|
117
|
+
sections.push('');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// 结构化 API 元数据
|
|
121
|
+
if (apiJson && apiJson.api && apiJson.api.length > 0) {
|
|
122
|
+
sections.push('---');
|
|
123
|
+
sections.push('');
|
|
124
|
+
sections.push('## 📊 结构化 API 元数据(自动提取自源码 JSDoc)');
|
|
125
|
+
sections.push('');
|
|
126
|
+
|
|
127
|
+
for (const item of apiJson.api) {
|
|
128
|
+
const typeLabel = {
|
|
129
|
+
component: '🧩 组件',
|
|
130
|
+
function: '🔧 函数/Hook',
|
|
131
|
+
type: '📐 类型',
|
|
132
|
+
interface: '📋 接口',
|
|
133
|
+
constant: '📌 常量',
|
|
134
|
+
}[item.type] || '📄';
|
|
135
|
+
|
|
136
|
+
sections.push(`### ${typeLabel} \`${item.name}\``);
|
|
137
|
+
sections.push('');
|
|
138
|
+
sections.push(`**类型:** ${item.type}`);
|
|
139
|
+
if (item.signature) {
|
|
140
|
+
sections.push('');
|
|
141
|
+
sections.push('```typescript');
|
|
142
|
+
sections.push(item.signature);
|
|
143
|
+
sections.push('```');
|
|
144
|
+
}
|
|
145
|
+
if (item.description) {
|
|
146
|
+
sections.push('');
|
|
147
|
+
sections.push(item.description);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (item.typeParams && item.typeParams.length > 0) {
|
|
151
|
+
sections.push('');
|
|
152
|
+
sections.push('**泛型参数:**');
|
|
153
|
+
for (const tp of item.typeParams) {
|
|
154
|
+
const extras = [];
|
|
155
|
+
if (tp.extends) extras.push(`extends ${tp.extends}`);
|
|
156
|
+
if (tp.default) extras.push(`默认 ${tp.default}`);
|
|
157
|
+
const extra = extras.length ? ` (${extras.join(', ')})` : '';
|
|
158
|
+
sections.push(`- \`${tp.name}\`${extra}`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (item.params && item.params.length > 0) {
|
|
163
|
+
sections.push('');
|
|
164
|
+
sections.push('**参数:**');
|
|
165
|
+
sections.push('');
|
|
166
|
+
sections.push('| 参数名 | 类型 | 可选 | 描述 |');
|
|
167
|
+
sections.push('| :--- | :--- | :--- | :--- |');
|
|
168
|
+
for (const p of item.params) {
|
|
169
|
+
sections.push(`| \`${p.name}\` | \`${p.type}\` | ${p.optional ? '是' : '否'} | ${p.description} |`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (item.returns) {
|
|
174
|
+
sections.push('');
|
|
175
|
+
sections.push(`**返回值:** ${item.returns}`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (item.examples && item.examples.length > 0) {
|
|
179
|
+
sections.push('');
|
|
180
|
+
sections.push('**示例:**');
|
|
181
|
+
for (const ex of item.examples) {
|
|
182
|
+
sections.push('');
|
|
183
|
+
sections.push(ex);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
sections.push('');
|
|
188
|
+
sections.push('---');
|
|
189
|
+
sections.push('');
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// vant 官方文档参考
|
|
194
|
+
sections.push('---');
|
|
195
|
+
sections.push('');
|
|
196
|
+
sections.push('## 🔗 vant v4 组件 API 参考');
|
|
197
|
+
sections.push('');
|
|
198
|
+
sections.push(`${PKG_NAME} 基于 vant v4 移动端组件库封装。所有 Field 配置中的透传属性最终绑定到 vant 组件。`);
|
|
199
|
+
sections.push('');
|
|
200
|
+
sections.push('编写 Field 配置中的输入控件属性前,务必查阅 vant 官方文档确认属性名和类型:');
|
|
201
|
+
sections.push('');
|
|
202
|
+
sections.push('- **[vant v4 官方文档](https://vant-ui.com/)** — 全部组件 Demo + API 文档');
|
|
203
|
+
sections.push('');
|
|
204
|
+
sections.push('### vant-pro 与 vant 的关键对应关系');
|
|
205
|
+
sections.push('');
|
|
206
|
+
sections.push('| Field `component` | vant 组件 | 文档链接 |');
|
|
207
|
+
sections.push('|:--|:--|:--|');
|
|
208
|
+
sections.push('| `field` | Field | https://vant-ui.com/#/field |');
|
|
209
|
+
sections.push('| `switch` | Switch | https://vant-ui.com/#/switch |');
|
|
210
|
+
sections.push('| `stepper` | Stepper | https://vant-ui.com/#/stepper |');
|
|
211
|
+
sections.push('| `rate` | Rate | https://vant-ui.com/#/rate |');
|
|
212
|
+
sections.push('| `slider` | Slider | https://vant-ui.com/#/slider |');
|
|
213
|
+
sections.push('| `uploader` | Uploader | https://vant-ui.com/#/uploader |');
|
|
214
|
+
sections.push('| `checkbox-group` | CheckboxGroup | https://vant-ui.com/#/checkbox |');
|
|
215
|
+
sections.push('| `radio-group` | RadioGroup | https://vant-ui.com/#/radio |');
|
|
216
|
+
sections.push('| `picker` | Picker | https://vant-ui.com/#/picker |');
|
|
217
|
+
sections.push('| `date-picker` | DatePicker | https://vant-ui.com/#/date-picker |');
|
|
218
|
+
sections.push('| `time-picker` | TimePicker | https://vant-ui.com/#/time-picker |');
|
|
219
|
+
sections.push('| `cascader` | Cascader | https://vant-ui.com/#/cascader |');
|
|
220
|
+
sections.push('| `area` | Area | https://vant-ui.com/#/area |');
|
|
221
|
+
sections.push('| `signature` | Signature | https://vant-ui.com/#/signature |');
|
|
222
|
+
sections.push('| `button` | Button | https://vant-ui.com/#/button |');
|
|
223
|
+
sections.push('');
|
|
224
|
+
sections.push('> 注意:vant 使用 `modelValue` 作为 v-model 绑定属性名,使用 `clearable` 而非 `allowClear`。');
|
|
225
|
+
|
|
226
|
+
return sections.join('\n');
|
|
227
|
+
}
|
|
228
|
+
|
|
71
229
|
// ==================== 文件写入 ====================
|
|
72
230
|
|
|
73
231
|
function ensureDir(dirPath) {
|
|
@@ -76,31 +234,43 @@ function ensureDir(dirPath) {
|
|
|
76
234
|
}
|
|
77
235
|
}
|
|
78
236
|
|
|
237
|
+
function writeFileWithLog(filePath, content, label) {
|
|
238
|
+
const dir = path.dirname(filePath);
|
|
239
|
+
ensureDir(dir);
|
|
240
|
+
const existed = fs.existsSync(filePath);
|
|
241
|
+
fs.writeFileSync(filePath, content, 'utf-8');
|
|
242
|
+
const status = existed ? yellow('[更新]') : green('[创建]');
|
|
243
|
+
console.log(` ${status} ${cyan(label)}`);
|
|
244
|
+
}
|
|
245
|
+
|
|
79
246
|
// ==================== CLI 入口 ====================
|
|
80
247
|
|
|
81
248
|
function printHelp() {
|
|
82
249
|
console.log(`
|
|
83
|
-
${bold(`${PKG_NAME} CLI
|
|
250
|
+
${bold(`${PKG_NAME} CLI — AI 上下文初始化`)}
|
|
84
251
|
|
|
85
252
|
${bold('用法:')}
|
|
86
253
|
npx ${PKG_NAME} init-ai
|
|
87
254
|
|
|
88
|
-
${bold('
|
|
89
|
-
|
|
255
|
+
${bold('说明:')}
|
|
256
|
+
在项目中生成分层 AI 上下文文件,使 AI 工具能够深度理解和规范使用 ${PKG_NAME}。
|
|
257
|
+
|
|
258
|
+
生成的文件结构:
|
|
259
|
+
.agents/
|
|
260
|
+
rules/
|
|
261
|
+
${PKG_SHORT}.md 规则文件(架构、透传规则、反模式、Popup 模式)
|
|
262
|
+
docs/
|
|
263
|
+
${PKG_SHORT}-api.md API 参考(完整文档 + 结构化元数据 + vant 组件对照)
|
|
90
264
|
|
|
91
265
|
${bold('选项:')}
|
|
92
266
|
--help 显示帮助信息
|
|
93
|
-
|
|
94
|
-
${bold('说明:')}
|
|
95
|
-
该命令将采用统一的 Agentic 标准,在项目的 .agents/rules/ 目录下
|
|
96
|
-
生成上下文文件。兼容支持读取 .agents 的主流 AI IDE 和 CLI 工具。
|
|
97
267
|
`);
|
|
98
268
|
}
|
|
99
269
|
|
|
100
270
|
function main() {
|
|
101
271
|
const args = process.argv.slice(2);
|
|
102
|
-
const subcommand = args.find(
|
|
103
|
-
const flags = args.filter(
|
|
272
|
+
const subcommand = args.find(a => !a.startsWith('-'));
|
|
273
|
+
const flags = args.filter(a => a.startsWith('-'));
|
|
104
274
|
|
|
105
275
|
if (!subcommand || flags.includes('--help') || flags.includes('-h')) {
|
|
106
276
|
printHelp();
|
|
@@ -108,35 +278,55 @@ function main() {
|
|
|
108
278
|
}
|
|
109
279
|
|
|
110
280
|
if (subcommand !== 'init-ai') {
|
|
111
|
-
console.error(
|
|
281
|
+
console.error(`\n ❌ 未知命令: ${subcommand}\n`);
|
|
112
282
|
printHelp();
|
|
113
283
|
process.exit(1);
|
|
114
284
|
}
|
|
115
285
|
|
|
116
286
|
console.log('');
|
|
117
|
-
console.log(bold(`📦 ${PKG_NAME} — AI 上下文初始化
|
|
287
|
+
console.log(bold(`📦 ${PKG_NAME} — AI 上下文初始化 v${PKG_JSON.version}`));
|
|
288
|
+
console.log(dim(` 基于 vant v4 的 Schema 驱动移动端表单组件库`));
|
|
118
289
|
console.log('');
|
|
119
|
-
|
|
120
|
-
const content = getUnifiedAgentContent();
|
|
121
|
-
const dirPath = '.agents/rules';
|
|
122
|
-
const fileName = `${PKG_SHORT}.md`;
|
|
123
|
-
|
|
124
|
-
const fullDir = path.join(process.cwd(), dirPath);
|
|
125
|
-
const fullPath = path.join(fullDir, fileName);
|
|
126
290
|
|
|
127
|
-
|
|
128
|
-
|
|
291
|
+
// 1. 生成 Rules 文件
|
|
292
|
+
console.log(bold('📋 规则层 (Rules)'));
|
|
293
|
+
const rulesContent = getRulesContent();
|
|
294
|
+
writeFileWithLog(
|
|
295
|
+
path.join(process.cwd(), '.agents/rules', `${PKG_SHORT}.md`),
|
|
296
|
+
rulesContent,
|
|
297
|
+
`.agents/rules/${PKG_SHORT}.md`
|
|
298
|
+
);
|
|
299
|
+
console.log(dim(' → 架构概览、属性分层(Field 容器 / 输入控件)、渐进用法、反模式、Popup 弹窗模式'));
|
|
300
|
+
console.log('');
|
|
129
301
|
|
|
130
|
-
|
|
131
|
-
console.log(
|
|
302
|
+
// 2. 生成 API 文档
|
|
303
|
+
console.log(bold('📖 参考层 (Docs)'));
|
|
304
|
+
const apiDocContent = getApiDocContent();
|
|
305
|
+
writeFileWithLog(
|
|
306
|
+
path.join(process.cwd(), '.agents/docs', `${PKG_SHORT}-api.md`),
|
|
307
|
+
apiDocContent,
|
|
308
|
+
`.agents/docs/${PKG_SHORT}-api.md`
|
|
309
|
+
);
|
|
310
|
+
console.log(dim(' → 完整 README 文档 + 结构化 API 元数据 + vant v4 组件对照表'));
|
|
311
|
+
console.log('');
|
|
132
312
|
|
|
313
|
+
// 3. 完成提示
|
|
314
|
+
console.log(green('✅ 完成!已生成分层 AI 上下文文件。'));
|
|
133
315
|
console.log('');
|
|
134
|
-
console.log(
|
|
316
|
+
console.log(`${bold('📂 生成的文件:')}`);
|
|
317
|
+
console.log(` ${cyan('.agents/')}`);
|
|
318
|
+
console.log(` ├── ${cyan('rules/')}`);
|
|
319
|
+
console.log(` │ └── ${cyan(PKG_SHORT + '.md')} ${dim('← 核心规则(AI 优先读取)')}`);
|
|
320
|
+
console.log(` └── ${cyan('docs/')}`);
|
|
321
|
+
console.log(` └── ${cyan(PKG_SHORT + '-api.md')} ${dim('← 完整 API 参考')}`);
|
|
322
|
+
console.log('');
|
|
323
|
+
|
|
324
|
+
console.log(`${bold('🔄 建议的下一步:')}`);
|
|
325
|
+
console.log(` 1. 提交 ${cyan('.agents/')} 目录到 Git 仓库,团队共享`);
|
|
326
|
+
console.log(` 2. 查阅 ${bold('vant v4 官方文档')}:`);
|
|
327
|
+
console.log(` ${cyan('https://vant-ui.com/')}`);
|
|
328
|
+
console.log(` 3. ${dim('(可选)了解 vant-pro 独有的 Popup 弹窗表单模式,移动端表单利器')}`);
|
|
135
329
|
console.log('');
|
|
136
|
-
console.log(`${bold('下一步:')}`);
|
|
137
|
-
console.log(
|
|
138
|
-
` 将 ${cyan(dirPath)} 目录提交到 Git,团队即可自动享受 AI 增强\n`
|
|
139
|
-
);
|
|
140
330
|
}
|
|
141
331
|
|
|
142
332
|
main();
|