组件拆分重构,属性设置拆分重构。
parent
d94f5b1596
commit
77779eefa9
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "variant-form",
|
||||
"version": "2.0.1",
|
||||
"version": "2.1.0",
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve --open src/main.js",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* author: vformAdmin
|
||||
* email: vdpadmin@163.com
|
||||
* website: http://www.vform666.com/
|
||||
* website: http://www.vform666.com
|
||||
* date: 2021.08.18
|
||||
* remark: 如果要分发VForm源码,需在本文件顶部保留此文件头信息!!
|
||||
*/
|
||||
|
@ -40,6 +40,8 @@ export function createDesigner(vueInstance) {
|
|||
|
||||
formWidget: null, //表单设计容器
|
||||
|
||||
cssClassList: [], //自定义样式列表
|
||||
|
||||
historyData: {
|
||||
index: -1, //index: 0,
|
||||
maxStep: 20,
|
||||
|
@ -528,7 +530,7 @@ export function createDesigner(vueInstance) {
|
|||
})
|
||||
|
||||
return newTable
|
||||
} else {
|
||||
} else { //其他容器组件不支持clone操作
|
||||
return null
|
||||
}
|
||||
},
|
||||
|
@ -683,6 +685,14 @@ export function createDesigner(vueInstance) {
|
|||
this.vueInstance.$on(evtName, (data) => callback(data))
|
||||
},
|
||||
|
||||
setCssClassList(cssClassList) {
|
||||
this.cssClassList = cssClassList
|
||||
},
|
||||
|
||||
getCssClassList() {
|
||||
return this.cssClassList
|
||||
},
|
||||
|
||||
registerFormWidget(formWidget) {
|
||||
this.formWidget = formWidget
|
||||
},
|
||||
|
|
|
@ -1,408 +0,0 @@
|
|||
<template>
|
||||
<div class="container-wrapper">
|
||||
|
||||
<el-row v-if="widget.type === 'grid'" :key="widget.id" :gutter="widget.options.gutter" class="grid-container"
|
||||
:class="[selected ? 'selected' : '', customClass]"
|
||||
@click.native.stop="selectWidget(widget)">
|
||||
<template v-for="(colWidget, colIdx) in widget.cols">
|
||||
<grid-col-widget :widget="colWidget" :designer="designer" :key="colWidget.id" :parent-list="widget.cols"
|
||||
:index-of-parent-list="colIdx" :parent-widget="widget"></grid-col-widget>
|
||||
</template>
|
||||
|
||||
</el-row>
|
||||
|
||||
<div v-else-if="widget.type === 'table'" :key="widget.id" class="table-container"
|
||||
:class="{'selected': selected}" @click.stop="selectWidget(widget)">
|
||||
<table class="table-layout">
|
||||
<tbody>
|
||||
<tr v-for="(row, rowIdx) in widget.rows" :key="row.id">
|
||||
<template v-for="(colWidget, colIdx) in row.cols">
|
||||
<table-cell-widget v-if="!colWidget.merged" :widget="colWidget" :designer="designer"
|
||||
:key="colWidget.id" :parent-list="widget.cols"
|
||||
:row-index="rowIdx" :row-length="widget.rows.length"
|
||||
:col-index="colIdx" :col-length="row.cols.length"
|
||||
:col-array="row.cols" :row-array="widget.rows"
|
||||
:parent-widget="widget"></table-cell-widget>
|
||||
</template>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div v-else-if="widget.type === 'tab'" :key="widget.id" class="tab-container"
|
||||
:class="{'selected': selected}" @click.stop="selectWidget(widget)">
|
||||
<el-tabs :type="widget.displayType" v-model="activeTab" @tab-click="onTabClick">
|
||||
|
||||
<el-tab-pane v-for="(tab, index) in widget.tabs" :key="index" :label="tab.options.label" :name="tab.options.name"
|
||||
@click.native.stop="selectWidget(widget)">
|
||||
<draggable :list="tab.widgetList" v-bind="{group:'dragGroup', ghostClass: 'ghost',animation: 200}"
|
||||
handle=".drag-handler"
|
||||
@add="(evt) => onContainerDragAdd(evt, tab.widgetList)"
|
||||
@update="onContainerDragUpdate" :move="checkContainerMove">
|
||||
<transition-group name="fade" tag="div" class="form-widget-list">
|
||||
<template v-for="(subWidget, swIdx) in tab.widgetList">
|
||||
<template v-if="'container' === subWidget.category">
|
||||
<container-widget :widget="subWidget" :designer="designer" :key="subWidget.id" :parent-list="tab.widgetList"
|
||||
:index-of-parent-list="swIdx" :parent-widget="widget"></container-widget>
|
||||
</template>
|
||||
<template v-else>
|
||||
<field-widget :field="subWidget" :designer="designer" :key="subWidget.id" :parent-list="tab.widgetList"
|
||||
:index-of-parent-list="swIdx" :parent-widget="widget" :design-state="true"></field-widget>
|
||||
</template>
|
||||
</template>
|
||||
</transition-group>
|
||||
</draggable>
|
||||
</el-tab-pane>
|
||||
|
||||
</el-tabs>
|
||||
</div>
|
||||
|
||||
<div v-else-if="widget.type === 'section'" :key="widget.id" class="section-container"
|
||||
:class="{'selected': selected}" @click.stop="selectWidget(widget)">
|
||||
<draggable :list="widget.widgetList" v-bind="{group:'dragGroup', ghostClass: 'ghost', animation: 200}"
|
||||
handle=".drag-handler"
|
||||
@add="(evt) => onContainerDragAdd(evt, widget.widgetList)"
|
||||
@update="onContainerDragUpdate" :move="checkContainerMove">
|
||||
<transition-group name="fade" tag="div" class="form-widget-list">
|
||||
<template v-for="(subWidget, swIdx) in widget.widgetList">
|
||||
<template v-if="'container' === subWidget.category">
|
||||
<container-widget :widget="subWidget" :designer="designer" :key="subWidget.id" :parent-list="widget.widgetList"
|
||||
:index-of-parent-list="swIdx" :parent-widget="widget"></container-widget>
|
||||
</template>
|
||||
<template v-else>
|
||||
<field-widget :field="subWidget" :designer="designer" :key="subWidget.id" :parent-list="widget.widgetList"
|
||||
:index-of-parent-list="swIdx" :parent-widget="widget" :design-state="true"></field-widget>
|
||||
</template>
|
||||
</template>
|
||||
</transition-group>
|
||||
</draggable>
|
||||
</div>
|
||||
|
||||
<div class="container-action" v-if="designer.selectedId === widget.id && !widget.internal">
|
||||
<i class="el-icon-back" :title="i18nt('designer.hint.selectParentWidget')"
|
||||
@click.stop="selectParentWidget(widget)"></i>
|
||||
<i class="el-icon-top" v-if="!!parentList && (parentList.length > 1)" :title="i18nt('designer.hint.moveUpWidget')"
|
||||
@click.stop="moveUpWidget()"></i>
|
||||
<i class="el-icon-bottom" v-if="!!parentList && (parentList.length > 1)" :title="i18nt('designer.hint.moveDownWidget')"
|
||||
@click.stop="moveDownWidget()"></i>
|
||||
<i v-if="widget.type === 'table'" class="iconfont icon-insertrow" :title="i18nt('designer.hint.insertRow')"
|
||||
@click.stop="insertTableRow(widget)"></i>
|
||||
<i v-if="widget.type === 'table'" class="iconfont icon-insertcolumn" :title="i18nt('designer.hint.insertColumn')"
|
||||
@click.stop="insertTableCol(widget)"></i>
|
||||
<i class="el-icon-copy-document" v-if="(widget.type === 'grid') || (widget.type === 'table')"
|
||||
:title="i18nt('designer.hint.cloneWidget')" @click.stop="cloneContainer(widget)"></i>
|
||||
<i class="el-icon-delete" :title="i18nt('designer.hint.remove')" @click.stop="removeWidget"></i>
|
||||
</div>
|
||||
|
||||
<div class="drag-handler" v-if="designer.selectedId === widget.id && !widget.internal">
|
||||
<i class="el-icon-rank" :title="i18nt('designer.hint.dragHandler')"></i>
|
||||
<i>{{i18nt('designer.widgetLabel.' + widget.type)}}</i>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Draggable from 'vuedraggable'
|
||||
import FieldWidget from "@/components/form-designer/form-widget/field-widget";
|
||||
import GridColWidget from "@/components/form-designer/form-widget/grid-col-widget";
|
||||
import TableCellWidget from "@/components/form-designer/form-widget/table-cell-widget";
|
||||
import VTabPane from "@/components/form-designer/form-widget/tab-pane";
|
||||
import i18n from "@/utils/i18n";
|
||||
|
||||
export default {
|
||||
name: "container-widget",
|
||||
componentName: 'ContainerWidget',
|
||||
mixins: [i18n],
|
||||
components: {
|
||||
Draggable,
|
||||
FieldWidget,
|
||||
GridColWidget,
|
||||
TableCellWidget,
|
||||
VTabPane,
|
||||
},
|
||||
props: {
|
||||
widget: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
//
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeTab: 'tab1',
|
||||
//
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
selected() {
|
||||
return this.widget.id === this.designer.selectedId
|
||||
},
|
||||
|
||||
customClass() {
|
||||
return this.widget.options.customClass || ''
|
||||
},
|
||||
|
||||
},
|
||||
watch: {
|
||||
//
|
||||
},
|
||||
mounted() {
|
||||
//
|
||||
},
|
||||
methods: {
|
||||
insertTableRow(widget) {
|
||||
this.designer.insertTableRow(widget)
|
||||
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
insertTableCol(widget) {
|
||||
this.designer.insertTableCol(widget)
|
||||
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
onContainerDragAdd(evt, subList) {
|
||||
const newIndex = evt.newIndex
|
||||
if (!!subList[newIndex]) {
|
||||
this.designer.setSelected( subList[newIndex] )
|
||||
}
|
||||
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
onContainerDragUpdate() {
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
checkContainerMove(evt) {
|
||||
return this.designer.checkWidgetMove(evt)
|
||||
},
|
||||
|
||||
selectWidget(widget) {
|
||||
this.designer.setSelected(widget)
|
||||
},
|
||||
|
||||
selectParentWidget() {
|
||||
if (this.parentWidget) {
|
||||
this.designer.setSelected(this.parentWidget)
|
||||
} else {
|
||||
this.designer.clearSelected()
|
||||
}
|
||||
},
|
||||
|
||||
moveUpWidget() {
|
||||
this.designer.moveUpWidget(this.parentList, this.indexOfParentList)
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
moveDownWidget() {
|
||||
this.designer.moveDownWidget(this.parentList, this.indexOfParentList)
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
cloneContainer(widget) {
|
||||
if (!!this.parentList) {
|
||||
let newCon = this.designer.cloneContainer(widget)
|
||||
this.parentList.splice(this.indexOfParentList + 1, 0, newCon)
|
||||
this.designer.setSelected(newCon)
|
||||
|
||||
this.designer.emitHistoryChange()
|
||||
}
|
||||
},
|
||||
|
||||
removeWidget() {
|
||||
if (!!this.parentList) {
|
||||
let nextSelected = null
|
||||
if (this.parentList.length === 1) {
|
||||
if (!!this.parentWidget) {
|
||||
nextSelected = this.parentWidget
|
||||
}
|
||||
} else if (this.parentList.length === (1 + this.indexOfParentList)) {
|
||||
nextSelected = this.parentList[this.indexOfParentList - 1]
|
||||
} else {
|
||||
nextSelected = this.parentList[this.indexOfParentList + 1]
|
||||
}
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.parentList.splice(this.indexOfParentList, 1)
|
||||
//if (!!nextSelected) {
|
||||
this.designer.setSelected(nextSelected)
|
||||
//}
|
||||
|
||||
this.designer.emitHistoryChange()
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
onSubFormDragAdd(evt, subList) {
|
||||
const newIndex = evt.newIndex
|
||||
if (!!subList[newIndex]) {
|
||||
this.designer.setSelected( subList[newIndex] )
|
||||
}
|
||||
|
||||
this.designer.emitHistoryChange()
|
||||
console.log('test', 'onSubFormDragAdd')
|
||||
this.designer.emitEvent('field-selected', this.widget)
|
||||
},
|
||||
|
||||
onSubFormDragEnd(evt) {
|
||||
console.log('sub form drag end: ', evt)
|
||||
},
|
||||
|
||||
onTabClick(evt) {
|
||||
console.log('onTabClick', evt)
|
||||
let paneName = evt.name
|
||||
this.widget.tabs.forEach((tp) => {
|
||||
tp.options.active = tp.options.name === paneName;
|
||||
})
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container-wrapper {
|
||||
position: relative;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.container-action{
|
||||
position: absolute;
|
||||
//bottom: -30px;
|
||||
bottom: 0;
|
||||
right: -2px;
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
background: $--color-primary;
|
||||
z-index: 999;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
margin: 0 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.drag-handler {
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
//bottom: -24px; /* 拖拽手柄位于组件下方,有时无法正常拖动,原因未明?? */
|
||||
left: -6px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
background: $--color-primary;
|
||||
z-index: 9;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
color: #fff;
|
||||
margin: 4px;
|
||||
cursor: move;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.el-row.grid-container {
|
||||
min-height: 50px;
|
||||
//line-height: 48px;
|
||||
//padding: 6px;
|
||||
outline: 1px dashed #336699;
|
||||
|
||||
.form-widget-list {
|
||||
min-height: 28px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
div.table-container {
|
||||
padding: 5px;
|
||||
border: 1px dashed #336699;
|
||||
box-sizing: border-box;
|
||||
|
||||
table.table-layout {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
//border: 1px solid #c8ebfb;
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
|
||||
::v-deep td {
|
||||
height: 48px;
|
||||
border: 1px dashed #336699;
|
||||
padding: 3px;
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.form-widget-list {
|
||||
border: 1px dashed #336699;
|
||||
min-height: 36px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tab-container {
|
||||
//padding: 5px;
|
||||
margin: 2px;
|
||||
|
||||
.form-widget-list {
|
||||
min-height: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
.grid-container.selected, .table-container.selected, .tab-container.selected,
|
||||
.sub-form-container.selected, .section-container.selected, .grid-cell.selected {
|
||||
outline: 2px solid $--color-primary !important;
|
||||
}
|
||||
|
||||
//.el-tabs.selected {
|
||||
// outline: 2px solid $--color-primary;
|
||||
//}
|
||||
|
||||
.section-container {
|
||||
border: 1px dashed #336699;
|
||||
border-radius: 5px;
|
||||
margin: 6px 0;
|
||||
padding: 6px;
|
||||
|
||||
::v-deep .form-widget-list {
|
||||
min-height: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
.sub-form-container {
|
||||
//width: 100%;
|
||||
padding: 8px;
|
||||
border: 1px dashed #336699;
|
||||
|
||||
::v-deep .sub-form-table {
|
||||
min-height: 68px;
|
||||
|
||||
div.sub-form-table-column {
|
||||
display: inline-block;
|
||||
//width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .ghost{
|
||||
content: '';
|
||||
font-size: 0;
|
||||
//height: 3px;
|
||||
height: 74px;
|
||||
width: 1px;
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
background: $--color-primary;
|
||||
border: 2px solid $--color-primary;
|
||||
outline-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,100 @@
|
|||
<!--
|
||||
/**
|
||||
* author: vformAdmin
|
||||
* email: vdpadmin@163.com
|
||||
* website: http://www.vform666.com
|
||||
* date: 2021.08.18
|
||||
* remark: 如果要分发VForm源码,需在本文件顶部保留此文件头信息!!
|
||||
*/
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="container-wrapper">
|
||||
<slot></slot>
|
||||
|
||||
<div class="container-action" v-if="designer.selectedId === widget.id && !widget.internal">
|
||||
<i class="el-icon-back" :title="i18nt('designer.hint.selectParentWidget')"
|
||||
@click.stop="selectParentWidget(widget)"></i>
|
||||
<i class="el-icon-top" v-if="!!parentList && (parentList.length > 1)" :title="i18nt('designer.hint.moveUpWidget')"
|
||||
@click.stop="moveUpWidget()"></i>
|
||||
<i class="el-icon-bottom" v-if="!!parentList && (parentList.length > 1)" :title="i18nt('designer.hint.moveDownWidget')"
|
||||
@click.stop="moveDownWidget()"></i>
|
||||
<i v-if="widget.type === 'table'" class="iconfont icon-insertrow" :title="i18nt('designer.hint.insertRow')"
|
||||
@click.stop="insertTableRow(widget)"></i>
|
||||
<i v-if="widget.type === 'table'" class="iconfont icon-insertcolumn" :title="i18nt('designer.hint.insertColumn')"
|
||||
@click.stop="insertTableCol(widget)"></i>
|
||||
<i class="el-icon-copy-document" v-if="(widget.type === 'grid') || (widget.type === 'table')"
|
||||
:title="i18nt('designer.hint.cloneWidget')" @click.stop="cloneContainer(widget)"></i>
|
||||
<i class="el-icon-delete" :title="i18nt('designer.hint.remove')" @click.stop="removeWidget"></i>
|
||||
</div>
|
||||
|
||||
<div class="drag-handler" v-if="designer.selectedId === widget.id && !widget.internal">
|
||||
<i class="el-icon-rank" :title="i18nt('designer.hint.dragHandler')"></i>
|
||||
<i>{{i18nt('designer.widgetLabel.' + widget.type)}}</i>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n";
|
||||
import containerMixin from "@/components/form-designer/form-widget/container-widget/containerMixin";
|
||||
|
||||
export default {
|
||||
name: "container-wrapper",
|
||||
mixins: [i18n, containerMixin],
|
||||
props: {
|
||||
widget: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container-wrapper {
|
||||
position: relative;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.container-action{
|
||||
position: absolute;
|
||||
//bottom: -30px;
|
||||
bottom: 0;
|
||||
right: -2px;
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
background: $--color-primary;
|
||||
z-index: 999;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
margin: 0 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.drag-handler {
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
//bottom: -24px; /* 拖拽手柄位于组件下方,有时无法正常拖动,原因未明?? */
|
||||
left: -6px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
background: $--color-primary;
|
||||
z-index: 9;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
color: #fff;
|
||||
margin: 4px;
|
||||
cursor: move;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
</style>
|
|
@ -0,0 +1,89 @@
|
|||
export default {
|
||||
methods: {
|
||||
insertTableRow(widget) {
|
||||
this.designer.insertTableRow(widget)
|
||||
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
insertTableCol(widget) {
|
||||
this.designer.insertTableCol(widget)
|
||||
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
onContainerDragAdd(evt, subList) {
|
||||
const newIndex = evt.newIndex
|
||||
if (!!subList[newIndex]) {
|
||||
this.designer.setSelected( subList[newIndex] )
|
||||
}
|
||||
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
onContainerDragUpdate() {
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
checkContainerMove(evt) {
|
||||
return this.designer.checkWidgetMove(evt)
|
||||
},
|
||||
|
||||
selectWidget(widget) {
|
||||
this.designer.setSelected(widget)
|
||||
},
|
||||
|
||||
selectParentWidget() {
|
||||
if (this.parentWidget) {
|
||||
this.designer.setSelected(this.parentWidget)
|
||||
} else {
|
||||
this.designer.clearSelected()
|
||||
}
|
||||
},
|
||||
|
||||
moveUpWidget() {
|
||||
this.designer.moveUpWidget(this.parentList, this.indexOfParentList)
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
moveDownWidget() {
|
||||
this.designer.moveDownWidget(this.parentList, this.indexOfParentList)
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
cloneContainer(widget) {
|
||||
if (!!this.parentList) {
|
||||
let newCon = this.designer.cloneContainer(widget)
|
||||
this.parentList.splice(this.indexOfParentList + 1, 0, newCon)
|
||||
this.designer.setSelected(newCon)
|
||||
|
||||
this.designer.emitHistoryChange()
|
||||
}
|
||||
},
|
||||
|
||||
removeWidget() {
|
||||
if (!!this.parentList) {
|
||||
let nextSelected = null
|
||||
if (this.parentList.length === 1) {
|
||||
if (!!this.parentWidget) {
|
||||
nextSelected = this.parentWidget
|
||||
}
|
||||
} else if (this.parentList.length === (1 + this.indexOfParentList)) {
|
||||
nextSelected = this.parentList[this.indexOfParentList - 1]
|
||||
} else {
|
||||
nextSelected = this.parentList[this.indexOfParentList + 1]
|
||||
}
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.parentList.splice(this.indexOfParentList, 1)
|
||||
//if (!!nextSelected) {
|
||||
this.designer.setSelected(nextSelected)
|
||||
//}
|
||||
|
||||
this.designer.emitHistoryChange()
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
}
|
|
@ -9,12 +9,12 @@
|
|||
<transition-group name="fade" tag="div" class="form-widget-list">
|
||||
<template v-for="(subWidget, swIdx) in widget.widgetList">
|
||||
<template v-if="'container' === subWidget.category">
|
||||
<container-widget :widget="subWidget" :designer="designer" :key="subWidget.id" :parent-list="widget.widgetList"
|
||||
:index-of-parent-list="swIdx" :parent-widget="widget"></container-widget>
|
||||
<component :is="subWidget.type + '-widget'" :widget="subWidget" :designer="designer" :key="subWidget.id" :parent-list="widget.widgetList"
|
||||
:index-of-parent-list="swIdx" :parent-widget="widget"></component>
|
||||
</template>
|
||||
<template v-else>
|
||||
<field-widget :field="subWidget" :designer="designer" :key="subWidget.id" :parent-list="widget.widgetList"
|
||||
:index-of-parent-list="swIdx" :parent-widget="widget" :design-state="true"></field-widget>
|
||||
<component :is="subWidget.type + '-widget'" :field="subWidget" :designer="designer" :key="subWidget.id" :parent-list="widget.widgetList"
|
||||
:index-of-parent-list="swIdx" :parent-widget="widget" :design-state="true"></component>
|
||||
</template>
|
||||
</template>
|
||||
</transition-group>
|
||||
|
@ -39,9 +39,9 @@
|
|||
|
||||
<script>
|
||||
import Draggable from 'vuedraggable'
|
||||
//import ContainerWidget from "@/components/form-designer/form-widget/container-widget";
|
||||
import FieldWidget from "@/components/form-designer/form-widget/field-widget";
|
||||
import i18n from "@/utils/i18n";
|
||||
import ContainerComponents from '@/components/form-designer/form-widget/container-widget/index'
|
||||
import FieldComponents from '@/components/form-designer/form-widget/field-widget/index'
|
||||
|
||||
export default {
|
||||
name: "GridColWidget",
|
||||
|
@ -49,8 +49,8 @@
|
|||
mixins: [i18n],
|
||||
components: {
|
||||
Draggable,
|
||||
//'container-widget': ContainerWidget, /* 递归组件必须使用这种写法!! */
|
||||
FieldWidget,
|
||||
...ContainerComponents,
|
||||
...FieldComponents,
|
||||
},
|
||||
props: {
|
||||
widget: Object,
|
|
@ -0,0 +1,88 @@
|
|||
<!--
|
||||
/**
|
||||
* author: vformAdmin
|
||||
* email: vdpadmin@163.com
|
||||
* website: http://www.vform666.com
|
||||
* date: 2021.08.18
|
||||
* remark: 如果要分发VForm源码,需在本文件顶部保留此文件头信息!!
|
||||
*/
|
||||
-->
|
||||
|
||||
<template>
|
||||
<container-wrapper :designer="designer" :widget="widget" :parent-widget="parentWidget" :parent-list="parentList"
|
||||
:index-of-parent-list="indexOfParentList">
|
||||
|
||||
<el-row :key="widget.id" :gutter="widget.options.gutter" class="grid-container"
|
||||
:class="[selected ? 'selected' : '', customClass]"
|
||||
@click.native.stop="selectWidget(widget)">
|
||||
<template v-for="(colWidget, colIdx) in widget.cols">
|
||||
<grid-col-widget :widget="colWidget" :designer="designer" :key="colWidget.id" :parent-list="widget.cols"
|
||||
:index-of-parent-list="colIdx" :parent-widget="widget"></grid-col-widget>
|
||||
</template>
|
||||
</el-row>
|
||||
|
||||
</container-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import GridColWidget from "@/components/form-designer/form-widget/container-widget/grid-col-widget"
|
||||
import containerMixin from "@/components/form-designer/form-widget/container-widget/containerMixin";
|
||||
import ContainerWrapper from "@/components/form-designer/form-widget/container-widget/container-wrapper";
|
||||
|
||||
export default {
|
||||
name: "grid-widget",
|
||||
componentName: 'ContainerWidget',
|
||||
mixins: [i18n, containerMixin],
|
||||
components: {
|
||||
ContainerWrapper,
|
||||
GridColWidget
|
||||
},
|
||||
props: {
|
||||
widget: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
},
|
||||
computed: {
|
||||
selected() {
|
||||
return this.widget.id === this.designer.selectedId
|
||||
},
|
||||
|
||||
customClass() {
|
||||
return this.widget.options.customClass || ''
|
||||
},
|
||||
|
||||
},
|
||||
watch: {
|
||||
//
|
||||
},
|
||||
mounted() {
|
||||
//
|
||||
},
|
||||
methods: {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-row.grid-container {
|
||||
min-height: 50px;
|
||||
//line-height: 48px;
|
||||
//padding: 6px;
|
||||
outline: 1px dashed #336699;
|
||||
|
||||
.form-widget-list {
|
||||
min-height: 28px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.grid-container.selected, .grid-cell.selected {
|
||||
outline: 2px solid $--color-primary !important;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,10 @@
|
|||
const requireComponent = require.context('./', false, /\w+\.vue$/)
|
||||
|
||||
let comps = {}
|
||||
|
||||
requireComponent.keys().map(fileName => {
|
||||
let comp = requireComponent(fileName).default;
|
||||
comps[comp.name] = comp
|
||||
})
|
||||
|
||||
export default comps;
|
|
@ -0,0 +1,121 @@
|
|||
<!--
|
||||
/**
|
||||
* author: vformAdmin
|
||||
* email: vdpadmin@163.com
|
||||
* website: http://www.vform666.com
|
||||
* date: 2021.08.18
|
||||
* remark: 如果要分发VForm源码,需在本文件顶部保留此文件头信息!!
|
||||
*/
|
||||
-->
|
||||
|
||||
<template>
|
||||
<container-wrapper :designer="designer" :widget="widget" :parent-widget="parentWidget" :parent-list="parentList"
|
||||
:index-of-parent-list="indexOfParentList">
|
||||
|
||||
<div :key="widget.id" class="tab-container"
|
||||
:class="{'selected': selected}" @click.stop="selectWidget(widget)">
|
||||
<el-tabs :type="widget.displayType" v-model="activeTab" @tab-click="onTabClick">
|
||||
|
||||
<el-tab-pane v-for="(tab, index) in widget.tabs" :key="index" :label="tab.options.label" :name="tab.options.name"
|
||||
@click.native.stop="selectWidget(widget)">
|
||||
<draggable :list="tab.widgetList" v-bind="{group:'dragGroup', ghostClass: 'ghost',animation: 200}"
|
||||
handle=".drag-handler"
|
||||
@add="(evt) => onContainerDragAdd(evt, tab.widgetList)"
|
||||
@update="onContainerDragUpdate" :move="checkContainerMove">
|
||||
<transition-group name="fade" tag="div" class="form-widget-list">
|
||||
<template v-for="(subWidget, swIdx) in tab.widgetList">
|
||||
<template v-if="'container' === subWidget.category">
|
||||
<component :is="subWidget.type + '-widget'" :widget="subWidget" :designer="designer" :key="subWidget.id" :parent-list="tab.widgetList"
|
||||
:index-of-parent-list="swIdx" :parent-widget="widget"></component>
|
||||
</template>
|
||||
<template v-else>
|
||||
<component :is="subWidget.type + '-widget'" :field="subWidget" :designer="designer" :key="subWidget.id" :parent-list="tab.widgetList"
|
||||
:index-of-parent-list="swIdx" :parent-widget="widget" :design-state="true"></component>
|
||||
</template>
|
||||
</template>
|
||||
</transition-group>
|
||||
</draggable>
|
||||
</el-tab-pane>
|
||||
|
||||
</el-tabs>
|
||||
</div>
|
||||
|
||||
</container-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Draggable from 'vuedraggable'
|
||||
import i18n from "@/utils/i18n"
|
||||
import containerMixin from "@/components/form-designer/form-widget/container-widget/containerMixin"
|
||||
import ContainerWrapper from "@/components/form-designer/form-widget/container-widget/container-wrapper"
|
||||
import ContainerComponents from '@/components/form-designer/form-widget/container-widget/index'
|
||||
import FieldComponents from '@/components/form-designer/form-widget/field-widget/index'
|
||||
|
||||
export default {
|
||||
name: "tab-widget",
|
||||
componentName: 'ContainerWidget',
|
||||
mixins: [i18n, containerMixin],
|
||||
components: {
|
||||
ContainerWrapper,
|
||||
Draggable,
|
||||
|
||||
...ContainerComponents,
|
||||
...FieldComponents,
|
||||
},
|
||||
props: {
|
||||
widget: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeTab: 'tab1',
|
||||
//
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
selected() {
|
||||
return this.widget.id === this.designer.selectedId
|
||||
},
|
||||
|
||||
customClass() {
|
||||
return this.widget.options.customClass || ''
|
||||
},
|
||||
|
||||
},
|
||||
watch: {
|
||||
//
|
||||
},
|
||||
mounted() {
|
||||
//
|
||||
},
|
||||
methods: {
|
||||
onTabClick(evt) {
|
||||
console.log('onTabClick', evt)
|
||||
let paneName = evt.name
|
||||
this.widget.tabs.forEach((tp) => {
|
||||
tp.options.active = tp.options.name === paneName;
|
||||
})
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.tab-container {
|
||||
//padding: 5px;
|
||||
margin: 2px;
|
||||
|
||||
.form-widget-list {
|
||||
min-height: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-container.selected {
|
||||
outline: 2px solid $--color-primary !important;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -10,12 +10,12 @@
|
|||
<transition-group name="fade" tag="div" class="form-widget-list">
|
||||
<template v-for="(subWidget, swIdx) in widget.widgetList">
|
||||
<template v-if="'container' === subWidget.category">
|
||||
<container-widget :widget="subWidget" :designer="designer" :key="subWidget.id" :parent-list="widget.widgetList"
|
||||
:index-of-parent-list="swIdx" :parent-widget="widget"></container-widget>
|
||||
<component :is="subWidget.type + '-widget'" :widget="subWidget" :designer="designer" :key="subWidget.id" :parent-list="widget.widgetList"
|
||||
:index-of-parent-list="swIdx" :parent-widget="widget"></component>
|
||||
</template>
|
||||
<template v-else>
|
||||
<field-widget :field="subWidget" :designer="designer" :key="subWidget.id" :parent-list="widget.widgetList"
|
||||
:index-of-parent-list="swIdx" :parent-widget="widget" :design-state="true"></field-widget>
|
||||
<component :is="subWidget.type + '-widget'" :field="subWidget" :designer="designer" :key="subWidget.id" :parent-list="widget.widgetList"
|
||||
:index-of-parent-list="swIdx" :parent-widget="widget" :design-state="true"></component>
|
||||
</template>
|
||||
</template>
|
||||
</transition-group>
|
||||
|
@ -53,8 +53,9 @@
|
|||
|
||||
<script>
|
||||
import Draggable from 'vuedraggable'
|
||||
import FieldWidget from "@/components/form-designer/form-widget/field-widget";
|
||||
import i18n from "@/utils/i18n";
|
||||
import i18n from "@/utils/i18n"
|
||||
import ContainerComponents from '@/components/form-designer/form-widget/container-widget/index'
|
||||
import FieldComponents from '@/components/form-designer/form-widget/field-widget/index'
|
||||
|
||||
export default {
|
||||
name: "TableCellWidget",
|
||||
|
@ -62,7 +63,8 @@
|
|||
mixins: [i18n],
|
||||
components: {
|
||||
Draggable,
|
||||
FieldWidget,
|
||||
...ContainerComponents,
|
||||
...FieldComponents,
|
||||
},
|
||||
props: {
|
||||
widget: Object,
|
|
@ -0,0 +1,111 @@
|
|||
<!--
|
||||
/**
|
||||
* author: vformAdmin
|
||||
* email: vdpadmin@163.com
|
||||
* website: http://www.vform666.com
|
||||
* date: 2021.08.18
|
||||
* remark: 如果要分发VForm源码,需在本文件顶部保留此文件头信息!!
|
||||
*/
|
||||
-->
|
||||
|
||||
<template>
|
||||
<container-wrapper :designer="designer" :widget="widget" :parent-widget="parentWidget" :parent-list="parentList"
|
||||
:index-of-parent-list="indexOfParentList">
|
||||
|
||||
<div :key="widget.id" class="table-container"
|
||||
:class="[selected ? 'selected' : '', customClass]" @click.stop="selectWidget(widget)">
|
||||
<table class="table-layout">
|
||||
<tbody>
|
||||
<tr v-for="(row, rowIdx) in widget.rows" :key="row.id">
|
||||
<template v-for="(colWidget, colIdx) in row.cols">
|
||||
<table-cell-widget v-if="!colWidget.merged" :widget="colWidget" :designer="designer"
|
||||
:key="colWidget.id" :parent-list="widget.cols"
|
||||
:row-index="rowIdx" :row-length="widget.rows.length"
|
||||
:col-index="colIdx" :col-length="row.cols.length"
|
||||
:col-array="row.cols" :row-array="widget.rows"
|
||||
:parent-widget="widget"></table-cell-widget>
|
||||
</template>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</container-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import containerMixin from "@/components/form-designer/form-widget/container-widget/containerMixin"
|
||||
import ContainerWrapper from "@/components/form-designer/form-widget/container-widget/container-wrapper"
|
||||
import TableCellWidget from "@/components/form-designer/form-widget/container-widget/table-cell-widget"
|
||||
|
||||
export default {
|
||||
name: "table-widget",
|
||||
componentName: 'ContainerWidget',
|
||||
mixins: [i18n, containerMixin],
|
||||
components: {
|
||||
ContainerWrapper,
|
||||
TableCellWidget,
|
||||
},
|
||||
props: {
|
||||
widget: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
},
|
||||
computed: {
|
||||
selected() {
|
||||
return this.widget.id === this.designer.selectedId
|
||||
},
|
||||
|
||||
customClass() {
|
||||
return this.widget.options.customClass || ''
|
||||
},
|
||||
|
||||
},
|
||||
watch: {
|
||||
//
|
||||
},
|
||||
mounted() {
|
||||
//
|
||||
},
|
||||
methods: {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
div.table-container {
|
||||
padding: 5px;
|
||||
border: 1px dashed #336699;
|
||||
box-sizing: border-box;
|
||||
|
||||
table.table-layout {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
//border: 1px solid #c8ebfb;
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
|
||||
::v-deep td {
|
||||
height: 48px;
|
||||
border: 1px dashed #336699;
|
||||
padding: 3px;
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.form-widget-list {
|
||||
border: 1px dashed #336699;
|
||||
min-height: 36px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table-container.selected {
|
||||
outline: 2px solid $--color-primary !important;
|
||||
}
|
||||
|
||||
</style>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,87 @@
|
|||
<template>
|
||||
<static-content-wrapper :designer="designer" :field="field" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<el-button ref="fieldEditor" :type="field.options.type"
|
||||
:plain="field.options.plain" :round="field.options.round"
|
||||
:circle="field.options.circle" :icon="field.options.icon"
|
||||
:disabled="field.options.disabled"
|
||||
@click.native="handleButtonWidgetClick">
|
||||
{{field.options.label}}</el-button>
|
||||
</static-content-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import StaticContentWrapper from './static-content-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "button-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
StaticContentWrapper,
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* static-content-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
</style>
|
|
@ -0,0 +1,104 @@
|
|||
<template>
|
||||
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<el-cascader ref="fieldEditor" :options="field.options.optionItems" v-model="fieldModel" class="full-width-input"
|
||||
:disabled="field.options.disabled"
|
||||
:size="field.options.size"
|
||||
:clearable="field.options.clearable"
|
||||
:filterable="field.options.filterable"
|
||||
:placeholder="field.options.placeholder || i18nt('render.hint.selectPlaceholder')"
|
||||
@focus="handleFocusCustomEvent" @blur="handleBlurCustomEvent"
|
||||
@change="handleChangeEvent">
|
||||
</el-cascader>
|
||||
</form-item-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormItemWrapper from './form-item-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "cascader-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
FormItemWrapper,
|
||||
},
|
||||
inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel'],
|
||||
data() {
|
||||
return {
|
||||
oldFieldValue: null, //field组件change之前的值
|
||||
fieldModel: null,
|
||||
rules: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.initOptionItems()
|
||||
this.initFieldModel()
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
this.buildFieldRules()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* form-item-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
.full-width-input {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,105 @@
|
|||
<template>
|
||||
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<el-checkbox-group ref="fieldEditor" v-model="fieldModel"
|
||||
:disabled="field.options.disabled" :size="field.options.size"
|
||||
@change="handleChangeEvent">
|
||||
<template v-if="!!field.options.buttonStyle">
|
||||
<el-checkbox-button v-for="(item, index) in field.options.optionItems" :key="index" :label="item.value"
|
||||
:disabled="item.disabled" :border="field.options.border"
|
||||
:style="{display: field.options.displayStyle}">{{item.label}}</el-checkbox-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-checkbox v-for="(item, index) in field.options.optionItems" :key="index" :label="item.value"
|
||||
:disabled="item.disabled" :border="field.options.border"
|
||||
:style="{display: field.options.displayStyle}">{{item.label}}</el-checkbox>
|
||||
</template>
|
||||
</el-checkbox-group>
|
||||
</form-item-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormItemWrapper from './form-item-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "checkbox-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
FormItemWrapper,
|
||||
},
|
||||
inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel'],
|
||||
data() {
|
||||
return {
|
||||
oldFieldValue: null, //field组件change之前的值
|
||||
fieldModel: null,
|
||||
rules: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.initOptionItems()
|
||||
this.initFieldModel()
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
this.buildFieldRules()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* form-item-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
</style>
|
|
@ -0,0 +1,99 @@
|
|||
<template>
|
||||
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<el-color-picker ref="fieldEditor" v-model="fieldModel"
|
||||
:size="field.options.size"
|
||||
:disabled="field.options.disabled"
|
||||
@change="handleChangeEvent">
|
||||
</el-color-picker>
|
||||
</form-item-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormItemWrapper from './form-item-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "color-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
FormItemWrapper,
|
||||
},
|
||||
inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel'],
|
||||
data() {
|
||||
return {
|
||||
oldFieldValue: null, //field组件change之前的值
|
||||
fieldModel: null,
|
||||
rules: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.initFieldModel()
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
this.buildFieldRules()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* form-item-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
.full-width-input {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,104 @@
|
|||
<template>
|
||||
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<el-date-picker ref="fieldEditor" :type="field.options.type" v-model="fieldModel" class="full-width-input"
|
||||
:disabled="field.options.disabled" :readonly="field.options.readonly"
|
||||
:size="field.options.size"
|
||||
:clearable="field.options.clearable" :editable="field.options.editable"
|
||||
:format="field.options.format" :value-format="field.options.valueFormat"
|
||||
:start-placeholder="field.options.startPlaceholder || i18nt('render.hint.startDatePlaceholder')"
|
||||
:end-placeholder="field.options.endPlaceholder || i18nt('render.hint.endDatePlaceholder')"
|
||||
@focus="handleFocusCustomEvent" @blur="handleBlurCustomEvent"
|
||||
@change="handleChangeEvent">
|
||||
</el-date-picker>
|
||||
</form-item-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormItemWrapper from './form-item-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "date-range-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
FormItemWrapper,
|
||||
},
|
||||
inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel'],
|
||||
data() {
|
||||
return {
|
||||
oldFieldValue: null, //field组件change之前的值
|
||||
fieldModel: null,
|
||||
rules: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.initFieldModel()
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
this.buildFieldRules()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* form-item-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
.full-width-input {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,103 @@
|
|||
<template>
|
||||
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<el-date-picker ref="fieldEditor" :type="field.options.type" v-model="fieldModel" class="full-width-input"
|
||||
:readonly="field.options.readonly" :disabled="field.options.disabled"
|
||||
:size="field.options.size"
|
||||
:clearable="field.options.clearable" :editable="field.options.editable"
|
||||
:format="field.options.format" :value-format="field.options.valueFormat"
|
||||
:placeholder="field.options.placeholder || i18nt('render.hint.datePlaceholder')"
|
||||
@focus="handleFocusCustomEvent" @blur="handleBlurCustomEvent"
|
||||
@change="handleChangeEvent">
|
||||
</el-date-picker>
|
||||
</form-item-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormItemWrapper from './form-item-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "date-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
FormItemWrapper,
|
||||
},
|
||||
inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel'],
|
||||
data() {
|
||||
return {
|
||||
oldFieldValue: null, //field组件change之前的值
|
||||
fieldModel: null,
|
||||
rules: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.initFieldModel()
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
this.buildFieldRules()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* form-item-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
.full-width-input {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,83 @@
|
|||
<template>
|
||||
<static-content-wrapper :designer="designer" :field="field" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<el-divider ref="fieldEditor" direction="horizontal" :content-position="field.options.contentPosition">
|
||||
{{field.options.label}}</el-divider>
|
||||
</static-content-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import StaticContentWrapper from './static-content-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "divider-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
StaticContentWrapper,
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* static-content-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
</style>
|
|
@ -0,0 +1,451 @@
|
|||
import {deepClone} from "@/utils/util";
|
||||
|
||||
export default {
|
||||
inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel'],
|
||||
|
||||
computed: {
|
||||
subFormName() {
|
||||
return !!this.parentWidget ? this.parentWidget.options.name : ''
|
||||
},
|
||||
|
||||
subFormItemFlag() {
|
||||
return !!this.parentWidget ? this.parentWidget.type === 'sub-form' : false
|
||||
},
|
||||
|
||||
formModel: {
|
||||
cache: false,
|
||||
get() {
|
||||
return this.globalModel.formModel
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
//--------------------- 组件内部方法 begin ------------------//
|
||||
|
||||
initFieldModel() {
|
||||
if (this.field.formItemFlag === false) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!!this.subFormItemFlag && !this.designState) { //SubForm子表单组件需要特殊处理!!
|
||||
let subFormData = this.formModel[this.subFormName]
|
||||
if (((subFormData === undefined) || (subFormData[this.subFormRowIndex] === undefined) ||
|
||||
(subFormData[this.subFormRowIndex][this.field.options.name] === undefined)) &&
|
||||
(this.field.options.defaultValue !== undefined)) {
|
||||
this.fieldModel = this.field.options.defaultValue
|
||||
subFormData[this.subFormRowIndex][this.field.options.name] = this.field.options.defaultValue
|
||||
} else if (subFormData[this.subFormRowIndex][this.field.options.name] === undefined) {
|
||||
this.fieldModel = null
|
||||
subFormData[this.subFormRowIndex][this.field.options.name] = null
|
||||
} else {
|
||||
this.fieldModel = subFormData[this.subFormRowIndex][this.field.options.name]
|
||||
}
|
||||
|
||||
/* 主动触发子表单内field-widget的onChange事件!! */
|
||||
setTimeout(() => { //延时触发onChange事件, 便于更新计算字段!!
|
||||
this.handleOnChangeForSubForm(this.fieldModel, this.oldFieldValue, subFormData, this.subFormRowId)
|
||||
}, 800)
|
||||
this.oldFieldValue = deepClone(this.fieldModel)
|
||||
|
||||
this.initFileList() //处理图片上传、文件上传字段
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if ((this.formModel[this.field.options.name] === undefined) &&
|
||||
(this.field.options.defaultValue !== undefined)) {
|
||||
this.fieldModel = this.field.options.defaultValue
|
||||
} else if (this.formModel[this.field.options.name] === undefined) { //如果formModel为空对象,则初始化字段值为null!!
|
||||
this.formModel[this.field.options.name] = null
|
||||
} else {
|
||||
this.fieldModel = this.formModel[this.field.options.name]
|
||||
}
|
||||
this.oldFieldValue = deepClone(this.fieldModel)
|
||||
this.initFileList() //处理图片上传、文件上传字段
|
||||
},
|
||||
|
||||
initFileList() { //初始化上传组件的已上传文件列表
|
||||
if ( ((this.field.type !== 'picture-upload') && (this.field.type !== 'file-upload')) || (this.designState === true) ) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!!this.fieldModel) {
|
||||
if (Array.isArray(this.fieldModel)) {
|
||||
this.fileList = deepClone(this.fieldModel)
|
||||
} else {
|
||||
this.fileList.splice(0, 0, deepClone(this.fieldModel))
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
initEventHandler() {
|
||||
this.$on('setFormData', function (newFormData) {
|
||||
console.log('formModel of globalModel----------', this.globalModel.formModel)
|
||||
if (!this.subFormItemFlag) {
|
||||
this.setValue(newFormData[this.field.options.name])
|
||||
}
|
||||
})
|
||||
|
||||
this.$on('field-value-changed', function (values) {
|
||||
if (!!this.subFormItemFlag) {
|
||||
let subFormData = this.formModel[this.subFormName]
|
||||
this.handleOnChangeForSubForm(values[0], values[1], subFormData, this.subFormRowId)
|
||||
} else {
|
||||
this.handleOnChange(values[0], values[1])
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
handleOnCreated() {
|
||||
if (!!this.field.options.onCreated) {
|
||||
let customFunc = new Function(this.field.options.onCreated)
|
||||
customFunc.call(this)
|
||||
}
|
||||
},
|
||||
|
||||
handleOnMounted() {
|
||||
if (!!this.field.options.onMounted) {
|
||||
let mountFunc = new Function(this.field.options.onMounted)
|
||||
mountFunc.call(this)
|
||||
}
|
||||
},
|
||||
|
||||
registerToRefList(oldRefName) {
|
||||
if ((this.refList !== null) && !!this.field.options.name) {
|
||||
if (this.subFormItemFlag && !this.designState) { //处理子表单元素(且非设计状态)
|
||||
if (!!oldRefName) {
|
||||
delete this.refList[oldRefName + '@row' + this.subFormRowId]
|
||||
}
|
||||
this.refList[this.field.options.name + '@row' + this.subFormRowId] = this
|
||||
} else {
|
||||
if (!!oldRefName) {
|
||||
delete this.refList[oldRefName]
|
||||
}
|
||||
this.refList[this.field.options.name] = this
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
unregisterFromRefList() { //销毁组件时注销组件ref
|
||||
if ((this.refList !== null) && !!this.field.options.name) {
|
||||
let oldRefName = this.field.options.name
|
||||
if (this.subFormItemFlag && !this.designState) { //处理子表单元素(且非设计状态)
|
||||
delete this.refList[oldRefName + '@row' + this.subFormRowId]
|
||||
} else {
|
||||
delete this.refList[oldRefName]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
initOptionItems() {
|
||||
if (this.designState) {
|
||||
return
|
||||
}
|
||||
|
||||
if ((this.field.type === 'radio') || (this.field.type === 'checkbox')
|
||||
|| (this.field.type === 'select') || (this.field.type === 'cascader')) {
|
||||
if (!!this.globalOptionData && this.globalOptionData.hasOwnProperty(this.field.options.name)) {
|
||||
this.loadOptions( this.globalOptionData[this.field.options.name] )
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
refreshDefaultValue() {
|
||||
if ((this.designState === true) && (this.field.options.defaultValue !== undefined)) {
|
||||
this.fieldModel = this.field.options.defaultValue
|
||||
}
|
||||
},
|
||||
|
||||
buildFieldRules() {
|
||||
this.rules.splice(0, this.rules.length) //清空已有
|
||||
if (!!this.field.options.required) {
|
||||
this.rules.push({
|
||||
required: true,
|
||||
message: this.i18nt('render.hint.fieldRequired'),
|
||||
})
|
||||
}
|
||||
|
||||
if (!!this.field.options.validation) {
|
||||
let vldName = this.field.options.validation
|
||||
if (!!FormValidators[vldName]) {
|
||||
this.rules.push({
|
||||
validator: FormValidators[vldName],
|
||||
trigger: ['blur', 'change'],
|
||||
label: this.field.options.label,
|
||||
errorMsg: this.field.options.validationHint
|
||||
})
|
||||
} else {
|
||||
this.rules.push({
|
||||
validator: FormValidators['regExp'],
|
||||
trigger: ['blur', 'change'],
|
||||
regExp: vldName,
|
||||
label: this.field.options.label,
|
||||
errorMsg: this.field.options.validationHint
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (!!this.field.options.onValidate) {
|
||||
let customFn = new Function('rule', 'value', 'callback', this.field.options.onValidate)
|
||||
this.rules.push({
|
||||
validator: customFn,
|
||||
trigger: ['blur', 'change'],
|
||||
label: this.field.options.label
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
disableOptionOfList(optionList, optionValue) {
|
||||
if (!!optionList && (optionList.length > 0)) {
|
||||
optionList.forEach(opt => {
|
||||
if (opt.value === optionValue) {
|
||||
opt.disabled = true
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
enableOptionOfList(optionList, optionValue) {
|
||||
if (!!optionList && (optionList.length > 0)) {
|
||||
optionList.forEach(opt => {
|
||||
if (opt.value === optionValue) {
|
||||
opt.disabled = false
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------- 组件内部方法 end ------------------//
|
||||
|
||||
//--------------------- 事件处理 begin ------------------//
|
||||
|
||||
emitFieldDataChange(newValue, oldValue) {
|
||||
this.$emit('field-value-changed', [newValue, oldValue])
|
||||
|
||||
/* 必须用dispatch向指定父组件派发消息!! */
|
||||
this.dispatch('VFormRender', 'fieldChange',
|
||||
[this.field.options.name, newValue, oldValue, this.subFormName, this.subFormRowIndex])
|
||||
},
|
||||
|
||||
syncUpdateFormModel(value) {
|
||||
if (!!this.designState) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!!this.subFormItemFlag) {
|
||||
let subFormData = this.formModel[this.subFormName] || [{}]
|
||||
let subFormDataRow = subFormData[this.subFormRowIndex]
|
||||
subFormDataRow[this.field.options.name] = value
|
||||
} else {
|
||||
this.formModel[this.field.options.name] = value
|
||||
}
|
||||
},
|
||||
|
||||
handleChangeEvent(value) {
|
||||
this.syncUpdateFormModel(value)
|
||||
this.emitFieldDataChange(value, this.oldFieldValue)
|
||||
|
||||
//number组件一般不会触发focus事件,故此处需要手工赋值oldFieldValue!!
|
||||
this.oldFieldValue = deepClone(value) /* oldFieldValue需要在initFieldModel()方法中赋初值!! */
|
||||
},
|
||||
|
||||
handleFocusCustomEvent(event) {
|
||||
this.oldFieldValue = deepClone(this.fieldModel) //保存修改change之前的值
|
||||
|
||||
if (!!this.field.options.onFocus) {
|
||||
let customFn = new Function('event', this.field.options.onFocus)
|
||||
customFn.call(this, event)
|
||||
}
|
||||
},
|
||||
|
||||
handleBlurCustomEvent(event) {
|
||||
if (!!this.field.options.onBlur) {
|
||||
let customFn = new Function('event', this.field.options.onBlur)
|
||||
customFn.call(this, event)
|
||||
}
|
||||
},
|
||||
|
||||
handleInputCustomEvent(value) {
|
||||
if (!!this.field.options.onInput) {
|
||||
let customFn = new Function('value', this.field.options.onInput)
|
||||
customFn.call(this, value)
|
||||
}
|
||||
},
|
||||
|
||||
emitAppendButtonClick() {
|
||||
/* 必须调用mixins中的dispatch方法逐级向父组件发送消息!! */
|
||||
this.dispatch('VFormRender', 'appendButtonClick', [this]);
|
||||
},
|
||||
|
||||
handleOnChange(val, oldVal) { //自定义onChange事件
|
||||
if (!!this.field.options.onChange) {
|
||||
let changeFn = new Function('value', 'oldValue', this.field.options.onChange)
|
||||
changeFn.call(this, val, oldVal)
|
||||
}
|
||||
},
|
||||
|
||||
handleOnChangeForSubForm(val, oldVal, subFormData, rowId) { //子表单自定义onChange事件
|
||||
if (!!this.field.options.onChange) {
|
||||
let changeFn = new Function('value', 'oldValue', 'subFormData', 'rowId', this.field.options.onChange)
|
||||
changeFn.call(this, val, oldVal, subFormData, rowId)
|
||||
}
|
||||
},
|
||||
|
||||
handleButtonWidgetClick() {
|
||||
if (!!this.designState) { //设计状态不触发点击事件
|
||||
return
|
||||
}
|
||||
|
||||
if (!!this.field.options.onClick) {
|
||||
let changeFn = new Function(this.field.options.onClick)
|
||||
changeFn.call(this)
|
||||
} else {
|
||||
this.dispatch('VFormRender', 'buttonClick', [this]);
|
||||
}
|
||||
},
|
||||
|
||||
remoteQuery(keyword) {
|
||||
if (!!this.field.options.onRemoteQuery) {
|
||||
let remoteFn = new Function('keyword', this.field.options.onRemoteQuery)
|
||||
remoteFn.call(this, keyword)
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------- 事件处理 end ------------------//
|
||||
|
||||
//--------------------- 以下为组件支持外部调用的API方法 begin ------------------//
|
||||
/* 提示:用户可自行扩充这些方法!!! */
|
||||
|
||||
getFormRef() { /* 获取VFrom引用,必须在VForm组件created之后方可调用 */
|
||||
return this.refList['v_form_ref']
|
||||
},
|
||||
|
||||
getWidgetRef(widgetName, showError) {
|
||||
let foundRef = this.refList[widgetName]
|
||||
if (!foundRef && !!showError) {
|
||||
this.$message.error(this.i18nt('render.hint.refNotFound') + widgetName)
|
||||
}
|
||||
return foundRef
|
||||
},
|
||||
|
||||
getFieldEditor() { //获取内置的el表单组件
|
||||
return this.$refs['fieldEditor']
|
||||
},
|
||||
|
||||
/*
|
||||
注意:VFormRender的setFormData方法不会触发子表单内field-widget的setValue方法,
|
||||
因为setFormData方法调用后,子表单内所有field-widget组件已被清空,接收不到setFormData事件!!
|
||||
* */
|
||||
setValue(newValue) {
|
||||
/* if ((this.field.type === 'picture-upload') || (this.field.type === 'file-upload')) {
|
||||
this.fileList = newValue
|
||||
} else */ if (!!this.field.formItemFlag) {
|
||||
let oldValue = deepClone(this.fieldModel)
|
||||
this.fieldModel = newValue
|
||||
this.initFileList()
|
||||
|
||||
this.syncUpdateFormModel(newValue)
|
||||
this.emitFieldDataChange(newValue, oldValue)
|
||||
}
|
||||
},
|
||||
|
||||
getValue() {
|
||||
/* if ((this.field.type === 'picture-upload') || (this.field.type === 'file-upload')) {
|
||||
return this.fileList
|
||||
} else */ {
|
||||
return this.fieldModel
|
||||
}
|
||||
},
|
||||
|
||||
resetField() {
|
||||
let defaultValue = this.field.options.defaultValue
|
||||
this.setValue(defaultValue)
|
||||
},
|
||||
|
||||
setWidgetOption(optionName, optionValue) { //通用组件选项修改API
|
||||
if (this.field.options.hasOwnProperty(optionName)) {
|
||||
this.field.options[optionName] = optionValue
|
||||
//TODO: 是否重新构建组件??有些属性修改后必须重新构建组件才能生效,比如字段校验规则。
|
||||
}
|
||||
},
|
||||
|
||||
setReadonly(flag) {
|
||||
this.field.options.readonly = flag
|
||||
},
|
||||
|
||||
setDisabled(flag) {
|
||||
this.field.options.disabled = flag
|
||||
},
|
||||
|
||||
setAppendButtonVisible(flag) {
|
||||
this.field.options.appendButton = flag
|
||||
},
|
||||
|
||||
setAppendButtonDisabled(flag) {
|
||||
this.field.options.appendButtonDisabled = flag
|
||||
},
|
||||
|
||||
setHidden(flag) {
|
||||
this.field.options.hidden = flag
|
||||
},
|
||||
|
||||
setRequired(flag) {
|
||||
this.field.options.required = flag
|
||||
this.buildFieldRules()
|
||||
},
|
||||
|
||||
setLabel(newLabel) {
|
||||
this.field.options.label = newLabel
|
||||
},
|
||||
|
||||
focus() {
|
||||
if (!!this.getFieldEditor() && !!this.getFieldEditor().focus) {
|
||||
this.getFieldEditor().focus()
|
||||
}
|
||||
},
|
||||
|
||||
clearSelectedOptions() { //清空已选选项
|
||||
if ((this.field.type !== 'checkbox') && (this.field.type !== 'radio') && (this.field.type !== 'select')) {
|
||||
return
|
||||
}
|
||||
|
||||
if ((this.field.type === 'checkbox') ||
|
||||
((this.field.type === 'select') && this.field.options.multiple)) {
|
||||
this.fieldModel = []
|
||||
} else {
|
||||
this.fieldModel = ''
|
||||
}
|
||||
},
|
||||
|
||||
loadOptions(options) {
|
||||
this.field.options.optionItems = deepClone(options)
|
||||
this.clearSelectedOptions() //清空已选选项
|
||||
},
|
||||
|
||||
disableOption(optionValue) {
|
||||
this.disableOptionOfList(this.field.options.optionItems, optionValue)
|
||||
},
|
||||
|
||||
enableOption(optionValue) {
|
||||
this.enableOptionOfList(this.field.options.optionItems, optionValue)
|
||||
},
|
||||
|
||||
setUploadHeader(name, value) {
|
||||
this.$set(this.uploadHeaders, name, value)
|
||||
},
|
||||
|
||||
setUploadData(name, value) {
|
||||
this.$set(this.uploadData, name, value)
|
||||
},
|
||||
|
||||
setToolbar(customToolbar) {
|
||||
this.customToolbar = customToolbar
|
||||
},
|
||||
|
||||
//--------------------- 以上为组件支持外部调用的API方法 end ------------------//
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,264 @@
|
|||
<template>
|
||||
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<el-upload ref="fieldEditor" :disabled="field.options.disabled"
|
||||
:style="styleVariables" class="dynamicPseudoAfter"
|
||||
:action="field.options.uploadURL" :headers="uploadHeaders" :data="uploadData"
|
||||
:with-credentials="field.options.withCredentials"
|
||||
:multiple="field.options.multipleSelect" :file-list="fileList"
|
||||
:show-file-list="field.options.showFileList" :class="{'hideUploadDiv': uploadBtnHidden}"
|
||||
:limit="field.options.limit" :on-exceed="handleFileExceed" :before-upload="beforeFileUpload"
|
||||
:on-success="handleFileUpload" :on-error="handelUploadError" :on-remove="handleFileRemove">
|
||||
<div slot="tip" class="el-upload__tip"
|
||||
v-if="!!field.options.uploadTip">{{field.options.uploadTip}}</div>
|
||||
<i slot="default" class="el-icon-plus avatar-uploader-icon"></i>
|
||||
<div slot="file" slot-scope="{file}" class="upload-file-list">
|
||||
<span class="upload-file-name" :title="file.name">{{file.name}}</span>
|
||||
<a :href="file.url" download="">
|
||||
<i class="el-icon-download file-action" title="i18nt('render.hint.downloadFile')"></i></a>
|
||||
<i class="el-icon-delete file-action" title="i18nt('render.hint.removeFile')" v-if="!field.options.disabled"
|
||||
@click="removeUploadFile(file.name)"></i>
|
||||
</div>
|
||||
</el-upload>
|
||||
</form-item-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormItemWrapper from './form-item-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import {deepClone} from "@/utils/util";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
let selectFileText = "'" + translate('render.hint.selectFile') + "'"
|
||||
|
||||
export default {
|
||||
name: "file-upload-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
FormItemWrapper,
|
||||
},
|
||||
inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel'],
|
||||
data() {
|
||||
return {
|
||||
oldFieldValue: null, //field组件change之前的值
|
||||
fieldModel: null,
|
||||
rules: [],
|
||||
|
||||
uploadHeaders: {},
|
||||
uploadData: {
|
||||
key: '', //七牛云上传文件名
|
||||
//token: '', //七牛云上传token
|
||||
|
||||
//policy: '', //又拍云上传policy
|
||||
//authorization: '', //又拍云上传签名
|
||||
},
|
||||
fileList: [], //上传文件列表
|
||||
uploadBtnHidden: false,
|
||||
|
||||
styleVariables: {
|
||||
'--select-file-action': selectFileText,
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.initFieldModel()
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
this.buildFieldRules()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
handleFileExceed() {
|
||||
//let uploadLimit = this.field.options.limit
|
||||
this.$message.warning(eval('`' + this.i18nt('render.hint.uploadExceed') + '`'));
|
||||
},
|
||||
|
||||
updateUploadFieldModelAndEmitDataChange() {
|
||||
let oldValue = deepClone(this.fieldModel)
|
||||
this.fieldModel = deepClone(this.fileList)
|
||||
this.syncUpdateFormModel(this.fieldModel)
|
||||
this.emitFieldDataChange(this.fieldModel, oldValue)
|
||||
},
|
||||
|
||||
beforeFileUpload(file) {
|
||||
let fileTypeCheckResult = false
|
||||
let extFileName = file.name.substring(file.name.lastIndexOf('.') + 1)
|
||||
if (!!this.field.options && !!this.field.options.fileTypes) {
|
||||
let uploadFileTypes = this.field.options.fileTypes
|
||||
if (uploadFileTypes.length > 0) {
|
||||
fileTypeCheckResult = uploadFileTypes.some( (ft) => {
|
||||
return extFileName.toLowerCase() === ft.toLowerCase()
|
||||
})
|
||||
}
|
||||
}
|
||||
if (!fileTypeCheckResult) {
|
||||
this.$message.error(this.i18nt('render.hint.unsupportedFileType') + extFileName)
|
||||
return false;
|
||||
}
|
||||
|
||||
let fileSizeCheckResult = false
|
||||
let uploadFileMaxSize = 5 //5MB
|
||||
if (!!this.field.options && !!this.field.options.fileMaxSize) {
|
||||
uploadFileMaxSize = this.field.options.fileMaxSize
|
||||
}
|
||||
fileSizeCheckResult = file.size / 1024 / 1024 <= uploadFileMaxSize
|
||||
if (!fileSizeCheckResult) {
|
||||
this.$message.error(this.i18nt('render.hint.fileSizeExceed') + uploadFileMaxSize + 'MB')
|
||||
return false;
|
||||
}
|
||||
|
||||
this.uploadData.key = file.name
|
||||
return this.handleOnBeforeUpload(file)
|
||||
},
|
||||
|
||||
handleFileUpload(res, file, fileList) {
|
||||
if (!!this.field.options.onUploadSuccess) {
|
||||
let mountFunc = new Function('result', 'file', 'fileList', this.field.options.onUploadSuccess)
|
||||
mountFunc.call(this, res, file, fileList)
|
||||
} else {
|
||||
if (file.status === 'success') {
|
||||
this.fileList.push(file)
|
||||
this.updateUploadFieldModelAndEmitDataChange()
|
||||
|
||||
this.uploadBtnHidden = this.fileList.length >= this.field.options.limit
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
handleFileRemove(file, fileList) {
|
||||
let foundIdx = -1
|
||||
this.fileList.forEach((tf,idx) => {
|
||||
if (tf.name === file.name) {
|
||||
foundIdx = idx
|
||||
}
|
||||
})
|
||||
|
||||
this.fileList = fileList
|
||||
this.updateUploadFieldModelAndEmitDataChange()
|
||||
|
||||
this.uploadBtnHidden = fileList.length >= this.field.options.limit
|
||||
},
|
||||
|
||||
removeUploadFile(fileName) {
|
||||
let foundIdx = -1
|
||||
this.fileList.forEach((file,idx) => {
|
||||
if (file.name === fileName) {
|
||||
foundIdx = idx
|
||||
}
|
||||
})
|
||||
|
||||
if (foundIdx >= 0) {
|
||||
this.fileList.splice(foundIdx, 1)
|
||||
this.updateUploadFieldModelAndEmitDataChange()
|
||||
|
||||
this.uploadBtnHidden = this.fileList.length >= this.field.options.limit
|
||||
}
|
||||
},
|
||||
|
||||
handelUploadError(err, file, fileList) {
|
||||
if (!!this.field.options.onUploadError) {
|
||||
let customFn = new Function('error', 'file', 'fileList', this.field.options.onUploadError)
|
||||
customFn.call(this, err, file, fileList)
|
||||
} else {
|
||||
this.$message({
|
||||
message: this.i18nt('render.hint.uploadError') + err,
|
||||
duration: 3000,
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* form-item-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
.full-width-input {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.dynamicPseudoAfter ::v-deep .el-upload.el-upload--text {
|
||||
color: $--color-primary;
|
||||
font-size: 12px;
|
||||
.el-icon-plus:after {
|
||||
content: var(--select-file-action);
|
||||
}
|
||||
}
|
||||
|
||||
.hideUploadDiv {
|
||||
::v-deep div.el-upload--picture-card { /* 隐藏最后的图片上传按钮 */
|
||||
display: none;
|
||||
}
|
||||
|
||||
::v-deep div.el-upload--text { /* 隐藏最后的文件上传按钮 */
|
||||
display: none;
|
||||
}
|
||||
|
||||
::v-deep div.el-upload__tip { /* 隐藏最后的文件上传按钮 */
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-file-list {
|
||||
font-size: 12px;
|
||||
|
||||
.file-action {
|
||||
color: $--color-primary;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,331 @@
|
|||
<!--
|
||||
/**
|
||||
* author: vformAdmin
|
||||
* email: vdpadmin@163.com
|
||||
* website: http://www.vform666.com
|
||||
* date: 2021.08.18
|
||||
* remark: 如果要分发VForm源码,需在本文件顶部保留此文件头信息!!
|
||||
*/
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="field-wrapper" :class="{'design-time-bottom-margin': !!this.designer}">
|
||||
<el-form-item v-if="!!field.formItemFlag" :label="label" :label-width="labelWidth + 'px'"
|
||||
:title="field.options.labelTooltip"
|
||||
v-show="!field.options.hidden || (designState === true)"
|
||||
:rules="rules" :prop="getPropName()"
|
||||
:class="[selected ? 'selected' : '', labelAlign, customClass, field.options.required ? 'required' : '']"
|
||||
@click.native.stop="selectField(field)">
|
||||
|
||||
<span v-if="!!field.options.labelIconClass" slot="label" class="custom-label">
|
||||
<template v-if="field.options.labelIconPosition === 'front'">
|
||||
<template v-if="!!field.options.labelTooltip">
|
||||
<el-tooltip :content="field.options.labelTooltip" effect="light">
|
||||
<i :class="field.options.labelIconClass"></i></el-tooltip>{{label}}</template>
|
||||
<template v-else>
|
||||
<i :class="field.options.labelIconClass"></i>{{label}}</template>
|
||||
</template>
|
||||
<template v-else-if="field.options.labelIconPosition === 'rear'">
|
||||
<template v-if="!!field.options.labelTooltip">
|
||||
{{label}}<el-tooltip :content="field.options.labelTooltip" effect="light">
|
||||
<i :class="field.options.labelIconClass"></i></el-tooltip></template>
|
||||
<template v-else>
|
||||
{{label}}<i :class="field.options.labelIconClass"></i></template>
|
||||
</template>
|
||||
</span>
|
||||
<slot></slot>
|
||||
</el-form-item>
|
||||
|
||||
<template v-if="!!this.designer">
|
||||
<div class="field-action" v-if="designer.selectedId === field.id">
|
||||
<i class="el-icon-back" :title="i18nt('designer.hint.selectParentWidget')" @click.stop="selectParentWidget(field)"></i>
|
||||
<i class="el-icon-top" v-if="!!parentList && (parentList.length > 1)" :title="i18nt('designer.hint.moveUpWidget')"
|
||||
@click.stop="moveUpWidget(field)"></i>
|
||||
<i class="el-icon-bottom" v-if="!!parentList && (parentList.length > 1)" :title="i18nt('designer.hint.moveDownWidget')"
|
||||
@click.stop="moveDownWidget(field)"></i>
|
||||
<i class="el-icon-delete" :title="i18nt('designer.hint.remove')" @click.stop="removeFieldWidget"></i>
|
||||
</div>
|
||||
|
||||
<div class="drag-handler background-opacity" v-if="designer.selectedId === field.id">
|
||||
<i class="el-icon-rank" :title="i18nt('designer.hint.dragHandler')"></i>
|
||||
<i>{{i18nt('designer.widgetLabel.' + field.type)}}</i>
|
||||
<i v-if="field.options.hidden === true" class="iconfont icon-hide"></i>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n";
|
||||
|
||||
export default {
|
||||
name: "form-item-wrapper",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
designer: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
rules: Array,
|
||||
},
|
||||
inject: ['formConfig'],
|
||||
computed: {
|
||||
selected() {
|
||||
return !!this.designer && this.field.id === this.designer.selectedId
|
||||
},
|
||||
|
||||
label() {
|
||||
if (!!this.field.options.labelHidden) {
|
||||
return ''
|
||||
}
|
||||
|
||||
return this.field.options.label
|
||||
},
|
||||
|
||||
labelWidth() {
|
||||
if (!!this.field.options.labelHidden) {
|
||||
return 0
|
||||
}
|
||||
|
||||
if (!!this.field.options.labelWidth) {
|
||||
return this.field.options.labelWidth
|
||||
}
|
||||
|
||||
if (!!this.designer) {
|
||||
return this.designer.formConfig.labelWidth
|
||||
} else {
|
||||
return this.formConfig.labelWidth
|
||||
}
|
||||
},
|
||||
|
||||
labelAlign() {
|
||||
if (!!this.field.options.labelAlign) {
|
||||
return this.field.options.labelAlign
|
||||
}
|
||||
|
||||
if (!!this.designer) {
|
||||
return this.designer.formConfig.labelAlign || 'label-left-align'
|
||||
} else {
|
||||
return this.formConfig.labelAlign || 'label-left-align'
|
||||
}
|
||||
},
|
||||
|
||||
customClass() {
|
||||
return !!this.field.options.customClass ? this.field.options.customClass.join(' ') : ''
|
||||
},
|
||||
|
||||
subFormName() {
|
||||
return !!this.parentWidget ? this.parentWidget.options.name : ''
|
||||
},
|
||||
|
||||
subFormItemFlag() {
|
||||
return !!this.parentWidget ? this.parentWidget.type === 'sub-form' : false
|
||||
},
|
||||
|
||||
},
|
||||
created() {
|
||||
//
|
||||
},
|
||||
methods: {
|
||||
|
||||
selectField(field) {
|
||||
if (!!this.designer) {
|
||||
this.designer.setSelected(field)
|
||||
this.designer.emitEvent('field-selected', this.parentWidget) //发送选中组件的父组件对象
|
||||
}
|
||||
},
|
||||
|
||||
selectParentWidget() {
|
||||
if (this.parentWidget) {
|
||||
this.designer.setSelected(this.parentWidget)
|
||||
} else {
|
||||
this.designer.clearSelected()
|
||||
}
|
||||
},
|
||||
|
||||
moveUpWidget() {
|
||||
this.designer.moveUpWidget(this.parentList, this.indexOfParentList)
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
moveDownWidget() {
|
||||
this.designer.moveDownWidget(this.parentList, this.indexOfParentList)
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
removeFieldWidget() {
|
||||
if (!!this.parentList) {
|
||||
let nextSelected = null
|
||||
if (this.parentList.length === 1) {
|
||||
if (!!this.parentWidget) {
|
||||
nextSelected = this.parentWidget
|
||||
}
|
||||
} else if (this.parentList.length === (1 + this.indexOfParentList)) {
|
||||
nextSelected = this.parentList[this.indexOfParentList - 1]
|
||||
} else {
|
||||
nextSelected = this.parentList[this.indexOfParentList + 1]
|
||||
}
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.parentList.splice(this.indexOfParentList, 1)
|
||||
//if (!!nextSelected) {
|
||||
this.designer.setSelected(nextSelected)
|
||||
//}
|
||||
|
||||
this.designer.emitHistoryChange()
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
getPropName() {
|
||||
if (this.subFormItemFlag && !this.designState) {
|
||||
return this.subFormName + "." + this.subFormRowIndex + "." + this.field.options.name + ""
|
||||
} else {
|
||||
return this.field.options.name
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss";
|
||||
|
||||
.design-time-bottom-margin {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.field-wrapper {
|
||||
position: relative;
|
||||
|
||||
.field-action{
|
||||
position: absolute;
|
||||
//bottom: -24px;
|
||||
bottom: 0;
|
||||
right: -2px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
background: $--color-primary;
|
||||
z-index: 9;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
margin: 0 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.drag-handler {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
//bottom: -22px; /* 拖拽手柄位于组件下方,有时无法正常拖动,原因未明?? */
|
||||
left: -1px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
//background: $--color-primary;
|
||||
z-index: 9;
|
||||
|
||||
i {
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
color: #fff;
|
||||
margin: 4px;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
//opacity: 1;
|
||||
background: $--color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
//margin-bottom: 0 !important;
|
||||
//margin-bottom: 6px;
|
||||
|
||||
//margin-top: 2px;
|
||||
position: relative;
|
||||
|
||||
::v-deep .el-form-item__label {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
::v-deep .el-form-item__content {
|
||||
//position: unset; /* TODO: 忘了这个样式设置是为了解决什么问题?? */
|
||||
}
|
||||
|
||||
span.custom-label i {
|
||||
margin: 0 3px;
|
||||
}
|
||||
|
||||
/* 隐藏Chrome浏览器中el-input数字输入框右侧的上下调整小箭头 */
|
||||
::v-deep .hide-spin-button input::-webkit-outer-spin-button,
|
||||
::v-deep .hide-spin-button input::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none !important;
|
||||
}
|
||||
|
||||
/* 隐藏Firefox浏览器中el-input数字输入框右侧的上下调整小箭头 */
|
||||
::v-deep .hide-spin-button input[type="number"] {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
}
|
||||
|
||||
.required ::v-deep .el-form-item__label::before {
|
||||
content: '*';
|
||||
color: #F56C6C;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.static-content-item {
|
||||
min-height: 20px;
|
||||
display: flex; /* 垂直居中 */
|
||||
align-items: center; /* 垂直居中 */
|
||||
|
||||
::v-deep .el-divider--horizontal {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.el-form-item.selected, .static-content-item.selected {
|
||||
outline: 2px solid $--color-primary;
|
||||
}
|
||||
|
||||
::v-deep .label-left-align .el-form-item__label {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
::v-deep .label-center-align .el-form-item__label {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
::v-deep .label-right-align .el-form-item__label {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
|
@ -0,0 +1,82 @@
|
|||
<template>
|
||||
<static-content-wrapper :designer="designer" :field="field" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<div ref="fieldEditor" v-html="field.options.htmlContent"></div>
|
||||
</static-content-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import StaticContentWrapper from './static-content-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "html-text-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
StaticContentWrapper,
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* static-content-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
</style>
|
|
@ -0,0 +1,10 @@
|
|||
const requireComponent = require.context('./', false, /\w+\.vue$/)
|
||||
|
||||
let comps = {}
|
||||
|
||||
requireComponent.keys().map(fileName => {
|
||||
let comp = requireComponent(fileName).default;
|
||||
comps[comp.name] = comp
|
||||
})
|
||||
|
||||
export default comps;
|
|
@ -0,0 +1,112 @@
|
|||
<template>
|
||||
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<el-input ref="fieldEditor" v-model="fieldModel"
|
||||
:disabled="field.options.disabled" :readonly="field.options.readonly"
|
||||
:size="field.options.size" class="hide-spin-button"
|
||||
:type="inputType"
|
||||
:show-password="field.options.showPassword"
|
||||
:placeholder="field.options.placeholder"
|
||||
:clearable="field.options.clearable"
|
||||
:minlength="field.options.minLength" :maxlength="field.options.maxLength"
|
||||
:show-word-limit="field.options.showWordLimit"
|
||||
:prefix-icon="field.options.prefixIcon" :suffix-icon="field.options.suffixIcon"
|
||||
@focus="handleFocusCustomEvent" @blur="handleBlurCustomEvent" @input="handleInputCustomEvent"
|
||||
@change="handleChangeEvent">
|
||||
<el-button slot="append" v-if="field.options.appendButton" :disabled="field.options.disabled || field.options.appendButtonDisabled"
|
||||
:class="field.options.buttonIcon" @click.native="emitAppendButtonClick"></el-button>
|
||||
</el-input>
|
||||
</form-item-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormItemWrapper from './form-item-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "input-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
FormItemWrapper,
|
||||
},
|
||||
inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel'],
|
||||
data() {
|
||||
return {
|
||||
oldFieldValue: null, //field组件change之前的值
|
||||
fieldModel: null,
|
||||
rules: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
inputType() {
|
||||
if (this.field.options.type === 'number') {
|
||||
return 'text' //当input的type设置为number时,如果输入非数字字符,则v-model拿到的值为空字符串,无法实现输入校验!故屏蔽之!!
|
||||
}
|
||||
|
||||
return this.field.options.type
|
||||
},
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.initFieldModel()
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
this.buildFieldRules()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* form-item-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
</style>
|
|
@ -0,0 +1,103 @@
|
|||
<template>
|
||||
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<el-input-number ref="fieldEditor" v-model="fieldModel" class="full-width-input"
|
||||
:disabled="field.options.disabled"
|
||||
:size="field.options.size" :controls-position="field.options.controlsPosition"
|
||||
:placeholder="field.options.placeholder"
|
||||
:min="field.options.min" :max="field.options.max"
|
||||
:precision="field.options.precision" :step="field.options.step"
|
||||
@focus="handleFocusCustomEvent" @blur="handleBlurCustomEvent"
|
||||
@change="handleChangeEvent">
|
||||
</el-input-number>
|
||||
</form-item-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormItemWrapper from './form-item-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "number-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
FormItemWrapper,
|
||||
},
|
||||
inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel'],
|
||||
data() {
|
||||
return {
|
||||
oldFieldValue: null, //field组件change之前的值
|
||||
fieldModel: null,
|
||||
rules: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.initFieldModel()
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
this.buildFieldRules()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* form-item-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
.full-width-input {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,219 @@
|
|||
<template>
|
||||
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<el-upload ref="fieldEditor" :disabled="field.options.disabled"
|
||||
:action="field.options.uploadURL" :headers="uploadHeaders" :data="uploadData"
|
||||
:with-credentials="field.options.withCredentials"
|
||||
:multiple="field.options.multipleSelect" :file-list="fileList" :show-file-list="field.options.showFileList"
|
||||
list-type="picture-card" :class="{'hideUploadDiv': uploadBtnHidden}"
|
||||
:limit="field.options.limit" :on-exceed="handlePictureExceed"
|
||||
:before-upload="beforePictureUpload"
|
||||
:on-success="handlePictureUpload" :on-error="handelUploadError" :on-remove="handlePictureRemove">
|
||||
<div slot="tip" class="el-upload__tip"
|
||||
v-if="!!field.options.uploadTip">{{field.options.uploadTip}}</div>
|
||||
<i class="el-icon-plus avatar-uploader-icon"></i>
|
||||
</el-upload>
|
||||
</form-item-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormItemWrapper from './form-item-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import {deepClone} from "@/utils/util";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "picture-upload-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
FormItemWrapper,
|
||||
},
|
||||
inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel'],
|
||||
data() {
|
||||
return {
|
||||
oldFieldValue: null, //field组件change之前的值
|
||||
fieldModel: null,
|
||||
rules: [],
|
||||
|
||||
uploadHeaders: {},
|
||||
uploadData: {
|
||||
key: '', //七牛云上传文件名
|
||||
//token: '', //七牛云上传token
|
||||
|
||||
//policy: '', //又拍云上传policy
|
||||
//authorization: '', //又拍云上传签名
|
||||
},
|
||||
fileList: [], //上传文件列表
|
||||
uploadBtnHidden: false,
|
||||
|
||||
// styleVariables: {
|
||||
// '--select-file-action': selectFileText,
|
||||
// },
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.initFieldModel()
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
this.buildFieldRules()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
handlePictureExceed() {
|
||||
//let uploadLimit = this.field.options.limit
|
||||
this.$message.warning(eval('`' + this.i18nt('render.hint.uploadExceed') + '`'));
|
||||
},
|
||||
|
||||
updateUploadFieldModelAndEmitDataChange() {
|
||||
let oldValue = deepClone(this.fieldModel)
|
||||
this.fieldModel = deepClone(this.fileList)
|
||||
this.syncUpdateFormModel(this.fieldModel)
|
||||
this.emitFieldDataChange(this.fieldModel, oldValue)
|
||||
},
|
||||
|
||||
beforePictureUpload(file) {
|
||||
let fileTypeCheckResult = false
|
||||
if (!!this.field.options && !!this.field.options.fileTypes) {
|
||||
let uploadFileTypes = this.field.options.fileTypes
|
||||
if (uploadFileTypes.length > 0) {
|
||||
fileTypeCheckResult = uploadFileTypes.some( (ft) => {
|
||||
return file.type === 'image/' + ft
|
||||
})
|
||||
}
|
||||
}
|
||||
if (!fileTypeCheckResult) {
|
||||
this.$message.error(this.i18nt('render.hint.unsupportedFileType') + file.type)
|
||||
return false;
|
||||
}
|
||||
|
||||
let fileSizeCheckResult = false
|
||||
let uploadFileMaxSize = 5 //5MB
|
||||
if (!!this.field.options && !!this.field.options.fileMaxSize) {
|
||||
uploadFileMaxSize = this.field.options.fileMaxSize
|
||||
}
|
||||
fileSizeCheckResult = file.size / 1024 / 1024 <= uploadFileMaxSize
|
||||
if (!fileSizeCheckResult) {
|
||||
this.$message.error(this.$('render.hint.fileSizeExceed') + uploadFileMaxSize + 'MB')
|
||||
return false;
|
||||
}
|
||||
|
||||
this.uploadData.key = file.name
|
||||
return this.handleOnBeforeUpload(file)
|
||||
},
|
||||
|
||||
handlePictureUpload(res, file, fileList) {
|
||||
if (!!this.field.options.onUploadSuccess) {
|
||||
let customFn = new Function('result', 'file', 'fileList', this.field.options.onUploadSuccess)
|
||||
customFn.call(this, res, file, fileList)
|
||||
} else {
|
||||
if (file.status === 'success') {
|
||||
this.fileList.push(file)
|
||||
this.updateUploadFieldModelAndEmitDataChange()
|
||||
|
||||
this.uploadBtnHidden = this.fileList.length >= this.field.options.limit
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
handlePictureRemove(file, fileList) {
|
||||
let foundIdx = -1
|
||||
this.fileList.forEach((tf,idx) => {
|
||||
if (tf.name === file.name) {
|
||||
foundIdx = idx
|
||||
}
|
||||
})
|
||||
|
||||
this.fileList = fileList
|
||||
this.updateUploadFieldModelAndEmitDataChange()
|
||||
|
||||
this.uploadBtnHidden = fileList.length >= this.field.options.limit
|
||||
},
|
||||
|
||||
handelUploadError(err, file, fileList) {
|
||||
if (!!this.field.options.onUploadError) {
|
||||
let customFn = new Function('error', 'file', 'fileList', this.field.options.onUploadError)
|
||||
customFn.call(this, err, file, fileList)
|
||||
} else {
|
||||
this.$message({
|
||||
message: this.i18nt('render.hint.uploadError') + err,
|
||||
duration: 3000,
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* form-item-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
.full-width-input {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.hideUploadDiv {
|
||||
::v-deep div.el-upload--picture-card { /* 隐藏最后的图片上传按钮 */
|
||||
display: none;
|
||||
}
|
||||
|
||||
::v-deep div.el-upload--text { /* 隐藏最后的文件上传按钮 */
|
||||
display: none;
|
||||
}
|
||||
|
||||
::v-deep div.el-upload__tip { /* 隐藏最后的文件上传按钮 */
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,105 @@
|
|||
<template>
|
||||
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<el-radio-group ref="fieldEditor" v-model="fieldModel"
|
||||
:disabled="field.options.disabled" :size="field.options.size"
|
||||
@change="handleChangeEvent">
|
||||
<template v-if="!!field.options.buttonStyle">
|
||||
<el-radio-button v-for="(item, index) in field.options.optionItems" :key="index" :label="item.value"
|
||||
:disabled="item.disabled" :border="field.options.border"
|
||||
:style="{display: field.options.displayStyle}">{{item.label}}</el-radio-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-radio v-for="(item, index) in field.options.optionItems" :key="index" :label="item.value"
|
||||
:disabled="item.disabled" :border="field.options.border"
|
||||
:style="{display: field.options.displayStyle}">{{item.label}}</el-radio>
|
||||
</template>
|
||||
</el-radio-group>
|
||||
</form-item-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormItemWrapper from './form-item-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "radio-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
FormItemWrapper,
|
||||
},
|
||||
inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel'],
|
||||
data() {
|
||||
return {
|
||||
oldFieldValue: null, //field组件change之前的值
|
||||
fieldModel: null,
|
||||
rules: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.initOptionItems()
|
||||
this.initFieldModel()
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
this.buildFieldRules()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* form-item-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
</style>
|
|
@ -0,0 +1,102 @@
|
|||
<template>
|
||||
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<el-rate ref="fieldEditor" v-model="fieldModel"
|
||||
:disabled="field.options.disabled"
|
||||
:max="field.options.max"
|
||||
:low-threshold="field.options.lowThreshold" :high-threshold="field.options.highThreshold"
|
||||
:allow-half="field.options.allowHalf"
|
||||
:show-text="field.options.showText" :show-score="field.options.showScore"
|
||||
@change="handleChangeEvent">
|
||||
</el-rate>
|
||||
</form-item-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormItemWrapper from './form-item-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "rate-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
FormItemWrapper,
|
||||
},
|
||||
inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel'],
|
||||
data() {
|
||||
return {
|
||||
oldFieldValue: null, //field组件change之前的值
|
||||
fieldModel: null,
|
||||
rules: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.initFieldModel()
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
this.buildFieldRules()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* form-item-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
.full-width-input {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,121 @@
|
|||
<template>
|
||||
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<vue-editor ref="fieldEditor" v-model="fieldModel" :editor-toolbar="customToolbar"
|
||||
:disabled="field.options.disabled" :placeholder="field.options.placeholder"
|
||||
@text-change="handleRichEditorChangeEvent"
|
||||
@focus="handleRichEditorFocusEvent" @blur="handleRichEditorBlurEvent">
|
||||
</vue-editor>
|
||||
</form-item-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormItemWrapper from './form-item-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import {deepClone} from "@/utils/util";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "rich-editor-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
FormItemWrapper,
|
||||
|
||||
VueEditor: resolve => { //懒加载!!
|
||||
require(['vue2-editor'], ({VueEditor}) => resolve(VueEditor))
|
||||
}
|
||||
},
|
||||
inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel'],
|
||||
data() {
|
||||
return {
|
||||
oldFieldValue: null, //field组件change之前的值
|
||||
fieldModel: null,
|
||||
rules: [],
|
||||
|
||||
customToolbar: [], //富文本编辑器自定义工具栏
|
||||
valueChangedFlag: false, //vue2-editor数据值是否改变标志
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.initFieldModel()
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
this.buildFieldRules()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleRichEditorChangeEvent() {
|
||||
this.valueChangedFlag = true
|
||||
},
|
||||
|
||||
handleRichEditorFocusEvent() {
|
||||
this.oldFieldValue = deepClone(this.fieldModel)
|
||||
},
|
||||
|
||||
handleRichEditorBlurEvent() {
|
||||
if (this.valueChangedFlag) {
|
||||
this.emitFieldDataChange(this.fieldModel, this.oldFieldValue)
|
||||
this.valueChangedFlag = false
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* form-item-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
.full-width-input {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,115 @@
|
|||
<template>
|
||||
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<el-select ref="fieldEditor" v-model="fieldModel" class="full-width-input"
|
||||
:disabled="field.options.disabled"
|
||||
:size="field.options.size"
|
||||
:clearable="field.options.clearable"
|
||||
:filterable="field.options.filterable"
|
||||
:allow-create="field.options.allowCreate"
|
||||
:default-first-option="allowDefaultFirstOption"
|
||||
:automatic-dropdown="field.options.automaticDropdown"
|
||||
:multiple="field.options.multiple" :multiple-limit="field.options.multipleLimit"
|
||||
:placeholder="field.options.placeholder || i18nt('render.hint.selectPlaceholder')"
|
||||
:remote="this.field.options.remote" :remote-method="remoteQuery"
|
||||
@focus="handleFocusCustomEvent" @blur="handleBlurCustomEvent"
|
||||
@change="handleChangeEvent">
|
||||
<el-option v-for="item in field.options.optionItems" :key="item.value" :label="item.label"
|
||||
:value="item.value" :disabled="item.disabled">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</form-item-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormItemWrapper from './form-item-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "select-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
FormItemWrapper,
|
||||
},
|
||||
inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel'],
|
||||
data() {
|
||||
return {
|
||||
oldFieldValue: null, //field组件change之前的值
|
||||
fieldModel: null,
|
||||
rules: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
allowDefaultFirstOption() {
|
||||
return (!!this.field.options.filterable && !!this.field.options.allowCreate)
|
||||
},
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.initOptionItems()
|
||||
this.initFieldModel()
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
this.buildFieldRules()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* form-item-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
.full-width-input {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,100 @@
|
|||
<template>
|
||||
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<el-slider ref="fieldEditor" v-model="fieldModel"
|
||||
:disabled="field.options.disabled"
|
||||
:min="field.options.min" :max="field.options.max" :step="field.options.step"
|
||||
:range="field.options.range" :vertical="field.options.vertical"
|
||||
@change="handleChangeEvent">
|
||||
</el-slider>
|
||||
</form-item-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormItemWrapper from './form-item-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "slider-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
FormItemWrapper,
|
||||
},
|
||||
inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel'],
|
||||
data() {
|
||||
return {
|
||||
oldFieldValue: null, //field组件change之前的值
|
||||
fieldModel: null,
|
||||
rules: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.initFieldModel()
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
this.buildFieldRules()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* form-item-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
.full-width-input {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,185 @@
|
|||
<template>
|
||||
<div class="field-wrapper" :class="{'design-time-bottom-margin': !!this.designer}">
|
||||
<div class="static-content-item" v-show="!field.options.hidden || (designState === true)"
|
||||
:class="{'selected': selected}" @click.stop="selectField(field)">
|
||||
<slot></slot>
|
||||
</div>
|
||||
|
||||
<template v-if="!!this.designer">
|
||||
<div class="field-action" v-if="designer.selectedId === field.id">
|
||||
<i class="el-icon-back" :title="i18nt('designer.hint.selectParentWidget')" @click.stop="selectParentWidget(field)"></i>
|
||||
<i class="el-icon-top" v-if="!!parentList && (parentList.length > 1)" :title="i18nt('designer.hint.moveUpWidget')"
|
||||
@click.stop="moveUpWidget(field)"></i>
|
||||
<i class="el-icon-bottom" v-if="!!parentList && (parentList.length > 1)" :title="i18nt('designer.hint.moveDownWidget')"
|
||||
@click.stop="moveDownWidget(field)"></i>
|
||||
<i class="el-icon-delete" :title="i18nt('designer.hint.remove')" @click.stop="removeFieldWidget"></i>
|
||||
</div>
|
||||
|
||||
<div class="drag-handler background-opacity" v-if="designer.selectedId === field.id">
|
||||
<i class="el-icon-rank" :title="i18nt('designer.hint.dragHandler')"></i>
|
||||
<i>{{i18nt('designer.widgetLabel.' + field.type)}}</i>
|
||||
<i v-if="field.options.hidden === true" class="iconfont icon-hide"></i>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n";
|
||||
|
||||
export default {
|
||||
name: "static-content-wrapper",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
designer: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
selected() {
|
||||
return !!this.designer && this.field.id === this.designer.selectedId
|
||||
},
|
||||
|
||||
},
|
||||
methods: {
|
||||
|
||||
selectField(field) {
|
||||
if (!!this.designer) {
|
||||
this.designer.setSelected(field)
|
||||
this.designer.emitEvent('field-selected', this.parentWidget) //发送选中组件的父组件对象
|
||||
}
|
||||
},
|
||||
|
||||
selectParentWidget() {
|
||||
if (this.parentWidget) {
|
||||
this.designer.setSelected(this.parentWidget)
|
||||
} else {
|
||||
this.designer.clearSelected()
|
||||
}
|
||||
},
|
||||
|
||||
moveUpWidget() {
|
||||
this.designer.moveUpWidget(this.parentList, this.indexOfParentList)
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
moveDownWidget() {
|
||||
this.designer.moveDownWidget(this.parentList, this.indexOfParentList)
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
removeFieldWidget() {
|
||||
if (!!this.parentList) {
|
||||
let nextSelected = null
|
||||
if (this.parentList.length === 1) {
|
||||
if (!!this.parentWidget) {
|
||||
nextSelected = this.parentWidget
|
||||
}
|
||||
} else if (this.parentList.length === (1 + this.indexOfParentList)) {
|
||||
nextSelected = this.parentList[this.indexOfParentList - 1]
|
||||
} else {
|
||||
nextSelected = this.parentList[this.indexOfParentList + 1]
|
||||
}
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.parentList.splice(this.indexOfParentList, 1)
|
||||
//if (!!nextSelected) {
|
||||
this.designer.setSelected(nextSelected)
|
||||
//}
|
||||
|
||||
this.designer.emitHistoryChange()
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss";
|
||||
|
||||
.design-time-bottom-margin {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.field-wrapper {
|
||||
position: relative;
|
||||
|
||||
.field-action{
|
||||
position: absolute;
|
||||
//bottom: -24px;
|
||||
bottom: 0;
|
||||
right: -2px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
background: $--color-primary;
|
||||
z-index: 9;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
margin: 0 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.drag-handler {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
//bottom: -22px; /* 拖拽手柄位于组件下方,有时无法正常拖动,原因未明?? */
|
||||
left: -1px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
//background: $--color-primary;
|
||||
z-index: 9;
|
||||
|
||||
i {
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
color: #fff;
|
||||
margin: 4px;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
//opacity: 1;
|
||||
background: $--color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.static-content-item {
|
||||
min-height: 20px;
|
||||
display: flex; /* 垂直居中 */
|
||||
align-items: center; /* 垂直居中 */
|
||||
|
||||
::v-deep .el-divider--horizontal {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.el-form-item.selected, .static-content-item.selected {
|
||||
outline: 2px solid $--color-primary;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,82 @@
|
|||
<template>
|
||||
<static-content-wrapper :designer="designer" :field="field" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<div ref="fieldEditor">{{field.options.textContent}}</div>
|
||||
</static-content-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import StaticContentWrapper from './static-content-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "static-text-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
StaticContentWrapper,
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* static-content-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
</style>
|
|
@ -0,0 +1,101 @@
|
|||
<template>
|
||||
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<el-switch ref="fieldEditor" v-model="fieldModel"
|
||||
:disabled="field.options.disabled"
|
||||
:active-text="field.options.activeText" :inactive-text="field.options.inactiveText"
|
||||
:active-color="field.options.activeColor" :inactive-color="field.options.inactiveColor"
|
||||
:width="field.options.switchWidth"
|
||||
@change="handleChangeEvent">
|
||||
</el-switch>
|
||||
</form-item-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormItemWrapper from './form-item-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "switch-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
FormItemWrapper,
|
||||
},
|
||||
inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel'],
|
||||
data() {
|
||||
return {
|
||||
oldFieldValue: null, //field组件change之前的值
|
||||
fieldModel: null,
|
||||
rules: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.initFieldModel()
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
this.buildFieldRules()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* form-item-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
.full-width-input {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,99 @@
|
|||
<template>
|
||||
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<el-input type="textarea" ref="fieldEditor" v-model="fieldModel"
|
||||
:disabled="field.options.disabled" :readonly="field.options.readonly"
|
||||
:size="field.options.size"
|
||||
:placeholder="field.options.placeholder" :rows="field.options.rows"
|
||||
:minlength="field.options.minLength" :maxlength="field.options.maxLength"
|
||||
:show-word-limit="field.options.showWordLimit"
|
||||
@focus="handleFocusCustomEvent" @blur="handleBlurCustomEvent" @input="handleInputCustomEvent"
|
||||
@change="handleChangeEvent">
|
||||
</el-input>
|
||||
</form-item-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormItemWrapper from './form-item-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "textarea-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
FormItemWrapper,
|
||||
},
|
||||
inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel'],
|
||||
data() {
|
||||
return {
|
||||
oldFieldValue: null, //field组件change之前的值
|
||||
fieldModel: null,
|
||||
rules: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.initFieldModel()
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
this.buildFieldRules()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* form-item-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
</style>
|
|
@ -0,0 +1,104 @@
|
|||
<template>
|
||||
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<el-time-picker ref="fieldEditor" is-range v-model="fieldModel" class="full-width-input"
|
||||
:disabled="field.options.disabled" :readonly="field.options.readonly"
|
||||
:size="field.options.size"
|
||||
:clearable="field.options.clearable" :editable="field.options.editable"
|
||||
:format="field.options.format" value-format="HH:mm:ss"
|
||||
:start-placeholder="field.options.startPlaceholder || i18nt('render.hint.startTimePlaceholder')"
|
||||
:end-placeholder="field.options.endPlaceholder || i18nt('render.hint.endTimePlaceholder')"
|
||||
@focus="handleFocusCustomEvent" @blur="handleBlurCustomEvent"
|
||||
@change="handleChangeEvent">
|
||||
</el-time-picker>
|
||||
</form-item-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormItemWrapper from './form-item-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "time-range-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
FormItemWrapper,
|
||||
},
|
||||
inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel'],
|
||||
data() {
|
||||
return {
|
||||
oldFieldValue: null, //field组件change之前的值
|
||||
fieldModel: null,
|
||||
rules: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.initFieldModel()
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
this.buildFieldRules()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* form-item-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
.full-width-input {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,103 @@
|
|||
<template>
|
||||
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
|
||||
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
|
||||
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
|
||||
<el-time-picker ref="fieldEditor" v-model="fieldModel" class="full-width-input"
|
||||
:disabled="field.options.disabled" :readonly="field.options.readonly"
|
||||
:size="field.options.size"
|
||||
:clearable="field.options.clearable" :editable="field.options.editable"
|
||||
:format="field.options.format" value-format="HH:mm:ss"
|
||||
:placeholder="field.options.placeholder || i18nt('render.hint.timePlaceholder')"
|
||||
@focus="handleFocusCustomEvent" @blur="handleBlurCustomEvent"
|
||||
@change="handleChangeEvent">
|
||||
</el-time-picker>
|
||||
</form-item-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormItemWrapper from './form-item-wrapper'
|
||||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
import i18n, {translate} from "@/utils/i18n";
|
||||
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
|
||||
|
||||
export default {
|
||||
name: "time-widget",
|
||||
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
|
||||
mixins: [emitter, fieldMixin, i18n],
|
||||
props: {
|
||||
field: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
|
||||
designState: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
FormItemWrapper,
|
||||
},
|
||||
inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel'],
|
||||
data() {
|
||||
return {
|
||||
oldFieldValue: null, //field组件change之前的值
|
||||
fieldModel: null,
|
||||
rules: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
beforeCreate() {
|
||||
/* 这里不能访问方法和属性!! */
|
||||
},
|
||||
|
||||
created() {
|
||||
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
|
||||
需要在父组件created中初始化!! */
|
||||
this.initFieldModel()
|
||||
this.registerToRefList()
|
||||
this.initEventHandler()
|
||||
this.buildFieldRules()
|
||||
|
||||
this.handleOnCreated()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.handleOnMounted()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unregisterFromRefList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../../../styles/global.scss"; //* form-item-wrapper已引入,还需要重复引入吗? *//
|
||||
|
||||
.full-width-input {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -11,12 +11,12 @@
|
|||
<transition-group name="fade" tag="div" class="form-widget-list">
|
||||
<template v-for="(widget, index) in designer.widgetList">
|
||||
<template v-if="'container' === widget.category">
|
||||
<container-widget :widget="widget" :designer="designer" :key="widget.id" :parent-list="designer.widgetList"
|
||||
:index-of-parent-list="index" :parent-widget="null"></container-widget>
|
||||
<component :is="getWidgetName(widget)" :widget="widget" :designer="designer" :key="widget.id" :parent-list="designer.widgetList"
|
||||
:index-of-parent-list="index" :parent-widget="null"></component>
|
||||
</template>
|
||||
<template v-else>
|
||||
<field-widget :field="widget" :designer="designer" :key="widget.id" :parent-list="designer.widgetList"
|
||||
:index-of-parent-list="index" :parent-widget="null" :design-state="true"></field-widget>
|
||||
<component :is="getWidgetName(widget)" :field="widget" :designer="designer" :key="widget.id" :parent-list="designer.widgetList"
|
||||
:index-of-parent-list="index" :parent-widget="null" :design-state="true"></component>
|
||||
</template>
|
||||
</template>
|
||||
</transition-group>
|
||||
|
@ -29,9 +29,9 @@
|
|||
|
||||
<script>
|
||||
import Draggable from 'vuedraggable'
|
||||
import ContainerWidget from "@/components/form-designer/form-widget/container-widget";
|
||||
import FieldWidget from "@/components/form-designer/form-widget/field-widget";
|
||||
import i18n from "@/utils/i18n";
|
||||
import ContainerComponents from '@/components/form-designer/form-widget/container-widget/index'
|
||||
import FieldComponents from '@/components/form-designer/form-widget/field-widget/index'
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "VFormWidget",
|
||||
|
@ -39,8 +39,9 @@
|
|||
mixins: [i18n],
|
||||
components: {
|
||||
Draggable,
|
||||
ContainerWidget,
|
||||
FieldWidget,
|
||||
|
||||
...ContainerComponents,
|
||||
...FieldComponents,
|
||||
},
|
||||
props: {
|
||||
designer: Object,
|
||||
|
@ -116,6 +117,10 @@
|
|||
this.designer.registerFormWidget(this)
|
||||
},
|
||||
methods: {
|
||||
getWidgetName(widget) {
|
||||
return widget.type + '-widget'
|
||||
},
|
||||
|
||||
disableFirefoxDefaultDrop() {
|
||||
let isFirefox = (navigator.userAgent.toLowerCase().indexOf("firefox") !== -1)
|
||||
if (isFirefox) {
|
||||
|
|
|
@ -1,90 +0,0 @@
|
|||
<template>
|
||||
<el-tab-pane :name="'tab1'" :label="widget.label" @click.native.stop="selectWidget(widget)">
|
||||
<draggable :list="widget.widgetList" v-bind="{group:'dragGroup', ghostClass: 'ghost',animation: 200}"
|
||||
handle=".drag-handler" @end="(evt) => onTabDragEnd(evt, widget.widgetList)"
|
||||
@add="(evt) => onTabDragAdd(evt, widget.widgetList)"
|
||||
@update="onTabDragUpdate" :move="checkContainerMove">
|
||||
<transition-group name="fade" tag="div" class="form-widget-list">
|
||||
<template v-for="(subWidget, swIdx) in widget.widgetList">
|
||||
<template v-if="'container' === subWidget.category">
|
||||
<container-widget :widget="subWidget" :designer="designer" :key="subWidget.id" :parent-list="widget.widgetList"
|
||||
:index-of-parent-list="swIdx" :parent-widget="widget"></container-widget>
|
||||
</template>
|
||||
<template v-else>
|
||||
<field-widget :field="subWidget" :designer="designer" :key="subWidget.id" :parent-list="widget.widgetList"
|
||||
:index-of-parent-list="swIdx" :parent-widget="widget" :design-state="true"></field-widget>
|
||||
</template>
|
||||
</template>
|
||||
</transition-group>
|
||||
</draggable>
|
||||
</el-tab-pane>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/* 此组件未用上!! */
|
||||
|
||||
import Draggable from 'vuedraggable'
|
||||
import ContainerWidget from "@/components/form-designer/form-widget/container-widget";
|
||||
import FieldWidget from "@/components/form-designer/form-widget/field-widget";
|
||||
import i18n from "@/utils/i18n";
|
||||
|
||||
export default {
|
||||
name: "VTabPane",
|
||||
mixins: [i18n],
|
||||
components: {
|
||||
Draggable,
|
||||
ContainerWidget,
|
||||
FieldWidget,
|
||||
},
|
||||
props: {
|
||||
widget: Object,
|
||||
parentWidget: Object,
|
||||
parentList: Array,
|
||||
indexOfParentList: Number,
|
||||
designer: Object,
|
||||
},
|
||||
computed: {
|
||||
selected() {
|
||||
return this.widget.id === this.designer.selectedId
|
||||
},
|
||||
|
||||
},
|
||||
methods: {
|
||||
selectWidget(widget) {
|
||||
this.designer.setSelected(widget)
|
||||
},
|
||||
|
||||
onTabDragEnd(obj, subList) {
|
||||
//
|
||||
},
|
||||
|
||||
onTabDragAdd(evt, subList) { //重复代码,可合并
|
||||
const newIndex = evt.newIndex
|
||||
console.log(newIndex)
|
||||
if (!!subList[newIndex]) {
|
||||
this.designer.setSelected( subList[newIndex] )
|
||||
}
|
||||
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
onTabDragUpdate() {
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
checkContainerMove(evt) {
|
||||
return this.designer.checkWidgetMove(evt)
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-tab-pane {
|
||||
|
||||
::v-deep .form-widget-list {
|
||||
min-height: 28px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -2,7 +2,7 @@
|
|||
/**
|
||||
* author: vformAdmin
|
||||
* email: vdpadmin@163.com
|
||||
* website: http://www.vform666.com/
|
||||
* website: http://www.vform666.com
|
||||
* date: 2021.08.18
|
||||
* remark: 如果要分发VForm源码,需在本文件顶部保留此文件头信息!!
|
||||
*/
|
||||
|
@ -62,7 +62,7 @@
|
|||
import VFormWidget from './form-widget/index'
|
||||
import {createDesigner} from "@/components/form-designer/designer";
|
||||
import {addWindowResizeHandler, getQueryParam} from "@/utils/util";
|
||||
import {VARIANT_FORM_VERSION} from "@/utils/config";
|
||||
import {MOCK_CASE_URL, VARIANT_FORM_VERSION} from "@/utils/config";
|
||||
import i18n, { changeLocale } from "@/utils/i18n";
|
||||
|
||||
export default {
|
||||
|
@ -81,6 +81,8 @@
|
|||
curLangName: '',
|
||||
|
||||
vsCodeFlag: false,
|
||||
caseName: '',
|
||||
|
||||
docUrl: 'http://www.vform666.com/document.html',
|
||||
gitUrl: 'https://github.com/vform666/variant-form',
|
||||
chatUrl: 'http://www.vform666.com/chat-group.html',
|
||||
|
@ -98,6 +100,7 @@
|
|||
},
|
||||
created() {
|
||||
this.vsCodeFlag = getQueryParam('vscode') == 1
|
||||
this.caseName = getQueryParam('case')
|
||||
},
|
||||
mounted() {
|
||||
this.initLocale()
|
||||
|
@ -108,6 +111,8 @@
|
|||
this.scrollerHeight = window.innerHeight - 56 - 36 + 'px'
|
||||
})
|
||||
})
|
||||
|
||||
this.loadCase()
|
||||
},
|
||||
methods: {
|
||||
openHome() {
|
||||
|
@ -138,6 +143,24 @@
|
|||
}
|
||||
},
|
||||
|
||||
loadCase() {
|
||||
if (!this.caseName) {
|
||||
return
|
||||
}
|
||||
|
||||
axios.get(MOCK_CASE_URL + this.caseName).then(res => {
|
||||
if (!!res.data.code) {
|
||||
this.$message.error(this.i18nt('designer.hint.sampleLoadedFail'))
|
||||
return
|
||||
}
|
||||
|
||||
this.setFormJson(res.data)
|
||||
this.$message.success(this.i18nt('designer.hint.sampleLoadedSuccess'))
|
||||
}).catch(error => {
|
||||
this.$message.error(this.i18nt('designer.hint.sampleLoadedFail') + ':' +error)
|
||||
})
|
||||
},
|
||||
|
||||
initLocale() {
|
||||
let curLocale = localStorage.getItem('v_form_locale')
|
||||
if (!!this.vsCodeFlag) {
|
||||
|
|
|
@ -0,0 +1,300 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-form :model="formConfig" size="mini" label-position="left" label-width="120px"
|
||||
class="setting-form" @submit.native.prevent>
|
||||
<el-collapse v-model="formActiveCollapseNames" class="setting-collapse">
|
||||
<el-collapse-item name="1" :title="i18nt('designer.setting.basicSetting')">
|
||||
<el-form-item :label="i18nt('designer.setting.formSize')">
|
||||
<el-select v-model="formConfig.size">
|
||||
<el-option v-for="item in formSizes" :key="item.value" :label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="i18nt('designer.setting.labelPosition')">
|
||||
<el-radio-group v-model="formConfig.labelPosition" class="radio-group-custom">
|
||||
<el-radio-button label="left">{{i18nt('designer.setting.leftPosition')}}</el-radio-button>
|
||||
<el-radio-button label="top">{{i18nt('designer.setting.topPosition')}}</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="i18nt('designer.setting.labelAlign')">
|
||||
<el-radio-group v-model="formConfig.labelAlign" class="radio-group-custom">
|
||||
<el-radio-button label="label-left-align">{{i18nt('designer.setting.leftAlign')}}</el-radio-button>
|
||||
<el-radio-button label="label-center-align">{{i18nt('designer.setting.centerAlign')}}</el-radio-button>
|
||||
<el-radio-button label="label-right-align">{{i18nt('designer.setting.rightAlign')}}</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="i18nt('designer.setting.labelWidth')">
|
||||
<el-input-number v-model="formConfig.labelWidth" :min="0" style="width: 100%"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item :label="i18nt('designer.setting.formCss')">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editFormCss">{{i18nt('designer.setting.addCss')}}</el-button>
|
||||
</el-form-item>
|
||||
<!-- -->
|
||||
<el-form-item :label="i18nt('designer.setting.customClass')">
|
||||
<el-select v-model="formConfig.customClass" multiple filterable allow-create
|
||||
default-first-option>
|
||||
<el-option v-for="(item, idx) in cssClassList" :key="idx" :label="item" :value="item"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- -->
|
||||
<el-form-item :label="i18nt('designer.setting.globalFunctions')">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editGlobalFunctions">{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="0">
|
||||
<el-divider class="custom-divider">{{i18nt('designer.setting.formSFCSetting')}}</el-divider>
|
||||
</el-form-item>
|
||||
<el-form-item :label="i18nt('designer.setting.formModelName')">
|
||||
<el-input type="text" v-model="formConfig.modelName"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="i18nt('designer.setting.formRefName')">
|
||||
<el-input type="text" v-model="formConfig.refName"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="i18nt('designer.setting.formRulesName')">
|
||||
<el-input type="text" v-model="formConfig.rulesName"></el-input>
|
||||
</el-form-item>
|
||||
</el-collapse-item>
|
||||
|
||||
<el-collapse-item name="2" :title="i18nt('designer.setting.eventSetting')">
|
||||
<el-form-item label="onFormCreated" label-width="150px">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editFormEventHandler('onFormCreated')">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label="onFormMounted" label-width="150px">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editFormEventHandler('onFormMounted')">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
<!-- -->
|
||||
<el-form-item label="onFormDataChange" label-width="150px">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editFormEventHandler('onFormDataChange')">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
<!-- -->
|
||||
<!--
|
||||
<el-form-item label="onFormValidate">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editFormEventHandler('onFormValidate')">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
-->
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</el-form>
|
||||
|
||||
<el-dialog :title="i18nt('designer.setting.editFormEventHandler')" :visible.sync="showFormEventDialogFlag"
|
||||
v-if="showFormEventDialogFlag" :show-close="true" class="small-padding-dialog" v-dialog-drag
|
||||
:close-on-click-modal="false" :close-on-press-escape="false" :destroy-on-close="true">
|
||||
<el-alert type="info" :closable="false" :title="'form.' + eventParamsMap[curEventName]"></el-alert>
|
||||
<code-editor :mode="'javascript'" :readonly="false" v-model="formEventHandlerCode"></code-editor>
|
||||
<el-alert type="info" :closable="false" title="}"></el-alert>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="showFormEventDialogFlag = false">
|
||||
{{i18nt('designer.hint.cancel')}}</el-button>
|
||||
<el-button type="primary" @click="saveFormEventHandler">
|
||||
{{i18nt('designer.hint.confirm')}}</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog :title="i18nt('designer.setting.formCss')" :visible.sync="showEditFormCssDialogFlag"
|
||||
v-if="showEditFormCssDialogFlag" :show-close="true" class="small-padding-dialog" v-dialog-drag
|
||||
:close-on-click-modal="false" :close-on-press-escape="false" :destroy-on-close="true">
|
||||
<code-editor :mode="'css'" :readonly="false" v-model="formCssCode"></code-editor>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="showEditFormCssDialogFlag = false">
|
||||
{{i18nt('designer.hint.cancel')}}</el-button>
|
||||
<el-button type="primary" @click="saveFormCss">
|
||||
{{i18nt('designer.hint.confirm')}}</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog :title="i18nt('designer.setting.globalFunctions')" :visible.sync="showEditFunctionsDialogFlag"
|
||||
v-if="showEditFunctionsDialogFlag" :show-close="true" class="small-padding-dialog" v-dialog-drag
|
||||
:close-on-click-modal="false" :close-on-press-escape="false" :destroy-on-close="true">
|
||||
<code-editor :mode="'javascript'" :readonly="false" v-model="functionsCode"></code-editor>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="showEditFunctionsDialogFlag = false">
|
||||
{{i18nt('designer.hint.cancel')}}</el-button>
|
||||
<el-button type="primary" @click="saveGlobalFunctions">
|
||||
{{i18nt('designer.hint.confirm')}}</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import CodeEditor from '@/components/code-editor/index'
|
||||
import {deepClone, insertCustomCssToHead, insertGlobalFunctionsToHtml} from "@/utils/util"
|
||||
|
||||
export default {
|
||||
name: "form-setting",
|
||||
mixins: [i18n],
|
||||
components: {
|
||||
CodeEditor,
|
||||
},
|
||||
props: {
|
||||
designer: Object,
|
||||
formConfig: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
formActiveCollapseNames: ['1', '2'],
|
||||
|
||||
formSizes: [
|
||||
{label: 'default', value: ''},
|
||||
{label: 'large', value: 'large'},
|
||||
{label: 'medium', value: 'medium'},
|
||||
{label: 'small', value: 'small'},
|
||||
{label: 'mini', value: 'mini'},
|
||||
],
|
||||
|
||||
showEditFormCssDialogFlag: false,
|
||||
formCssCode: '',
|
||||
cssClassList: [],
|
||||
|
||||
showEditFunctionsDialogFlag: false,
|
||||
functionsCode: '',
|
||||
|
||||
showFormEventDialogFlag: false,
|
||||
formEventHandlerCode: '',
|
||||
curEventName: '',
|
||||
|
||||
eventParamsMap: {
|
||||
'onFormCreated': 'onFormCreated() {',
|
||||
'onFormMounted': 'onFormMounted() {',
|
||||
'onFormDataChange': 'onFormDataChange(fieldName, newValue, oldValue, formModel, subFormName, subFormRowIndex) {',
|
||||
//'onFormValidate': 'onFormValidate() {',
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
/* SettingPanel和FormWidget为兄弟组件, 在FormWidget加载formConfig时,
|
||||
此处SettingPanel可能无法获取到formConfig.cssCode, 故加个延时函数! */
|
||||
setTimeout(() => {
|
||||
this.formCssCode = this.formConfig.cssCode
|
||||
insertCustomCssToHead(this.formCssCode)
|
||||
this.extractCssClass()
|
||||
this.designer.emitEvent('form-css-updated', deepClone(this.cssClassList))
|
||||
}, 1200)
|
||||
},
|
||||
methods: {
|
||||
editFormCss() {
|
||||
this.formCssCode = this.designer.formConfig.cssCode
|
||||
this.showEditFormCssDialogFlag = true
|
||||
},
|
||||
|
||||
extractCssClass() {
|
||||
let regExp = /\..*{/g
|
||||
let result = this.formCssCode.match(regExp)
|
||||
//this.cssClassList.length = 0
|
||||
this.cssClassList.splice(0, this.cssClassList.length) //清除数组必须用splice,length=0不会响应式更新!!
|
||||
if (!!result && result.length > 0) {
|
||||
result.forEach((rItem) => {
|
||||
let classArray = rItem.split(',') //切分逗号分割的多个class
|
||||
if (classArray.length > 0) {
|
||||
classArray.forEach((cItem) => {
|
||||
let caItem = cItem.trim()
|
||||
if (caItem.indexOf('.', 1) !== -1) { //查找第二个.位置
|
||||
let newClass = caItem.substring(caItem.indexOf('.') + 1, caItem.indexOf('.', 1)) //仅截取第一、二个.号之间的class
|
||||
if (!!newClass) {
|
||||
this.cssClassList.push(newClass.trim())
|
||||
}
|
||||
} else if (caItem.indexOf(' ') !== -1) { //查找第一个空格位置
|
||||
let newClass = caItem.substring(caItem.indexOf('.') + 1, caItem.indexOf(' ')) //仅截取第一、二个.号之间的class
|
||||
if (!!newClass) {
|
||||
this.cssClassList.push(newClass.trim())
|
||||
}
|
||||
} else {
|
||||
if (caItem.indexOf('{') !== -1) { //查找第一个{位置
|
||||
let newClass = caItem.substring(caItem.indexOf('.') + 1, caItem.indexOf('{'))
|
||||
this.cssClassList.push( newClass.trim() )
|
||||
} else {
|
||||
let newClass = caItem.substring(caItem.indexOf('.') + 1)
|
||||
this.cssClassList.push( newClass.trim() )
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
saveFormCss() {
|
||||
this.extractCssClass()
|
||||
this.designer.formConfig.cssCode = this.formCssCode
|
||||
insertCustomCssToHead(this.formCssCode)
|
||||
this.showEditFormCssDialogFlag = false
|
||||
|
||||
this.designer.emitEvent('form-css-updated', deepClone(this.cssClassList))
|
||||
},
|
||||
|
||||
editGlobalFunctions() {
|
||||
this.functionsCode = this.designer.formConfig.functions
|
||||
this.showEditFunctionsDialogFlag = true
|
||||
},
|
||||
|
||||
saveGlobalFunctions() {
|
||||
this.designer.formConfig.functions = this.functionsCode
|
||||
insertGlobalFunctionsToHtml(this.functionsCode)
|
||||
this.showEditFunctionsDialogFlag = false
|
||||
},
|
||||
|
||||
editFormEventHandler(eventName) {
|
||||
this.curEventName = eventName
|
||||
this.formEventHandlerCode = this.formConfig[eventName]
|
||||
this.showFormEventDialogFlag = true
|
||||
},
|
||||
|
||||
saveFormEventHandler() {
|
||||
this.formConfig[this.curEventName] = this.formEventHandlerCode
|
||||
this.showFormEventDialogFlag = false
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.setting-form {
|
||||
::v-deep .el-form-item__label {
|
||||
font-size: 13px;
|
||||
//text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
::v-deep .el-form-item--mini.el-form-item {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.radio-group-custom {
|
||||
::v-deep .el-radio-button__inner {
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.custom-divider.el-divider--horizontal {
|
||||
margin: 10px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.setting-collapse {
|
||||
::v-deep .el-collapse-item__content {
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
::v-deep .el-collapse-item__header {
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.small-padding-dialog {
|
||||
::v-deep .el-dialog__body {
|
||||
padding: 6px 15px 12px 15px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,24 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.allowCreate')">
|
||||
<el-checkbox v-model="optionModel.allowCreate"></el-checkbox>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "allowCreate-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,28 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-form-item label-width="0">
|
||||
<el-divider class="custom-divider">{{i18nt('designer.setting.inputButton')}}</el-divider>
|
||||
</el-form-item>
|
||||
<el-form-item :label="i18nt('designer.setting.appendButton')">
|
||||
<el-checkbox v-model="optionModel.appendButton"></el-checkbox>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "appendButton-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.appendButtonDisabled')">
|
||||
<el-checkbox v-model="optionModel.appendButtonDisabled"></el-checkbox>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "appendButtonDisabled-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.automaticDropdown')">
|
||||
<el-checkbox v-model="optionModel.automaticDropdown"></el-checkbox>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "automaticDropdown-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.border')">
|
||||
<el-checkbox v-model="optionModel.border"></el-checkbox>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "border-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.appendButtonIcon')">
|
||||
<el-input type="text" v-model="optionModel.buttonIcon"></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "buttonIcon-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.buttonStyle')">
|
||||
<el-checkbox v-model="optionModel.buttonStyle"></el-checkbox>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "buttonStyle-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.clearable')">
|
||||
<el-checkbox v-model="optionModel.clearable"></el-checkbox>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "clearable-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,40 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-form-item :label="i18nt('designer.setting.widgetColumnWidth')" v-show="!!subFormChildWidgetFlag">
|
||||
<el-input type="text" v-model="optionModel.columnWidth"></el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "columnWidth-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
//subFormChildWidgetFlag: false,
|
||||
subFormChildWidgetFlag: true,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
mounted() {
|
||||
this.designer.handleEvent('field-selected', (parentWidget) => {
|
||||
this.subFormChildWidgetFlag = !!parentWidget && (parentWidget.type === 'sub-form');
|
||||
//console.log('subFormChildWidgetFlag', this.subFormChildWidgetFlag)
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,24 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.colSpanTitle')">
|
||||
<el-input-number v-model.number="optionModel.span" :min="1" :max="24"
|
||||
style="width: 100%"></el-input-number>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n";
|
||||
|
||||
export default {
|
||||
name: "grid-col-span-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,81 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-form-item label-width="0">
|
||||
<el-divider class="custom-divider">{{i18nt('designer.setting.columnSetting')}}</el-divider>
|
||||
</el-form-item>
|
||||
<el-form-item :label="i18nt('designer.setting.gutter')">
|
||||
<el-input-number v-model="optionModel.gutter" style="width: 100%"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item :label="i18nt('designer.setting.colsOfGrid')"></el-form-item>
|
||||
<el-form-item label-width="0">
|
||||
<li v-for="(colItem, colIdx) in selectedWidget.cols" :key="colIdx" class="col-item">
|
||||
<span class="col-span-title">{{i18nt('designer.setting.colSpanTitle')}}{{colIdx + 1}}</span>
|
||||
<el-input-number v-model.number="colItem.options.span" :min="1" :max="24"
|
||||
@change="(newValue, oldValue) => spanChanged(selectedWidget, colItem, colIdx, newValue, oldValue)"
|
||||
class="cell-span-input"></el-input-number>
|
||||
<el-button circle plain size="mini" type="danger" @click="deleteCol(selectedWidget, colIdx)"
|
||||
icon="el-icon-minus" class="col-delete-button"></el-button>
|
||||
</li>
|
||||
<div>
|
||||
<el-button type="text" @click="addNewCol(selectedWidget)">{{i18nt('designer.setting.addColumn')}}</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "gutter-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
methods: {
|
||||
spanChanged(curGrid) {
|
||||
let spanSum = 0
|
||||
curGrid.cols.forEach((colItem) => {
|
||||
spanSum += colItem.options.span
|
||||
})
|
||||
if (spanSum > 24) {
|
||||
//this.$message.info('列栅格之和超出24')
|
||||
console.log('列栅格之和超出24')
|
||||
//TODO: 语言字符串资源化
|
||||
}
|
||||
|
||||
this.designer.saveCurrentHistoryStep()
|
||||
},
|
||||
|
||||
deleteCol(curGrid, colIdx) {
|
||||
this.designer.deleteColOfGrid(curGrid, colIdx)
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
addNewCol(curGrid) {
|
||||
this.designer.addNewColOfGrid(curGrid)
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
li.col-item {
|
||||
list-style: none;
|
||||
|
||||
span.col-span-title {
|
||||
display: inline-block;
|
||||
font-size: 13px;
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
.col-delete-button {
|
||||
margin-left: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.showBlankRow')">
|
||||
<el-checkbox v-model="optionModel.showBlankRow"></el-checkbox>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "showBlankRow-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.showRowNumber')">
|
||||
<el-checkbox v-model="optionModel.showRowNumber"></el-checkbox>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "showRowNumber-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,36 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.labelAlign')">
|
||||
<el-radio-group v-model="optionModel.labelAlign" class="radio-group-custom">
|
||||
<el-radio-button label="label-left-align">
|
||||
{{i18nt('designer.setting.leftAlign')}}</el-radio-button>
|
||||
<el-radio-button label="label-center-align">
|
||||
{{i18nt('designer.setting.centerAlign')}}</el-radio-button>
|
||||
<el-radio-button label="label-right-align">
|
||||
{{i18nt('designer.setting.rightAlign')}}</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n";
|
||||
|
||||
export default {
|
||||
name: "sub-form-labelAlign-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.radio-group-custom {
|
||||
::v-deep .el-radio-button__inner {
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,119 @@
|
|||
<!--
|
||||
因tabs属性并不包含于options属性之中,故只能跟其他options属性之内的属性值合并设置,此处选择与customClass合并!!
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<el-form-item :label="i18nt('designer.setting.customClass')">
|
||||
<el-select v-model="optionModel.customClass" multiple filterable allow-create
|
||||
default-first-option>
|
||||
<el-option v-for="(item, idx) in cssClassList" :key="idx" :label="item" :value="item"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="i18nt('designer.setting.tabPaneSetting')"></el-form-item>
|
||||
<el-form-item label-width="0" class="panes-setting">
|
||||
<draggable tag="ul" :list="selectedWidget.tabs"
|
||||
v-bind="{group:'panesGroup', ghostClass: 'ghost', handle: '.drag-option'}">
|
||||
<li v-for="(tpItem, tpIdx) in selectedWidget.tabs" :key="tpIdx" class="col-item">
|
||||
<!-- span style="margin-right: 12px">{{tpIdx + 1}}</span -->
|
||||
<el-checkbox v-model="tpItem.options.active" disabled @change="(evt) => onTabPaneActiveChange(evt, tpItem)"
|
||||
style="margin-right: 8px">{{i18nt('designer.setting.paneActive')}}</el-checkbox>
|
||||
<el-input type="text" v-model="tpItem.options.label" style="width: 155px"></el-input>
|
||||
<i class="iconfont icon-drag drag-option"></i>
|
||||
<el-button circle plain size="mini" type="danger" @click="deleteTabPane(selectedWidget, tpIdx)"
|
||||
icon="el-icon-minus" class="col-delete-button"></el-button>
|
||||
</li>
|
||||
<div>
|
||||
<el-button type="text" @click="addTabPane(selectedWidget)">{{i18nt('designer.setting.addTabPane')}}</el-button>
|
||||
</div>
|
||||
</draggable>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import Draggable from 'vuedraggable'
|
||||
import {deepClone} from "@/utils/util";
|
||||
|
||||
export default {
|
||||
name: "tab-customClass-editor",
|
||||
componentName: 'PropertyEditor',
|
||||
mixins: [i18n],
|
||||
components: {
|
||||
Draggable,
|
||||
},
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
cssClassList: [],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.cssClassList = deepClone(this.designer.getCssClassList())
|
||||
//监听表单css代码改动事件并重新加载!
|
||||
this.designer.handleEvent('form-css-updated', (cssClassList) => {
|
||||
this.cssClassList = cssClassList
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
onTabPaneActiveChange(evt, tpItem) {
|
||||
//TODO: !!!
|
||||
},
|
||||
|
||||
addTabPane(curTabs) {
|
||||
this.designer.addTabPaneOfTabs(curTabs)
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
deleteTabPane(curTabs, tpIdx) {
|
||||
if (curTabs.tabs.length === 1) {
|
||||
this.$message.info(this.i18nt('designer.hint.lastPaneCannotBeDeleted'))
|
||||
return
|
||||
}
|
||||
|
||||
this.designer.deleteTabPaneOfTabs(curTabs, tpIdx)
|
||||
this.designer.emitHistoryChange()
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
li.col-item {
|
||||
list-style: none;
|
||||
|
||||
span.col-span-title {
|
||||
display: inline-block;
|
||||
font-size: 13px;
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
.col-delete-button {
|
||||
margin-left: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.panes-setting {
|
||||
ul {
|
||||
padding-inline-start: 0;
|
||||
padding-left: 0; /* 重置IE11默认样式 */
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.drag-option {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
li.ghost {
|
||||
background: #fff;
|
||||
border: 2px dotted $--color-primary;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.cellHeight')">
|
||||
<el-input type="text" v-model="optionModel.cellHeight"></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "cellHeight-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.cellWidth')">
|
||||
<el-input type="text" v-model="optionModel.cellWidth"></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "cellWidth-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,40 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.customClass')">
|
||||
<el-select v-model="optionModel.customClass" multiple filterable allow-create
|
||||
default-first-option>
|
||||
<el-option v-for="(item, idx) in cssClassList" :key="idx" :label="item" :value="item"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n";
|
||||
import {deepClone} from "@/utils/util";
|
||||
|
||||
export default {
|
||||
name: "customClass-editor",
|
||||
componentName: 'PropertyEditor',
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
cssClassList: [],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.cssClassList = deepClone(this.designer.getCssClassList())
|
||||
//监听表单css代码改动事件并重新加载!
|
||||
this.designer.handleEvent('form-css-updated', (cssClassList) => {
|
||||
this.cssClassList = cssClassList
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,25 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.defaultValue')">
|
||||
<el-input v-if="!hasConfig('optionItems')" type="text" v-model="optionModel.defaultValue"
|
||||
@change="emitDefaultValueChange"></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import propertyMixin from "@/components/form-designer/setting-panel/property-editor/propertyMixin"
|
||||
|
||||
export default {
|
||||
name: "defaultValue-editor",
|
||||
mixins: [i18n, propertyMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.disabled')">
|
||||
<el-checkbox v-model="optionModel.disabled"></el-checkbox>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "disabled-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,26 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.displayStyle')">
|
||||
<el-radio-group v-model="optionModel.displayStyle">
|
||||
<el-radio label="inline">{{i18nt('designer.setting.inlineLayout')}}</el-radio>
|
||||
<el-radio label="block">{{i18nt('designer.setting.blockLayout')}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "displayStyle-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,24 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.editable')">
|
||||
<el-checkbox v-model="optionModel.editable"></el-checkbox>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "editable-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.endPlaceholder')">
|
||||
<el-input type="text" v-model="optionModel.endPlaceholder"></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "endPlaceholder-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,19 @@
|
|||
import emitter from 'element-ui/lib/mixins/emitter'
|
||||
|
||||
export default {
|
||||
mixins: [emitter],
|
||||
created() {
|
||||
// this.$on('saveEventHandler', function (params) {
|
||||
// //this.optionModel[eventName] = handlerCodes
|
||||
// this.optionModel[params[0]] = params[1]
|
||||
// })
|
||||
|
||||
},
|
||||
methods: {
|
||||
editEventHandler(eventName, eventParams) {
|
||||
this.dispatch('SettingPanel', 'editEventHandler', [eventName, [...eventParams]])
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<el-form-item label="onBeforeUpload" label-width="150px">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editEventHandler('onBeforeUpload', eventParams)">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import eventMixin from "@/components/form-designer/setting-panel/property-editor/event-handler/eventMixin"
|
||||
|
||||
export default {
|
||||
name: "onBeforeUpload-editor",
|
||||
mixins: [i18n, eventMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
eventParams: ['file'],
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<el-form-item label="onBlur" label-width="150px">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editEventHandler('onBlur', eventParams)">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import eventMixin from "@/components/form-designer/setting-panel/property-editor/event-handler/eventMixin"
|
||||
|
||||
export default {
|
||||
name: "onBlur-editor",
|
||||
mixins: [i18n, eventMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
eventParams: ['event'],
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<el-form-item label="onChange" label-width="150px">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editEventHandler('onChange', eventParams)">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import eventMixin from "@/components/form-designer/setting-panel/property-editor/event-handler/eventMixin"
|
||||
|
||||
export default {
|
||||
name: "onChange-editor",
|
||||
mixins: [i18n, eventMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
eventParams: ['value', 'oldValue', 'subFormData', 'rowId'],
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<el-form-item label="onClick" label-width="150px">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editEventHandler('onClick', eventParams)">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import eventMixin from "@/components/form-designer/setting-panel/property-editor/event-handler/eventMixin"
|
||||
|
||||
export default {
|
||||
name: "onClick-editor",
|
||||
mixins: [i18n, eventMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
eventParams: [],
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,31 @@
|
|||
<template>
|
||||
<el-form-item label="onCreated" label-width="150px">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editEventHandler('onCreated', eventParams)">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import eventMixin from "@/components/form-designer/setting-panel/property-editor/event-handler/eventMixin"
|
||||
|
||||
export default {
|
||||
name: "onCreated-editor",
|
||||
mixins: [i18n, eventMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
eventParams: [],
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<el-form-item label="onFocus" label-width="150px">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editEventHandler('onFocus', eventParams)">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import eventMixin from "@/components/form-designer/setting-panel/property-editor/event-handler/eventMixin"
|
||||
|
||||
export default {
|
||||
name: "onFocus-editor",
|
||||
mixins: [i18n, eventMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
eventParams: ['event'],
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<el-form-item label="onInput" label-width="150px">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editEventHandler('onInput', eventParams)">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import eventMixin from "@/components/form-designer/setting-panel/property-editor/event-handler/eventMixin"
|
||||
|
||||
export default {
|
||||
name: "onInput-editor",
|
||||
mixins: [i18n, eventMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
eventParams: ['value'],
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<el-form-item label="onMounted" label-width="150px">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editEventHandler('onMounted', eventParams)">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import eventMixin from "@/components/form-designer/setting-panel/property-editor/event-handler/eventMixin"
|
||||
|
||||
export default {
|
||||
name: "onMounted-editor",
|
||||
mixins: [i18n, eventMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
eventParams: [],
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<el-form-item label="onRemoteQuery" label-width="150px">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editEventHandler('onRemoteQuery', eventParams)">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import eventMixin from "@/components/form-designer/setting-panel/property-editor/event-handler/eventMixin"
|
||||
|
||||
export default {
|
||||
name: "onRemoteQuery-editor",
|
||||
mixins: [i18n, eventMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
eventParams: ['keyword'],
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<el-form-item label="onSubFormRowAdd" label-width="150px">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editEventHandler('onSubFormRowAdd', eventParams)">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import eventMixin from "@/components/form-designer/setting-panel/property-editor/event-handler/eventMixin"
|
||||
|
||||
export default {
|
||||
name: "onSubFormRowAdd-editor",
|
||||
mixins: [i18n, eventMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
eventParams: ['subFormData', 'newRowId'],
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<el-form-item label="onSubFormRowChange" label-width="150px">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editEventHandler('onSubFormRowChange', eventParams)">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import eventMixin from "@/components/form-designer/setting-panel/property-editor/event-handler/eventMixin"
|
||||
|
||||
export default {
|
||||
name: "onSubFormRowChange-editor",
|
||||
mixins: [i18n, eventMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
eventParams: ['subFormData'],
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<el-form-item label="onSubFormRowDelete" label-width="150px">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editEventHandler('onSubFormRowDelete', eventParams)">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import eventMixin from "@/components/form-designer/setting-panel/property-editor/event-handler/eventMixin"
|
||||
|
||||
export default {
|
||||
name: "onSubFormRowDelete-editor",
|
||||
mixins: [i18n, eventMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
eventParams: ['subFormData', 'deletedDataRow'],
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<el-form-item label="onSubFormRowInsert" label-width="150px">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editEventHandler('onSubFormRowInsert', eventParams)">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import eventMixin from "@/components/form-designer/setting-panel/property-editor/event-handler/eventMixin"
|
||||
|
||||
export default {
|
||||
name: "onSubFormRowInsert-editor",
|
||||
mixins: [i18n, eventMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
eventParams: ['subFormData', 'newRowId'],
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<el-form-item label="onUploadError" label-width="150px">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editEventHandler('onUploadError', eventParams)">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import eventMixin from "@/components/form-designer/setting-panel/property-editor/event-handler/eventMixin"
|
||||
|
||||
export default {
|
||||
name: "onUploadError-editor",
|
||||
mixins: [i18n, eventMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
eventParams: ['error', 'file', 'fileList'],
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<el-form-item label="onUploadSuccess" label-width="150px">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editEventHandler('onUploadSuccess', eventParams)">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import eventMixin from "@/components/form-designer/setting-panel/property-editor/event-handler/eventMixin"
|
||||
|
||||
export default {
|
||||
name: "onUploadSuccess-editor",
|
||||
mixins: [i18n, eventMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
eventParams: ['result', 'file', 'fileList'],
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<el-form-item label="onValidate" label-width="150px">
|
||||
<el-button type="info" icon="el-icon-edit" plain round @click="editEventHandler('onValidate', eventParams)">
|
||||
{{i18nt('designer.setting.addEventHandler')}}</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import eventMixin from "@/components/form-designer/setting-panel/property-editor/event-handler/eventMixin"
|
||||
|
||||
export default {
|
||||
name: "onValidate-editor",
|
||||
mixins: [i18n, eventMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
eventParams: ['rule', 'value', 'callback'],
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,32 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.displayType')">
|
||||
<el-select v-model="optionModel.type">
|
||||
<el-option label="default" value=""></el-option>
|
||||
<el-option label="primary" value="primary"></el-option>
|
||||
<el-option label="success" value="success"></el-option>
|
||||
<el-option label="warning" value="warning"></el-option>
|
||||
<el-option label="danger" value="danger"></el-option>
|
||||
<el-option label="info" value="info"></el-option>
|
||||
<el-option label="text" value="text"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import propertyMixin from "@/components/form-designer/setting-panel/property-editor/propertyMixin"
|
||||
|
||||
export default {
|
||||
name: "button-type-editor",
|
||||
mixins: [i18n, propertyMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.circle')">
|
||||
<el-checkbox v-model="optionModel.circle"></el-checkbox>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n";
|
||||
|
||||
export default {
|
||||
name: "circle-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.buttonIcon')">
|
||||
<el-input type="text" v-model="optionModel.icon"></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "icon-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,24 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.plain')">
|
||||
<el-checkbox v-model="optionModel.plain"></el-checkbox>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "plain-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.round')">
|
||||
<el-checkbox v-model="optionModel.round"></el-checkbox>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n";
|
||||
|
||||
export default {
|
||||
name: "round-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<el-color-picker v-model="optionModel.defaultValue" @change="emitDefaultValueChange">
|
||||
</el-color-picker>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import propertyMixin from "@/components/form-designer/setting-panel/property-editor/propertyMixin"
|
||||
|
||||
export default {
|
||||
name: "color-defaultValue-editor",
|
||||
mixins: [i18n, propertyMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,24 @@
|
|||
<template>
|
||||
<el-date-picker :type="optionModel.type" v-model="optionModel.defaultValue" @change="emitDefaultValueChange"
|
||||
:format="optionModel.format" :value-format="optionModel.valueFormat" style="width: 100%">
|
||||
</el-date-picker>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import propertyMixin from "@/components/form-designer/setting-panel/property-editor/propertyMixin"
|
||||
|
||||
export default {
|
||||
name: "date-range-defaultValue-editor",
|
||||
mixins: [i18n, propertyMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.format')">
|
||||
<el-select v-model="optionModel.format" filterable allow-create>
|
||||
<el-option label="yyyy-MM-dd" value="yyyy-MM-dd"></el-option>
|
||||
<el-option label="yyyy/MM/dd" value="yyyy/MM/dd"></el-option>
|
||||
<el-option label="yyyy年MM月dd日" value="yyyy年MM月dd日"></el-option>
|
||||
<el-option label="yyyy-MM-dd HH:mm:ss" value="yyyy-MM-dd HH:mm:ss"></el-option>
|
||||
<el-option label="yyyy-MM-dd hh:mm:ss" value="yyyy-MM-dd hh:mm:ss"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "date-range-format-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,27 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.displayType')">
|
||||
<el-select v-model="optionModel.type">
|
||||
<el-option label="daterange" value="daterange"></el-option>
|
||||
<el-option label="datetimerange" value="datetimerange"></el-option>
|
||||
<el-option label="monthrange" value="monthrange"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n";
|
||||
|
||||
export default {
|
||||
name: "date-range-type-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,26 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.valueFormat')">
|
||||
<el-select v-model="optionModel.valueFormat" filterable allow-create>
|
||||
<el-option label="yyyy-MM-dd" value="yyyy-MM-dd"></el-option>
|
||||
<el-option label="yyyy-MM-dd HH:mm:ss" value="yyyy-MM-dd HH:mm:ss"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "date-range-valueFormat-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,24 @@
|
|||
<template>
|
||||
<el-date-picker :type="optionModel.type" v-model="optionModel.defaultValue" @change="emitDefaultValueChange"
|
||||
:format="optionModel.format" :value-format="optionModel.valueFormat" style="width: 100%">
|
||||
</el-date-picker>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
import propertyMixin from "@/components/form-designer/setting-panel/property-editor/propertyMixin"
|
||||
|
||||
export default {
|
||||
name: "date-defaultValue-editor",
|
||||
mixins: [i18n, propertyMixin],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.format')">
|
||||
<el-select v-model="optionModel.format" filterable allow-create>
|
||||
<el-option label="yyyy-MM-dd" value="yyyy-MM-dd"></el-option>
|
||||
<el-option label="yyyy/MM/dd" value="yyyy/MM/dd"></el-option>
|
||||
<el-option label="yyyy年MM月dd日" value="yyyy年MM月dd日"></el-option>
|
||||
<el-option label="yyyy-MM-dd HH:mm:ss" value="yyyy-MM-dd HH:mm:ss"></el-option>
|
||||
<el-option label="yyyy-MM-dd hh:mm:ss" value="yyyy-MM-dd hh:mm:ss"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "date-format-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.displayType')">
|
||||
<el-select v-model="optionModel.type">
|
||||
<el-option label="datetime" value="datetime"></el-option>
|
||||
<el-option label="date" value="date"></el-option>
|
||||
<el-option label="dates" value="dates"></el-option>
|
||||
<el-option label="year" value="year"></el-option>
|
||||
<el-option label="month" value="month"></el-option>
|
||||
<el-option label="week" value="week"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n";
|
||||
|
||||
export default {
|
||||
name: "date-type-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,26 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.valueFormat')">
|
||||
<el-select v-model="optionModel.valueFormat" filterable allow-create>
|
||||
<el-option label="yyyy-MM-dd" value="yyyy-MM-dd"></el-option>
|
||||
<el-option label="yyyy-MM-dd HH:mm:ss" value="yyyy-MM-dd HH:mm:ss"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "date-valueFormat-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,27 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.contentPosition')">
|
||||
<el-select v-model="optionModel.contentPosition">
|
||||
<el-option label="center" value="center"></el-option>
|
||||
<el-option label="left" value="left"></el-option>
|
||||
<el-option label="right" value="right"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "contentPosition-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,44 @@
|
|||
<template>
|
||||
<el-form-item>
|
||||
<span slot="label">{{i18nt('designer.setting.fileTypes')}}
|
||||
<el-tooltip effect="light" :content="i18nt('designer.setting.fileTypesHelp')">
|
||||
<i class="el-icon-info"></i></el-tooltip>
|
||||
</span>
|
||||
<el-select multiple allow-create filterable default-first-option
|
||||
v-model="optionModel.fileTypes" style="width: 100%">
|
||||
<el-option v-for="(ft, ftIdx) in uploadFileTypes"
|
||||
:key="ftIdx"
|
||||
:label="ft.label"
|
||||
:value="ft.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "fileTypes-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
uploadFileTypes: [
|
||||
{value: 'doc', label: 'doc'},
|
||||
{value: 'xls', label: 'xls'},
|
||||
{value: 'docx', label: 'docx'},
|
||||
{value: 'xlsx', label: 'xlsx'},
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<el-form-item :label="i18nt('designer.setting.htmlContent')">
|
||||
<el-input v-model="optionModel.htmlContent"></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from "@/utils/i18n"
|
||||
|
||||
export default {
|
||||
name: "htmlContent-editor",
|
||||
mixins: [i18n],
|
||||
props: {
|
||||
designer: Object,
|
||||
selectedWidget: Object,
|
||||
optionModel: Object,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue