vue3结合Element Plus动态表单组件
背景介绍
在开发公司内部使用的管理后台时,通过原型发现表单较多,内容层级复杂,而且包含一些联动。
例如:
- 通过input在输入内容后需自动生成对应后缀,以便编辑者了解含义;
- 通过select选择不同的值展示不同的表单项;
- 通过switch设置某个值的开关去控制子组件的显示隐藏;
- 通过input-number输入值控制子表单项个数;
所以决定结合Element已有的组件再重新单独封装一套组件,这样只需要传入js配置文件即可动态生成成对应子项,无需复杂的写很多冗余的html文件。
使用场景
表单较多的后台管理系统
表单内容项多
动态生成表单项
表单联动交互多
组件简介
- 传入配置文件动态生成对应的输入框,文本框,按钮,switch开关,下来选择器,树形选择器,日期选择器,时间选择器,日期范围选择器,日期时间选择器,颜色选择器等表单项。
- 将表单配置项传入(例如tag名称,绑定属性名,是否必填,是否可填,最大值,最小值,可输入最大长度,下拉选择器的数据源,提示语,tips语等,详见下方formConfig.js文件),再将各组件的修改值事件抛出,在父组件中去处理相关值以及联动交互。
- 考虑到层级问题,有可能同一个表单下有多级子级,故组件分为两部分,
els.vue
和index.vue
- 目录
复制
代码部分
参数描述
参数名 | 描述 | 类型 | 示例 |
---|
el | 表单单项配置 | Object | { el: ‘input-number’, prop: ‘time’, label: ‘活动时长’, min: 1, max: 999 } |
data | 表单值 | Any | |
isView | 是否只读 | Boolean | true/false |
回调描述
方法名 | 描述 | 回调形参 | 参数描述 |
---|
change | 值被修改 | Object | {res:修改后的值,el:当前表单项配置} |
组件代码
| <template> |
| <div class="els-container"> |
| <h3 v-show="el.el == 'point-select'"> |
| <el-icon v-if="data.type" @click.stop="$emit('point-handle', { show: true, type: 'add' })"> |
| <CirclePlusFilled /> |
| </el-icon> |
| <el-icon v-if="data.id" @click.stop="$emit('point-handle', { show: true, type: 'set' })"> |
| <EditPen /> |
| </el-icon> |
| </h3> |
| <h2 v-if="el.el == 'h2'">{{el.label}}</h2> |
| <h3 v-else-if="el.el == 'h3'">{{el.label}}</h3> |
| |
| <el-input |
| v-else-if="el.el == 'input'" |
| :placeholder="`输入${el.label || el.place}`" |
| v-model="data[el.prop]" |
| :maxlength="el.max || 1000" |
| :type="el.type || 'text'" |
| :disabled="el.disabled || isView || el.hidden" |
| @input="$emit('change', { res: $event, el })" |
| ></el-input> |
| <el-input-number |
| v-else-if="el.el == 'input-number'" |
| :placeholder="`${el.place ? '输入' + el.place : ''}`" |
| :min="el.min || 0" |
| :max="el.max || 9999999999999999" |
| v-model="data[el.prop]" |
| @input="onInputNumber({ el, res: $event })" |
| :disabled="el.disabled || isView || el.hidden" |
| /> |
| <el-input |
| v-else-if="el.el == 'text-area'" |
| type="textarea" |
| autosize |
| :placeholder="`输入${el.label || el.place}`" |
| v-model="data[el.prop]" |
| :maxlength="el.max || 1000" |
| show-word-limit |
| @input="$emit('change', { res: $event, el })" |
| :disabled="el.disabled || isView || el.hidden" |
| /> |
| <el-date-picker |
| v-else-if="el.el == 'date'" |
| v-model="data[el.prop]" |
| type="date" |
| placeholder="选择一个日期" |
| :disabled="el.disabled || isView || el.hidden" |
| :clearable="false" |
| value-format="YYYY-MM-DD" |
| format="YYYY-MM-DD" |
| :default-value="new Date()" |
| @change="$emit('change', { res: $event, el })" |
| /> |
| <el-date-picker |
| v-else-if="el.el == 'time'" |
| v-model="data[el.prop]" |
| type="datetime" |
| placeholder="选择一个日期时间" |
| :disabled="el.disabled || isView || el.hidden" |
| value-format="YYYY-MM-DD HH:mm:ss" |
| format="YYYY-MM-DD HH:mm:ss" |
| @change="$emit('change', { res: $event, el })" |
| /> |
| <el-date-picker |
| v-else-if="el.el == 'date-range'" |
| v-model="data[el.prop]" |
| type="daterange" |
| placeholder="选择一个日期时段" |
| :disabled="el.disabled || isView || el.hidden" |
| :clearable="false" |
| value-format="YYYY-MM-DD" |
| format="YYYY-MM-DD" |
| @change="$emit('change', { res: $event, el })" |
| /> |
| <el-date-picker |
| v-else-if="el.el == 'time-range'" |
| v-model="data[el.prop]" |
| type="datetimerange" |
| placeholder="选择一个日期时间范围" |
| :disabled="el.disabled || isView || el.hidden" |
| :clearable="false" |
| value-format="YYYY-MM-DD HH:mm:ss" |
| format="YYYY-MM-DD HH:mm:ss" |
| @change="$emit('change', { res: $event, el })" |
| /> |
| <el-switch |
| v-else-if="el.el == 'switch'" |
| v-model="data[el.prop]" |
| active-color="#13C75B" |
| @change="$emit('change', { res: $event, el })" |
| :active-value="el.type ? 1 : true" |
| :inactive-value="el.type ? 0 : false" |
| :disabled="el.disabled || isView || el.hidden" |
| /> |
| <el-radio-group |
| v-else-if="el.el == 'radio'" |
| v-model="data[el.prop]" |
| :disabled="el.disabled || isView || el.hidden" |
| > |
| <el-radio |
| v-for="oitem in el.options" |
| :key="oitem.value" |
| :label="oitem.value" |
| :disabled="oitem.disabled || el.hidden" |
| @click="$emit('change', { res: oitem.value, el })" |
| >{{ oitem.label }}</el-radio> |
| </el-radio-group> |
| <p v-else-if="el.el == 'p'" :class="el.class" @click="$emit('change', { el })"> |
| {{ el.prop?data[el.prop]:'' }} |
| </p> |
| <el-tree-select |
| v-else-if="el.el == 'three-select'" |
| filterable |
| v-model="data[el.prop]" |
| class="m-2" |
| :placeholder="`选择${el.label || el.place}`" |
| :multiple="el.multiple" |
| :data="el.options" |
| :render-after-expand="false" |
| :props="el.props" |
| @change="$emit('change', { res: $event, el })" |
| :disabled="el.disabled || isView || el.hidden" |
| /> |
| <el-select |
| v-else |
| :disabled="el.disabled || isView || el.hidden" |
| :clearable="el.isClear" |
| filterable |
| v-model="data[el.prop]" |
| class="m-2" |
| :placeholder="`选择${el.label || el.place}`" |
| :multiple="el.multiple" |
| @clear="$emit('change',{ |
| item: el, |
| res:'', |
| el, |
| })" |
| > |
| <template #prefix v-if="showIcon(data, el)"> |
| <img :src="data.icon || data.url" class="icon_22" alt /> |
| </template> |
| <el-option |
| v-for="(oitem) in el.options" |
| :key="el.props.value == 'self' ? oitem : oitem[el.props.value]" |
| @click=" |
| onSelectChange({ |
| item: el, |
| res: el.props.value == 'self' ? oitem : oitem[el.props.value], |
| el, |
| oitem, |
| }) |
| " |
| :label="el.props.label == 'self' ? oitem : oitem[el.props.label]" |
| :value="el.props.value == 'self' ? oitem : oitem[el.props.value]" |
| > |
| <img |
| v-if="oitem.url" |
| :src="oitem.url" |
| alt |
| srcset |
| class="icon_22" |
| style="margin-right: 20px" |
| /> |
| <img |
| v-if="oitem.icon" |
| :src="oitem.icon" |
| alt |
| srcset |
| class="icon_22" |
| style="margin-right: 20px" |
| /> |
| <span>{{ el.props.label == "self" ? oitem : oitem[el.props.label] }}</span> |
| </el-option> |
| </el-select> |
| <p v-if="el.fn">{{ el.fn && el.fn(data[el.prop],data) }}</p> |
| </div> |
| </template> |
| <script> |
| export default { |
| name: "els-container" |
| }; |
| </script> |
| <script setup> |
| import { defineProps, ref, defineEmits, onMounted, computed } from "vue"; |
| import { onCheck } from "@/utils/rules"; |
| const emits = defineEmits([ |
| "change" |
| ]); |
| const props = defineProps({ |
| el: { |
| type: Object, |
| default: () => {} |
| }, |
| data: { |
| type: Object, |
| default: () => {} |
| }, |
| isView: { |
| type: Boolean, |
| default: false |
| } |
| }); |
| |
| const disabled = computed(() => { |
| let { isView, el } = props; |
| return isView || el.disabled || el.hidden; |
| }); |
| const showIcon = (data, item) => { |
| return ( |
| (data.icon || data.url) && |
| item.options && |
| typeof item.options[0] == "object" && |
| (item.options[0].url || item.options[0].icon) |
| ); |
| }; |
| const onSelectChange = e => { |
| emits("change", e); |
| }; |
| const onInputNumber = e => { |
| let { res, el } = e; |
| emits("change", e); |
| }; |
| </script> |
| <style scoped lang="scss"> |
| </style> |
复制
参数描述
参数名 | 描述 | 类型 | 默认值 |
---|
sureText | 表单确认文字 | String | 确认 |
cancelText | 表单取消文字 | String | 取消 |
showSure | 是否显示确认按钮 | Boolean | true |
showCancel | 是否显示取消按钮 | Boolean | true |
showClear | 是否显示清除按钮 | Boolean | false |
ddata | 当前表单值 | object | {} |
form | 表单配置项 | object | 示例如下formConfig.js 文件 |
name | 表单名称 | String | |
flex | 表单主轴弹性方向 | String | col |
isView | 是否只读模式 | Boolean | false |
回调描述
方法名 | 描述 | 回调形参 | 参数描述 |
---|
cancel | 取消修改 | null | |
confirm | 确认修改 | null | |
change | 表单项修改 | Object | {res:当前值,el:表单项配置} |
remove | 清除当前表单项值 | null | |
组件代码
| <template> |
| <div> |
| <el-form |
| :ref="($event) => setRef($event)" |
| :model="ddata" |
| label-width="auto" |
| class="q-form flex wrap" |
| :class="['q-form-' + name, 'q-form-' + name.slice(-4), `flex-${flex}-start`, refName]" |
| > |
| <div |
| v-for="(i, n) in form.filter((i) => i)" |
| :key="n" |
| :class="[i.class, i.prop]" |
| :style="i.hidden && { display: 'none', margin: 0 }" |
| > |
| <h4 v-if="i.els && i.label" :class="!i.hidden && 'm-required'">{{ i.label }}</h4> |
| <slot :name="i.slot" :pItem="i" v-if="!i.hidden"> |
| <div class="flex has-els" v-if="i.els" :class="[i.prop,i.class]"> |
| <el-form-item |
| v-for="(el, elIndex) in i.els" |
| :key="elIndex" |
| :class="[el.class, el.prop, el.prop + '_' + el.el]" |
| :label="el.label&&!['h2','h3'].includes(el.el)?el.label:''" |
| :prop="el.prop" |
| :rules="getRules(el)" |
| :style="el.hidden && { display: 'none', margin: 0 }" |
| > |
| <slot :name="el.slot" :sItem="el" v-if="!el.hidden"> |
| <elsContainer |
| :el="el" |
| :isView="isView" |
| :data="ddata" |
| @change="$emit('change',$event)" |
| @point-handle="$emit('point-handle',$event)" |
| /> |
| </slot> |
| </el-form-item> |
| </div> |
| <div v-else class="no-els" :class="i.prop + '_' + i.el"> |
| <el-form-item |
| :label="i.label&&!['h2','h3'].includes(i.el)?i.label:''" |
| :class="[i.class, i.prop]" |
| :prop="i.prop" |
| :rules="getRules(i)" |
| :style="i.hidden && { display: 'none', margin: 0 }" |
| > |
| <elsContainer |
| :el="i" |
| :isView="isView" |
| :data="ddata" |
| @change="$emit('change',$event)" |
| @point-handle="$emit('point-handle',$event)" |
| /> |
| </el-form-item> |
| </div> |
| </slot> |
| <slot name="item-handle" :pItem="i"></slot> |
| </div> |
| <div class="handle"> |
| <el-button plain type="danger" v-show="showClear" @click.stop="$emit('remove')">清 除</el-button> |
| <el-button v-if="showCancel" plain @click="$emit('cancel')"> |
| {{ |
| cancelText |
| }} |
| </el-button> |
| <el-button |
| v-if="showSure" |
| plain |
| type="primary" |
| @click=" |
| onCheck( |
| refName == 'flowDigFormRef' |
| ? flowDigFormRef:FormRef, |
| () => $emit('confirm') |
| ) |
| " |
| >{{ sureText }}</el-button> |
| </div> |
| </el-form> |
| </div> |
| </template> |
| <script> |
| export default { |
| name: "q-form" |
| }; |
| </script> |
| <script setup> |
| import { defineProps, ref, defineEmits } from "vue"; |
| import elsContainer from "./els.vue"; |
| const emits = defineEmits([ |
| "cancel", |
| "confirm", |
| "change", |
| "check", |
| ]); |
| const props = defineProps({ |
| sureText: { |
| type: String, |
| default: "确 定" |
| }, |
| cancelText: { |
| type: String, |
| default: "取 消" |
| }, |
| showSure: { |
| type: Boolean, |
| default: true |
| }, |
| showCancel: { |
| type: Boolean, |
| default: true |
| }, |
| showClear: { |
| type: Boolean, |
| default: false |
| }, |
| refName: { |
| type: String, |
| default: "FormRef" |
| }, |
| ddata: { |
| type: Object, |
| default: () => {} |
| }, |
| form: { |
| type: Array, |
| default: () => [] |
| }, |
| name: { |
| type: String, |
| default: "" |
| }, |
| flex: { |
| type: String, |
| default: "col" |
| }, |
| isView: { |
| type: Boolean, |
| default: false |
| }, |
| }); |
| const FormRef = ref(); |
| const flowDigFormRef = ref(); |
| const setRef = e => { |
| let { refName } = props; |
| switch (refName) { |
| case "FormRef": |
| FormRef.value = e; |
| break; |
| case "flowDigFormRef": |
| flowDigFormRef.value = e; |
| break; |
| } |
| }; |
| |
| const getRules = e => { |
| let { el, hidden, els, required, label, place } = e; |
| let message = `请${el && el.includes("input") ? "输入" : "选择"}${label || |
| place || |
| "内容"}`; |
| let nowrequired; |
| if (required == undefined) { |
| nowrequired = |
| hidden == undefined |
| ? ["true", "1"].includes( |
| `${ |
| required == undefined ? !(el == "p" || hidden || els) : required |
| }` |
| ) |
| : !hidden; |
| } else { |
| nowrequired = required; |
| } |
| return [ |
| { |
| required:nowrequired, |
| message, |
| trigger: ["blur", "change"] |
| } |
| ]; |
| }; |
| const onCheck = (formRef, fn) => { |
| if (!formRef) return; |
| formRef.validate((valid) => { |
| if (valid) { |
| console.log("submit!"); |
| fn && fn(); |
| } else { |
| console.error("error submit!"); |
| return false; |
| } |
| }); |
| }; |
| </script> |
| <style scoped lang="scss"> |
| .condition { |
| min-width: 100%; |
| } |
| .tip { |
| p { |
| color: #f00; |
| font-size: 10px; |
| transform: scale(0.9); |
| position: absolute; |
| margin-left: 68px !important; |
| margin-top: 5px; |
| } |
| } |
| .flex-col-start { |
| > div { |
| width: 100%; |
| } |
| } |
| .el-form { |
| padding-bottom: 10px; |
| > div { |
| ::v-deep .el-form-item { |
| width: 100%; |
| .el-form-item__content { |
| > div { |
| > p { |
| margin-left: 20px; |
| } |
| } |
| } |
| } |
| } |
| .handle { |
| width: 100% !important; |
| } |
| > div { |
| // flex: 0 0 50%; |
| flex: 0 0 100%; |
| // margin-top: 10px; |
| align-items: center; |
| // background: #f00; |
| > h4 { |
| margin-bottom: 10px; |
| font-size: 15px; |
| > i { |
| color: #f00; |
| margin-right: 4px; |
| } |
| } |
| > div { |
| .el-form-item { |
| margin-bottom: 15px; |
| > div { |
| > div { |
| } |
| } |
| ::v-deep .el-form-item__error { |
| // top: 105%; |
| left: 10px; |
| } |
| } |
| } |
| } |
| > .handle { |
| flex: 0 0 100% !important; |
| text-align: right; |
| } |
| } |
| |
| </style> |
| |
复制
使用示例
- 创建
formConfig.js
配置文件代码
| let formConfig = [ |
| { |
| "label": "活动名称与别名", |
| "els": [ |
| { |
| "label": "活动名称", |
| "el": "input", |
| "prop": "name", |
| "place": "活动名称", |
| "max": 15 |
| }, |
| { |
| "label": "活动别名", |
| "el": "input", |
| "prop": "alias", |
| "place": "活动别名", |
| "max": 10 |
| } |
| ] |
| }, |
| { |
| "label": "选择入口与分组", |
| "prop": "display_object", |
| "els": [ |
| { |
| "el": "three-select", |
| "prop": "display_object_value", |
| "label": "UI入口和分组", |
| "options": [ |
| { |
| "id": 101, |
| "name": "商店", |
| "group_name": [ |
| { |
| "id": 1, |
| "value": "101_1", |
| "label": "分组:日常" |
| } |
| ], |
| "state": 0, |
| "label": "UI入口:商店", |
| "value": "101", |
| "children": [ |
| { |
| "id": 1, |
| "value": "101_1", |
| "label": "分组:日常" |
| } |
| ] |
| }, |
| { |
| "id": 100, |
| "name": "充值", |
| "group_name": [ |
| { |
| "id": 1001, |
| "value": "100_1001", |
| "label": "分组:主入口" |
| } |
| ], |
| "state": 0, |
| "label": "UI入口:充值", |
| "value": "100", |
| "children": [ |
| { |
| "id": 1001, |
| "value": "100_1001", |
| "label": "分组:主入口" |
| } |
| ] |
| }, |
| |
| ] |
| }, |
| { |
| "el": "select", |
| "props": { |
| "label": "label", |
| "value": "value" |
| }, |
| "prop": "display_object_index", |
| "label": "排序等级", |
| "options": [ |
| { |
| "label": "第1级", |
| "value": 1 |
| }, |
| { |
| "label": "第2级", |
| "value": 2 |
| }, |
| { |
| "label": "第3级", |
| "value": 3 |
| }, |
| |
| ], |
| "default": 1 |
| } |
| ] |
| }, |
| { |
| "label": "任务tab数量和任务tab解锁方式", |
| "els": [ |
| { |
| "el": "input-number", |
| "prop": "group_num", |
| "label": "任务tab数量", |
| "mix": 1 |
| }, |
| { |
| "el": "select", |
| "props": { |
| "label": "label", |
| "value": "value" |
| }, |
| "label": "任务tab解锁方式", |
| "prop": "group_relation", |
| "options": [ |
| { |
| "label": "自由完成", |
| "value": 0 |
| }, |
| { |
| "label": "按日递进", |
| "value": 1 |
| }, |
| { |
| "label": "按日开放", |
| "value": 2 |
| }, |
| |
| ] |
| } |
| ] |
| }, |
| { |
| "label": "子组模式", |
| "els": [ |
| { |
| "label": "子组开关", |
| "el": "switch", |
| "prop": "sub_group_switch" |
| } |
| ] |
| }, |
| { |
| "label": "积分奖励开关", |
| "els": [ |
| { |
| "label": "活动积分", |
| "el": "switch", |
| "prop": "activity_point_enable" |
| }, |
| { |
| "label": "分组积分", |
| "el": "switch", |
| "prop": "group_point_enable" |
| } |
| ] |
| }, |
| { |
| "label": "奖励是否补发", |
| "prop": "reward_reissue_object", |
| "els": [ |
| { |
| "el": "switch", |
| "prop": "is_reissue", |
| "label": "是否补发" |
| }, |
| { |
| "label": "奖励补发邮件", |
| "el": "select", |
| "prop": "mail_id", |
| "props": { |
| "label": "name", |
| "value": "id" |
| }, |
| "api": "EMAIL_GET", |
| "options": [ |
| { |
| "id": 1, |
| "name": "道具奖励补发", |
| "state": 0 |
| }, |
| { |
| "id": 5, |
| "name": "任务奖励补发", |
| "state": 0 |
| }, |
| { |
| "id": 6, |
| "name": "招募奖励补发", |
| "state": 0 |
| }, |
| { |
| "id": 10, |
| "name": "社团请离通知", |
| "state": 0 |
| }, |
| |
| ], |
| "hidden": false |
| } |
| ] |
| }, |
| { |
| "label": "选择循环模式", |
| "prop": "LoopObject", |
| "els": [ |
| { |
| "el": "select", |
| "props": { |
| "label": "label", |
| "value": "value" |
| }, |
| "prop": "mode", |
| "label": "选择时间循环", |
| "options": [ |
| { |
| "label": "单次", |
| "value": 0 |
| }, |
| { |
| "label": "按日重开", |
| "value": 1 |
| }, |
| |
| ] |
| }, |
| { |
| "el": "input-number", |
| "prop": "cycle", |
| "label": "周期参数", |
| "default": 0, |
| "hidden": true |
| }, |
| { |
| "el": "select", |
| "prop": "version_upgrade_mode", |
| "label": "版本模式", |
| "options": [ |
| { |
| "label": "提升大版本", |
| "value": 1 |
| }, |
| { |
| "label": "提升小版本", |
| "value": 2 |
| } |
| ], |
| "default": 1, |
| "props": { |
| "label": "label", |
| "value": "value" |
| }, |
| "hidden": true |
| }, |
| { |
| "el": "input-number", |
| "prop": "loop_num", |
| "label": "循环次数", |
| "min": 1, |
| "hidden": true |
| } |
| ] |
| }, |
| { |
| "label": "奖励转化", |
| "els": [ |
| { |
| "label": "奖励转化", |
| "el": "switch", |
| "prop": "activity_overdue_recycle_switch" |
| }, |
| { |
| "label": "转化类型", |
| "el": "select", |
| "props": { |
| "label": "label", |
| "value": "value" |
| }, |
| "options": [ |
| { |
| "label": "清空", |
| "value": 1 |
| }, |
| { |
| "label": "回收", |
| "value": 2 |
| } |
| ], |
| "prop": "activity_overdue_recycle_recycle_type", |
| "hidden": true |
| }, |
| { |
| "label": "清空内容", |
| "el": "prize-group", |
| "prop": "activity_overdue_recycle_a_consumes", |
| "person_prop": "activity_overdue_recycle_a_consumes", |
| "default": {}, |
| "prizeType": "all", |
| "hidden": true |
| }, |
| { |
| "label": "回收配置", |
| "slot": "recycle-0101", |
| "hidden": true |
| }, |
| { |
| "label": "发奖方式", |
| "el": "select", |
| "prop": "activity_overdue_recycle_reward_get_type", |
| "props": { |
| "label": "label", |
| "value": "value" |
| }, |
| "options": [ |
| { |
| "label": "邮件领取", |
| "value": 1 |
| }, |
| { |
| "label": "自动发背包", |
| "value": 2 |
| } |
| ], |
| "hidden": true |
| }, |
| { |
| "label": "邮件格式", |
| "el": "select", |
| "prop": "activity_overdue_recycle_mail_id", |
| "props": { |
| "label": "name", |
| "value": "id" |
| }, |
| "api": "EMAIL_GET", |
| "options": [ |
| { |
| "id": 1, |
| "name": "道具奖励补发", |
| "state": 0 |
| }, |
| { |
| "id": 5, |
| "name": "任务奖励补发", |
| "state": 0 |
| }, |
| |
| ], |
| "hidden": true |
| } |
| ] |
| }, |
| { |
| "label": "活动隐藏", |
| "prop": "reward_reissue_object", |
| "els": [ |
| { |
| "el": "switch", |
| "prop": "hide_after_reward", |
| "label": "任务领奖后隐藏活动" |
| } |
| ] |
| } |
| ] |
复制
- 在父组件中使用
| <el-dialog |
| :width="nowDialog.width" |
| :title="nowDialog.title" |
| v-model="nowDialog.show" |
| :close-on-press-escape="false" |
| @close="onDialogCancel" |
| > |
| <m-form |
| :ddata="nowDialog.data" |
| :form="nowDialog.form" |
| :name="nowDialog.name" |
| :flex="nowDialog.flex" |
| :nowDialog="nowDialog" |
| :isView="nowDialog.isView" |
| @change="onDialogChange" |
| @confirm="onDialogConfirm" |
| @cancel="onDialogCancel" |
| > |
| </m-form> |
| </el-dialog> |
| |
| <script setup> |
| import formConfig from './formConfig.js' |
| let nowDialog=reactive({ |
| "title": "任务内容主体编辑", |
| "width": 827.11, |
| "name": "task", |
| "name2": "task", |
| "show": true, |
| "data": {}, |
| "form":formConfig, |
| "flex": "col" |
| }) |
| const onDialogChange=e=>{} |
| const onDialogConfirm=e=>{} |
| const onDialogCancel=e=>{} |
| <script> |
| |
复制