You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
341 lines
8.8 KiB
341 lines
8.8 KiB
<template>
|
|
<div>
|
|
<el-dialog
|
|
title="提示"
|
|
:visible.sync="dialogVisible"
|
|
:fullscreen="true"
|
|
:before-close="handleClose"
|
|
>
|
|
<template #title>
|
|
<div class="btns">
|
|
<span class="title">{{ custom_form.name }}</span>
|
|
<el-button
|
|
size="small"
|
|
type="primary"
|
|
icon="el-icon-refresh-right"
|
|
circle
|
|
@click="$store.dispatch('form/getFormList', custom_form_id)"
|
|
></el-button>
|
|
<el-button
|
|
size="small"
|
|
type="primary"
|
|
icon="el-icon-refresh"
|
|
circle
|
|
@click="update({ id:custom_form_id })"
|
|
></el-button>
|
|
<el-button
|
|
size="small"
|
|
type="primary"
|
|
icon="el-icon-check"
|
|
circle
|
|
@click="submit"
|
|
></el-button>
|
|
</div>
|
|
</template>
|
|
<template>
|
|
<div style="height: 100%">
|
|
<Split v-model="splitL" :min="0.05">
|
|
<template #left>
|
|
<draggable
|
|
v-model="types"
|
|
:sort="false"
|
|
:group="{ name: 'items', pull: 'clone' }"
|
|
>
|
|
<div class="type-item" v-for="item in types">
|
|
{{ item.name }}
|
|
</div>
|
|
</draggable>
|
|
</template>
|
|
<template #right>
|
|
<Split v-model="splitR" :min="0.2">
|
|
<template #left>
|
|
<div style="height: 100%">
|
|
<el-dialog
|
|
id="template-dialog"
|
|
:title="custom_form.name || '模板表单'"
|
|
style="position: relative; inset: 0 0 0 0; height: 100%"
|
|
width="600px"
|
|
top="40px"
|
|
:visible="true"
|
|
:modal="false"
|
|
:append-to-body="false"
|
|
:modal-append-to-body="false"
|
|
>
|
|
<template>
|
|
<el-form
|
|
style="min-height: 200px;"
|
|
label-width="80px"
|
|
label-position="right"
|
|
size="small"
|
|
>
|
|
<draggable
|
|
:value="formList"
|
|
group="items"
|
|
@change="changeHandler"
|
|
>
|
|
<el-form-item
|
|
:label="i.name || '字段名称'"
|
|
:required="
|
|
i.validation instanceof Array ? !!i.validation.find(i => i === 'required') : false
|
|
"
|
|
v-for="(i, index) in formList"
|
|
@click.native="selectPick(i, index)"
|
|
>
|
|
<formSlotRender
|
|
:config="i"
|
|
:index="index"
|
|
></formSlotRender>
|
|
</el-form-item>
|
|
</draggable>
|
|
</el-form>
|
|
</template>
|
|
|
|
<div slot="footer">
|
|
<div>
|
|
<el-button>取 消</el-button>
|
|
<el-button type="warning" plain>重 置</el-button>
|
|
<el-button type="primary">确 定</el-button>
|
|
</div>
|
|
</div>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
<template #right>
|
|
<editPane :rules="rules" :types="types"></editPane>
|
|
</template>
|
|
</Split>
|
|
</template>
|
|
</Split>
|
|
</div>
|
|
</template>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { index, config } from "@/api/system/customFormField";
|
|
import { mapState } from "vuex";
|
|
import { deepCopy } from "@/utils";
|
|
import { update } from "@/api/system/customForm";
|
|
|
|
import formSlotRender from "../components/formSlotRender.vue";
|
|
import editPane from "../components/editPane.vue";
|
|
export default {
|
|
components: {
|
|
formSlotRender,
|
|
editPane,
|
|
},
|
|
data() {
|
|
return {
|
|
//分割面板
|
|
splitL: 0.13,
|
|
splitR: 0.7,
|
|
|
|
custom_form: {},
|
|
custom_form_id: "",
|
|
dialogVisible: false,
|
|
|
|
types: [], //输入类型
|
|
rules: [],
|
|
};
|
|
},
|
|
methods: {
|
|
deepCopy,update,
|
|
show() {
|
|
this.dialogVisible = true;
|
|
},
|
|
hidden() {
|
|
this.dialogVisible = false;
|
|
},
|
|
/**
|
|
* @param key:string | array
|
|
* @param value:string | array
|
|
**/
|
|
set(key, value) {
|
|
if (
|
|
key instanceof Array &&
|
|
value instanceof Array &&
|
|
key?.length === value?.length
|
|
) {
|
|
key.forEach((k, i) => {
|
|
this[k] = value[i];
|
|
});
|
|
} else if (typeof key === "string") {
|
|
this[key] = value;
|
|
} else {
|
|
throw new Error("参数key类型错误");
|
|
}
|
|
},
|
|
handleClose(done) {
|
|
this.$confirm("确认退出?")
|
|
.then((_) => {
|
|
done();
|
|
})
|
|
.catch((_) => {});
|
|
},
|
|
|
|
//获取列表数据
|
|
async getConfig() {
|
|
const { edit_to_migration, validation_rules } = await config(false);
|
|
this.types = edit_to_migration;
|
|
this.rules = validation_rules;
|
|
},
|
|
|
|
selectPick(i, index) {
|
|
this.$store.commit("form/SET_SELECTED_INDEX", index);
|
|
this.$store.commit("form/SET_SELECTED", deepCopy(i));
|
|
},
|
|
//拖拽
|
|
changeHandler(e) {
|
|
if (e.added) {
|
|
const { element, newIndex } = e.added;
|
|
const originalData = element;
|
|
const newItem = {
|
|
id: "",
|
|
custom_form_id: this.custom_form_id,
|
|
field: "",
|
|
name: "",
|
|
parameter_id: "",
|
|
search_input: originalData.edit_input,
|
|
edit_input: originalData.edit_input,
|
|
sort: newIndex,
|
|
help: "",
|
|
validation: "",
|
|
select_item: "",
|
|
list_show: 1,
|
|
form_show: 1,
|
|
is_fix: "",
|
|
width: ""
|
|
};
|
|
|
|
this.$store.commit("form/SPLICE_FORM_LIST", {
|
|
index: newIndex,
|
|
length: 0,
|
|
config: newItem,
|
|
});
|
|
}
|
|
if (e.moved) {
|
|
const { element, newIndex, oldIndex } = e.moved;
|
|
|
|
if (element?.sort) {
|
|
element.sort = newIndex;
|
|
}
|
|
|
|
this.$store.commit("form/SPLICE_FORM_LIST", {
|
|
index: oldIndex,
|
|
length: 1,
|
|
});
|
|
this.$store.commit("form/SPLICE_FORM_LIST", {
|
|
index: newIndex,
|
|
length: 0,
|
|
config: element,
|
|
});
|
|
}
|
|
},
|
|
|
|
submit() {
|
|
this.$store.dispatch("form/submit").then((res) => {
|
|
setTimeout(() => {
|
|
update({ id: this.custom_form_id })
|
|
.then((res) => {
|
|
this.$message({
|
|
type: "success",
|
|
message: "数据库同步成功",
|
|
});
|
|
})
|
|
.catch((err) => {
|
|
this.$message({
|
|
type: "error",
|
|
message: "数据库同步失败,请手动同步",
|
|
});
|
|
});
|
|
}, 2000);
|
|
});
|
|
},
|
|
},
|
|
computed: {
|
|
...mapState("form", ["selectedForm", "formList", "selectedIndex"]),
|
|
},
|
|
watch: {
|
|
async dialogVisible(newVal) {
|
|
if (newVal) {
|
|
await this.$store.dispatch("form/getFormList", this.custom_form_id);
|
|
}
|
|
},
|
|
},
|
|
created() {
|
|
this.getConfig();
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.title {
|
|
font-weight: 600;
|
|
letter-spacing: 2px;
|
|
|
|
padding: 0 20px;
|
|
}
|
|
.type-item {
|
|
min-width: 40px;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
text-overflow: ellipsis;
|
|
cursor: pointer;
|
|
color: $primaryColor;
|
|
border: solid 1px $primaryColor;
|
|
border-radius: 0.4em;
|
|
position: relative;
|
|
transition: all 0.2s ease-out;
|
|
|
|
padding: 0.5em 1em;
|
|
margin: 0.6em 1em;
|
|
|
|
&:hover {
|
|
color: #fff;
|
|
background: $primaryColor;
|
|
}
|
|
}
|
|
::v-deep .el-dialog__headerbtn {
|
|
position: absolute;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
}
|
|
::v-deep .el-dialog__header {
|
|
padding: 10px !important;
|
|
box-shadow: 0 2px 10px 2px rgba(0, 0, 0, 0.2);
|
|
position: relative;
|
|
}
|
|
::v-deep .el-dialog__body {
|
|
height: calc(100% - 62px);
|
|
padding: 8px 0 !important;
|
|
}
|
|
#template-dialog {
|
|
::v-deep .el-dialog__header {
|
|
box-shadow: none;
|
|
padding: 20px;
|
|
position: relative;
|
|
}
|
|
::v-deep .el-dialog__body {
|
|
padding: 30px 20px !important;
|
|
}
|
|
}
|
|
::v-deep .ivu-split-trigger-vertical {
|
|
width: 2px;
|
|
}
|
|
::v-deep .ivu-split-trigger-bar-con.vertical {
|
|
display: none;
|
|
}
|
|
::v-deep .ivu-split-horizontal > .ivu-split-trigger-con {
|
|
width: 2px;
|
|
}
|
|
::v-deep .ivu-split-pane {
|
|
height: 100%;
|
|
overflow: scroll;
|
|
|
|
&::-webkit-scrollbar {
|
|
width: 2px;
|
|
}
|
|
}
|
|
</style>
|