dynamicformdjx 0.4.4 → 0.5.0
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/README.md +631 -327
- package/dist/elementPlus/EleDynamicForm.d.ts +3 -3
- package/dist/elementPlus/ElePopupModal.d.ts +89 -0
- package/dist/elementPlus/EleZealCard.d.ts +49 -0
- package/dist/elementPlus/EleZealTableTool.d.ts +202 -0
- package/dist/elementPlus/index.cjs +1 -1
- package/dist/elementPlus/index.d.ts +11 -6
- package/dist/elementPlus/index.mjs +924 -464
- package/dist/hooks/useTool.d.ts +14 -0
- package/dist/hooks/zealForm.d.ts +14 -0
- package/dist/index-BRJXkpNJ.cjs +1 -0
- package/dist/index-a2ON2stt.js +180 -0
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.mjs +252 -305
- package/dist/naiveUi/NaiPopupModal.d.ts +79 -0
- package/dist/naiveUi/NaiZealCard.d.ts +49 -0
- package/dist/naiveUi/NaiZealTableTool.d.ts +134 -0
- package/dist/naiveUi/index.cjs +1 -1
- package/dist/naiveUi/index.d.ts +11 -6
- package/dist/naiveUi/index.mjs +819 -420
- package/dist/types/form.d.ts +30 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/slots.d.ts +37 -0
- package/dist/utils/tools.d.ts +6 -1
- package/package.json +1 -1
- package/dist/index-B7xg-BCF.js +0 -42
- package/dist/index-DyThWcVg.cjs +0 -1
package/README.md
CHANGED
|
@@ -4,29 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
[Document](https://xczcdjx.github.io/dynamicFormDoc/v3/install.html)
|
|
6
6
|
|
|
7
|
-
[Vue2 版本](https://www.npmjs.com/package/dynamicformdjx-vue2)
|
|
7
|
+
[Vue2 版本](https://www.npmjs.com/package/dynamicformdjx-vue2)
|
|
8
8
|
|
|
9
|
-
[React 版本](https://www.npmjs.com/package/dynamicformdjx-react)
|
|
10
|
-
|
|
11
|
-
[//]: # (### 组件版本说明)
|
|
12
|
-
|
|
13
|
-
[//]: # (- **v0.2 及以上版本**)
|
|
14
|
-
|
|
15
|
-
[//]: # (- Form字段改为Input, ElementPlus缩短为Ele, NaiveUi缩短为Nai)
|
|
16
|
-
|
|
17
|
-
[//]: # (- 请使用:`DynamicInput`, `DynamicCascadeInput`,`EleDynamicInput`,`NaiDynamicInput` 等导入)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
[//]: # (| 版本范围 | 组件导入方式 |)
|
|
21
|
-
|
|
22
|
-
[//]: # (|---------|--------------|)
|
|
23
|
-
|
|
24
|
-
[//]: # (| ≥ 0.2 | DynamicInput, DynamicCascadeInput |)
|
|
25
|
-
|
|
26
|
-
[//]: # (| < 0.2 | DynamicForm, DynamicCascadeForm |)
|
|
9
|
+
[React 版本](https://www.npmjs.com/package/dynamicformdjx-react)
|
|
27
10
|
|
|
28
11
|
## 概述
|
|
29
12
|
|
|
13
|
+
> 新增综合`CRUD`模板
|
|
14
|
+
|
|
30
15
|
`DynamicForm` 一个灵活且动态的表单组件,使用数组,简化模版操作,提供多种hook快速操作表单等。
|
|
31
16
|
|
|
32
17
|
- 简化template代码,快速处理表单
|
|
@@ -38,6 +23,7 @@
|
|
|
38
23
|
- 支持通过 `v-model` 双向绑定任意对象,(包含受控和非受控) 可动态增删字段
|
|
39
24
|
- 支持将值解析为:字符串 / 数字 / 数组(字符串数组、数字数组)
|
|
40
25
|
- 文案、样式、数组分隔符等均可配置
|
|
26
|
+
|
|
41
27
|
---
|
|
42
28
|
|
|
43
29
|
## 安装
|
|
@@ -50,11 +36,542 @@ yarn add dynamicformdjx
|
|
|
50
36
|
# or
|
|
51
37
|
pnpm add dynamicformdjx
|
|
52
38
|
```
|
|
53
|
-
|
|
54
|
-
|
|
39
|
+
|
|
40
|
+
### 综合`CRUD` template **新**
|
|
41
|
+
|
|
42
|
+
> (依赖于naive ui或element plus组件库,请配合一起使用)
|
|
43
|
+
|
|
55
44
|
#### 与Naive ui配合
|
|
56
|
-
|
|
45
|
+
|
|
46
|
+
```vue
|
|
47
|
+
|
|
48
|
+
<script setup lang="ts">
|
|
49
|
+
import {h, nextTick, onMounted, ref} from "vue";
|
|
50
|
+
import {type DataTableColumnKey, type DataTableColumns, NButton, NDataTable, NSpace, useMessage} from "naive-ui";
|
|
51
|
+
import {
|
|
52
|
+
NaiPopupModal,
|
|
53
|
+
useDecorateForm,
|
|
54
|
+
NaiZealCard,
|
|
55
|
+
NaiDynamicForm,
|
|
56
|
+
NaiZealTableSearch,
|
|
57
|
+
NaiZealTablePaginationControl,
|
|
58
|
+
renderInput,
|
|
59
|
+
renderInputNumber,
|
|
60
|
+
} from "dynamicformdjx/naiveUi";
|
|
61
|
+
import type {
|
|
62
|
+
naiPopupModalRef,
|
|
63
|
+
naiDynamicFormRef,
|
|
64
|
+
naiZealTableSearchRef
|
|
65
|
+
} from "dynamicformdjx/naiveUi"
|
|
66
|
+
import {useDyForm, useReactiveForm, usePagination} from "dynamicformdjx";
|
|
67
|
+
|
|
68
|
+
interface SongType {
|
|
69
|
+
no: number | string
|
|
70
|
+
title: string
|
|
71
|
+
length: string
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const zealData = ref<SongType[]>([
|
|
75
|
+
{no: 3, title: 'Wonderwall', length: '4:18'},
|
|
76
|
+
{no: 4, title: 'Don\'t Look Back in Anger', length: '4:48'},
|
|
77
|
+
{no: 12, title: 'Champagne Supernova', length: '7:27'},
|
|
78
|
+
...Array.from({length: 50}).map((_, i) => ({no: i + 13, title: `test Data ${i + 1}`, length: `${i * i}`}))
|
|
79
|
+
])
|
|
80
|
+
const message = useMessage()
|
|
81
|
+
const referId = ref<string | number>('-1')
|
|
82
|
+
const tableData = ref<SongType[]>([])
|
|
83
|
+
const handleDynamicFormRef = ref<naiDynamicFormRef | null>(null)
|
|
84
|
+
const naiZealTableSearchRef = ref<naiZealTableSearchRef | null>(null)
|
|
85
|
+
const naiPopupModalRef = ref<naiPopupModalRef | null>(null)
|
|
86
|
+
const tableLoading = ref<boolean>(false)
|
|
87
|
+
const selectOpts = ref<(number | string)[]>([])
|
|
88
|
+
// search form
|
|
89
|
+
const searchFormItems = useDecorateForm([
|
|
90
|
+
{
|
|
91
|
+
key: "no",
|
|
92
|
+
label: "No",
|
|
93
|
+
renderType: 'renderInputNumber',
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
key: "title",
|
|
97
|
+
label: "Title",
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
key: "length",
|
|
101
|
+
label: "Length",
|
|
102
|
+
},
|
|
103
|
+
].map(it => ({
|
|
104
|
+
value: null,
|
|
105
|
+
clearable: true,
|
|
106
|
+
renderType: 'renderInput',
|
|
107
|
+
span: 8,
|
|
108
|
+
...it,
|
|
109
|
+
})) as any[])
|
|
110
|
+
// table column
|
|
111
|
+
const columns: DataTableColumns<SongType> = [
|
|
112
|
+
{
|
|
113
|
+
type: 'selection'
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
title: 'No',
|
|
117
|
+
key: 'no'
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
title: 'Title',
|
|
121
|
+
key: 'title'
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
title: 'Length',
|
|
125
|
+
key: 'length'
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
title: 'Action',
|
|
129
|
+
key: 'actions',
|
|
130
|
+
fixed: 'right',
|
|
131
|
+
render(row) {
|
|
132
|
+
return h(
|
|
133
|
+
NSpace, {}, [
|
|
134
|
+
h(NButton,
|
|
135
|
+
{
|
|
136
|
+
size: 'small',
|
|
137
|
+
onClick: () => upItem(row)
|
|
138
|
+
},
|
|
139
|
+
{default: () => 'update'}),
|
|
140
|
+
h(NButton,
|
|
141
|
+
{
|
|
142
|
+
size: 'small',
|
|
143
|
+
type: 'error',
|
|
144
|
+
onClick: () => delItem(row)
|
|
145
|
+
},
|
|
146
|
+
{default: () => 'delete'})
|
|
147
|
+
]
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
const pagination = usePagination(fetchData)
|
|
153
|
+
const updateFormItems = useReactiveForm<SongType>([
|
|
154
|
+
{
|
|
155
|
+
key: "no",
|
|
156
|
+
label: "No",
|
|
157
|
+
clearable: true,
|
|
158
|
+
value: null,
|
|
159
|
+
render2: (f) => renderInputNumber(f.value, {}, f)
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
key: "title",
|
|
163
|
+
label: "Title",
|
|
164
|
+
value: null,
|
|
165
|
+
clearable: true,
|
|
166
|
+
render2: (f) => renderInput(f.value, {}, f),
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
key: "length",
|
|
170
|
+
label: "Length",
|
|
171
|
+
value: null,
|
|
172
|
+
clearable: true,
|
|
173
|
+
render2: (f) => renderInput(f.value, {}, f),
|
|
174
|
+
},
|
|
175
|
+
])
|
|
176
|
+
const useForm = useDyForm(updateFormItems)
|
|
177
|
+
const doSearch = () => {
|
|
178
|
+
fetchData()
|
|
179
|
+
pagination.pageNo = 1
|
|
180
|
+
}
|
|
181
|
+
const doReset = () => {
|
|
182
|
+
fetchData()
|
|
183
|
+
pagination.pageNo = 1
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function rowKey(row: SongType) {
|
|
187
|
+
return row.no
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// mock http request
|
|
191
|
+
async function fetchData() {
|
|
192
|
+
tableLoading.value = true
|
|
193
|
+
const {pageNo, pageSize} = pagination
|
|
194
|
+
const params = naiZealTableSearchRef.value?.getParams<SongType>?.()
|
|
195
|
+
const r = await new Promise<{ data: SongType[], total: number }>((resolve, reject) => {
|
|
196
|
+
setTimeout(() => {
|
|
197
|
+
const start = (pageNo - 1) * pageSize
|
|
198
|
+
const {length, no, title} = params!
|
|
199
|
+
const data = zealData.value.filter(it => (!length || it.length.includes(length)) && (!title || it.title.includes(title)) && (!no || it.no === parseInt(no as string)))
|
|
200
|
+
resolve({
|
|
201
|
+
data: data.slice(start, start + pageSize),
|
|
202
|
+
total: data.length
|
|
203
|
+
})
|
|
204
|
+
}, 1500)
|
|
205
|
+
})
|
|
206
|
+
tableData.value = r.data
|
|
207
|
+
pagination.setTotalSize(r.total)
|
|
208
|
+
tableLoading.value = false
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const newItem = () => {
|
|
212
|
+
referId.value = '-1'
|
|
213
|
+
useForm.onReset()
|
|
214
|
+
nextTick(() => {
|
|
215
|
+
naiPopupModalRef.value?.toggle?.(true)
|
|
216
|
+
})
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function upItem(r: SongType) {
|
|
220
|
+
referId.value = r.no
|
|
221
|
+
useForm.setValues(r)
|
|
222
|
+
nextTick(() => {
|
|
223
|
+
naiPopupModalRef.value?.toggle?.(true)
|
|
224
|
+
})
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function delItem(r: SongType) {
|
|
228
|
+
zealData.value = zealData.value.filter(it2 => it2.no !== r.no)
|
|
229
|
+
message.success('delete successful')
|
|
230
|
+
fetchData()
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const deleteAll = () => {
|
|
234
|
+
zealData.value = zealData.value.filter(it2 => !selectOpts.value.includes(it2.no))
|
|
235
|
+
message.success('delete all successful')
|
|
236
|
+
fetchData()
|
|
237
|
+
}
|
|
238
|
+
const onSubmit = async () => {
|
|
239
|
+
handleDynamicFormRef.value?.validator().then((v: any) => {
|
|
240
|
+
if (referId.value === '-1') {
|
|
241
|
+
zealData.value.unshift({...v, key: Date.now()})
|
|
242
|
+
message.success('Add successful')
|
|
243
|
+
} else {
|
|
244
|
+
zealData.value = zealData.value.map(it => {
|
|
245
|
+
if (referId.value === it.no) return v as SongType
|
|
246
|
+
return it
|
|
247
|
+
})
|
|
248
|
+
message.success('Update successful')
|
|
249
|
+
}
|
|
250
|
+
nextTick(() => {
|
|
251
|
+
naiPopupModalRef.value?.toggle?.(false)
|
|
252
|
+
fetchData()
|
|
253
|
+
})
|
|
254
|
+
})
|
|
255
|
+
}
|
|
256
|
+
const handleSelectionChange = (v: DataTableColumnKey[]) => {
|
|
257
|
+
selectOpts.value = v
|
|
258
|
+
}
|
|
259
|
+
onMounted(() => {
|
|
260
|
+
fetchData()
|
|
261
|
+
})
|
|
262
|
+
</script>
|
|
263
|
+
|
|
264
|
+
<template>
|
|
265
|
+
<NaiZealCard>
|
|
266
|
+
<template #header="{isMobile}">
|
|
267
|
+
<NaiZealTableSearch :isMobile="isMobile" :search-items="searchFormItems" ref="naiZealTableSearchRef"
|
|
268
|
+
:mobile-drawer="true"
|
|
269
|
+
title="zeal test" @onReset="doReset"
|
|
270
|
+
@onSearch="doSearch"/>
|
|
271
|
+
</template>
|
|
272
|
+
<template #controlBtn>
|
|
273
|
+
<n-button type="success" size="small" @click="newItem">Add</n-button>
|
|
274
|
+
<n-button type="error" size="small" @click="deleteAll" :disabled="!selectOpts.length">Del Selected</n-button>
|
|
275
|
+
</template>
|
|
276
|
+
<template #toolBtn>
|
|
277
|
+
<n-button type="default" size="small" @click="()=>{}">
|
|
278
|
+
Tool...
|
|
279
|
+
</n-button>
|
|
280
|
+
</template>
|
|
281
|
+
<template #default="{tableHeight}">
|
|
282
|
+
<n-data-table
|
|
283
|
+
:row-key="rowKey"
|
|
284
|
+
:loading="tableLoading"
|
|
285
|
+
:columns="columns"
|
|
286
|
+
:data="tableData"
|
|
287
|
+
:bordered="false"
|
|
288
|
+
:style="{ height: tableHeight+'px'}"
|
|
289
|
+
:flex-height="true"
|
|
290
|
+
:scroll-x="600"
|
|
291
|
+
@update:checked-row-keys="handleSelectionChange"
|
|
292
|
+
/>
|
|
293
|
+
</template>
|
|
294
|
+
<template #footer="{isMobile}">
|
|
295
|
+
<NaiZealTablePaginationControl :is-mobile="isMobile" :pagination="pagination">
|
|
296
|
+
<template #prefix="{ itemCount }">
|
|
297
|
+
Total {{ itemCount }}
|
|
298
|
+
</template>
|
|
299
|
+
</NaiZealTablePaginationControl>
|
|
300
|
+
</template>
|
|
301
|
+
<template #rest>
|
|
302
|
+
<NaiPopupModal :title="referId==='-1'?'add Test':'update Test'" ref="naiPopupModalRef" :on-submit="onSubmit">
|
|
303
|
+
<NaiDynamicForm :items="updateFormItems" ref="handleDynamicFormRef"/>
|
|
304
|
+
</NaiPopupModal>
|
|
305
|
+
</template>
|
|
306
|
+
</NaiZealCard>
|
|
307
|
+
</template>
|
|
308
|
+
|
|
309
|
+
<style scoped>
|
|
310
|
+
|
|
311
|
+
</style>
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
#### 与Element-plus配合
|
|
315
|
+
|
|
57
316
|
```vue
|
|
317
|
+
|
|
318
|
+
<script setup lang="ts">
|
|
319
|
+
import {h, nextTick, onMounted, ref} from "vue";
|
|
320
|
+
import {ElMessage, ElButton, ElSpace} from "element-plus";
|
|
321
|
+
import {
|
|
322
|
+
ElePopupModal,
|
|
323
|
+
useDecorateForm,
|
|
324
|
+
EleZealCard,
|
|
325
|
+
EleDynamicForm,
|
|
326
|
+
EleZealTableSearch,
|
|
327
|
+
EleZealTablePaginationControl,
|
|
328
|
+
EleZealTable,
|
|
329
|
+
renderInput,
|
|
330
|
+
renderInputNumber,
|
|
331
|
+
} from "dynamicformdjx/elementPlus";
|
|
332
|
+
import type {
|
|
333
|
+
elePopupModalRef,
|
|
334
|
+
eleDynamicFormRef,
|
|
335
|
+
eleZealTableSearchRef
|
|
336
|
+
} from "dynamicformdjx/elementPlus"
|
|
337
|
+
import {useDyForm, useReactiveForm, usePagination} from "dynamicformdjx";
|
|
338
|
+
import type {ZealColumn} from "dynamicformdjx/types/form";
|
|
339
|
+
|
|
340
|
+
interface SongType {
|
|
341
|
+
no: number | string
|
|
342
|
+
title: string
|
|
343
|
+
length: string
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const zealData = ref<SongType[]>([
|
|
347
|
+
{no: 3, title: 'Wonderwall', length: '4:18'},
|
|
348
|
+
{no: 4, title: 'Don\'t Look Back in Anger', length: '4:48'},
|
|
349
|
+
{no: 12, title: 'Champagne Supernova', length: '7:27'},
|
|
350
|
+
...Array.from({length: 50}).map((_, i) => ({no: i + 13, title: `test Data ${i + 1}`, length: `${i * i}`}))
|
|
351
|
+
])
|
|
352
|
+
const referId = ref<string | number>('-1')
|
|
353
|
+
const tableData = ref<SongType[]>([])
|
|
354
|
+
const handleDynamicFormRef = ref<eleDynamicFormRef | null>(null)
|
|
355
|
+
const naiZealTableSearchRef = ref<eleZealTableSearchRef | null>(null)
|
|
356
|
+
const naiPopupModalRef = ref<elePopupModalRef | null>(null)
|
|
357
|
+
const tableLoading = ref<boolean>(false)
|
|
358
|
+
const selectOpts = ref<(number | string)[]>([])
|
|
359
|
+
// search form
|
|
360
|
+
const searchFormItems = useDecorateForm([
|
|
361
|
+
{
|
|
362
|
+
key: "no",
|
|
363
|
+
label: "No",
|
|
364
|
+
renderType: 'renderInputNumber',
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
key: "title",
|
|
368
|
+
label: "Title",
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
key: "length",
|
|
372
|
+
label: "Length",
|
|
373
|
+
},
|
|
374
|
+
].map(it => ({
|
|
375
|
+
value: null,
|
|
376
|
+
clearable: true,
|
|
377
|
+
renderType: 'renderInput',
|
|
378
|
+
span: 8,
|
|
379
|
+
...it,
|
|
380
|
+
})) as any[])
|
|
381
|
+
// table column
|
|
382
|
+
const columns: ZealColumn<SongType>[] = [
|
|
383
|
+
{type: 'selection', width: 55},
|
|
384
|
+
{type: 'expand', render2: row => h('div', {}, JSON.stringify(row, null, 2))},
|
|
385
|
+
{label: "No", prop: "no", width: 80},
|
|
386
|
+
{label: "Title", prop: "title", slot: "title"},
|
|
387
|
+
{label: "Length", prop: "length"},
|
|
388
|
+
{
|
|
389
|
+
label: "Actions", fixed: 'right', width: 160, render2: (row) => h(
|
|
390
|
+
ElSpace, {}, [
|
|
391
|
+
h(ElButton,
|
|
392
|
+
{
|
|
393
|
+
size: 'small',
|
|
394
|
+
onClick: () => upItem(row)
|
|
395
|
+
},
|
|
396
|
+
'update'),
|
|
397
|
+
h(ElButton,
|
|
398
|
+
{
|
|
399
|
+
size: 'small',
|
|
400
|
+
type: 'danger',
|
|
401
|
+
onClick: () => delItem(row)
|
|
402
|
+
},
|
|
403
|
+
'delete')
|
|
404
|
+
]
|
|
405
|
+
)
|
|
406
|
+
},
|
|
407
|
+
];
|
|
408
|
+
|
|
409
|
+
const pagination = usePagination(fetchData)
|
|
410
|
+
const updateFormItems = useReactiveForm<SongType>([
|
|
411
|
+
{
|
|
412
|
+
key: "no",
|
|
413
|
+
label: "No",
|
|
414
|
+
clearable: true,
|
|
415
|
+
value: null,
|
|
416
|
+
render2: (f) => renderInputNumber(f.value, {}, f)
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
key: "title",
|
|
420
|
+
label: "Title",
|
|
421
|
+
value: null,
|
|
422
|
+
clearable: true,
|
|
423
|
+
render2: (f) => renderInput(f.value, {}, f),
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
key: "length",
|
|
427
|
+
label: "Length",
|
|
428
|
+
value: null,
|
|
429
|
+
clearable: true,
|
|
430
|
+
render2: (f) => renderInput(f.value, {}, f),
|
|
431
|
+
},
|
|
432
|
+
])
|
|
433
|
+
const useForm = useDyForm(updateFormItems)
|
|
434
|
+
const doSearch = () => {
|
|
435
|
+
fetchData()
|
|
436
|
+
pagination.pageNo = 1
|
|
437
|
+
}
|
|
438
|
+
const doReset = () => {
|
|
439
|
+
fetchData()
|
|
440
|
+
pagination.pageNo = 1
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// mock http request
|
|
444
|
+
async function fetchData() {
|
|
445
|
+
tableLoading.value = true
|
|
446
|
+
const {pageNo, pageSize} = pagination
|
|
447
|
+
const params = naiZealTableSearchRef.value?.getParams<SongType>?.()
|
|
448
|
+
const r = await new Promise<{ data: SongType[], total: number }>((resolve, reject) => {
|
|
449
|
+
setTimeout(() => {
|
|
450
|
+
const start = (pageNo - 1) * pageSize
|
|
451
|
+
const {length, no, title} = params!
|
|
452
|
+
const data = zealData.value.filter(it => (!length || it.length.includes(length)) && (!title || it.title.includes(title)) && (!no || it.no === parseInt(no as string)))
|
|
453
|
+
resolve({
|
|
454
|
+
data: data.slice(start, start + pageSize),
|
|
455
|
+
total: data.length
|
|
456
|
+
})
|
|
457
|
+
}, 1500)
|
|
458
|
+
})
|
|
459
|
+
tableData.value = r.data
|
|
460
|
+
pagination.setTotalSize(r.total)
|
|
461
|
+
tableLoading.value = false
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const newItem = () => {
|
|
465
|
+
referId.value = '-1'
|
|
466
|
+
useForm.onReset()
|
|
467
|
+
nextTick(() => {
|
|
468
|
+
naiPopupModalRef.value?.toggle?.(true)
|
|
469
|
+
})
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
function upItem(r: SongType) {
|
|
473
|
+
referId.value = r.no
|
|
474
|
+
useForm.setValues(r)
|
|
475
|
+
nextTick(() => {
|
|
476
|
+
naiPopupModalRef.value?.toggle?.(true)
|
|
477
|
+
})
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
function delItem(r: SongType) {
|
|
481
|
+
zealData.value = zealData.value.filter(it2 => it2.no !== r.no)
|
|
482
|
+
ElMessage.success('delete successful')
|
|
483
|
+
fetchData()
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
const deleteAll = () => {
|
|
487
|
+
zealData.value = zealData.value.filter(it2 => !selectOpts.value.includes(it2.no))
|
|
488
|
+
ElMessage.success('delete all successful')
|
|
489
|
+
fetchData()
|
|
490
|
+
}
|
|
491
|
+
const onSubmit = async () => {
|
|
492
|
+
handleDynamicFormRef.value?.validator().then((v: any) => {
|
|
493
|
+
if (referId.value === '-1') {
|
|
494
|
+
zealData.value.unshift({...v, key: Date.now()})
|
|
495
|
+
ElMessage.success('Add successful')
|
|
496
|
+
} else {
|
|
497
|
+
zealData.value = zealData.value.map(it => {
|
|
498
|
+
if (referId.value === it.no) return v as SongType
|
|
499
|
+
return it
|
|
500
|
+
})
|
|
501
|
+
ElMessage.success('Update successful')
|
|
502
|
+
}
|
|
503
|
+
nextTick(() => {
|
|
504
|
+
naiPopupModalRef.value?.toggle?.(false)
|
|
505
|
+
fetchData()
|
|
506
|
+
})
|
|
507
|
+
})
|
|
508
|
+
}
|
|
509
|
+
const handleSelectionChange = (v: SongType[]) => {
|
|
510
|
+
selectOpts.value = v.map(it => it.no)
|
|
511
|
+
}
|
|
512
|
+
onMounted(() => {
|
|
513
|
+
fetchData()
|
|
514
|
+
})
|
|
515
|
+
</script>
|
|
516
|
+
|
|
517
|
+
<template>
|
|
518
|
+
<EleZealCard>
|
|
519
|
+
<template #header="{isMobile}">
|
|
520
|
+
<EleZealTableSearch :is-mobile="isMobile" :search-items="searchFormItems" ref="naiZealTableSearchRef"
|
|
521
|
+
:mobile-drawer="true"
|
|
522
|
+
title="zeal test" @onReset="doReset"
|
|
523
|
+
@onSearch="doSearch">
|
|
524
|
+
<template #drawerBtn="{openDrawer}">
|
|
525
|
+
<el-button @click="openDrawer">+</el-button>
|
|
526
|
+
</template>
|
|
527
|
+
</EleZealTableSearch>
|
|
528
|
+
</template>
|
|
529
|
+
<template #controlBtn>
|
|
530
|
+
<el-button type="success" size="small" @click="newItem">Add</el-button>
|
|
531
|
+
<el-button type="danger" size="small" @click="deleteAll" :disabled="!selectOpts.length">Del Selected</el-button>
|
|
532
|
+
</template>
|
|
533
|
+
<template #toolBtn>
|
|
534
|
+
<el-button type="default" size="small" @click="()=>{}">
|
|
535
|
+
Tool...
|
|
536
|
+
</el-button>
|
|
537
|
+
</template>
|
|
538
|
+
<template #default="{tableHeight}">
|
|
539
|
+
<EleZealTable :data="tableData" :columns="columns" :max-height="tableHeight" :loading="tableLoading"
|
|
540
|
+
@selection-change="handleSelectionChange">
|
|
541
|
+
<template #title="{ row }">
|
|
542
|
+
<el-tag>{{ row.title }}</el-tag>
|
|
543
|
+
</template>
|
|
544
|
+
<template #empty>
|
|
545
|
+
<p> no data</p>
|
|
546
|
+
</template>
|
|
547
|
+
</EleZealTable>
|
|
548
|
+
</template>
|
|
549
|
+
<template #footer="{isMobile}">
|
|
550
|
+
<EleZealTablePaginationControl :is-mobile="isMobile" :pagination="pagination"/>
|
|
551
|
+
</template>
|
|
552
|
+
<template #rest>
|
|
553
|
+
<ElePopupModal :title="referId==='-1'?'add Test':'update Test'" ref="naiPopupModalRef" :on-submit="onSubmit">
|
|
554
|
+
<EleDynamicForm :items="updateFormItems" ref="handleDynamicFormRef"/>
|
|
555
|
+
</ElePopupModal>
|
|
556
|
+
</template>
|
|
557
|
+
</EleZealCard>
|
|
558
|
+
</template>
|
|
559
|
+
|
|
560
|
+
<style scoped>
|
|
561
|
+
|
|
562
|
+
</style>
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
### 动态表单
|
|
566
|
+
|
|
567
|
+
#### 与Naive ui配合
|
|
568
|
+
|
|
569
|
+
##### 简单表单
|
|
570
|
+
|
|
571
|
+
> 还有自定义表单,装饰表单请参考文档
|
|
572
|
+
|
|
573
|
+
```vue
|
|
574
|
+
|
|
58
575
|
<script setup lang="ts">
|
|
59
576
|
import {ref} from "vue";
|
|
60
577
|
import {NButton} from "naive-ui";
|
|
@@ -91,7 +608,7 @@ pnpm add dynamicformdjx
|
|
|
91
608
|
render2: f => renderInput(f.value, {showPasswordOn: 'click'}, f),
|
|
92
609
|
span: 8,
|
|
93
610
|
offset: 2,
|
|
94
|
-
requiredHint:l
|
|
611
|
+
requiredHint: l => `${l} is not empty`
|
|
95
612
|
},
|
|
96
613
|
{
|
|
97
614
|
key: "preset",
|
|
@@ -154,314 +671,95 @@ pnpm add dynamicformdjx
|
|
|
154
671
|
</template>
|
|
155
672
|
|
|
156
673
|
<style scoped>
|
|
157
|
-
h3{
|
|
674
|
+
h3 {
|
|
158
675
|
text-align: center;
|
|
159
|
-
margin:0 0 10px 0;
|
|
676
|
+
margin: 0 0 10px 0;
|
|
160
677
|
}
|
|
678
|
+
|
|
161
679
|
.control {
|
|
162
680
|
display: flex;
|
|
163
681
|
gap: 5px;
|
|
164
682
|
}
|
|
165
683
|
</style>
|
|
166
684
|
```
|
|
167
|
-
##### 2.自定义表单
|
|
168
|
-
> (所有render2函数使用自定义)
|
|
169
|
-
##### InputTest.vue
|
|
170
|
-
```vue
|
|
171
|
-
<script setup lang="ts">
|
|
172
|
-
import {NInput} from "naive-ui";
|
|
173
|
-
import {useAttrs} from "vue";
|
|
174
|
-
const fv=defineModel()
|
|
175
|
-
const attrs=useAttrs()
|
|
176
|
-
</script>
|
|
177
|
-
|
|
178
|
-
<template>
|
|
179
|
-
<n-input v-model="fv" v-bind="attrs"/>
|
|
180
|
-
</template>
|
|
181
685
|
|
|
182
|
-
|
|
686
|
+
#### 与Element-plus配合
|
|
183
687
|
|
|
184
|
-
|
|
185
|
-
```
|
|
186
|
-
##### Render.vue
|
|
187
|
-
```vue
|
|
188
|
-
<script setup lang="ts">
|
|
189
|
-
import {h, ref} from "vue";
|
|
190
|
-
import {NButton, NInput} from "naive-ui";
|
|
191
|
-
import {useDyForm, useReactiveForm} from "dynamicformdjx";
|
|
192
|
-
import {type naiDynamicFormRef, NaiDynamicForm, NaiDynamicInput, type naiDynamicInputRef} from "dynamicformdjx/naiveUi";
|
|
193
|
-
import type {FormItemRule, FormRules} from "naive-ui/es/form/src/interface";
|
|
194
|
-
import InputTest from "./InputTest.vue";
|
|
195
|
-
|
|
196
|
-
type FormRow = {
|
|
197
|
-
name: string
|
|
198
|
-
desc: string
|
|
199
|
-
json: object
|
|
200
|
-
}
|
|
201
|
-
const naiDynamicFormRef = ref<naiDynamicFormRef | null>(null)
|
|
202
|
-
const naiDynamicInputRef = ref<naiDynamicInputRef | null>(null)
|
|
203
|
-
const formItems = useReactiveForm<FormRow, FormRules | FormItemRule>([
|
|
204
|
-
{
|
|
205
|
-
key: "name",
|
|
206
|
-
label: "姓名",
|
|
207
|
-
value: ref<string | null>(null),
|
|
208
|
-
clearable: true,
|
|
209
|
-
placeholder: '请输入姓名',
|
|
210
|
-
required: true,
|
|
211
|
-
// @ts-ignore
|
|
212
|
-
render2: f => h(NInput, {
|
|
213
|
-
...f,
|
|
214
|
-
value: f.value.value, "onUpdate:value"(v) {
|
|
215
|
-
f.value.value = v
|
|
216
|
-
}
|
|
217
|
-
}),
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
key: "desc",
|
|
221
|
-
label: "描述",
|
|
222
|
-
value: ref<string | null>(null),
|
|
223
|
-
clearable: true,
|
|
224
|
-
placeholder: '请输入描述',
|
|
225
|
-
required: true,
|
|
226
|
-
type: 'textarea',
|
|
227
|
-
render2: f => h(InputTest, {
|
|
228
|
-
...f,
|
|
229
|
-
value: f.value.value, "onUpdate:value"(v) {
|
|
230
|
-
f.value.value = v
|
|
231
|
-
}
|
|
232
|
-
}),
|
|
233
|
-
},
|
|
234
|
-
{
|
|
235
|
-
key: "json",
|
|
236
|
-
label: "Json",
|
|
237
|
-
value: ref<object>({}),
|
|
238
|
-
rule: {
|
|
239
|
-
required: true,
|
|
240
|
-
validator(_: FormItemRule, value: object) {
|
|
241
|
-
return Object.keys(value).length > 0
|
|
242
|
-
},
|
|
243
|
-
trigger: ['blur', 'change'],
|
|
244
|
-
message: 'json 不能为空'
|
|
245
|
-
},
|
|
246
|
-
render2: f => h(NaiDynamicInput, {
|
|
247
|
-
modelValue: f.value.value, "onUpdate:modelValue"(v) {
|
|
248
|
-
f.value.value = v
|
|
249
|
-
},
|
|
250
|
-
isController: true,
|
|
251
|
-
ref: naiDynamicInputRef
|
|
252
|
-
}),
|
|
253
|
-
},
|
|
254
|
-
])
|
|
255
|
-
const useForm = useDyForm<FormRow>(formItems)
|
|
256
|
-
const getData = () => {
|
|
257
|
-
console.log(useForm.getValues())
|
|
258
|
-
}
|
|
259
|
-
const resetData = () => {
|
|
260
|
-
useForm.onReset()
|
|
261
|
-
naiDynamicInputRef.value?.onSet?.({})
|
|
262
|
-
}
|
|
263
|
-
const setData = () => {
|
|
264
|
-
useForm.setValues({
|
|
265
|
-
name: 'naive-ui',
|
|
266
|
-
desc:`A Vue 3 Component Library Fairly Complete, Theme Customizable, Uses TypeScript, Fast Kinda Interesting`
|
|
267
|
-
})
|
|
268
|
-
naiDynamicInputRef.value?.onSet?.({
|
|
269
|
-
question: 'how are you?',
|
|
270
|
-
answer: "I'm fine,Thank you"
|
|
271
|
-
})
|
|
272
|
-
}
|
|
273
|
-
const validatorData = () => {
|
|
274
|
-
// 校验
|
|
275
|
-
naiDynamicFormRef.value?.validator().then(data => {
|
|
276
|
-
console.log(data)
|
|
277
|
-
}).catch(err => {
|
|
278
|
-
console.log(err)
|
|
279
|
-
})
|
|
280
|
-
}
|
|
281
|
-
</script>
|
|
688
|
+
> (只是导入从"dynamicformdjx/elementPlus"中,类型方法与上方naive ui一致)
|
|
282
689
|
|
|
283
|
-
|
|
284
|
-
<NaiDynamicForm :items="formItems" ref="naiDynamicFormRef"/>
|
|
285
|
-
<div class="control">
|
|
286
|
-
<n-button @click="getData" type="success" size="small">get Data</n-button>
|
|
287
|
-
<n-button @click="setData" type="warning" size="small">set Data</n-button>
|
|
288
|
-
<n-button @click="validatorData" type="default" size="small">validate Data</n-button>
|
|
289
|
-
<n-button @click="resetData" type="error" size="small">reset Data</n-button>
|
|
290
|
-
</div>
|
|
291
|
-
</template>
|
|
690
|
+
##### 简单表单
|
|
292
691
|
|
|
293
|
-
<style scoped>
|
|
294
|
-
.control {
|
|
295
|
-
display: flex;
|
|
296
|
-
gap: 5px;
|
|
297
|
-
}
|
|
298
|
-
</style>
|
|
299
|
-
```
|
|
300
|
-
##### 3.装饰表单
|
|
301
|
-
> (可省略render2函数)
|
|
302
692
|
```vue
|
|
303
|
-
<script setup lang="ts">
|
|
304
|
-
import { ref} from "vue";
|
|
305
|
-
import {NButton} from "naive-ui";
|
|
306
|
-
import {useDyForm} from "dynamicformdjx";
|
|
307
|
-
import {
|
|
308
|
-
type naiDynamicFormRef,
|
|
309
|
-
NaiDynamicForm,
|
|
310
|
-
useDecorateForm,
|
|
311
|
-
renderDatePicker
|
|
312
|
-
} from "dynamicformdjx/naiveUi";
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
type FormRow = {
|
|
316
|
-
password: string
|
|
317
|
-
job: number
|
|
318
|
-
birthday: number
|
|
319
|
-
}
|
|
320
|
-
const naiDynamicFormRef = ref<naiDynamicFormRef | null>(null)
|
|
321
|
-
const formItems = useDecorateForm<FormRow>([
|
|
322
|
-
{
|
|
323
|
-
key: "password",
|
|
324
|
-
label: "密码",
|
|
325
|
-
value: null,
|
|
326
|
-
clearable: true,
|
|
327
|
-
placeholder: '请输入密码',
|
|
328
|
-
required: true,
|
|
329
|
-
type:'password',
|
|
330
|
-
renderType: 'renderInput',
|
|
331
|
-
renderProps:{
|
|
332
|
-
showPasswordOn:'click'
|
|
333
|
-
}
|
|
334
|
-
},
|
|
335
|
-
{
|
|
336
|
-
key: "job",
|
|
337
|
-
label: "职位",
|
|
338
|
-
value: null,
|
|
339
|
-
clearable: true,
|
|
340
|
-
options: ['前端', '后端'].map((label, value) => ({label, value})),
|
|
341
|
-
renderType: 'renderSelect',
|
|
342
|
-
},
|
|
343
|
-
{
|
|
344
|
-
key: "birthday",
|
|
345
|
-
label: "生日",
|
|
346
|
-
value: null,
|
|
347
|
-
render2: f => renderDatePicker(f.value, {type: 'datetime'}, f),
|
|
348
|
-
},
|
|
349
|
-
])
|
|
350
|
-
const useForm = useDyForm<FormRow>(formItems)
|
|
351
|
-
const getData = () => {
|
|
352
|
-
const res = naiDynamicFormRef.value?.getResult?.()
|
|
353
|
-
console.log(res)
|
|
354
|
-
}
|
|
355
|
-
const resetData = () => {
|
|
356
|
-
naiDynamicFormRef.value?.reset?.()
|
|
357
|
-
}
|
|
358
|
-
const setData = () => {
|
|
359
|
-
useForm.setValues({
|
|
360
|
-
password: 'naive-ui',
|
|
361
|
-
job: 0,
|
|
362
|
-
birthday: Date.now(),
|
|
363
|
-
})
|
|
364
|
-
}
|
|
365
|
-
const validatorData = () => {
|
|
366
|
-
naiDynamicFormRef.value?.validator().then(data => {
|
|
367
|
-
console.log(data)
|
|
368
|
-
}).catch(err => {
|
|
369
|
-
console.log(err)
|
|
370
|
-
})
|
|
371
|
-
}
|
|
372
|
-
</script>
|
|
373
|
-
|
|
374
|
-
<template>
|
|
375
|
-
<NaiDynamicForm :items="formItems" ref="naiDynamicFormRef"/>
|
|
376
|
-
<div class="control">
|
|
377
|
-
<n-button @click="getData" type="success" size="small">get Data</n-button>
|
|
378
|
-
<n-button @click="setData" type="warning" size="small">set Data</n-button>
|
|
379
|
-
<n-button @click="validatorData" type="default" size="small">validate Data</n-button>
|
|
380
|
-
<n-button @click="resetData" type="error" size="small">reset Data</n-button>
|
|
381
|
-
</div>
|
|
382
|
-
</template>
|
|
383
693
|
|
|
384
|
-
<style scoped>
|
|
385
|
-
.control {
|
|
386
|
-
display: flex;
|
|
387
|
-
gap: 5px;
|
|
388
|
-
}
|
|
389
|
-
</style>
|
|
390
|
-
```
|
|
391
|
-
|
|
392
|
-
#### 与Element-plus配合
|
|
393
|
-
> (这里只展示一种,只是导入从"dynamicformdjx/elementPlus"中,类型方法与上方naive ui一致)
|
|
394
|
-
##### 简单表单
|
|
395
|
-
```vue
|
|
396
694
|
<script setup lang="ts">
|
|
397
|
-
import {ref} from "vue";
|
|
398
|
-
import {ElButton} from "element-plus";
|
|
399
|
-
import {useDyForm, useReactiveForm} from "dynamicformdjx";
|
|
400
|
-
import {type eleDynamicFormRef, renderInput, renderRadioGroup, EleDynamicForm} from "dynamicformdjx/elementPlus";
|
|
401
|
-
import type {PresetType} from "dynamicformdjx/types/index";
|
|
402
|
-
|
|
403
|
-
type FormRow = {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
}
|
|
408
|
-
const eleDynamicFormRef = ref<eleDynamicFormRef | null>(null)
|
|
409
|
-
const presetType = ref<PresetType>('fullRow')
|
|
410
|
-
const formItems = useReactiveForm<FormRow>([
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
])
|
|
447
|
-
const useForm = useDyForm<FormRow>(formItems)
|
|
448
|
-
const getData = () => {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
}
|
|
452
|
-
const resetData = () => eleDynamicFormRef.value?.reset?.()
|
|
453
|
-
const setData = () => useForm.setValues({
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
})
|
|
457
|
-
const validatorData = () => {
|
|
458
|
-
// 校验
|
|
459
|
-
eleDynamicFormRef.value?.validator().then(data => {
|
|
460
|
-
console.log(data)
|
|
461
|
-
}).catch(err => {
|
|
462
|
-
console.log(err)
|
|
695
|
+
import {ref} from "vue";
|
|
696
|
+
import {ElButton} from "element-plus";
|
|
697
|
+
import {useDyForm, useReactiveForm} from "dynamicformdjx";
|
|
698
|
+
import {type eleDynamicFormRef, renderInput, renderRadioGroup, EleDynamicForm} from "dynamicformdjx/elementPlus";
|
|
699
|
+
import type {PresetType} from "dynamicformdjx/types/index";
|
|
700
|
+
|
|
701
|
+
type FormRow = {
|
|
702
|
+
username: string
|
|
703
|
+
password: string
|
|
704
|
+
preset: PresetType
|
|
705
|
+
}
|
|
706
|
+
const eleDynamicFormRef = ref<eleDynamicFormRef | null>(null)
|
|
707
|
+
const presetType = ref<PresetType>('fullRow')
|
|
708
|
+
const formItems = useReactiveForm<FormRow>([
|
|
709
|
+
{
|
|
710
|
+
key: "username",
|
|
711
|
+
label: "姓名",
|
|
712
|
+
value: ref<string | null>(null),
|
|
713
|
+
clearable: true,
|
|
714
|
+
placeholder: '请输入姓名',
|
|
715
|
+
required: true, // 是否必填 (简化rules规则)
|
|
716
|
+
render2: f => renderInput(f.value, {}, f),
|
|
717
|
+
span: 8
|
|
718
|
+
},
|
|
719
|
+
{
|
|
720
|
+
key: "password",
|
|
721
|
+
label: "密码",
|
|
722
|
+
value: ref<string | null>(null),
|
|
723
|
+
clearable: true,
|
|
724
|
+
type: 'password',
|
|
725
|
+
required: true,
|
|
726
|
+
placeholder: '请输入密码',
|
|
727
|
+
render2: f => renderInput(f.value, {showPassword: true}, f),
|
|
728
|
+
span: 8,
|
|
729
|
+
offset: 2,
|
|
730
|
+
requiredHint: l => `${l} is not empty`
|
|
731
|
+
},
|
|
732
|
+
{
|
|
733
|
+
key: "preset",
|
|
734
|
+
label: "表格预设",
|
|
735
|
+
value: ref<PresetType | null>(presetType.value),
|
|
736
|
+
render2: f => renderRadioGroup(f.value, [
|
|
737
|
+
{label: '整行', value: 'fullRow'},
|
|
738
|
+
{label: '表格', value: 'grid'},
|
|
739
|
+
], {name: 'preset'}, f),
|
|
740
|
+
onChange: (v) => {
|
|
741
|
+
presetType.value = v
|
|
742
|
+
}
|
|
743
|
+
},
|
|
744
|
+
])
|
|
745
|
+
const useForm = useDyForm<FormRow>(formItems)
|
|
746
|
+
const getData = () => {
|
|
747
|
+
const res = eleDynamicFormRef.value?.getResult?.()
|
|
748
|
+
console.log(res)
|
|
749
|
+
}
|
|
750
|
+
const resetData = () => eleDynamicFormRef.value?.reset?.()
|
|
751
|
+
const setData = () => useForm.setValues({
|
|
752
|
+
username: 'element-plus',
|
|
753
|
+
password: '520'
|
|
463
754
|
})
|
|
464
|
-
|
|
755
|
+
const validatorData = () => {
|
|
756
|
+
// 校验
|
|
757
|
+
eleDynamicFormRef.value?.validator().then(data => {
|
|
758
|
+
console.log(data)
|
|
759
|
+
}).catch(err => {
|
|
760
|
+
console.log(err)
|
|
761
|
+
})
|
|
762
|
+
}
|
|
465
763
|
</script>
|
|
466
764
|
|
|
467
765
|
<template>
|
|
@@ -481,21 +779,26 @@ const validatorData = () => {
|
|
|
481
779
|
</template>
|
|
482
780
|
|
|
483
781
|
<style scoped>
|
|
484
|
-
h3 {
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
.control {
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
}
|
|
782
|
+
h3 {
|
|
783
|
+
text-align: center;
|
|
784
|
+
margin: 0 0 10px 0;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
.control {
|
|
788
|
+
display: flex;
|
|
789
|
+
gap: 5px;
|
|
790
|
+
}
|
|
493
791
|
</style>
|
|
494
792
|
```
|
|
495
|
-
|
|
793
|
+
|
|
794
|
+
### 动态录入
|
|
795
|
+
|
|
796
|
+
> 此录入无需组件库依赖
|
|
496
797
|
|
|
497
798
|
#### 1.单组件
|
|
799
|
+
|
|
498
800
|
```vue
|
|
801
|
+
|
|
499
802
|
<script setup lang="ts">
|
|
500
803
|
import {ref} from "vue";
|
|
501
804
|
import {DynamicInput, type dynamicInputRef} from "dynamicformdjx";
|
|
@@ -525,9 +828,10 @@ h3 {
|
|
|
525
828
|
#### 2.级联基本使用
|
|
526
829
|
|
|
527
830
|
```vue
|
|
831
|
+
|
|
528
832
|
<script setup lang="ts">
|
|
529
833
|
import {ref} from "vue";
|
|
530
|
-
import {dynamicCascadeInputRef,DynamicCascadeInput} from "dynamicformdjx";
|
|
834
|
+
import {dynamicCascadeInputRef, DynamicCascadeInput} from "dynamicformdjx";
|
|
531
835
|
|
|
532
836
|
const dyCascadeRef = ref<dynamicCascadeInputRef | null>(null)
|
|
533
837
|
const test2 = ref({
|
|
@@ -550,7 +854,7 @@ h3 {
|
|
|
550
854
|
|
|
551
855
|
<template>
|
|
552
856
|
<p>Cascade dynamicInput</p>
|
|
553
|
-
<dynamic-cascade-input
|
|
857
|
+
<dynamic-cascade-input v-model="test2" :depth="5" ref="dyCascadeRef" is-controller/>
|
|
554
858
|
<pre>{{ test2 }}</pre>
|
|
555
859
|
<p>Result</p>
|
|
556
860
|
<button @click="setData">setData 8888</button>
|