Skip to content

Commit

Permalink
feat(GenerateForm): 新增Prop rules 支持组件联动
Browse files Browse the repository at this point in the history
  • Loading branch information
BoBoooooo committed Feb 22, 2021
1 parent 4c6ff60 commit 45011e3
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 115 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "element-pro-crud",
"version": "0.8.7-5",
"version": "0.8.8",
"author": "BoBo<[email protected]>",
"main": "lib/ProCrud.umd.min.js",
"files": [
Expand Down
5 changes: 5 additions & 0 deletions src/component/crud-table/src/CrudTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
:dialogFormDesignerName="dialogFormDesignerName"
:tableParams="tableParams"
@afterSave="tableReload"
:rules="formRules"
:textMap="text"
@change="formChange"
:formValuesAsync="formValuesAsync"
Expand Down Expand Up @@ -220,6 +221,10 @@ export default defineComponent({
default: false,
type: Boolean,
},
formRules: {
default: () => [],
type: Array,
},
formValuesAsync: {
default: () => ({}),
type: Object,
Expand Down
8 changes: 8 additions & 0 deletions src/component/crud-table/src/GenerateFormDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<GenerateForm ref="generateDialogForm"
:value="formValues"
:data="formDesign"
:rules="rules"
:readOnly="isReadOnly"
:remote="remoteFuncs"
:entity.sync="entity"
Expand Down Expand Up @@ -117,6 +118,13 @@ export default class GenerateFormDialog extends Vue {
// 表单是否全屏
@Prop({ default: false, type: Boolean }) dialogFullscreen!: boolean;

// 组件联动规则
@Prop({
type: Array,
default: () => [],
})
rules!: any[];

$refs!: {
generateDialogForm: HTMLFormElement;
};
Expand Down
1 change: 1 addition & 0 deletions src/component/crud-table/types/CrudTable.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ interface CrudTableProps {
dialogFullscreen: boolean // 表单是否全屏
formValuesAsync: AnyObject // 异步更新表单数据
formTableConfig: AnyObject // 子表tableConfig
formRules: AnyObject // 子表tableConfig
actionColumnWidth: number // 操作列宽度
totalField: string // totalField
}
Expand Down
15 changes: 4 additions & 11 deletions src/component/form-designer/src/FormDesigner.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
<!-- 左侧边栏 -->
<el-aside style="width: 20%;max-width:250px">
<div class="components-list">
<div class="widget-cate">基础组件</div>
<div class="widget-cate">表单组件</div>
<Draggable :clone="handleClone" tag="ul" :list="basicComponents" v-bind="getDraggableOptions()" :move="handleMove">
<li class="form-edit-widget-label" v-for="(item, index) in basicComponents" :key="index">
<div>
Expand All @@ -65,7 +65,7 @@
</div>
</li>
</Draggable>
<div class="widget-cate">高级组件</div>
<div class="widget-cate">高级/异步组件</div>
<Draggable :clone="handleClone" tag="ul" :list="advanceComponents" v-bind="getDraggableOptions()" :move="handleMove">
<li class="form-edit-widget-label" v-for="(item, index) in advanceComponents" :key="index">
<div>
Expand Down Expand Up @@ -107,8 +107,9 @@
<el-main :class="{ 'widget-empty': widgetForm.list.length == 0 }">
<WidgetForm v-if="currentMode === 'design'" ref="widgetForm" :data="widgetForm" :select.sync="widgetFormSelect"></WidgetForm>
<template v-else>
<el-alert type="warning" :closable="false" style="margin-bottom:15px">组件依赖远端数据需要结合代码!</el-alert>
<el-alert type="warning" :closable="false" style="margin-bottom:15px">异步及依赖远端数据的组件需要结合代码!</el-alert>
<GenerateForm :data="widgetForm" :value="widgetModels" ref="generateForm"> </GenerateForm>
<el-button size="small" style="float:right;margin-top: 15px" type="primary" @click="handleTest">获取表单数据</el-button>
</template>
</el-main>
</el-container>
Expand Down Expand Up @@ -436,20 +437,12 @@ export default {
handleMove() {
return true;
},
// 预览按钮
handlePreview() {
this.previewVisible = true;
},
// 预览点确定获取表单数据
handleTest() {
this.$refs.generateForm
.getData()
.then((data) => {
this.$alert(data, '').catch(() => {});
this.$refs.widgetPreview.end();
})
.catch(() => {
this.$refs.widgetPreview.end();
});
},
// 生成json
Expand Down
65 changes: 55 additions & 10 deletions src/component/form-designer/src/GenerateForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -123,25 +123,25 @@ export default class GenerateForm extends Vue {
value: any;

// 表单当前实时对象

@Prop({
type: Object,
default: () => ({}),
})
entity: any;

// 是否只读
@Prop({
type: Boolean,
default: false,
})
readOnly!: boolean;

// 设置隐藏区域
// 组件联动规则
@Prop({
type: Array,
default: () => [],
})
setHidden: any;
rules!: any[];

// 远端数据
@Prop({
Expand All @@ -157,15 +157,58 @@ export default class GenerateForm extends Vue {
})
formTableConfig: any;

// 当前表单实体对象
models: any = {};

// 内部属性记录字段对应组件,用于联动时快速修改
fieldMap :any = {};


created() {
if (this.data.list) {
// 根据数据结构生成给子组件的数据源
this.generateModel(this.data.list);
}
}

// 组件联动handler
controlFieldHandler(model) {
this.rules.forEach((r) => {
const value = this.models[r.field];
if (value) {
const controlRule = r.control.find(_ => _.value === value);
if (controlRule) {
const { rule: insideRule } = controlRule;
if (insideRule) {
insideRule.forEach((_) => {
const field = this.fieldMap[_.field];
if (field) {
switch (_.operator) {
case 'show': field.hidden = false; this.models[_.field] = _.value; break;
case 'hidden': field.hidden = true; break;
case 'required':
field.options.required = true;
field.rules.push({
message: `${field.name}必须填写`,
required: true,
trigger: 'blur',
});
break;
case 'unrequired':
field.options.required = false;
// eslint-disable-next-line no-shadow
field.rules.shift(field.rules.findIndex(_ => _.required));
break;
default: break;
}
}
});
}
}
}
});
}

getTableSelection($event, item) {
const tableSelections = {};
tableSelections[item.model] = $event;
Expand All @@ -188,17 +231,15 @@ export default class GenerateForm extends Vue {
} else {
this.setDefaultValue(row);
}
// 表单隐藏设置
if (this.setHidden.includes(row.model)) {
row.hidden = true;
}
// 组件option跟字段映射
this.$set(this.fieldMap, row.model, row);
}
}
this.models = { ...this.value, ...this.models };
}

// 多选情况下数组转字符串
formValueToString() {
filterFormData() {
const model = { ...this.models };
Object.keys(model).forEach((k) => {
if (Array.isArray(model[k])) {
Expand Down Expand Up @@ -233,7 +274,7 @@ export default class GenerateForm extends Vue {
return new Promise((resolve, reject) => {
this.$refs.generateForm.validate((valid) => {
if (valid) {
resolve(this.formValueToString());
resolve(this.filterFormData());
} else {
// 校验失败时focus到文本框
// 注意此处没有考虑textarea的情况,多行文本会失败
Expand All @@ -254,7 +295,7 @@ export default class GenerateForm extends Vue {

// 不经过验证直接获取表单内容
getDataWithoutValidate() {
return new Promise(resolve => resolve(this.formValueToString()));
return new Promise(resolve => resolve(this.filterFormData()));
}

// 生成的按钮点击
Expand Down Expand Up @@ -307,6 +348,10 @@ export default class GenerateForm extends Vue {
// immediate: true,
})
modelsOnChange(val) {
// 组件值改变时检查是否需要联动其他组件
if (this.rules.length > 0) {
this.controlFieldHandler(val);
}
this.$emit('update:entity', val);
}

Expand Down
Loading

0 comments on commit 45011e3

Please sign in to comment.