el-plus-crud 0.1.13 → 0.1.14
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/.eslintignore +18 -18
- package/.eslintrc.js +78 -78
- package/.lintstagedrc +3 -3
- package/.prettierrc.js +39 -39
- package/CHANGELOG.md +261 -259
- package/LICENSE +21 -21
- package/README.md +19 -19
- package/build.js +31 -31
- package/dist/el-plus-crud.mjs +1952 -1952
- package/example/App.vue +252 -252
- package/example/main.js +18 -18
- package/example/style.css +4 -4
- package/index.html +13 -13
- package/lib/components/el-plus-form/ElPlusForm.vue +4 -7
- package/lib/components/el-plus-form/ElPlusFormDialog.vue +93 -93
- package/lib/components/el-plus-form/ElPlusFormGroup.vue +201 -201
- package/lib/components/el-plus-form/components/ElPlusFormCascader.vue +65 -65
- package/lib/components/el-plus-form/components/ElPlusFormCascaderPanel.vue +72 -72
- package/lib/components/el-plus-form/components/ElPlusFormCheckbox.vue +81 -81
- package/lib/components/el-plus-form/components/ElPlusFormImage.vue +115 -115
- package/lib/components/el-plus-form/components/ElPlusFormLink.vue +285 -285
- package/lib/components/el-plus-form/components/ElPlusFormQuickInput.vue +98 -98
- package/lib/components/el-plus-form/components/ElPlusFormRadio.vue +69 -69
- package/lib/components/el-plus-form/components/ElPlusFormSelect.vue +185 -185
- package/lib/components/el-plus-form/components/ElPlusFormStatus.vue +102 -102
- package/lib/components/el-plus-form/components/ElPlusFormText.vue +113 -113
- package/lib/components/el-plus-form/components/ElPlusFormTree.vue +79 -79
- package/lib/components/el-plus-form/components/ElPlusFormTreeSelect.vue +62 -62
- package/lib/components/el-plus-form/components/components/file-icons/data/index.ts +27 -27
- package/lib/components/el-plus-form/components/components/file-icons/images/doc.svg +12 -12
- package/lib/components/el-plus-form/components/components/file-icons/images/file.svg +18 -18
- package/lib/components/el-plus-form/components/components/file-icons/images/jpg.svg +13 -13
- package/lib/components/el-plus-form/components/components/file-icons/images/pdf.svg +12 -12
- package/lib/components/el-plus-form/components/components/file-icons/images/png.svg +12 -12
- package/lib/components/el-plus-form/components/components/file-icons/images/ppt.svg +12 -12
- package/lib/components/el-plus-form/components/components/file-icons/images/xls.svg +12 -12
- package/lib/components/el-plus-form/components/index.ts +17 -17
- package/lib/components/el-plus-form/data/file.ts +74 -74
- package/lib/components/el-plus-form/util/validate.ts +346 -346
- package/lib/components/el-plus-table/ElPlusTable.vue +972 -972
- package/lib/components/el-plus-table/components/columnItem.vue +220 -220
- package/lib/components/el-plus-table/components/header.vue +345 -345
- package/lib/components/el-plus-table/components/statisticInfo.vue +47 -47
- package/lib/index.d.ts +4 -4
- package/lib/util/index.ts +390 -390
- package/package.json +70 -70
- package/tsconfig.json +78 -78
- package/types/global.d.ts +13 -13
- package/types/index.d.ts +561 -561
- package/vite.config.ts +78 -78
|
@@ -1,93 +1,93 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<el-dialog class="el-plus-form-dialog" v-model="currentShow" :title="props.title" v-bind="dialogAttrs" @closed="handelClosed">
|
|
3
|
-
<!-- title 插槽 -->
|
|
4
|
-
<template #header>
|
|
5
|
-
<slot name="header" />
|
|
6
|
-
</template>
|
|
7
|
-
<ElPlusForm ref="refElPlusDialogForm" style="padding: 20px" :isDialog="true" v-model="currentValue" :formDesc="formDesc" v-bind="attrs" :success="dialogSuccess" @cancel="currentShow = false">
|
|
8
|
-
<template #top>
|
|
9
|
-
<slot name="top" />
|
|
10
|
-
</template>
|
|
11
|
-
<template #default>
|
|
12
|
-
<slot name="default" />
|
|
13
|
-
</template>
|
|
14
|
-
</ElPlusForm>
|
|
15
|
-
<template #footer>
|
|
16
|
-
<slot name="footer" />
|
|
17
|
-
</template>
|
|
18
|
-
</el-dialog>
|
|
19
|
-
</template>
|
|
20
|
-
<script lang="ts">
|
|
21
|
-
export default {
|
|
22
|
-
name: 'ElPlusFormDialog',
|
|
23
|
-
inheritAttrs: false,
|
|
24
|
-
customOptions: {}
|
|
25
|
-
}
|
|
26
|
-
</script>
|
|
27
|
-
<script lang="ts" setup>
|
|
28
|
-
import { ref, computed, useAttrs } from 'vue'
|
|
29
|
-
import ElPlusForm from './ElPlusForm.vue'
|
|
30
|
-
import { ElMessage } from 'element-plus'
|
|
31
|
-
import { IFormBack, IFormDesc } from '../../../types'
|
|
32
|
-
|
|
33
|
-
const emits = defineEmits(['update:show', 'update:modelValue'])
|
|
34
|
-
const props = withDefaults(defineProps<{ modelValue?: { [key: string]: any } | {}; formDesc: IFormDesc; show?: boolean; title?: string; tableRef?: any; success?: Function; successTip?: string | ((data?: any) => string) }>(), {
|
|
35
|
-
title: '',
|
|
36
|
-
modelValue: () => {
|
|
37
|
-
return {}
|
|
38
|
-
},
|
|
39
|
-
show: false,
|
|
40
|
-
successTip: '操作成功!'
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
// 重新定义当前值
|
|
44
|
-
const currentValue = computed({
|
|
45
|
-
get: () => props.modelValue,
|
|
46
|
-
set(val: any) {
|
|
47
|
-
emits('update:modelValue', val)
|
|
48
|
-
}
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
// 是否显示弹框
|
|
52
|
-
const currentShow = computed({
|
|
53
|
-
get() {
|
|
54
|
-
refElPlusDialogForm.value?.refresh()
|
|
55
|
-
return props.show
|
|
56
|
-
},
|
|
57
|
-
set(val: boolean) {
|
|
58
|
-
emits('update:show', val)
|
|
59
|
-
}
|
|
60
|
-
})
|
|
61
|
-
const refElPlusDialogForm = ref(null as any)
|
|
62
|
-
|
|
63
|
-
// 合并属性
|
|
64
|
-
const { width, top, modal, appendToBody, showClose, draggable, closeOnClickModal, destroyOnClose, ...attrs } = Object.assign({ width: '700px', draggable: true, top: '15vh', closeOnClickModal: false, showCancel: true, destroyOnClose: true }, useAttrs())
|
|
65
|
-
// 弹框属性
|
|
66
|
-
const dialogAttrs = { width, top, modal, appendToBody, showClose, draggable, closeOnClickModal }
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* 这里重新定义一下成功事件
|
|
70
|
-
* @param formBack
|
|
71
|
-
*/
|
|
72
|
-
function dialogSuccess(formBack: IFormBack) {
|
|
73
|
-
if (props.success) {
|
|
74
|
-
props.success(formBack)
|
|
75
|
-
} else {
|
|
76
|
-
if (props.tableRef) {
|
|
77
|
-
ElMessage.success(typeof props.successTip === 'function' ? props.successTip() : props.successTip)
|
|
78
|
-
props.tableRef.reload()
|
|
79
|
-
currentShow.value = false
|
|
80
|
-
setTimeout(() => {
|
|
81
|
-
formBack.callBack()
|
|
82
|
-
}, 200)
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* 处理弹框关闭
|
|
89
|
-
*/
|
|
90
|
-
function handelClosed() {
|
|
91
|
-
refElPlusDialogForm.value?.clear()
|
|
92
|
-
}
|
|
93
|
-
</script>
|
|
1
|
+
<template>
|
|
2
|
+
<el-dialog class="el-plus-form-dialog" v-model="currentShow" :title="props.title" v-bind="dialogAttrs" @closed="handelClosed">
|
|
3
|
+
<!-- title 插槽 -->
|
|
4
|
+
<template #header>
|
|
5
|
+
<slot name="header" />
|
|
6
|
+
</template>
|
|
7
|
+
<ElPlusForm ref="refElPlusDialogForm" style="padding: 20px" :isDialog="true" v-model="currentValue" :formDesc="formDesc" v-bind="attrs" :success="dialogSuccess" @cancel="currentShow = false">
|
|
8
|
+
<template #top>
|
|
9
|
+
<slot name="top" />
|
|
10
|
+
</template>
|
|
11
|
+
<template #default>
|
|
12
|
+
<slot name="default" />
|
|
13
|
+
</template>
|
|
14
|
+
</ElPlusForm>
|
|
15
|
+
<template #footer>
|
|
16
|
+
<slot name="footer" />
|
|
17
|
+
</template>
|
|
18
|
+
</el-dialog>
|
|
19
|
+
</template>
|
|
20
|
+
<script lang="ts">
|
|
21
|
+
export default {
|
|
22
|
+
name: 'ElPlusFormDialog',
|
|
23
|
+
inheritAttrs: false,
|
|
24
|
+
customOptions: {}
|
|
25
|
+
}
|
|
26
|
+
</script>
|
|
27
|
+
<script lang="ts" setup>
|
|
28
|
+
import { ref, computed, useAttrs } from 'vue'
|
|
29
|
+
import ElPlusForm from './ElPlusForm.vue'
|
|
30
|
+
import { ElMessage } from 'element-plus'
|
|
31
|
+
import { IFormBack, IFormDesc } from '../../../types'
|
|
32
|
+
|
|
33
|
+
const emits = defineEmits(['update:show', 'update:modelValue'])
|
|
34
|
+
const props = withDefaults(defineProps<{ modelValue?: { [key: string]: any } | {}; formDesc: IFormDesc; show?: boolean; title?: string; tableRef?: any; success?: Function; successTip?: string | ((data?: any) => string) }>(), {
|
|
35
|
+
title: '',
|
|
36
|
+
modelValue: () => {
|
|
37
|
+
return {}
|
|
38
|
+
},
|
|
39
|
+
show: false,
|
|
40
|
+
successTip: '操作成功!'
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
// 重新定义当前值
|
|
44
|
+
const currentValue = computed({
|
|
45
|
+
get: () => props.modelValue,
|
|
46
|
+
set(val: any) {
|
|
47
|
+
emits('update:modelValue', val)
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
// 是否显示弹框
|
|
52
|
+
const currentShow = computed({
|
|
53
|
+
get() {
|
|
54
|
+
refElPlusDialogForm.value?.refresh()
|
|
55
|
+
return props.show
|
|
56
|
+
},
|
|
57
|
+
set(val: boolean) {
|
|
58
|
+
emits('update:show', val)
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
const refElPlusDialogForm = ref(null as any)
|
|
62
|
+
|
|
63
|
+
// 合并属性
|
|
64
|
+
const { width, top, modal, appendToBody, showClose, draggable, closeOnClickModal, destroyOnClose, ...attrs } = Object.assign({ width: '700px', draggable: true, top: '15vh', closeOnClickModal: false, showCancel: true, destroyOnClose: true }, useAttrs())
|
|
65
|
+
// 弹框属性
|
|
66
|
+
const dialogAttrs = { width, top, modal, appendToBody, showClose, draggable, closeOnClickModal }
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* 这里重新定义一下成功事件
|
|
70
|
+
* @param formBack
|
|
71
|
+
*/
|
|
72
|
+
function dialogSuccess(formBack: IFormBack) {
|
|
73
|
+
if (props.success) {
|
|
74
|
+
props.success(formBack)
|
|
75
|
+
} else {
|
|
76
|
+
if (props.tableRef) {
|
|
77
|
+
ElMessage.success(typeof props.successTip === 'function' ? props.successTip() : props.successTip)
|
|
78
|
+
props.tableRef.reload()
|
|
79
|
+
currentShow.value = false
|
|
80
|
+
setTimeout(() => {
|
|
81
|
+
formBack.callBack()
|
|
82
|
+
}, 200)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* 处理弹框关闭
|
|
89
|
+
*/
|
|
90
|
+
function handelClosed() {
|
|
91
|
+
refElPlusDialogForm.value?.clear()
|
|
92
|
+
}
|
|
93
|
+
</script>
|
|
@@ -1,201 +1,201 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="el-plus-form-group">
|
|
3
|
-
<template v-for="(group, i) in getGroupFowmLayout" :key="i + group.formProps?.fid">
|
|
4
|
-
<template v-if="useSlots()['top' + indexList[i]]">
|
|
5
|
-
<slot :name="'top' + indexList[i]"> </slot>
|
|
6
|
-
</template>
|
|
7
|
-
<slot :name="'title' + indexList[i]">
|
|
8
|
-
<div class="title-line" v-if="group.title">{{ group.title }}</div>
|
|
9
|
-
</slot>
|
|
10
|
-
<ElPlusForm v-model="currentValue" v-bind="group.formProps" isGroupForm :ref="setComponentRef" @reset="handleReset(group.formProps?.fid || '')">
|
|
11
|
-
<template v-if="useSlots()['default' + indexList[i]]">
|
|
12
|
-
<slot :name="'default' + indexList[i]"> </slot>
|
|
13
|
-
</template>
|
|
14
|
-
</ElPlusForm>
|
|
15
|
-
</template>
|
|
16
|
-
<!-- 默认的插槽 -->
|
|
17
|
-
<slot name="default"> </slot>
|
|
18
|
-
</div>
|
|
19
|
-
</template>
|
|
20
|
-
<script lang="ts">
|
|
21
|
-
export default {
|
|
22
|
-
name: 'ElPlusFormGroup',
|
|
23
|
-
inheritAttrs: false,
|
|
24
|
-
customOptions: {}
|
|
25
|
-
}
|
|
26
|
-
</script>
|
|
27
|
-
<script lang="ts" setup>
|
|
28
|
-
import { cloneDeep } from 'lodash'
|
|
29
|
-
import { isPromiseLike } from '../../util'
|
|
30
|
-
import { computed, ref, useSlots } from 'vue'
|
|
31
|
-
import ElPlusForm, { IFormProps } from './ElPlusForm.vue'
|
|
32
|
-
import { IFormDesc, IFormGroupConfig } from '../../../types'
|
|
33
|
-
|
|
34
|
-
const emits = defineEmits(['update:show', 'update:modelValue', 'before-validate', 'before-request', 'request-success', 'request-error', 'request-end', 'request'])
|
|
35
|
-
const props = defineProps<{
|
|
36
|
-
modelValue: { [key: string]: any } | {}
|
|
37
|
-
// 表单Group项
|
|
38
|
-
formGroup: IFormGroupConfig
|
|
39
|
-
// 提交状态
|
|
40
|
-
isLoading?: boolean
|
|
41
|
-
// 是否禁用最后一个元素的tab
|
|
42
|
-
disabledTab?: boolean
|
|
43
|
-
}>()
|
|
44
|
-
|
|
45
|
-
const formRefs = ref([] as any[])
|
|
46
|
-
|
|
47
|
-
// 主要记录原来groupFowmLayout下标和group下标的对应
|
|
48
|
-
const indexList = ref([] as number[])
|
|
49
|
-
|
|
50
|
-
// 重新定义当前值
|
|
51
|
-
const currentValue = computed({
|
|
52
|
-
get: () => props.modelValue,
|
|
53
|
-
set(val: any) {
|
|
54
|
-
emits('update:modelValue', val)
|
|
55
|
-
}
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* 获取布局,且初始化
|
|
60
|
-
* @param groupItem
|
|
61
|
-
*/
|
|
62
|
-
const getGroupFowmLayout = computed(() => {
|
|
63
|
-
const formConfigList = [] as Array<{
|
|
64
|
-
title?: string
|
|
65
|
-
column?: number
|
|
66
|
-
formProps?: IFormProps
|
|
67
|
-
}>
|
|
68
|
-
// 清空refs列表
|
|
69
|
-
formRefs.value = []
|
|
70
|
-
indexList.value = []
|
|
71
|
-
|
|
72
|
-
const tempId = new Date().getTime()
|
|
73
|
-
props.formGroup.group.map((item, i): any => {
|
|
74
|
-
item.fid = item.fid || `${tempId + i}`
|
|
75
|
-
item._vif = getVIf.value(item.vif)
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
// 这里首先遍历一遍_vif
|
|
79
|
-
const tempGroupList = props.formGroup.group.filter((item, i) => {
|
|
80
|
-
// 这里单独存储下index 的对应关系
|
|
81
|
-
if (item._vif) indexList.value.push(i)
|
|
82
|
-
return item._vif
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
const tempFormConfig = cloneDeep(props.formGroup) as any
|
|
86
|
-
const column = props.formGroup.column || 1
|
|
87
|
-
// 移除无用
|
|
88
|
-
delete tempFormConfig.group
|
|
89
|
-
delete tempFormConfig.column
|
|
90
|
-
|
|
91
|
-
// 表单校验
|
|
92
|
-
tempFormConfig.beforeValidate = async (postData: any) => {
|
|
93
|
-
// 这里处理自带的 beforeValidate
|
|
94
|
-
if (props.formGroup.beforeValidate) {
|
|
95
|
-
const result = (props.formGroup.beforeValidate as Function)(postData)
|
|
96
|
-
if (!(isPromiseLike<any>(result) ? await result : result)) return false
|
|
97
|
-
}
|
|
98
|
-
return await Promise.all(formRefs.value.map((tempRef) => tempRef.validate()))
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
tempFormConfig.groupFormDesc = {} as IFormDesc
|
|
102
|
-
tempGroupList.map((item) => {
|
|
103
|
-
Object.assign(tempFormConfig.groupFormDesc, item.formDesc)
|
|
104
|
-
})
|
|
105
|
-
tempFormConfig.disabledTab = props.disabledTab
|
|
106
|
-
|
|
107
|
-
// 遍历
|
|
108
|
-
tempGroupList.map((groupItem, i) => {
|
|
109
|
-
formConfigList.push({
|
|
110
|
-
title: groupItem.title,
|
|
111
|
-
formProps: Object.assign({ column: groupItem.column || column }, i === tempGroupList.length - 1 ? tempFormConfig : { showBtns: false }, groupItem || {}) as IFormProps
|
|
112
|
-
})
|
|
113
|
-
})
|
|
114
|
-
return formConfigList
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* 获取vif
|
|
119
|
-
*/
|
|
120
|
-
const getVIf = computed(() => (vif: boolean | Function | undefined) => {
|
|
121
|
-
if (typeof vif === 'function') {
|
|
122
|
-
return vif(props.modelValue)
|
|
123
|
-
} else if (typeof vif === 'boolean') {
|
|
124
|
-
return vif
|
|
125
|
-
}
|
|
126
|
-
return true
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
// 设置子组件的ref-重置form的时候需要用到
|
|
130
|
-
function setComponentRef(el: any) {
|
|
131
|
-
if (!el) return
|
|
132
|
-
if (!formRefs.value.find((item) => item.fid === el.fid)) {
|
|
133
|
-
formRefs.value.push(el)
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
//重置
|
|
138
|
-
function handleReset(fid: string) {
|
|
139
|
-
setTimeout(() => {
|
|
140
|
-
formRefs.value.map((item) => {
|
|
141
|
-
if (item.fid !== fid) {
|
|
142
|
-
item.clearValid()
|
|
143
|
-
}
|
|
144
|
-
})
|
|
145
|
-
}, 100)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* 校验
|
|
150
|
-
*/
|
|
151
|
-
async function validate() {
|
|
152
|
-
return await Promise.all(formRefs.value.map((tempRef) => tempRef.validate()))
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* 清理校验
|
|
157
|
-
*/
|
|
158
|
-
async function clearValid() {
|
|
159
|
-
return await Promise.all(formRefs.value.map((tempRef) => tempRef.clearValid()))
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* 获取数据
|
|
164
|
-
*/
|
|
165
|
-
function getData() {
|
|
166
|
-
const tempData = {} as any
|
|
167
|
-
formRefs.value.map((tempRef) => {
|
|
168
|
-
Object.assign(tempData, tempRef.getData())
|
|
169
|
-
})
|
|
170
|
-
return tempData
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
defineExpose({ validate, getData, clearValid })
|
|
174
|
-
</script>
|
|
175
|
-
<style lang="scss">
|
|
176
|
-
.el-plus-form-group {
|
|
177
|
-
// Todo
|
|
178
|
-
/* 通用的标题-短线线 */
|
|
179
|
-
.title-line {
|
|
180
|
-
width: 100%;
|
|
181
|
-
height: 22px;
|
|
182
|
-
font-size: 16px;
|
|
183
|
-
font-weight: 500;
|
|
184
|
-
color: var(--text-color);
|
|
185
|
-
line-height: 22px;
|
|
186
|
-
position: relative;
|
|
187
|
-
padding-left: 10px;
|
|
188
|
-
margin-bottom: 20px;
|
|
189
|
-
&::before {
|
|
190
|
-
position: absolute;
|
|
191
|
-
content: '';
|
|
192
|
-
width: 3px;
|
|
193
|
-
height: 16px;
|
|
194
|
-
left: 0;
|
|
195
|
-
top: 1px;
|
|
196
|
-
background-color: var(--el-color-primary);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
</style>
|
|
201
|
-
./util/aaaaa
|
|
1
|
+
<template>
|
|
2
|
+
<div class="el-plus-form-group">
|
|
3
|
+
<template v-for="(group, i) in getGroupFowmLayout" :key="i + group.formProps?.fid">
|
|
4
|
+
<template v-if="useSlots()['top' + indexList[i]]">
|
|
5
|
+
<slot :name="'top' + indexList[i]"> </slot>
|
|
6
|
+
</template>
|
|
7
|
+
<slot :name="'title' + indexList[i]">
|
|
8
|
+
<div class="title-line" v-if="group.title">{{ group.title }}</div>
|
|
9
|
+
</slot>
|
|
10
|
+
<ElPlusForm v-model="currentValue" v-bind="group.formProps" isGroupForm :ref="setComponentRef" @reset="handleReset(group.formProps?.fid || '')">
|
|
11
|
+
<template v-if="useSlots()['default' + indexList[i]]">
|
|
12
|
+
<slot :name="'default' + indexList[i]"> </slot>
|
|
13
|
+
</template>
|
|
14
|
+
</ElPlusForm>
|
|
15
|
+
</template>
|
|
16
|
+
<!-- 默认的插槽 -->
|
|
17
|
+
<slot name="default"> </slot>
|
|
18
|
+
</div>
|
|
19
|
+
</template>
|
|
20
|
+
<script lang="ts">
|
|
21
|
+
export default {
|
|
22
|
+
name: 'ElPlusFormGroup',
|
|
23
|
+
inheritAttrs: false,
|
|
24
|
+
customOptions: {}
|
|
25
|
+
}
|
|
26
|
+
</script>
|
|
27
|
+
<script lang="ts" setup>
|
|
28
|
+
import { cloneDeep } from 'lodash'
|
|
29
|
+
import { isPromiseLike } from '../../util'
|
|
30
|
+
import { computed, ref, useSlots } from 'vue'
|
|
31
|
+
import ElPlusForm, { IFormProps } from './ElPlusForm.vue'
|
|
32
|
+
import { IFormDesc, IFormGroupConfig } from '../../../types'
|
|
33
|
+
|
|
34
|
+
const emits = defineEmits(['update:show', 'update:modelValue', 'before-validate', 'before-request', 'request-success', 'request-error', 'request-end', 'request'])
|
|
35
|
+
const props = defineProps<{
|
|
36
|
+
modelValue: { [key: string]: any } | {}
|
|
37
|
+
// 表单Group项
|
|
38
|
+
formGroup: IFormGroupConfig
|
|
39
|
+
// 提交状态
|
|
40
|
+
isLoading?: boolean
|
|
41
|
+
// 是否禁用最后一个元素的tab
|
|
42
|
+
disabledTab?: boolean
|
|
43
|
+
}>()
|
|
44
|
+
|
|
45
|
+
const formRefs = ref([] as any[])
|
|
46
|
+
|
|
47
|
+
// 主要记录原来groupFowmLayout下标和group下标的对应
|
|
48
|
+
const indexList = ref([] as number[])
|
|
49
|
+
|
|
50
|
+
// 重新定义当前值
|
|
51
|
+
const currentValue = computed({
|
|
52
|
+
get: () => props.modelValue,
|
|
53
|
+
set(val: any) {
|
|
54
|
+
emits('update:modelValue', val)
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 获取布局,且初始化
|
|
60
|
+
* @param groupItem
|
|
61
|
+
*/
|
|
62
|
+
const getGroupFowmLayout = computed(() => {
|
|
63
|
+
const formConfigList = [] as Array<{
|
|
64
|
+
title?: string
|
|
65
|
+
column?: number
|
|
66
|
+
formProps?: IFormProps
|
|
67
|
+
}>
|
|
68
|
+
// 清空refs列表
|
|
69
|
+
formRefs.value = []
|
|
70
|
+
indexList.value = []
|
|
71
|
+
|
|
72
|
+
const tempId = new Date().getTime()
|
|
73
|
+
props.formGroup.group.map((item, i): any => {
|
|
74
|
+
item.fid = item.fid || `${tempId + i}`
|
|
75
|
+
item._vif = getVIf.value(item.vif)
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
// 这里首先遍历一遍_vif
|
|
79
|
+
const tempGroupList = props.formGroup.group.filter((item, i) => {
|
|
80
|
+
// 这里单独存储下index 的对应关系
|
|
81
|
+
if (item._vif) indexList.value.push(i)
|
|
82
|
+
return item._vif
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
const tempFormConfig = cloneDeep(props.formGroup) as any
|
|
86
|
+
const column = props.formGroup.column || 1
|
|
87
|
+
// 移除无用
|
|
88
|
+
delete tempFormConfig.group
|
|
89
|
+
delete tempFormConfig.column
|
|
90
|
+
|
|
91
|
+
// 表单校验
|
|
92
|
+
tempFormConfig.beforeValidate = async (postData: any) => {
|
|
93
|
+
// 这里处理自带的 beforeValidate
|
|
94
|
+
if (props.formGroup.beforeValidate) {
|
|
95
|
+
const result = (props.formGroup.beforeValidate as Function)(postData)
|
|
96
|
+
if (!(isPromiseLike<any>(result) ? await result : result)) return false
|
|
97
|
+
}
|
|
98
|
+
return await Promise.all(formRefs.value.map((tempRef) => tempRef.validate()))
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
tempFormConfig.groupFormDesc = {} as IFormDesc
|
|
102
|
+
tempGroupList.map((item) => {
|
|
103
|
+
Object.assign(tempFormConfig.groupFormDesc, item.formDesc)
|
|
104
|
+
})
|
|
105
|
+
tempFormConfig.disabledTab = props.disabledTab
|
|
106
|
+
|
|
107
|
+
// 遍历
|
|
108
|
+
tempGroupList.map((groupItem, i) => {
|
|
109
|
+
formConfigList.push({
|
|
110
|
+
title: groupItem.title,
|
|
111
|
+
formProps: Object.assign({ column: groupItem.column || column }, i === tempGroupList.length - 1 ? tempFormConfig : { showBtns: false }, groupItem || {}) as IFormProps
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
return formConfigList
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* 获取vif
|
|
119
|
+
*/
|
|
120
|
+
const getVIf = computed(() => (vif: boolean | Function | undefined) => {
|
|
121
|
+
if (typeof vif === 'function') {
|
|
122
|
+
return vif(props.modelValue)
|
|
123
|
+
} else if (typeof vif === 'boolean') {
|
|
124
|
+
return vif
|
|
125
|
+
}
|
|
126
|
+
return true
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
// 设置子组件的ref-重置form的时候需要用到
|
|
130
|
+
function setComponentRef(el: any) {
|
|
131
|
+
if (!el) return
|
|
132
|
+
if (!formRefs.value.find((item) => item.fid === el.fid)) {
|
|
133
|
+
formRefs.value.push(el)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
//重置
|
|
138
|
+
function handleReset(fid: string) {
|
|
139
|
+
setTimeout(() => {
|
|
140
|
+
formRefs.value.map((item) => {
|
|
141
|
+
if (item.fid !== fid) {
|
|
142
|
+
item.clearValid()
|
|
143
|
+
}
|
|
144
|
+
})
|
|
145
|
+
}, 100)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 校验
|
|
150
|
+
*/
|
|
151
|
+
async function validate() {
|
|
152
|
+
return await Promise.all(formRefs.value.map((tempRef) => tempRef.validate()))
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* 清理校验
|
|
157
|
+
*/
|
|
158
|
+
async function clearValid() {
|
|
159
|
+
return await Promise.all(formRefs.value.map((tempRef) => tempRef.clearValid()))
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* 获取数据
|
|
164
|
+
*/
|
|
165
|
+
function getData() {
|
|
166
|
+
const tempData = {} as any
|
|
167
|
+
formRefs.value.map((tempRef) => {
|
|
168
|
+
Object.assign(tempData, tempRef.getData())
|
|
169
|
+
})
|
|
170
|
+
return tempData
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
defineExpose({ validate, getData, clearValid })
|
|
174
|
+
</script>
|
|
175
|
+
<style lang="scss">
|
|
176
|
+
.el-plus-form-group {
|
|
177
|
+
// Todo
|
|
178
|
+
/* 通用的标题-短线线 */
|
|
179
|
+
.title-line {
|
|
180
|
+
width: 100%;
|
|
181
|
+
height: 22px;
|
|
182
|
+
font-size: 16px;
|
|
183
|
+
font-weight: 500;
|
|
184
|
+
color: var(--text-color);
|
|
185
|
+
line-height: 22px;
|
|
186
|
+
position: relative;
|
|
187
|
+
padding-left: 10px;
|
|
188
|
+
margin-bottom: 20px;
|
|
189
|
+
&::before {
|
|
190
|
+
position: absolute;
|
|
191
|
+
content: '';
|
|
192
|
+
width: 3px;
|
|
193
|
+
height: 16px;
|
|
194
|
+
left: 0;
|
|
195
|
+
top: 1px;
|
|
196
|
+
background-color: var(--el-color-primary);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
</style>
|
|
201
|
+
./util/aaaaa
|