Commit f641a3ef authored by tianhongyang's avatar tianhongyang

自定义表单整体逻辑完成,待嵌入使用组件

parent cf0d067b
......@@ -47,6 +47,7 @@
"js-md5": "^0.7.3",
"jsencrypt": "3.0.0-rc.1",
"json-editor-vue": "^0.11.1",
"mitt": "^3.0.1",
"nprogress": "0.2.0",
"quill": "1.3.7",
"screenfull": "5.0.2",
......
import Vue from 'vue';
import VCA from '@vue/composition-api'; //composition APi
import mitt from "mitt";
import Cookies from 'js-cookie';
import Element from 'element-ui';
......@@ -60,6 +62,7 @@ Vue.prototype.selectDictLabel = selectDictLabel;
Vue.prototype.selectDictLabels = selectDictLabels;
Vue.prototype.download = download;
Vue.prototype.handleTree = handleTree;
Vue.prototype.$mitt = mitt();
// 全局组件挂载
Vue.component('DictTag', DictTag);
......
......@@ -4,14 +4,12 @@
* 模块模板
*/
export const subfieldModuleTemplate = {
defaultSubfieldModuleName: "分栏名称",
defaultSubfieldModuleName: "",
subfieldModuleName: "",
subfieldModuleNameRules: {
trigger: ["blur", "change"],
// required: true,
// message: "请输入分栏名称"
validator: (rule, value, callback) => {
alert(1)
alert(1);
if (!value) {
return callback(new Error("请输入分栏名称"));
}
......@@ -29,6 +27,8 @@ export const defaultComOptions = [
comType: "el-input",
// 组件展示图标
comShowIcon: require("@/assets/images/consultingAgencyManagement/customForm/icon_single_line_text@2x.png"),
// 验证通过
checkedAllow: false,
// 表单属性
formAttribute: {
// 验证规则
......
......@@ -7,7 +7,7 @@
<div class="design-main fields-main">
<vuedraggable :list="defaultComOptions" :group="{name: 'customComGroup', pull: 'clone', put: false}" class="design-draggable-fields"
draggable=".draggable-fields-item" ghostClass="subfield-origin-dragClass" :clone="targetComClone" :sort="false"
:disabled="!subfieldModuleForm.subfieldModuleList.length">
:disabled="!subfieldModuleForm.subfieldModuleList.length" :move="onMove">
<transition-group name="fade" tag="div" class="draggable-fields-list">
<div class="draggable-fields-item" :class="{'has-no-subfield-module' : !subfieldModuleForm.subfieldModuleList.length}"
v-for="(item,index) of defaultComOptions" :key="index" @click="fieldsItemClick">
......@@ -26,12 +26,12 @@
<!-- 最外层dragg容器 拖动模块module .subfield-module-dragg-target-icon -->
<vuedraggable :list="subfieldModuleForm.subfieldModuleList" group="customSubfieldmodule" class="subfield-module-container"
draggable=".subfield-module-item-container" handle=".subfield-module-dragg-target-icon" :animation="340">
draggable=".subfield-module-item-container" handle=".subfield-module-dragg-target-icon" :animation="340" :move="onMove">
<!-- 添加的分栏模块以及chidren模块 -->
<transition-group name="fade" tag="div" class="subfield-module-list">
<vuedraggable v-for="(item,index) of subfieldModuleForm.subfieldModuleList" :key="item.uid" draggable=".subfield-item-container"
handle=".subfield-module-item-dragg-target-icon" tag="subfield-module" :list="item.children" group="customComGroup"
:component-data="createComponentData(item,index)" :animation="340" ghostClass="subfield-item-dragClass" :sort="true"
:component-data="createComponentData(item,index)" :animation="340" :move="onMove" ghostClass="subfield-item-dragClass" :sort="true"
@change="dataChange">
<subfield-item v-for="(child,index) of item.children" :key="child.uid" :activeUid="activeUid" :parentUid="item.uid"
:childModuleInfo="child" @removeModuleItem="removeModuleItem" @activeSubfieldItem="activeSubfieldItem"></subfield-item>
......@@ -50,7 +50,8 @@
<div class="custom-form-design-field-options">
<div class="design-header field-options-header">字段设置</div>
<div class="design-main field-options-main">
<set-field-option :activeFieldData="activeItemData"></set-field-option>
<set-field-option v-if="showSetOption" :activeFieldData="activeItemData" :activeUid="activeUid" :parentUid="activeModuleId"
ref="setFieldOptionRef" @cancelSetOptions="cancelSetOptions" @setOptionsFinish="setOptionsFinish"></set-field-option>
</div>
</div>
</div>
......@@ -60,7 +61,7 @@
:custom-class="'subfield-module-dialog-inner'" @close="removeDialogClose">
<div class="subfield-module-dialog-content">
<img src="@/assets/images/consultingAgencyManagement/customForm/icon_tips@2x.png" alt="">
<span>{{removeSubfieldModule.subfieldModuleName ? `确认删除分栏“${removeSubfieldModule.subfieldModuleName}”吗?` : "确认删除该分栏吗?"}}</span>
<span>{{`确认删除“${removeSubfieldModule.subfieldModuleName ? removeSubfieldModule.subfieldModuleName : removeSubfieldModule.defaultSubfieldModuleName}”吗?`}}</span>
</div>
<div class="subfield-module-dialog-footer">
<el-button size="default" @click="removeSubFiledModuleDialog = false">取消</el-button>
......@@ -74,6 +75,7 @@
import { defaultComOptions, subfieldModuleTemplate } from "@/utils/generator/custom-design-options";
import SubfieldItem from "@/views/consultingOrgManagement/components/CustomForm/components/SubfieldItem";
import SetFieldOption from "@/views/consultingOrgManagement/components/CustomForm/components/SetFieldOption";
import { elementMessageSingleton } from "@/utils";
import vuedraggable from "vuedraggable";
import { v4 } from 'uuid';
export default {
......@@ -100,8 +102,12 @@ export default {
activeUid: "",
// 编辑的组件数据
activeItemData: {},
// 编辑的组件原始数据
activeItemDataOrigin: {},
// active moduleId 当前命中的模块id
activeModuleId: ""
activeModuleId: "",
// 分栏计数
moduleCount: 0,
};
},
watch: {
......@@ -114,19 +120,56 @@ export default {
},
//可访问data属性
created() {
this.initModule();
},
//计算集
computed: {
showSetOption() {
return this.activeUid ? true : false;
}
},
//方法集
methods: {
generateRandomLowerCaseLetter() {
const alphabet = 'abcdefghijklmnopqrstuvwxyz';
const randomIndex = Math.floor(Math.random() * alphabet.length);
return alphabet[randomIndex];
},
initModule() {
// 模块初始化
this.addSubfieldModule();
const component = JSON.parse(JSON.stringify(defaultComOptions[0]));
component.uid = v4();
component.formAttribute.fieldName = this.generateRandomLowerCaseLetter() + component.uid.split("-").join("");
this.activeItemData = component;
this.activeItemDataOrigin = JSON.parse(JSON.stringify(this.activeItemData));
this.activeModuleId = this.subfieldModuleForm.subfieldModuleList[0].uid;
this.activeUid = component.uid;
this.subfieldModuleForm.subfieldModuleList[0].children.push(component);
},
onMove(e, originalEvent) {
try {
if (this.activeUid && !this.activeItemData?.checkedAllow) {
elementMessageSingleton("warning", "请先保存字段设置");
return false;
}
return true;
} catch (error) {
console.log(error);
}
},
resetCurrent() {
this.activeUid = "";
this.activeModuleId = "";
this.activeItemData = {};
this.activeItemDataOrigin = {};
},
// 克隆目标组件
targetComClone(v) {
console.log("clone", v);
const cloneTarget = JSON.parse(JSON.stringify(v));
cloneTarget.uid = v4();
cloneTarget.formAttribute.fieldName = this.generateRandomLowerCaseLetter() + cloneTarget.uid.split("-").join("");
return cloneTarget;
},
// 字段组件点击事件
......@@ -135,6 +178,7 @@ export default {
this.$message.warning("请先添加分栏");
}
},
// 模块内部变化处理
dataChange({ added, removed, moved }) {
if (added) {
this.currentActiveByItemId(added.element);
......@@ -143,17 +187,40 @@ export default {
this.currentActiveByItemId(moved.element);
}
},
// 取消当前焦点设置
cancelSetOptions() {
this.activeItemData = JSON.parse(JSON.stringify(this.activeItemDataOrigin));
},
// 设置表单完成
setOptionsFinish(current, parentUid) {
const _temp = JSON.parse(JSON.stringify(current));
_temp.checkedAllow = true;
const index = this.subfieldModuleForm.subfieldModuleList.findIndex(item => item.uid == parentUid);
if (index > -1) {
const childIndex = this.subfieldModuleForm.subfieldModuleList[index].children.findIndex(child => child.uid == current.uid);
if (childIndex > -1) {
this.subfieldModuleForm.subfieldModuleList[index].children.splice(childIndex, 1, _temp);
this.resetCurrent();
}
}
},
// 命中变化的表单元素
currentActiveByItemId(current) {
const _temp = JSON.parse(JSON.stringify(current));
_temp.checkedAllow = false;
this.activeUid = current.uid;
this.activeItemData = current;
this.activeItemData = _temp;
this.activeItemDataOrigin = _temp;
this.activeModuleId = this.subfieldModuleForm.subfieldModuleList.find(item => item?.children?.findIndex(child => child.uid == current.uid) > -1).uid;
console.log(this.activeModuleId);
console.log(this.activeModuleId, "模块uid");
console.log(this.activeUid, "表单元素uid");
},
// 添加分栏
addSubfieldModule() {
const _temp = JSON.parse(JSON.stringify(subfieldModuleTemplate));
_temp.uid = v4();
this.moduleCount += 1;
_temp.defaultSubfieldModuleName = `分栏${this.moduleCount}`;
this.subfieldModuleForm.subfieldModuleList.push(_temp);
},
// 传递模块事件
......@@ -165,28 +232,44 @@ export default {
},
on: {
"removeModule": this.removeModule,
"editFinish": this.editFinish
"editFinish": this.editFinish,
"editModule": this.editModule
}
};
},
// 编辑模块名称
// 编辑模块 更新title
editModule(module) {
const _temp = JSON.parse(JSON.stringify(module));
const flag = this.onMove();
if (!flag) return;
const index = this.subfieldModuleForm.subfieldModuleList.findIndex(item => item.uid == _temp.uid);
if (index > -1) {
_temp.edit = true;
this.subfieldModuleForm.subfieldModuleList.splice(index, 1, _temp);
}
},
// 编辑模块名称结束
editFinish(module) {
const index = this.subfieldModuleForm.subfieldModuleList.findIndex(item => item.uid == module.uid);
if (index > -1) {
this.subfieldModuleForm.subfieldModuleList.splice(index, 1, module);
this.subfieldModuleForm.subfieldModuleList.splice(index, 1, { ...module, ...this.subfieldModuleForm.subfieldModuleList[index].children });
}
},
// 命中的模块
activeSubfieldItem(itemModule, parentUid) {
this.activeUid = itemModule.uid;
const flag = this.onMove();
if (!flag) return;
const _temp = JSON.parse(JSON.stringify(itemModule));
_temp.checkedAllow = false;
this.activeUid = _temp.uid;
this.activeModuleId = parentUid;
this.activeItemData = itemModule;
this.activeItemData = _temp;
this.activeItemDataOrigin = _temp;
},
// 删除模块表单输入框
removeModuleItem(itemModule, parentUid) {
if (itemModule.uid == this.activeUid) {
this.activeUid = "";
this.activeItemData = {};
this.resetCurrent();
}
const parentModule = this.subfieldModuleForm.subfieldModuleList.find(item => item.uid == parentUid);
if (parentModule) {
......@@ -210,8 +293,7 @@ export default {
if (this.removeSubfieldModule?.children?.length) {
const index = this.removeSubfieldModule.children.findIndex(item => item.uid == this.activeUid);
if (index > -1) {
this.activeUid = "";
this.activeItemData = {};
this.resetCurrent();
}
}
const index = this.subfieldModuleForm.subfieldModuleList.findIndex(item => item.uid == this.removeSubfieldModule.uid);
......@@ -239,6 +321,7 @@ export default {
.subfield-origin-dragClass,
.subfield-item-dragClass {
width: 100%;
display: flex;
align-items: center;
background: rgba(0, 129, 255, 0.3);
......@@ -377,7 +460,7 @@ export default {
border-left: none;
.custom-design-el-form {
width: 100%;
height: 100%;
min-height: 100%;
/* .subfield-module-draggable-list {
margin-bottom: 12px;
......
......@@ -6,6 +6,10 @@
:rules="setFieldOptionRules.fieldName">
<el-input v-model="comActiveFieldData.formAttribute.fieldName" placeholder="请输入字段名称" clearable></el-input>
</el-form-item>
<!-- label展示名称 -->
<el-form-item label="字段label" class="set-field-option-item" prop="formAttribute.label" v-if="comActiveFieldData.formAttribute">
<el-input v-model="comActiveFieldData.formAttribute.label" placeholder="请输入字段label" clearable></el-input>
</el-form-item>
<!-- placeholder文字 -->
<el-form-item label="提示文字" class="set-field-option-item" prop="componentAttribute.placeholder" v-if="comActiveFieldData.componentAttribute">
<el-input v-model="comActiveFieldData.componentAttribute.placeholder" placeholder="请输入提示文字" clearable></el-input>
......@@ -14,10 +18,6 @@
<el-form-item label="默认值" class="set-field-option-item" prop="componentAttribute.value" v-if="comActiveFieldData.componentAttribute">
<el-input v-model="comActiveFieldData.componentAttribute.value" placeholder="请输入默认值" clearable></el-input>
</el-form-item>
<!-- label展示名称 -->
<el-form-item label="字段label" class="set-field-option-item" prop="formAttribute.label" v-if="comActiveFieldData.formAttribute">
<el-input v-model="comActiveFieldData.formAttribute.label" placeholder="请输入字段label" clearable></el-input>
</el-form-item>
<!-- 表单样式 -->
<div class="set-field-option-styles-item" v-if="comActiveFieldData.formAttribute">
......@@ -43,7 +43,10 @@
</el-form>
<!-- 确定编辑 -->
<div class="set-field-option-footer">
<div class="set-field-option-inner" v-if="this.comActiveFieldData && this.comActiveFieldData.uid">
<el-button @click="cancelSet">取消</el-button>
<el-button type="primary" @click="formCheck">确定</el-button>
</div>
</div>
</div>
</template>
......@@ -59,29 +62,60 @@ export default {
componentAttribute: {},
componentOptions: {}
})
}
},
parentUid: String,
activeUid: String
},
watch: {
"activeFieldData.uid": {
handler(newValue) {
this.$refs["customDesignFormRef"].clearValidate();
}
},
activeFieldData: {
handler(newValue) {
// 通过保存更新源数据按钮
this.comActiveFieldData = newValue;
this.comActiveFieldData = JSON.parse(JSON.stringify(newValue));
},
deep: true
},
comActiveFieldData: {
handler(newValue) {
// 通过保存更新源数据按钮
this.$mitt.emit("fieldOptionChange", newValue);
},
deep: true
}
},
data() {
const fieldNameValidor = (rule, value, callback) => {
const reg = /^[a-zA-Z0-9_]+$/;
const numReg = /^[0-9]/;
if (!value) {
return callback(new Error("请输入字段名称"));
}
if (numReg.test(value)) {
return callback(new Error("字段名称不能以数字开头"));
}
if (!reg.test(value)) {
return callback(new Error("字段名称只能为数字、字母(大小写)、下划线组成"));
}
callback();
};
return {
// 通过保存更新源数据按钮
comActiveFieldData: this.activeFieldData,
comActiveFieldData: JSON.parse(JSON.stringify(this.activeFieldData)),
setFieldOptionRules: {
fieldName: [{ required: true, trigger: ["blur", "change"], message: "请输入字段名称" }]
fieldName: [{ required: true, trigger: ["blur", "change"], validator: fieldNameValidor }]
}
};
},
//可访问data属性
created() {
this.$mitt.on("subfieldItemChange", this.setOptions);
},
beforeDestroy() {
this.$mitt.off("subfieldItemChange");
},
//计算集
computed: {
......@@ -89,7 +123,22 @@ export default {
},
//方法集
methods: {
setOptions(value) {
this.comActiveFieldData = value;
},
cancelSet() {
this.$emit("cancelSetOptions");
},
async formCheck() {
try {
const result = await this.$refs["customDesignFormRef"].validate();
if (result) {
this.$emit("setOptionsFinish", this.comActiveFieldData, this.parentUid);
}
} catch (error) {
console.log(error);
}
}
},
}
</script>
......@@ -101,6 +150,7 @@ export default {
.set-field-option-form {
width: 100%;
height: calc(100% - 56px);
/* height: 100%; */
padding: 16px;
overflow-y: auto;
overflow-x: hidden;
......@@ -114,6 +164,17 @@ export default {
align-items: center;
border-top: 1px solid #eeeeee;
box-sizing: border-box;
padding: 0px 12px;
.set-field-option-inner {
button {
height: 32px;
line-height: 32px;
padding: 0px;
width: 60px;
border-radius: 4px;
}
}
}
::v-deep .set-field-option-item {
......
<template>
<div class="subfield-item-container" :class="{'is-active-subfield-item' : activeUid == comChildModuleInfo.uid}" @click="activeSubfieldItem">
<div class="subfield-item-container" :class="{'is-active-subfield-item' : activeUid == comChildModuleInfo.uid}" :style="styles"
@click="activeSubfieldItem">
<img src="@/assets/images/consultingAgencyManagement/customForm/icon_drag@2x.png" alt="" class="subfield-module-item-dragg-target-icon">
<el-form-item class="subfield-module-form-item" :label="comChildModuleInfo.formAttribute.label">
<el-form-item class="subfield-module-form-item" :class="{'is-required' : comChildModuleInfo.formAttribute.required}"
:label="comChildModuleInfo.formAttribute.label">
<!-- 输入框类型 -->
<el-input v-model="comChildModuleInfo.componentAttribute.value" :placeholder="comChildModuleInfo.componentAttribute.placeholder" clearable
v-if="comChildModuleInfo.comType == 'el-input'"></el-input>
......@@ -21,30 +23,47 @@ export default {
watch: {
childModuleInfo: {
handler(newValue) {
this.comChildModuleInfo = newValue;
this.comChildModuleInfo = JSON.parse(JSON.stringify(newValue));
},
deep: true
},
comChildModuleInfo: {
handler(newValue) {
this.$mitt.emit("subfieldItemChange", newValue);
},
deep: true
}
},
data() {
return {
comChildModuleInfo: this.childModuleInfo,
comChildModuleInfo: JSON.parse(JSON.stringify(this.childModuleInfo)),
};
},
//可访问data属性
created() {
this.$mitt.on("fieldOptionChange", this.setFieldOption);
},
beforeDestroy() {
this.$mitt.off("fieldOptionChange");
},
//计算集
computed: {
styles() {
return {
width: this.comChildModuleInfo.formAttribute ? `${this.comChildModuleInfo.formAttribute.width}%` : "100%"
};
}
},
//方法集
methods: {
setFieldOption(value) {
this.comChildModuleInfo = value;
},
removeModuleItem() {
this.$emit("removeModuleItem", this.comChildModuleInfo, this.parentUid);
},
activeSubfieldItem() {
if (this.activeUid == this.comChildModuleInfo?.uid) return;
this.$emit("activeSubfieldItem", this.comChildModuleInfo, this.parentUid);
}
},
......@@ -60,6 +79,8 @@ export default {
align-items: center;
background: #dcebff;
transition: width 0.3s linear;
&.is-active-subfield-item {
border: 1px solid #0081ff;
}
......@@ -78,6 +99,7 @@ export default {
font-size: 14px;
font-weight: 400;
color: rgba(35, 35, 35, 0.8);
white-space: nowrap;
}
.el-form-item__content {
flex: 1;
......
......@@ -68,7 +68,8 @@ export default {
this.$emit("removeModule", this.comModuleInfo);
},
editModule() {
this.comModuleInfo.edit = true;
this.$emit("editModule", this.comModuleInfo);
// this.comModuleInfo.edit = true;
},
editCancel() {
this.comModuleInfo.edit = false;
......@@ -85,6 +86,8 @@ export default {
</script>
<style lang="scss" scoped>
.subfield-module-item-container {
display: flex;
flex-wrap: wrap;
margin-bottom: 12px;
width: 100%;
border: 1px solid #dcdfe6;
......@@ -93,6 +96,7 @@ export default {
overflow: hidden;
.subfield-module-header {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment