@qin-ui/element-plus-pro 1.1.2 → 1.1.3
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 +266 -162
- package/README.md +303 -84
- package/api.json +95 -1
- package/bin/init-ai.mjs +118 -99
- package/package.json +4 -4
package/AI-CONTEXT.md
CHANGED
|
@@ -1,241 +1,345 @@
|
|
|
1
|
-
# @qin-ui/element-plus-pro
|
|
1
|
+
# @qin-ui/element-plus-pro
|
|
2
2
|
|
|
3
|
-
基于
|
|
3
|
+
基于 element-plus v2.x(`el-` 前缀)封装的 Schema 驱动组件库。
|
|
4
|
+
用 JS 配置对象描述 UI,不写 `<el-*>` 模板堆叠。ProForm/ProTable 是渲染引擎,所有真实 UI 来自 element-plus。
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
## 安装与注册
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
### 1.1 三层架构
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
┌─────────────────────────────────────────────────┐
|
|
13
|
-
│ Field[] 配置层(用户编写的 JS 对象) │
|
|
14
|
-
│ { path:'name', component:'input', span:8, ... } │
|
|
15
|
-
├─────────────────────────────────────────────────┤
|
|
16
|
-
│ @qin-ui/element-plus-pro(Schema 解析 + 组件解析)│
|
|
17
|
-
│ 属性分层剥离 → Grid→el-col, FormItem→el-form-item, 剩余→输入控件 │
|
|
18
|
-
├─────────────────────────────────────────────────┤
|
|
19
|
-
│ element-plus(Vue 3 组件库,el- 前缀) │
|
|
20
|
-
│ el-input / el-select / el-date-picker / el-table ...│
|
|
21
|
-
└─────────────────────────────────────────────────┘
|
|
8
|
+
```bash
|
|
9
|
+
pnpm add @qin-ui/element-plus-pro # peerDeps: element-plus ^2.13.6, vue ^3.5
|
|
22
10
|
```
|
|
23
11
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
| :----------------- | :---------------- | :--------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------- |
|
|
30
|
-
| `'input'` | el-input | textarea, password | placeholder, maxlength, clearable, showWordLimit, showPassword, autosize |
|
|
31
|
-
| `'input-number'` | el-input-number | — | min, max, step, precision, controls, placeholder |
|
|
32
|
-
| `'autocomplete'` | el-autocomplete | — | placeholder, clearable, fetchSuggestions, triggerOnFocus |
|
|
33
|
-
| `'select'` | el-select | — | **options**, multiple, filterable, clearable, allowCreate, loading, remote, remoteMethod |
|
|
34
|
-
| `'cascader'` | el-cascader | — | **options**, props, filterable, clearable, showAllLevels |
|
|
35
|
-
| `'date-picker'` | el-date-picker | date, daterange, datetime, datetimerange, week, month, monthrange, year, yearrange | format, valueFormat, disabledDate, clearable, startPlaceholder, endPlaceholder, shortcuts |
|
|
36
|
-
| `'time-picker'` | el-time-picker | — | format, clearable, isRange, startPlaceholder, endPlaceholder |
|
|
37
|
-
| `'time-select'` | el-time-select | — | start, end, step, clearable, minTime, maxTime |
|
|
38
|
-
| `'checkbox-group'` | el-checkbox-group | — | **options**, min, max, disabled |
|
|
39
|
-
| `'radio-group'` | el-radio-group | — | **options**, disabled, size |
|
|
40
|
-
| `'switch'` | el-switch | — | activeText, inactiveText, activeValue, inactiveValue, loading, size |
|
|
41
|
-
| `'slider'` | el-slider | — | min, max, step, showStops, range, marks |
|
|
42
|
-
| `'tree-select'` | el-tree-select | — | **data**, filterable, clearable, checkStrictly, props, multiple, showCheckbox |
|
|
43
|
-
| `'transfer'` | el-transfer | — | **data**, **titles**, filterable, filterMethod, props |
|
|
44
|
-
| `'custom'` | 自定义 | — | component 直接传入 Vue 组件或 h() 渲染函数 |
|
|
45
|
-
|
|
46
|
-
> **编写任何控件属性前,必须查阅 [element-plus 官方文档](https://element-plus.org/) 确认属性名和类型。**
|
|
12
|
+
```ts
|
|
13
|
+
import ElementPlusPro from '@qin-ui/element-plus-pro';
|
|
14
|
+
import '@qin-ui/element-plus-pro/element-plus-pro.css';
|
|
15
|
+
app.use(ElementPlusPro); // 全局注册 ProForm / ProTable / ProComponentProvider
|
|
16
|
+
```
|
|
47
17
|
|
|
48
|
-
|
|
18
|
+
## 两条核心心智模型
|
|
49
19
|
|
|
50
|
-
|
|
20
|
+
**1. 配置驱动**:`useForm(数据, Field[])` / `useTable({ columns, searchFields })` 生成实例,组件接收实例。
|
|
51
21
|
|
|
52
|
-
Field
|
|
22
|
+
**2. 属性分层透传**(最关键):Field 上的属性被"剥离到不同 DOM 层",不是全塞给输入控件。写错层就失效:
|
|
53
23
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
```
|
|
24
|
+
| 属性 | 落到哪一层 | 说明 |
|
|
25
|
+
| :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------- | :------------- |
|
|
26
|
+
| `span`/`offset`/`push`/`pull`/`xs`..`xl` | `<el-col>` Grid 层 | 仅 grid 开启时 |
|
|
27
|
+
| `label`/`rules`/`error`/`required`/`size`/`showMessage`/`inlineMessage`/`labelWidth`/`formItemClass`/`formItemStyle`/`formItemDataAttrs` | `<el-form-item>` 层 | 表单项 |
|
|
28
|
+
| `disabled`/`placeholder`/`clearable`/`options`/`filterable`/`multiple`/`maxlength`/`componentClass`/`componentStyle`/`componentDataAttrs` + 该控件其余 element-plus 原生属性 | 输入控件本身(el-input 等) | 其余全部 |
|
|
29
|
+
| `component`/`hidden`/`modelProp`/`valueFormatter`/`fields`/`slots`/`formItemContainer`/`componentContainer`/`extraProps` | ProForm 逻辑消费,**不绑到 DOM** | 框架级 |
|
|
61
30
|
|
|
62
|
-
|
|
31
|
+
> 规则:`span` 给 Grid,`label`/`rules` 给 FormItem,其余给输入控件。
|
|
32
|
+
> **element-plus 命名约定**:用 `clearable`(不是 `allowClear`)、`showWordLimit`(不是 `showCount`)、`autosize`(小写 d);el-form-item 插槽为 `label` 和 `error`。
|
|
63
33
|
|
|
64
|
-
|
|
34
|
+
## component 映射(Field.component 字符串 -> element-plus 组件)
|
|
65
35
|
|
|
66
|
-
|
|
36
|
+
`input`->el-input · `input-number`->el-input-number · `autocomplete`->el-autocomplete · `select`->el-select ·
|
|
37
|
+
`cascader`->el-cascader · `date-picker`->el-date-picker · `time-picker`->el-time-picker · `time-select`->el-time-select ·
|
|
38
|
+
`checkbox-group`->el-checkbox-group · `radio-group`->el-radio-group · `switch`->el-switch · `slider`->el-slider ·
|
|
39
|
+
`tree-select`->el-tree-select · `transfer`->el-transfer · `custom`->用户自定义组件
|
|
67
40
|
|
|
68
|
-
|
|
41
|
+
> `input` 通过 `type` 子类型区分:`type: 'textarea'` 文本域、`type: 'password'` 密码框。
|
|
42
|
+
> `date-picker` 通过 `type` 子类型区分:`date`/`dates`/`daterange`/`datetime`/`datetimerange`/`week`/`month`/`monthrange`/`months`/`year`/`yearrange`/`years`。
|
|
43
|
+
> 写 Field 中输入控件的具体属性前,**属性名/类型以 https://element-plus.org 官方文档为准**。
|
|
69
44
|
|
|
70
|
-
|
|
45
|
+
## 隐式默认行为(INJECT_CONFIG,易踩坑)
|
|
71
46
|
|
|
72
|
-
|
|
47
|
+
由 `ProComponentProvider` 注入,优先级低于 Field 配置。**不写也有这些默认值,需知晓以免行为与预期不符:**
|
|
73
48
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
49
|
+
| component | 默认预设 |
|
|
50
|
+
| :----------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
51
|
+
| `switch` | `{ modelProp: 'modelValue' }` -> v-model 绑 `modelValue`(element-plus 惯例,即 `v-model`) |
|
|
52
|
+
| `input` | `{ maxlength: 100, clearable: true, placeholder: '请输入' }` |
|
|
53
|
+
| `input.textarea` | `{ maxlength: 200, autosize: {minRows:3,maxRows:6}, showWordLimit: true, clearable: true, placeholder: '请输入' }` |
|
|
54
|
+
| `input.password` | `{ showPassword: true, maxlength: 100, clearable: true, placeholder: '请输入' }` |
|
|
55
|
+
| `input-number` | `{ max: 1e15-1, min: -(1e15+1), controls: false, placeholder: '请输入', style:{width:'100%'} }` |
|
|
56
|
+
| `select` / `cascader` / `autocomplete` / `tree-select` | `{ clearable: true, placeholder: '请选择' }` |
|
|
57
|
+
| `date-picker` / `time-picker` / `time-select` | `{ style:{width:'100%'}, placeholder: '请选择' }` |
|
|
58
|
+
| `pro-form` | `{ grid: { gutter: 24 } }` |
|
|
59
|
+
| `pro-form-item` | `{ span: 8 }` |
|
|
60
|
+
| `pro-table` | `{ pagination:{layout:'total,sizes,prev,pager,next,jumper', pageSizes:[10,20,30,40,50,100], background:true}, searchFormConfig:{layout:'grid', expand:{minExpandRows:2}}, control:true, addIndexColumn:true }` |
|
|
77
61
|
|
|
78
|
-
|
|
62
|
+
> `modelProp` 控制 v-model 绑定名,element-plus 默认 `'modelValue'`(即 `v-model`)。
|
|
63
|
+
> `date-picker` 支持按 type 子类型分别预设:`date-picker.date` / `.daterange` / `.datetime` / `.week` / `.month` / `.monthrange` / `.year` / `.yearrange` 等,范围类型自带 `startPlaceholder`/`endPlaceholder`。
|
|
79
64
|
|
|
80
|
-
|
|
81
|
-
- el-form-item 插槽为 `label` 和 `error`;其他 slot key 透传到底层输入组件(如 el-input 的 `prefix`/`suffix`/`append`/`prepend`)
|
|
65
|
+
## useForm -- 表单实例
|
|
82
66
|
|
|
83
|
-
|
|
67
|
+
```ts
|
|
68
|
+
// 重载一(常用):初始数据 + 字段配置
|
|
69
|
+
const form = useForm<User>(
|
|
70
|
+
{ name: '张三', age: 25 }, // initFormData
|
|
71
|
+
[
|
|
72
|
+
{
|
|
73
|
+
path: 'name',
|
|
74
|
+
label: '姓名',
|
|
75
|
+
component: 'input',
|
|
76
|
+
rules: [{ required: true }],
|
|
77
|
+
},
|
|
78
|
+
] // Field[]
|
|
79
|
+
);
|
|
80
|
+
// 重载二:仅拿实例(root=true/false)
|
|
81
|
+
const form = useForm<User>(true);
|
|
82
|
+
```
|
|
84
83
|
|
|
85
|
-
|
|
84
|
+
返回 `Form` 实例(**`formData` 是 reactive 对象,不用 `.value`**):
|
|
86
85
|
|
|
87
|
-
|
|
86
|
+
| 成员 | 说明 |
|
|
87
|
+
| :------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------- |
|
|
88
|
+
| `form.formData` | 响应式数据,可直接读写,支持深层路径 `formData.address.city` |
|
|
89
|
+
| `form.getFormData(path)` / `form.setFormData(path, value)` | 路径读写;setFormData 还支持 `setFormData(path, prev=>new)` 和 `setFormData({...})` 批量覆盖 |
|
|
90
|
+
| `form.fields` | 字段配置数组(Ref) |
|
|
91
|
+
| `form.getField(path)` / `form.setField(path, patch)` | 字段增改查;setField 默认合并,`{updateType:'rewrite'}` 覆盖 |
|
|
92
|
+
| `form.deleteField` / `form.appendField` / `form.prependField` / `form.getParentField` | 字段增删 |
|
|
93
|
+
| `form.formRef` | 底层 element-plus Form 实例引用(Ref),`formRef.value?.validate()` / `.resetFields()` |
|
|
88
94
|
|
|
89
|
-
|
|
95
|
+
## ProForm 最小示例
|
|
90
96
|
|
|
91
|
-
```
|
|
92
|
-
|
|
97
|
+
```vue
|
|
98
|
+
<script setup lang="ts">
|
|
99
|
+
import { ProForm, useForm } from '@qin-ui/element-plus-pro';
|
|
100
|
+
interface User {
|
|
101
|
+
username: string;
|
|
102
|
+
age: number;
|
|
103
|
+
gender: string;
|
|
104
|
+
}
|
|
105
|
+
const form = useForm<User>({ username: '', age: 18, gender: 'male' }, [
|
|
93
106
|
{
|
|
94
107
|
path: 'username',
|
|
95
108
|
component: 'input',
|
|
96
109
|
label: '用户名',
|
|
97
|
-
|
|
98
|
-
rules: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
|
|
110
|
+
rules: [{ required: true, trigger: 'blur' }],
|
|
99
111
|
},
|
|
112
|
+
{ path: 'age', component: 'input-number', label: '年龄', min: 1, max: 150 },
|
|
100
113
|
{
|
|
101
|
-
path: '
|
|
102
|
-
component: '
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
114
|
+
path: 'gender',
|
|
115
|
+
component: 'select',
|
|
116
|
+
label: '性别',
|
|
117
|
+
options: [
|
|
118
|
+
{ label: '男', value: 'male' },
|
|
119
|
+
{ label: '女', value: 'female' },
|
|
120
|
+
],
|
|
106
121
|
},
|
|
107
122
|
]);
|
|
108
|
-
|
|
123
|
+
const submit = async () => {
|
|
124
|
+
await form.formRef.value?.validate();
|
|
125
|
+
console.log(form.formData);
|
|
126
|
+
};
|
|
127
|
+
</script>
|
|
128
|
+
<template>
|
|
129
|
+
<ProForm :form="form" />
|
|
130
|
+
<el-button type="primary" @click="submit">提交</el-button>
|
|
131
|
+
</template>
|
|
109
132
|
```
|
|
110
133
|
|
|
111
|
-
|
|
134
|
+
## 自定义组件(4 种方式)
|
|
135
|
+
|
|
136
|
+
`Field.component` 的解析优先级(高 -> 低):
|
|
137
|
+
`teleport 插槽注入` > `ProComponentProvider.componentMap` > `内置 componentMap` > `原始 component 值`
|
|
112
138
|
|
|
113
|
-
|
|
139
|
+
### 方式 1:传入 SFC 单文件组件对象(推荐,单字段最常用)
|
|
140
|
+
|
|
141
|
+
`component` 直接传组件对象,**必须用 `markRaw` 包裹**。
|
|
114
142
|
|
|
115
143
|
```ts
|
|
116
|
-
|
|
117
|
-
|
|
144
|
+
import { markRaw } from 'vue';
|
|
145
|
+
import MyInput from './MyInput.vue';
|
|
146
|
+
{ path: 'code', label: '验证码', component: markRaw(MyInput) }
|
|
147
|
+
```
|
|
118
148
|
|
|
119
|
-
|
|
120
|
-
|
|
149
|
+
> ⚠️ **必须 markRaw**:不包会被 Vue 当成响应式对象深度代理,触发性能警告甚至渲染异常。
|
|
150
|
+
> 类型上 `component` 接受 `RenderComponentType | Raw<RenderComponentType>`,`Raw<T>` 即 markRaw 的类型标记。
|
|
151
|
+
> 此字段不支持响应式(不能包 ref/computed)。
|
|
121
152
|
|
|
122
|
-
|
|
123
|
-
|
|
153
|
+
### 方式 2:传入 render 函数(单字段,需动态拼装 props 时)
|
|
154
|
+
|
|
155
|
+
`component` 传 `(props, ctx) => VNode`。`props` 含 v-model 绑定值与 path,`ctx.attrs` 含透传属性。
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
import { h } from 'vue';
|
|
159
|
+
import MyInput from './MyInput.vue';
|
|
160
|
+
{ path: 'code', label: '验证码', component: (p, ctx) => h(MyInput, { ...p, ...ctx.attrs }) }
|
|
124
161
|
```
|
|
125
162
|
|
|
126
|
-
|
|
163
|
+
### 方式 3:ProComponentProvider 注入 componentMap(全局复用,推荐多字段场景)
|
|
164
|
+
|
|
165
|
+
在根用 `componentMap` 注册,Field 里用字符串引用。**可覆盖内置组件**(如 `input: MyInput` 替换全局 input)。
|
|
166
|
+
|
|
167
|
+
```vue
|
|
168
|
+
<script setup lang="ts">
|
|
169
|
+
import { ProComponentProvider } from '@qin-ui/element-plus-pro';
|
|
170
|
+
import MyRichTextEditor from './components/MyRichTextEditor.vue';
|
|
171
|
+
const componentMap = { 'rich-editor': MyRichTextEditor };
|
|
172
|
+
</script>
|
|
173
|
+
<template>
|
|
174
|
+
<ProComponentProvider :component-map="componentMap">
|
|
175
|
+
<ProForm :form="form" />
|
|
176
|
+
</ProComponentProvider>
|
|
177
|
+
</template>
|
|
178
|
+
```
|
|
127
179
|
|
|
128
|
-
|
|
180
|
+
**追加全局声明获取强类型补全**(项目任意 `.d.ts`):
|
|
129
181
|
|
|
130
182
|
```ts
|
|
131
|
-
|
|
132
|
-
|
|
183
|
+
declare module '@qin-ui/element-plus-pro' {
|
|
184
|
+
interface ComponentMap {
|
|
185
|
+
'rich-editor': typeof MyRichTextEditor;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
// 之后 component: 'rich-editor' 即获精准属性类型联想
|
|
133
189
|
```
|
|
134
190
|
|
|
135
|
-
|
|
136
|
-
|
|
191
|
+
### 方式 4:模板 scoped slot(声明式,简单替换)
|
|
192
|
+
|
|
193
|
+
插槽名 = 字段 `path`,绑定参数通过 `v-bind="scoped"` 转发(teleport 机制,优先级最高)。
|
|
194
|
+
|
|
195
|
+
```vue
|
|
137
196
|
<ProForm :form="form">
|
|
138
197
|
<template #agreement="scoped">
|
|
139
|
-
<el-checkbox v-bind="scoped"
|
|
198
|
+
<el-checkbox v-bind="scoped">同意协议</el-checkbox>
|
|
140
199
|
</template>
|
|
141
200
|
</ProForm>
|
|
142
201
|
```
|
|
143
202
|
|
|
144
|
-
|
|
203
|
+
### 选择建议
|
|
145
204
|
|
|
146
|
-
|
|
205
|
+
- 单字段复用一个 SFC -> 方式 1(markRaw(SFC))
|
|
206
|
+
- 单字段、需动态拼装 props -> 方式 2(render 函数)
|
|
207
|
+
- 多处复用 / 替换内置组件 -> 方式 3(componentMap + 声明扩充)
|
|
208
|
+
- 简单声明式替换、不想写 h() -> 方式 4(scoped slot)
|
|
147
209
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
210
|
+
### 自定义组件需遵守的约定
|
|
211
|
+
|
|
212
|
+
- **v-model**:默认绑 `modelValue`(`v-model`)。若组件用别的 prop,通过字段 `modelProp` 指定,或在 componentVars 预设 `modelProp`
|
|
213
|
+
- **接收 path**:组件会收到 `path` prop(字段路径)
|
|
214
|
+
- **属性透传**:Field 上除框架级属性外(component/hidden/modelProp/valueFormatter/fields/slots/formItemContainer/componentContainer/extraProps 等),其余作为 attrs 透传给自定义组件
|
|
215
|
+
|
|
216
|
+
## valueFormatter -- 字段值转换
|
|
217
|
+
|
|
218
|
+
控制表单值与组件值之间的转换(如日期字符串与对象互转)。**在 onUpdate:modelValue 前(即 v-model 写回前)执行**,支持两种形态:
|
|
156
219
|
|
|
157
220
|
```ts
|
|
158
|
-
//
|
|
159
|
-
{ path: '
|
|
160
|
-
|
|
161
|
-
|
|
221
|
+
// 函数形态:(新值, 旧值) => 转换后的值,写回 formData
|
|
222
|
+
{ path: 'name', valueFormatter: (val, oldVal) => val?.trim() }
|
|
223
|
+
|
|
224
|
+
// 对象形态:get 读出时转换,set 写入时转换
|
|
225
|
+
{ path: 'birthday', component: 'date-picker',
|
|
226
|
+
valueFormatter: {
|
|
227
|
+
get: (val) => val ? new Date(val) : null, // formData -> 组件显示
|
|
228
|
+
set: (val) => val ? dayjs(val).format('YYYY-MM-DD') : null, // 组件 -> formData
|
|
229
|
+
} }
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## useTable -- 表格实例
|
|
162
233
|
|
|
163
|
-
|
|
164
|
-
|
|
234
|
+
```ts
|
|
235
|
+
const table = useTable<SearchParams, User>({
|
|
236
|
+
columns: [{ prop: 'name', label: '姓名', width: 120 }],
|
|
237
|
+
data: [], // 数据源(element-plus 用 data,非 dataSource)
|
|
238
|
+
pageParam: { current: 1, pageSize: 10, total: 0 }, // 默认值
|
|
239
|
+
searchParam: { keyword: '', status: '' },
|
|
240
|
+
searchFields: [ // 与 ProForm 同一套 Field[] 格式
|
|
241
|
+
{ path: 'keyword', component: 'input', label: '关键词' },
|
|
242
|
+
{ path: 'status', component: 'select', label: '状态', options: [...] },
|
|
243
|
+
],
|
|
244
|
+
});
|
|
165
245
|
```
|
|
166
246
|
|
|
167
|
-
|
|
247
|
+
返回 `Table` 实例(**element-plus 版数据源字段名为 `data`,非 `dataSource`**):
|
|
168
248
|
|
|
169
|
-
|
|
249
|
+
| 成员 | 说明 |
|
|
250
|
+
| :-------------------------------------------------------------------- | :----------------------------------------------------- |
|
|
251
|
+
| `table.columns` | 列配置(Ref) |
|
|
252
|
+
| `table.data` | 表格数据源(Ref,element-plus 语义) |
|
|
253
|
+
| `table.pageParam` | 分页参数(reactive):`current` / `pageSize` / `total` |
|
|
254
|
+
| `table.searchForm` | 搜索表单实例(Form 类型,所有 useForm 方法可用) |
|
|
255
|
+
| `table.setColumn` / `deleteColumn` / `appendColumn` / `prependColumn` | 列增删改查(用法同 setField) |
|
|
256
|
+
| `table.setPageParam(patch)` | 设置分页参数 |
|
|
257
|
+
| `table.resetQueryParams()` | 重置分页到第一页 + 恢复搜索条件到初始值 |
|
|
170
258
|
|
|
171
|
-
|
|
259
|
+
## ProTable -- 配置驱动表格
|
|
172
260
|
|
|
173
|
-
|
|
261
|
+
**关键:ProTable 透传所有 element-plus TableProps**(`& TableProps`),可直接写 `row-key` / `bordered` / `stripe` / `row-selection` 等原生属性;`size`、`loading` 是 v-model。
|
|
174
262
|
|
|
175
|
-
|
|
|
176
|
-
|
|
|
177
|
-
| `
|
|
178
|
-
| `
|
|
179
|
-
| `
|
|
180
|
-
| `
|
|
181
|
-
| `
|
|
182
|
-
| `
|
|
183
|
-
| `
|
|
184
|
-
| `time-picker` / `time-select` | `{ style: {width:'100%'}, placeholder: '请选择' }` |
|
|
185
|
-
| `tree-select` | `{ clearable: true, placeholder: '请选择' }` |
|
|
186
|
-
| `pro-table` | `{ pagination: {layout:'total,sizes,prev,pager,next,jumper',pageSizes:[10,20,30,40,50,100],background:true}, searchFormConfig: {layout:'grid',expand:{minExpandRows:2,expandStatus:false}}, control: true, addIndexColumn: true }` |
|
|
187
|
-
| `pro-form` | `{ grid: { gutter: 24 } }` |
|
|
188
|
-
| `pro-form-item` | `{ span: 8 }` |
|
|
263
|
+
| prop | 说明 |
|
|
264
|
+
| :----------------- | :-------------------------------------------------------------- |
|
|
265
|
+
| `table` | useTable 实例 |
|
|
266
|
+
| `search` | 数据查询方法 `() => Promise`,ProTable 内部调用它(非自动触发) |
|
|
267
|
+
| `addIndexColumn` | 首列插入 index 列 |
|
|
268
|
+
| `immediateSearch` | onMounted 时立即触发一次 search |
|
|
269
|
+
| `control` | 是否显示 size/列控制按钮,可 `{sizeControl, columnControl}` |
|
|
270
|
+
| `searchFormConfig` | 搜索栏配置,含 `hidden`(隐藏搜索区)、`container` |
|
|
271
|
+
| `tableContainer` | 表格区容器 |
|
|
189
272
|
|
|
190
|
-
|
|
273
|
+
**数据流**:搜索->重置分页到第 1 页->调 `search()`;分页/排序变化->更新 `pageParam`->调 `search()`;重置->`resetQueryParams()`->调 `search()`。
|
|
191
274
|
|
|
192
|
-
|
|
193
|
-
2. `ProComponentProvider` 的 `componentVars` 参数
|
|
194
|
-
3. `INJECT_CONFIG` 内置预设
|
|
275
|
+
## Column -- 列配置
|
|
195
276
|
|
|
196
|
-
|
|
277
|
+
继承 element-plus `TableColumnCtx`,**所有原生列属性可用**(`prop` / `label` / `width` / `fixed` / `align` / `sortable` / `formatter` / `filters`…)。新增:
|
|
278
|
+
|
|
279
|
+
- `prop`:列数据字段(主用),对应数据源 key
|
|
280
|
+
- `hidden`:隐藏该列(配合列控制,支持响应式)
|
|
281
|
+
- `render(scope)`:自定义渲染函数,接收行 scope,**优先级高于 `formatter`**
|
|
282
|
+
|
|
283
|
+
> element-plus Table 列用 `prop`(不是 `dataIndex`),数据源用 `data`(不是 `dataSource`)。
|
|
284
|
+
|
|
285
|
+
## ProTable 最小示例
|
|
197
286
|
|
|
198
287
|
```vue
|
|
199
|
-
<template>
|
|
200
|
-
<ProComponentProvider :component-vars="config">
|
|
201
|
-
<ProForm :form="form" />
|
|
202
|
-
</ProComponentProvider>
|
|
203
|
-
</template>
|
|
204
288
|
<script setup lang="ts">
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
289
|
+
import { ProTable, useTable } from '@qin-ui/element-plus-pro';
|
|
290
|
+
interface User {
|
|
291
|
+
id: number;
|
|
292
|
+
name: string;
|
|
293
|
+
status: string;
|
|
294
|
+
}
|
|
295
|
+
interface Search {
|
|
296
|
+
keyword: string;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const table = useTable<Search, User>({
|
|
300
|
+
columns: [
|
|
301
|
+
{ prop: 'name', label: '姓名', width: 120 },
|
|
302
|
+
{ prop: 'status', label: '状态' },
|
|
303
|
+
],
|
|
304
|
+
searchFields: [{ path: 'keyword', component: 'input', label: '关键词' }],
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
const fetchData = async () => {
|
|
308
|
+
// 组装查询参数:搜索条件 + 分页
|
|
309
|
+
const res = await api.list({
|
|
310
|
+
...table.searchForm.formData,
|
|
311
|
+
...table.pageParam,
|
|
312
|
+
});
|
|
313
|
+
table.data.value = res.data;
|
|
314
|
+
table.setPageParam({ total: res.total });
|
|
209
315
|
};
|
|
210
316
|
</script>
|
|
317
|
+
<template>
|
|
318
|
+
<ProTable :table="table" :search="fetchData" row-key="id" immediate-search />
|
|
319
|
+
</template>
|
|
211
320
|
```
|
|
212
321
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
## 6. ProTable 速览
|
|
322
|
+
## 响应式联动(三种模式,选最简的)
|
|
216
323
|
|
|
217
324
|
```ts
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
{ prop: 'name', label: '姓名', width: 120 },
|
|
222
|
-
],
|
|
223
|
-
// searchFields 与 ProForm fields 格式一致,支持相同分层剥离
|
|
224
|
-
searchFields: [
|
|
225
|
-
{ path: 'name', component: 'input', placeholder: '搜索' },
|
|
226
|
-
{ path: 'status', component: 'select', options: [...] },
|
|
227
|
-
],
|
|
228
|
-
data: [],
|
|
229
|
-
});
|
|
230
|
-
// 模板:<ProTable :table="table" :search="() => fetchData()" immediateSearch />
|
|
325
|
+
disabled: computed(() => !form.formData.enabled), // A 声明式,初始化时已知(首选)
|
|
326
|
+
const isDisabled = ref(false); // B 外部共享状态
|
|
327
|
+
form.setField('limitCount', { disabled: true }); // C 命令式,事件驱动
|
|
231
328
|
```
|
|
232
329
|
|
|
233
|
-
>
|
|
330
|
+
> **不支持响应式**(不能包 ref/computed)的属性:`component` / `formItemContainer` / `componentContainer` / `valueFormatter` / `fields` / `slots` / `modelProp`。
|
|
331
|
+
|
|
332
|
+
## 反模式
|
|
234
333
|
|
|
235
|
-
|
|
334
|
+
- ❌ 在 `<ProForm>` 内手写 `<el-form-item>` -- ProForm 从 Field 配置自动渲染。
|
|
335
|
+
- ❌ 猜透传属性名 -- 先查 element-plus.org(element-plus 用 `clearable` 不是 `allowClear`,`filterable` 不是 `searchable`)。
|
|
336
|
+
- ❌ 把 `span` 当输入控件属性。
|
|
337
|
+
- ❌ 传 SFC 给 `component` 不用 `markRaw`。
|
|
338
|
+
- ❌ 在 ProTable 上忘了传 `:search`,或期望它自动请求 -- 查询由你提供并驱动。
|
|
339
|
+
- ❌ 把 element-plus 当 ant-design-vue -- 列用 `prop` 不是 `dataIndex`,数据源用 `data` 不是 `dataSource`,v-model 用 `modelValue` 不是 `value`。
|
|
236
340
|
|
|
237
|
-
##
|
|
341
|
+
## 按需深查
|
|
238
342
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
343
|
+
- `node_modules/@qin-ui/element-plus-pro/api.json` -- 结构化 API 元数据(函数签名、参数、类型)。
|
|
344
|
+
- `node_modules/@qin-ui/element-plus-pro/README.md` -- 完整用法与进阶示例。
|
|
345
|
+
- 底层 element-plus 组件属性查阅官方文档:https://element-plus.org 。
|