<template>
|
<div v-loading.lock="initLoading" ref="editor-container" class="yrt-editor-box" @keydown.f2="submit">
|
<yrt-editor-frame :edit-type="editType" :title="currentTitle" :label-position="config.labelPosition" :top="currentTop" :width="currentDialogWidth" :visible.sync="isShowDialog" :on-before-close="onBeforeClose" @opened="opened">
|
<div class="editor-container" @click="editorContainerClick">
|
<template v-if="masterFields">
|
<el-form ref="editor-form" :inline="config.formInline" :model="formData" :rules="rules" :label-width="config.labelWidth || '100px'" :style="{width:(config.formWidth || 'auto')}" :disabled="currentDisabled" class="editor-master">
|
<!--开启tab分组导航-->
|
<el-tabs v-if="dataOptions.openTabGroup" v-model="activeTabName">
|
<el-tab-pane v-for="(tabGroupName, index) in tabGroupList" :key="index" :label="tabGroupName" :name="tabGroupName">
|
<template v-for="(firstField, groupIndex) in getGroupFields(tabGroupName)">
|
<!--数据分组-->
|
<el-row v-if="firstField.type=='grid'" :key="groupIndex" :gutter="firstField.gutter">
|
<el-col v-for="(col, colIndex) in firstField.columns" :key="colIndex" :span="col.span">
|
<yrt-editor-input v-for="(subField, fieldIndex) in col.fields" :key="subField.key + '_' + fieldIndex" :field="subField" :form-data="formData" :disabled="currentDisabled" :dropdown-data="dropdownData" :rules="rules" :hide-feilds="hideFeilds" @on-change="(ref, val, field, formData)=>{onChange(ref, val, field, formData);}" @on-focus="(ref, val, event, field)=>{onFocus(ref, val, event, field)}" @on-blur="onBlur" @on-key-up="(ref, val, event, field, tableData)=>{onKeyup(ref, val, event, field, tableData);}" @on-row-change="(ref, selectedRow, field) => {onRowChange(ref, selectedRow, field);}" @on-item-click="(ref, val, itemData, field, formData) => {onItemClick(ref, val, itemData, field, formData);}">
|
<!-- label插槽 -->
|
<template v-if="useLabelSlot===true || (Array.isArray(useLabelSlot) && useLabelSlot.indexOf(subField.options.prop)>=0)" :slot="'label-' + subField.options.prop">
|
<slot :name="'label-' + subField.options.prop"></slot>
|
</template>
|
<!-- 空白自定义字段插槽 -->
|
<template slot-scope="props" :slot="'blank-' + subField.options.prop">
|
<slot :name="'blank-' + subField.options.prop" :formData="props.formData"></slot>
|
</template>
|
</yrt-editor-input>
|
</el-col>
|
</el-row>
|
|
<!--分割器-->
|
<div v-else-if="firstField.type=='splitter-group'" :key="groupIndex" class="splitter-title">
|
<div class="title">
|
{{ firstField.label }}
|
</div>
|
</div>
|
|
<!--编辑框在一行内 / 编辑框独立一行-->
|
<yrt-editor-input v-else ref="editorInput" :key="groupIndex" :field="firstField" :form-data="formData" :disabled="currentDisabled" :dropdown-data="dropdownData" :rules="rules" :hide-feilds="hideFeilds" @on-change="(ref, val, field, formData)=>{onChange(ref, val, field, formData);}" @on-focus="(ref, val, event, field)=>{onFocus(ref, val, event, field)}" @on-blur="onBlur" @on-tree-node-click="(data, node, el, labels, values, field)=>{onTreeNodeClick(data, node, el, labels, values, field)}">
|
<!--编辑框在一行内-->
|
<template v-if="firstField.fields">
|
<template v-for="subField in firstField.fields">
|
<!-- label插槽 -->
|
<template v-if="useLabelSlot===true || (Array.isArray(useLabelSlot) && useLabelSlot.indexOf(subField.options.prop)>=0)" :slot="'label-' + subField.options.prop">
|
<slot :name="'label-' + subField.options.prop"></slot>
|
</template>
|
<!-- 空白自定义字段插槽 -->
|
<template :slot="'blank-' + subField.options.prop">
|
<slot :name="'blank-' + subField.options.prop"></slot>
|
</template>
|
</template>
|
</template>
|
<!--编辑框独立一行-->
|
<template v-else>
|
<!-- label插槽 -->
|
<template v-if="useLabelSlot===true || (Array.isArray(useLabelSlot) && useLabelSlot.indexOf(subField.options.prop)>=0)" :slot="'label-' + subField.options.prop">
|
<slot :name="'label-' + firstField.options.prop"></slot>
|
</template>
|
<!-- 空白自定义字段插槽 -->
|
<template :slot="'blank-' + firstField.options.prop">
|
<slot :name="'blank-' + firstField.options.prop"></slot>
|
</template>
|
</template>
|
</yrt-editor-input>
|
</template>
|
</el-tab-pane>
|
</el-tabs>
|
<template v-else>
|
<template v-for="(firstField, groupIndex) in masterFields">
|
<!--数据分组-->
|
<el-row v-if="firstField.type=='grid'" :key="groupIndex" :gutter="firstField.gutter">
|
<el-col v-for="(col, colIndex) in firstField.columns" :key="colIndex" :span="col.span">
|
<yrt-editor-input v-for="(subField, index) in col.fields" :key="subField.key + '_' + index" :field="subField" :form-data="formData" :disabled="currentDisabled" :dropdown-data="dropdownData" :rules="rules" :hide-feilds="hideFeilds" @on-change="(ref, val, field, formData)=>{onChange(ref, val, field, formData);}" @on-focus="(ref, val, event, field)=>{onFocus(ref, val, event, field)}" @on-blur="onBlur" @on-key-up="(ref, val, event, field, tableData)=>{onKeyup(ref, val, event, field, tableData);}" @on-row-change="(ref, selectedRow, field) => {onRowChange(ref, selectedRow, field);}" @on-item-click="(ref, val, itemData, field, formData) => {onItemClick(ref, val, itemData, field, formData);}" @on-tree-node-click="(data, node, el, labels, values, field)=>{onTreeNodeClick(data, node, el, labels, values, field)}">
|
<!-- label插槽 -->
|
<template v-if="useLabelSlot===true || (Array.isArray(useLabelSlot) && useLabelSlot.indexOf(subField.options.prop)>=0)" :slot="'label-' + subField.options.prop">
|
<slot :name="'label-' + subField.options.prop"></slot>
|
</template>
|
<!-- 空白自定义字段插槽 -->
|
<template slot-scope="props" :slot="'blank-' + subField.options.prop">
|
<slot :name="'blank-' + subField.options.prop" :formData="props.formData"></slot>
|
</template>
|
</yrt-editor-input>
|
</el-col>
|
</el-row>
|
|
<!--分割器-->
|
<div v-else-if="firstField.type=='splitter-group'" :key="groupIndex" class="splitter-title">
|
<div class="title">
|
{{ firstField.label }}
|
</div>
|
</div>
|
|
<!--编辑框在一行内 / 编辑框独立一行-->
|
<yrt-editor-input v-else ref="editorInput" :key="groupIndex" :field="firstField" :form-data="formData" :disabled="currentDisabled" :dropdown-data="dropdownData" :rules="rules" :hide-feilds="hideFeilds" @on-change="(ref, val, field, formData)=>{onChange(ref, val, field, formData);}" @on-focus="(ref, val, event, field)=>{onFocus(ref, val, event, field)}" @on-blur="onBlur">
|
<!--编辑框在一行内-->
|
<template v-if="firstField.fields">
|
<template v-for="subField in firstField.fields">
|
<!-- label插槽 -->
|
<template v-if="useLabelSlot===true || (Array.isArray(useLabelSlot) && useLabelSlot.indexOf(subField.options.prop)>=0)" :slot="'label-' + subField.options.prop">
|
<slot :name="'label-' + subField.options.prop"></slot>
|
</template>
|
<!-- 空白自定义字段插槽 -->
|
<template :slot="'blank-' + subField.options.prop">
|
<slot :name="'blank-' + subField.options.prop"></slot>
|
</template>
|
</template>
|
</template>
|
<!--编辑框独立一行-->
|
<template v-else>
|
<!-- label插槽 -->
|
<template v-if="useLabelSlot===true || (Array.isArray(useLabelSlot) && useLabelSlot.indexOf(firstField.options.prop)>=0)" :slot="'label-' + firstField.options.prop">
|
<slot :name="'label-' + firstField.options.prop"></slot>
|
</template>
|
<!-- 空白自定义字段插槽 -->
|
<template :slot="'blank-' + firstField.options.prop">
|
<slot :name="'blank-' + firstField.options.prop"></slot>
|
</template>
|
</template>
|
</yrt-editor-input>
|
</template>
|
</template>
|
</el-form>
|
</template>
|
|
<!--明细数据-->
|
<template v-for="(detail, index) in detailFields">
|
<div :key="'detail_' + index" class="editor-detail">
|
<div v-if="detail.options.title" class="splitter-title">
|
<div class="title">
|
{{ detail.options.title }}
|
</div>
|
</div>
|
<div v-if="detail.buttons.length" class="detail-tool">
|
<slot name="detail-tool-slot">
|
<el-form>
|
<template v-for="(button, index) in detail.buttons">
|
<!--分组按钮-->
|
<el-button-group v-if="button.type=='button-group'" :key="index" class="tool-group">
|
<template v-for="(btn, btnIndex) in button.buttons">
|
<el-tooltip v-if="authNodes[btn.options.authNode]" :key="btnIndex" :content="btn.label" :open-delay="1000" placement="top">
|
<el-button v-if="authNodes[btn.options.authNode]" v-bind="btn.options" :disabled="btnReadOnly[btn.options.authNode]" size="mini" @click.native="()=>onDetailButtonAction(btn.options.authNode, detail, btn)">{{ btn.label }}</el-button>
|
</el-tooltip>
|
</template>
|
</el-button-group>
|
<!--不分组按钮-->
|
<template v-else>
|
<el-tooltip v-if="authNodes[button.options.authNode]" :key="index" :content="button.label" :open-delay="1000" placement="top">
|
<el-button v-if="authNodes[button.options.authNode]" v-bind="button" :disabled="btnReadOnly[btn.options.authNode]" size="mini" @click.native="()=>onDetailButtonAction(button.options.authNode, detail, btn)">{{ button.label }}</el-button>
|
</el-tooltip>
|
</template>
|
</template>
|
</el-form>
|
</slot>
|
</div>
|
|
<el-table :ref="'detail-table-'+detail.subTableView" v-bind="detail.options" :data="getDetailDataList(detail)" :max-height="400" :row-style="({row, rowIndex})=>detailRowStyle(row, rowIndex, detail)" :show-summary="detail.options.showSumField" :summary-method="({ columns, data })=>{return getDetailSummaries(columns, data, detail)}" style="width: 100%" highlight-current-row @selection-change="(val)=>handleSelectionChange(val, detail)" @cell-click="(row, column, cell, event)=>{onDetailCellClick(detail, row, column, cell, event)}" @current-change="(currentRow, oldCurrentRow)=>{onDetailCurrentChange(detail, currentRow, oldCurrentRow)}" @click.native.stop @header-click="(column, event) => {detailHeaderClick(column, event, detail)}">
|
<template>
|
<el-table-column :width="'35px'" type="selection" class="col-selection">
|
</el-table-column>
|
<el-table-column :width="'40px'" :index="(index)=>{return (detail.options.pageIndex-1) * detail.options.pageSize + index+1}" type="index" label="#" class="col-index">
|
</el-table-column>
|
<template v-for="(col, index) in detail.fields">
|
<!--操作列插槽-->
|
<el-table-column v-if="col.prop=='_action' && !col.hidden" :key="index" :sortable="!!col.sortable" :label="col.label" :width="col.width || 'auto'" :header-align="col.headerAlign || 'left'" :align="col.align || 'left'" fixed="right">
|
<template slot-scope="scope">
|
<slot :row="scope.row" :col="col" name="action-column-slot">
|
<el-button v-for="(btn, btnIndex) in col.action" :key="btnIndex" type="text" size="mini" @click="()=>onRowActionClick(btn, col, scope.row)">{{ btn.label }}</el-button>
|
</slot>
|
</template>
|
</el-table-column>
|
|
<!--通用列插槽-->
|
<yrt-detail-column :key="index" :col="col" :data-options="dataOptions" :dropdown-data="dropdownData" :disabled="currentDisabled" :show-fields="showFields" :current-row="detail.currentRow" @on-detail-change="onDetailChange">
|
<template v-if="useDetailSlot===true || (Array.isArray(useDetailSlot) && useDetailSlot.indexOf(col.prop)>=0)" slot="column-slot" slot-scope="{ row, column, index }">
|
<slot :row="row" :col="col" :index="index" :current-row="detail.currentRow" name="detail-column-slot"></slot>
|
</template>
|
</yrt-detail-column>
|
|
</template>
|
</template>
|
</el-table>
|
<div class="pagination-container">
|
<el-pagination :disabled="detailPageDisabled" :current-page="detail.options.pageIndex" :page-sizes="[ 1000]" :page-size="detail.options.pageSize" :total="formData[detail.subTableView].total" layout="total, sizes, prev, pager, next, jumper" @size-change="(val)=>handleSizeChange(val, detail)" @current-change="(val)=>handleCurrentChange(val, detail)">
|
</el-pagination>
|
</div>
|
</div>
|
</template>
|
</div>
|
|
<div slot="footer" class="dialog-footer">
|
<div class="left">
|
<!--自定义按钮-->
|
<template v-for="(item, index) in buttonList">
|
<el-button v-if="authNodes[item.authName]" :key="index" :disabled="btnReadOnly[item.authName]" :type="item.type" :icon="item.icon" @click.native="onButtonAction(item.authName)">{{ item.label }}</el-button>
|
</template>
|
|
<slot :form-data="formData" :details="detailFields" name="footer-button-region"></slot>
|
</div>
|
<div class="right">
|
<span style="color:white;cursor:pointer;" @click="$message.info('主键ID:' + dataOptions.idValue)">查看ID</span>
|
<el-button icon="el-icon-yrt-guanbi1" @click="cancel">取 消</el-button>
|
<el-button :loading="saveLoading" :disabled="currentDisabled || btnReadOnly['save'] || !authNodes.save" type="primary" icon="el-icon-yrt-baocun2" @click="_submit">{{ config.saveButtonText }}(F2)</el-button>
|
</div>
|
</div>
|
</yrt-editor-frame>
|
|
<!-- 批量导入对话框 -->
|
<import-dialog v-dialogDrag ref="import-dialog" :options="batchImport.options" :visible.sync="batchImport.visible" :import-data="importData"></import-dialog>
|
|
<!-- 批量导出对话框 -->
|
<export-dialog v-dialogDrag ref="export-dialog" :options="batchExport.options" :visible.sync="batchExport.visible" :export-data="exportData">
|
</export-dialog>
|
|
<!--显示字段属性-->
|
<table-info-dialog :visible.sync="tableAttr.showAttrDialog" :data-options="tableAttr.dataOptions" :fields="tableAttr.fields">
|
</table-info-dialog>
|
</div>
|
</template>
|
|
<script>
|
import TreeSelect from '@/components/base/TreeSelect'
|
import yrtEditorInput from './yrtEditorInput'
|
import yrtDetailColumn from './yrtDetailColumn'
|
import ImportDialog from './components/import-dialog'
|
import ExportDialog from './components/export-dialog'
|
import yrtEditorFrame from './components/yrt-editor-frame'
|
import TableInfoDialog from './components/table-info-dialog'
|
import Vue from 'vue'
|
Vue.config.keyCodes.f2 = 113
|
Vue.config.keyCodes.f3 = 114
|
|
export default {
|
name: 'yrt-editor',
|
components: {
|
TreeSelect,
|
yrtEditorInput,
|
yrtDetailColumn,
|
ImportDialog,
|
ExportDialog,
|
yrtEditorFrame,
|
TableInfoDialog
|
},
|
props: {
|
// 编辑类型:inner、dialog
|
editType: {
|
type: String,
|
default: 'dialog'
|
},
|
// 对话框宽度
|
dialogWidth: {
|
type: [Number, String],
|
default: null
|
},
|
// 编辑类型:add、edit
|
action: {
|
type: String,
|
default: 'add',
|
validator: function(value) {
|
// 接收值为:add、edit
|
return ['add', 'edit'].indexOf(value) !== -1
|
}
|
},
|
// 校验规则
|
rules: {
|
type: Object,
|
default: () => {
|
return null
|
}
|
},
|
// 主表字段信息
|
fields: {
|
type: Array,
|
default: () => {}
|
},
|
// 数据参数
|
dataOptions: {
|
type: Object,
|
default: () => {}
|
},
|
// 配置参数
|
config: {
|
type: Object,
|
default: () => {
|
return {
|
top: '10vh',
|
title: '对话框标题',
|
// 是否显示添加实验室小组对话框
|
visible: false,
|
// 是否禁用
|
disabled: false,
|
// 编辑时KeyId
|
id: 0,
|
// 保存按钮文本
|
saveButtonText: '保存',
|
// 行内表单模式
|
formInline: true
|
}
|
}
|
},
|
// 明细按钮单击事件
|
detailButtonClick: {
|
type: Function,
|
required: false,
|
default: null
|
},
|
// 编辑按钮点击事件
|
editButtonClick: {
|
type: Function,
|
required: false,
|
default: null
|
},
|
// 关联列表ref名
|
dataListRef: {
|
type: String,
|
default: 'data-list'
|
},
|
// 权限集合
|
authNodes: {
|
type: Object,
|
required: true,
|
default: () => {
|
return {}
|
}
|
},
|
// 按钮列表
|
buttonList: {
|
type: Array,
|
required: false,
|
default: () => {
|
return [
|
{
|
label: '审核',
|
authName: 'auditing',
|
icon: 'el-icon-yrt-gouxuan1',
|
type: 'success'
|
},
|
{
|
label: '复制',
|
authName: 'copy',
|
icon: 'el-icon-yrt-fuzhi',
|
type: 'success'
|
},
|
{
|
label: '终止',
|
authName: 'stop',
|
icon: 'el-icon-yrt-zhongzhiicon',
|
type: 'success'
|
},
|
{
|
label: '开启',
|
authName: 'open',
|
icon: 'el-icon-yrt-kaiqi',
|
type: 'success'
|
}
|
]
|
}
|
},
|
// 表单默认值,新建时用
|
defaultValue: {
|
type: Object,
|
required: false,
|
default: () => {
|
return {}
|
}
|
},
|
// 按钮是否可用
|
btnReadOnly: {
|
type: Object,
|
required: false,
|
default: () => {
|
return {
|
save: false,
|
auditing: false,
|
add: false,
|
delete: false,
|
stop: false,
|
open: false
|
}
|
}
|
},
|
// 关闭前钩子函数,return true可关闭对话框
|
beforeClose: {
|
type: Function,
|
required: false,
|
default: () => {
|
return true
|
}
|
},
|
// 明细字段使用插槽,值为true=所有列都使用插槽;值为数组,数组中存在的字段使用插槽
|
useDetailSlot: {
|
type: [Boolean, Array],
|
default: false
|
},
|
// 主表使用标签插槽,值为true=所有字段都使用插槽;值为数组,数组中存在的字段使用插槽
|
useLabelSlot: {
|
type: [Boolean, Array],
|
default: false
|
},
|
// 修改数据事件
|
onSaveBefore: {
|
type: Function,
|
default: () => {}
|
},
|
// 终止前事件
|
onStopBefore: {
|
type: Function,
|
default: () => {
|
return true
|
}
|
},
|
// 删除前事件
|
onDetailDeleteBefore: {
|
type: Function,
|
default: () => {
|
return true
|
}
|
},
|
// 数据处理方法
|
doDataParser: {
|
type: Function,
|
required: false,
|
default: null
|
},
|
// 审核成功后,不可编辑处理方法
|
auditDisabled: {
|
type: Function,
|
required: false,
|
default: null
|
},
|
// 控制显示字段,true=显示所有字段,Array=只显示数组内的字段
|
showFields: {
|
type: [Boolean, Array],
|
default: true
|
},
|
// 自定义查询条件
|
filteredValue: {
|
type: Array,
|
default: null
|
},
|
// 额外下拉框ID
|
dropdownIds: {
|
type: Array,
|
default: () => {
|
return []
|
}
|
},
|
// 隐藏字段
|
hideFeilds: {
|
type: Array,
|
default: () => {
|
return []
|
}
|
},
|
// 标准添加前事件
|
onAddDetailRowBefore: {
|
type: Function,
|
default: (rows, subTableView) => {
|
return true
|
}
|
}
|
},
|
data() {
|
return {
|
saveLoading: false, // 保存loading
|
initLoading: false, // 加载数据初始化loading
|
formData: {}, // 表单数据集合,明细数据集合:{subTableView:{total:10,rows:[{}], footer:[{}]}}
|
dropdownData: {}, // 下拉框数据集合
|
dropdownLoaded: false, // 下拉框已加载
|
// 模块tree prop参数配置
|
treeProps: {
|
label: 'label',
|
children: 'children',
|
value: 'value',
|
isLeaf: function(data, node) {
|
return data.hasChild !== 1
|
}
|
},
|
// TREE选择器右侧图标
|
treeSuffixIcon: 'el-icon-yrt-xiangxiajiantou1',
|
// 显示批量导入对话框参数
|
batchImport: {
|
visible: false,
|
label: '批量导入',
|
options: {
|
url: '/api/common/upload',
|
importInfo_Id: 0,
|
vueData_Id: 0,
|
fId: 0 // 主表主键值
|
}
|
},
|
// 显示批量导出对话框参数
|
batchExport: {
|
visible: false,
|
label: '批量导出',
|
options: {
|
exportInfo_Id: 0,
|
vueData_Id: 0
|
}
|
},
|
// 明细分页器禁用
|
detailPageDisabled: true,
|
// 显示字段属性对话框
|
tableAttr: {
|
showAttrDialog: false,
|
dataOptions: {},
|
fields: []
|
},
|
// 当前选中tab
|
activeTabName: null
|
}
|
},
|
computed: {
|
// 当前宽度
|
currentDialogWidth: function() {
|
if (this.dialogWidth) {
|
const width = Number.isInteger(this.dialogWidth) ? this.dialogWidth + 'px' : this.dialogWidth
|
return width
|
} else {
|
const width = Number.isInteger(this.config.width) ? this.config.width + 'px' : this.config.width
|
return width
|
}
|
},
|
// 主表字段
|
masterFields: function() {
|
if (this.fields) {
|
return this.fields.filter(item => item.type !== 'detail-grid')
|
} else {
|
return []
|
}
|
},
|
// 明细字段
|
detailFields: function() {
|
if (this.fields) {
|
var details = this.fields.filter(item => item.type === 'detail-grid')
|
|
// 初始化明细数据结构
|
details.forEach(detail => {
|
const subTableView = detail.subTableView
|
if (!this.formData[subTableView]) {
|
this.$set(this.formData, subTableView, {
|
total: 0,
|
rows: [],
|
footer: []
|
})
|
}
|
})
|
|
return details
|
} else {
|
return []
|
}
|
},
|
// 标题名称
|
currentTitle: function() {
|
if (!this.config.hiddenTitle) {
|
if (this.config.title) {
|
return this.config.title + ' - ' + (this.action === 'add' ? '新建' : '编辑')
|
} else {
|
return '编辑数据'
|
}
|
} else {
|
return ''
|
}
|
},
|
// 是否显示dialog
|
isShowDialog: {
|
get: function() {
|
return this.config.visible
|
},
|
set: function(newValue) {
|
this.$emit('update:visible', newValue) // 双向绑定prop.visible,通知父级组件变量值同步更新
|
}
|
},
|
// 当前编辑动作:add/edit
|
currentAction: {
|
get: function() {
|
return this.action
|
},
|
set: function(newValue) {
|
this.$emit('update:action', newValue) // 双向绑定prop.action,通知父级组件变量值同步更新
|
}
|
},
|
// 当前diaolog top
|
currentTop: {
|
get: function() {
|
return this.config.top
|
},
|
set: function(newValue) {
|
this.$emit('update:config.top', newValue) // 双向绑定,通知父级组件变量值同步更新
|
}
|
},
|
// 是否禁用
|
currentDisabled: {
|
get: function() {
|
return this.config.disabled || false
|
},
|
set: function(newValue) {
|
this.$emit('update:config.disabled', newValue) // 双向绑定,通知父级组件变量值同步更新
|
}
|
},
|
// 判断明细是否提供自定义插槽
|
// detailExistSlotContent: {
|
// get: function() {
|
// return !!this.$slots["detail-column-slot"];
|
// }
|
// },
|
// tab分组
|
tabGroupList: function() {
|
if (this.fields) {
|
let groupList = this.masterFields.reduce(
|
(all, next) => (all.some(item => item.tabGroupName === next.tabGroupName) ? all : [...all, next]),
|
[]
|
)
|
// 初始化明细数据结构
|
groupList = groupList.map(item => {
|
return item.tabGroupName || '[未分组]'
|
})
|
|
return groupList
|
} else {
|
return []
|
}
|
}
|
},
|
watch: {
|
formData: {
|
handler(formData) {
|
// 审核成功,将不可编辑
|
if (typeof this.auditDisabled === 'function') {
|
this.auditDisabled(formData, this.config)
|
} else {
|
if (formData.auditing === 2) {
|
this.$set(this.config, 'disabled', true)
|
} else {
|
this.$set(this.config, 'disabled', false)
|
}
|
}
|
},
|
deep: true
|
},
|
masterFields: {
|
handler(val) {},
|
deep: true
|
},
|
tabGroupList: {
|
handler(groupList) {
|
// 设置第一项默认选中项
|
if (groupList.length) {
|
this.activeTabName = groupList[0]
|
}
|
},
|
deep: true
|
}
|
},
|
methods: {
|
// 扩展按钮事件
|
onButtonAction(authNode) {
|
var result
|
if (this.editButtonClick) {
|
result = this.editButtonClick(authNode, this.formData)
|
}
|
if (result !== undefined) {
|
return
|
}
|
switch (authNode) {
|
case 'auditing':
|
// 审核
|
this.auditing()
|
break
|
case 'copy':
|
// 复制
|
this.copy()
|
break
|
case 'stop':
|
// 终止
|
this.stop()
|
break
|
case 'open':
|
// 终止
|
this.open()
|
break
|
}
|
},
|
// 明细按钮单击事件
|
onDetailButtonAction(authNode, detail, btnOpts) {
|
var result
|
if (this.detailButtonClick) {
|
result = this.detailButtonClick(authNode, detail, btnOpts)
|
}
|
if (result !== undefined) {
|
return
|
}
|
switch (authNode) {
|
case 'detailAdd':
|
// 批量添加
|
this.addDetailDataRow([{}], detail.subTableView)
|
break
|
case 'detailDelete':
|
// 批量删除
|
this.delete(detail.options.detailSelections, detail)
|
break
|
case 'detailImport':
|
// 批量导入
|
this.importDialog(btnOpts)
|
break
|
case 'detailExport':
|
// 批量导出
|
this.exportDialog(btnOpts)
|
break
|
}
|
},
|
// 获取默认值
|
getDefaultValue(fields) {
|
fields.forEach(item => {
|
if (['detail-grid'].indexOf(item.type) >= 0) {
|
return true
|
}
|
if (['grid'].indexOf(item.type) >= 0) {
|
item.columns.forEach(col => {
|
this.getDefaultValue(col.fields)
|
})
|
} else if (['inline-group'].indexOf(item.type) >= 0) {
|
this.getDefaultValue(item.fields)
|
} else {
|
if (!item.options.defaultValue && item.options.defaultValue !== 0) {
|
return
|
}
|
|
if (['byte', 'int32'].indexOf(item.options.dataType) >= 0) {
|
this.$set(this.formData, item.options.prop, parseInt(item.options.defaultValue))
|
} else if (['number', 'float'].indexOf(item.options.dataType) >= 0) {
|
this.$set(this.formData, item.options.prop, parseFloat(item.options.defaultValue))
|
} else if (['radio'].indexOf(item.type) >= 0) {
|
var v = item.options.defaultValue
|
if (item.options.dataType === 'float') {
|
v = parseFloat(item.options.defaultValue)
|
}
|
this.$set(this.formData, item.options.prop, v)
|
} else if (['date', 'datetime'].indexOf(item.options.dataType) >= 0) {
|
var defaultValue = item.options.defaultValue
|
if (defaultValue === '{currentDate}') {
|
const format = item.options.format || 'YYYY-MM-DD HH:mm:ss'
|
defaultValue = this.common.formatDate(new Date(), format)
|
}
|
this.$set(this.formData, item.options.prop, defaultValue)
|
} else {
|
defaultValue = item.options.defaultValue
|
// 当前默认用户
|
if (defaultValue === '{currentUserTrueName}') {
|
var userTrueName = this.common.getUserInfo().userTrueName
|
this.$set(this.formData, 'userTrueName', userTrueName)
|
var user_Id = this.common.getUserInfo().user_Id
|
this.$set(this.formData, 'user_Id', user_Id)
|
} else if (defaultValue === '{currentDeptName}') {
|
var deptName = this.common.getUserInfo().deptName
|
this.$set(this.formData, 'deptName', deptName)
|
var dept_Id = this.common.getUserInfo().dept_Id
|
this.$set(this.formData, 'dept_Id', dept_Id)
|
} else {
|
this.$set(this.formData, item.options.prop, item.options.defaultValue)
|
}
|
}
|
}
|
})
|
},
|
// 获得主表字段信息
|
getFieldInfo(fieldName) {
|
// 字段信息
|
var fieldInfo = null
|
var _getDropDownId = function(array) {
|
array.forEach(item => {
|
if (item.type === 'grid') {
|
item.columns.forEach(colItem => {
|
_getDropDownId(colItem.fields)
|
})
|
} else if (item.type === 'inline-group') {
|
_getDropDownId(item.fields)
|
} else if (item.type === 'detail-grid') {
|
_getDropDownId(item.fields)
|
} else {
|
if (item.options && item.options.prop === fieldName) {
|
fieldInfo = item
|
}
|
}
|
})
|
}
|
_getDropDownId(this.fields)
|
|
return fieldInfo
|
},
|
// 获得主明细字段信息
|
getDetailFieldInfo(fieldName) {
|
const _fields = this.detailFields[0].fields
|
return _fields.find(item => item.prop === fieldName)
|
},
|
// 加载下拉框数据
|
loadDropDown(refresh) {
|
if (this.dropdownLoaded && !refresh) return // 已加载下拉框不在重复加载
|
// 获得下拉框ID
|
var ddIDs = this.dropdownIds || []
|
var _getDropDownId = function(array) {
|
array.forEach(item => {
|
if (item.type === 'grid') {
|
item.columns.forEach(colItem => {
|
_getDropDownId(colItem.fields)
|
})
|
} else if (item.type === 'inline-group') {
|
_getDropDownId(item.fields)
|
} else if (item.type === 'detail-grid') {
|
_getDropDownId(item.fields)
|
} else {
|
if (item.options && item.options.dropdown_Id) {
|
ddIDs.push(item.options.dropdown_Id)
|
} else if (item.dropdown_Id) {
|
// 明细下拉框ID
|
ddIDs.push(item.dropdown_Id)
|
}
|
}
|
})
|
}
|
_getDropDownId(this.fields)
|
if (!ddIDs.length) return
|
|
this.initLoading = true
|
var url = '/api/common/loadDropDown'
|
var params = Object.assign({}, this.dataOptions, {
|
openNodeApi: true,
|
where: ddIDs.join(','),
|
data: JSON.stringify(this.formData)
|
})
|
this.common.ajax(
|
url,
|
params,
|
res => {
|
res = this.common.objectToCase(res)
|
if (res.result) {
|
this.dropdownLoaded = true // 记录已加载下拉框数据
|
Object.keys(res.data).forEach((key, index) => {
|
this.$set(this.dropdownData, key, res.data[key])
|
})
|
} else {
|
this.$message({
|
showClose: true,
|
duration: 6000,
|
message: res.msg,
|
type: 'error'
|
})
|
}
|
this.initLoading = false
|
// 下拉框加载完毕后事件
|
this.$emit('on-load-dropdown-after', this.formData)
|
},
|
true
|
)
|
},
|
// 重新加载下拉框数据
|
reLoadDropDown() {
|
this.dropdownLoaded = false
|
this.loadDropDown()
|
},
|
// 外部设置下拉框值,例如联动
|
setDropdownData(dropdown_Id, data) {
|
this.$set(this.dropdownData, 'dropdown' + dropdown_Id, data)
|
},
|
// 获得下拉框值
|
getDropdownData(dropdown_Id, data) {
|
return this.dropdownData['dropdown' + dropdown_Id]
|
},
|
// 允许外部调用新建数据
|
addData() {
|
this.isShowDialog = true
|
this.currentAction = 'add'
|
this.detailPageDisabled = true
|
var top = this.common.getDialogTop()
|
this.config.top = top
|
Object.keys(this.formData).forEach(key => {
|
if (Array.isArray(this.formData[key])) {
|
this.formData[key] = []
|
} else if (this.common.isObject(this.formData[key])) {
|
this.formData[key] = {
|
total: 0,
|
rows: [],
|
footer: []
|
}
|
} else {
|
this.formData[key] = null
|
}
|
})
|
this.loadDropDown()
|
this.getDefaultValue(this.fields)
|
// 新建设置默认值
|
Object.keys(this.defaultValue).forEach((key, index) => {
|
if (['value', 'label'].indexOf(key) < 0) {
|
this.$set(this.formData, key, this.defaultValue[key])
|
}
|
})
|
|
// 可编辑
|
this.currentDisabled = false
|
this.$nextTick(() => {
|
// 清除验证
|
this.$refs['editor-form'].clearValidate()
|
|
// 添加加载后事件
|
this.$emit('on-add-load-after', this.formData)
|
})
|
|
return this.formData
|
},
|
// 允许外部调用编辑数据
|
editData(id = 0, rowData, isInit) {
|
if (isInit) {
|
// 将明细分页码初始化为1
|
this.detailFields.forEach(item => {
|
item.options.pageIndex = 1
|
})
|
}
|
|
// 编辑加载前事件
|
this.$emit('on-edit-load-before', rowData)
|
this.isShowDialog = true
|
this.currentAction = 'edit'
|
this.detailPageDisabled = false
|
this.initLoading = true
|
var top = this.common.getDialogTop()
|
this.currentTop = top
|
|
this.getDefaultValue(this.fields)
|
this.loadDropDown()
|
this.dataOptions.idValue = id
|
|
var url = '/api/common/loadEditData'
|
var params = Object.assign({}, this.dataOptions)
|
// 明细参数处理
|
params.detailList = this.detailFields.map(item => {
|
const newItem = {
|
tableName: item.subTableView,
|
pageIndex: item.options.pageIndex,
|
pageSize: item.options.pageSize,
|
idField: item.options.idField,
|
orderBy: item.options.orderBy
|
}
|
if (item.options.showSumField) {
|
newItem.sumColumnNames = item.options.sumColumnNames
|
}
|
return newItem
|
})
|
|
this.common.ajax(
|
url,
|
params,
|
res => {
|
this.common.showMsg(res)
|
if (res.result) {
|
this.showData(res.data, params)
|
}
|
this.initLoading = false
|
},
|
false
|
)
|
},
|
// 显示数据
|
showData(dataInfo, params, showType = 'load') {
|
// 原始数据加工处理
|
if (typeof this.doDataParser === 'function') {
|
this.doDataParser(dataInfo)
|
}
|
|
if (!dataInfo) {
|
this.$message.error('没有加载到数据!')
|
this.initLoading = false
|
return
|
}
|
const tranData = this.translate(dataInfo)
|
if (showType === 'save') {
|
params.detailTableList.forEach(item => {
|
tranData[item.detailViewName] = this.formData[item.detailViewName]
|
})
|
}
|
this.formData = tranData
|
// 明细数据处理
|
this.detailFields.forEach(detail => {
|
const subTableView = detail.subTableView
|
// 新数据集合
|
const newDetailInfo = dataInfo[subTableView]
|
this.translateDetails(detail, newDetailInfo.rows)
|
if (showType === 'save') {
|
const newRows = newDetailInfo.rows
|
// 修改前数据集合
|
const oldRows = this.formData[subTableView].rows
|
oldRows.forEach((oldRow, index) => {
|
const newRow = newRows[index]
|
if (newRow) {
|
Object.keys(oldRow).forEach(key => {
|
oldRow[key] = newRow[key]
|
})
|
}
|
})
|
} else {
|
this.$set(this.formData, subTableView, newDetailInfo)
|
}
|
})
|
this.$nextTick(() => {
|
// 清除验证
|
window.setTimeout(() => {
|
this.$refs['editor-form'].clearValidate()
|
}, 50)
|
// 编辑加载后事件
|
this.$emit('on-edit-load-after', this.formData)
|
})
|
},
|
// 获得明细数据集
|
getDetailDataList(detailInfo) {
|
if (typeof detailInfo === 'string') {
|
detailInfo = {
|
subTableView: detailInfo
|
}
|
}
|
if (detailInfo.subTableView) {
|
const dataList = this.formData[detailInfo.subTableView]
|
if (dataList) {
|
return dataList.rows
|
} else {
|
return []
|
}
|
} else {
|
return []
|
}
|
},
|
// 刷新数据
|
reload() {
|
this.editData(this.dataOptions.idValue)
|
},
|
// 主表数据转换
|
translate(dataObj) {
|
// 转换函数
|
const _translate = fields => {
|
fields.forEach(field => {
|
var prop = field.options.prop
|
const v = dataObj[prop]
|
if (
|
field.type === 'cascader' ||
|
(field.type === 'select' && field.options.multiple) ||
|
(field.type === 'date' && field.options.type === 'dates')
|
) {
|
if (Array.isArray(v)) {
|
return v
|
} else if (v) {
|
dataObj[prop] = v.split('/')
|
if (['int', 'int32', 'byte', 'decimal'].indexOf(field.options.dataType) >= 0) {
|
dataObj[prop].forEach((p, index) => {
|
dataObj[prop][index] = parseInt(p)
|
})
|
}
|
// 主键ID处理为数组
|
const keyProp = field.options.keyProp
|
if (keyProp) {
|
const keyValues = dataObj[keyProp]
|
if (keyValues) {
|
if (!Array.isArray(keyValues)) {
|
dataObj[keyProp] = keyValues.split('/')
|
}
|
dataObj[keyProp].forEach((item, index) => {
|
dataObj[keyProp][index] = Number(item)
|
})
|
} else {
|
dataObj[keyProp] = []
|
}
|
}
|
} else {
|
dataObj[prop] = []
|
}
|
} else if (field.type === 'checkbox') {
|
if (Array.isArray(v)) {
|
return v
|
} else if (v) {
|
dataObj[prop] = v.split('/')
|
} else {
|
dataObj[prop] = []
|
}
|
} else if (field.dataType === 'decimal' || ['float', 'decimal'].indexOf(field.options && field.options.dataType) >= 0) {
|
let scale = 2
|
if (field.formatter) {
|
const arr = field.formatter.split('.')
|
scale = arr[1].length
|
} else if (field.options.formatter) {
|
const arr = field.options.formatter.split('.')
|
scale = arr[1].length
|
}
|
dataObj[prop] = Math.Round(v, scale) // 保留两位小数
|
} else if (field.dataType === 'date' || (field.options && field.options.dataType === 'date')) {
|
if (v) {
|
let formatter = 'yyyy-MM-dd'
|
if (field.formatter) formatter = field.formatter
|
dataObj[prop] = this.common.formatDate(v, formatter)
|
}
|
} else if (field.dataType === 'datetime' || (field.options && field.options.dataType === 'datetime')) {
|
if (v) {
|
let formatter = 'yyyy-MM-dd HH:mm:ss'
|
if (field.formatter) formatter = field.formatter
|
dataObj[prop] = this.common.formatDate(v, formatter)
|
}
|
}
|
})
|
}
|
|
// 循环转换
|
this.fields.forEach(item => {
|
if (['detail-grid'].indexOf(item.type) >= 0) {
|
return true
|
}
|
|
if (['grid'].indexOf(item.type) >= 0) {
|
item.columns.forEach(col => {
|
_translate(col.fields)
|
})
|
} else if (['inline-group'].indexOf(item.type) >= 0) {
|
_translate(item.fields)
|
}
|
})
|
_translate(this.fields)
|
|
return dataObj
|
},
|
// 明细表数据转换
|
translateDetails(detail, detailRows) {
|
for (const row of detailRows) {
|
detail.fields.forEach(field => {
|
var prop = field.prop
|
const v = row[prop]
|
if (field.dataType === 'date') {
|
if (v) {
|
let formatter = 'yyyy-MM-dd'
|
if (field.formatter) formatter = field.formatter
|
row[prop] = this.common.formatDate(v, formatter)
|
}
|
} else if (field.dataType === 'datetime') {
|
if (v) {
|
let formatter = 'yyyy-MM-dd HH:mm:ss'
|
if (field.formatter) formatter = field.formatter
|
row[prop] = this.common.formatDate(v, formatter)
|
}
|
} else if (field.dataType === 'decimal') {
|
let scale = 2
|
if (field.formatter === '%') {
|
scale = 2
|
} else if (field.formatter) {
|
const arr = field.formatter.split('.')
|
scale = arr[1].length
|
}
|
row[prop] = Math.Round(v, scale) // 保留两位小数
|
}
|
})
|
}
|
},
|
// 翻译下拉框值
|
translateText(prop, val, dropdown_Id) {
|
var ddList = this.dropdownData['dropdown' + dropdown_Id]
|
if (!ddList) return val
|
var item = ddList.find((item, index, arr) => {
|
return item.value === val
|
})
|
if (!item) return val
|
return item.label
|
},
|
|
// 修改主表字段值
|
changeValue(prop, value) {
|
this.$set(this.formData, prop, value)
|
if (this.$refs['editor-form']) {
|
this.$refs['editor-form'].validate()
|
}
|
},
|
|
// 关闭对话框
|
cancel() {
|
this.$emit('update:visible', !this.config.visible) // 双向绑定prop.visible,通知父级组件变量值同步更新
|
},
|
// 提交数据
|
_submit() {
|
this.$refs['editor-form'].validate(valid => {
|
if (valid) {
|
this.saveCheck()
|
} else {
|
this.$message.error('表单验证不通过,请正确填写表单!')
|
return false
|
}
|
})
|
},
|
// 保存数据
|
saveCheck() {
|
// 保存前事件
|
const reValue = this.onSaveBefore(this.formData)
|
if (reValue === false) return
|
this.save()
|
},
|
// 保存数据
|
save() {
|
this.setExtendFields()
|
this.saveLoading = true
|
var data = {}
|
// 数据转换
|
Object.keys(this.formData).forEach(key => {
|
var val = this.formData[key]
|
if (val === '') val = null
|
if (Array.isArray(val)) {
|
val = val.join('/')
|
data[key] = val
|
} else if (val !== null && typeof val === 'object' && val.rows) {
|
data[key] = val.rows.filter(row => {
|
return row.__ischange__
|
})
|
} else {
|
data[key] = val
|
}
|
})
|
// 明细表
|
const detailTableList = this.detailFields.map(item => {
|
const opts = item.options
|
opts.subTableView = item.subTableView
|
return opts
|
})
|
|
var url = '/api/common/saveEditData'
|
var params = Object.assign({}, this.dataOptions, {
|
data: JSON.stringify(data),
|
noDataSign: true, // 数据不参与签名
|
detailTableList: detailTableList
|
})
|
this.common.ajax(
|
url,
|
params,
|
res => {
|
this.common.showMsg(res)
|
if (res.result) {
|
if (res.data) {
|
this.showData(res.data, params, 'save')
|
var ref = this.findRef(this.dataListRef)
|
if (ref) {
|
ref.loadData()
|
}
|
// 保存后事件
|
this.$emit('on-save-after', this.formData)
|
} else {
|
this.$message.warning('保存数据返回数据失败!')
|
}
|
|
this.isShowDialog = false
|
}
|
this.saveLoading = false
|
},
|
true
|
)
|
},
|
// 删除数据
|
delete(selectedRows, detail) {
|
// 终止前事件
|
const reValue = this.onDetailDeleteBefore(selectedRows, detail)
|
if (!reValue) return
|
|
this.$confirm('此操作将永久删除选中的数据, 是否继续?', '删除操作', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
})
|
.then(() => {
|
_delete()
|
})
|
.catch(() => {
|
this.$message({
|
type: 'info',
|
message: '已取消删除'
|
})
|
})
|
|
const _delete = () => {
|
var deletedIDs = selectedRows
|
.map((item, index, Array) => {
|
return item[detail.options.idField] || '0'
|
})
|
.filter(item => {
|
return item !== '0'
|
})
|
.join(',')
|
if (!deletedIDs) {
|
// 没有任何已经保存要删除的数据
|
selectedRows.forEach((item, index, Array) => {
|
// 删除明细
|
var _detailRow = this.formData[detail.subTableView].rows
|
_detailRow.splice(_detailRow.findIndex(_row => _row === item), 1)
|
})
|
this.$message.success('数据删除成功')
|
return
|
}
|
|
var url = '/api/common/deleteData'
|
this.initLoading = true
|
var params = Object.assign({}, this.dataOptions, {
|
openNodeApi: true,
|
projectName: this.dataOptions.projectName,
|
tableName: detail.subTableView,
|
tableView: detail.subTableView,
|
deletedIDs: deletedIDs,
|
idField: detail.options.idField
|
})
|
this.common.ajax(
|
url,
|
params,
|
res => {
|
this.common.showMsg(res)
|
if (res.result) {
|
selectedRows.forEach((item, index, Array) => {
|
// 删除明细
|
var _detailRow = this.formData[detail.subTableView].rows
|
_detailRow.splice(_detailRow.findIndex(_row => _row === item), 1)
|
})
|
// 明细删除后事件
|
this.$emit('on-detail-delete-after', selectedRows, detail)
|
}
|
this.initLoading = false
|
},
|
true
|
)
|
}
|
},
|
// 添加明细数据
|
addDetailDataRow: function(rows, subTableView) {
|
// 明细添加前事件
|
if (this.onAddDetailRowBefore(rows, subTableView) === false) {
|
return
|
}
|
|
if (!Array.isArray(rows)) {
|
this.$message.error('添加明细数据必须为数组')
|
return
|
}
|
if (!subTableView && this.detailFields.length) {
|
// 默认为第一个明细表名称
|
subTableView = this.detailFields[0].subTableView
|
}
|
if (subTableView) {
|
rows.forEach(row => {
|
row.__ischange__ = true // 新增
|
row[this.dataOptions.idField] = 0 // 新增时外键ID为0
|
this.$set(this.formData[subTableView].rows, this.formData[subTableView].rows.length, row)
|
})
|
// 明细行数
|
this.formData[subTableView].total = this.formData[subTableView].rows.length
|
}
|
// 明细添加后事件
|
this.$emit('on-add-detail-row-after', rows)
|
},
|
// 明细背景颜色设置
|
detailRowStyle(row, rowIndex, detail) {
|
var style = ''
|
var idVal = row[detail.options.idField]
|
if (!idVal) {
|
style = 'background-color:#ffffdf'
|
}
|
return style
|
},
|
// 明细求和方式
|
getDetailSummaries(columns, data, detail) {
|
const sums = []
|
// 求和字段
|
var sumColumnNames = detail.fields
|
.filter(item => {
|
return item.isSum
|
})
|
.map(item => {
|
return item.prop
|
})
|
|
sums[0] = ''
|
sums[1] = ''
|
detail.fields.forEach((field, index) => {
|
var footerRows = this.formData[detail.subTableView].footer
|
if (sumColumnNames.indexOf(field.prop) >= 0 && footerRows && footerRows.length) {
|
var footerRow = footerRows[0]
|
sums[index + 2] = footerRow[field.prop]
|
} else {
|
sums[index + 2] = ''
|
}
|
})
|
|
return sums
|
},
|
|
// 字段change事件
|
onChange(ref, val, field, formData) {
|
this.$emit('on-change', ref, val, field, formData)
|
},
|
// 字段Focus事件
|
onFocus(ref, val, event, field) {
|
this.$emit('on-focus', ref, val, event, field)
|
},
|
// 字段blur事件
|
onBlur(ref, val, event, field) {
|
this.$emit('on-blur', ref, val, event, field)
|
},
|
// 明细字段change事件
|
onDetailChange(ref, val, row, field) {
|
this.$set(row, '__ischange__', true)
|
this.$emit('on-detail-change', ref, val, row, field)
|
},
|
// 选择items
|
handleSelectionChange(val, detail) {
|
detail.options.detailSelections = val
|
},
|
// 分页大小改变
|
handleSizeChange(val, detail) {
|
detail.options.pageSize = val
|
this.editData(this.dataOptions.idValue)
|
},
|
// 当前页码大小改变
|
handleCurrentChange(val, detail) {
|
detail.options.pageIndex = val
|
this.editData(this.dataOptions.idValue)
|
},
|
// 通用开启
|
open() {
|
this.$confirm('确定要进行开启操作吗, 是否继续?', '开启操作', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
})
|
|
.then(() => {
|
_open()
|
})
|
.catch(() => {
|
this.$message({
|
type: 'info',
|
message: '已取消开启'
|
})
|
})
|
|
const _open = () => {
|
var idField = this.dataOptions.idField
|
var idValue = this.formData[this.dataOptions.idField]
|
var tableName = this.dataOptions.tableView
|
var folder = this.dataOptions.folder
|
var url = '/api/common/open'
|
this.initLoading = true
|
var params = {
|
idField: idField,
|
idValues: [idValue],
|
tableName: tableName,
|
modelName: tableName,
|
folder: folder
|
}
|
this.common.ajax(
|
url,
|
params,
|
res => {
|
this.common.showMsg(res)
|
if (res.result) {
|
var ref = this.findRef(this.dataListRef)
|
ref.loadData()
|
this.isShowDialog = false
|
}
|
this.initLoading = false
|
},
|
true
|
)
|
}
|
},
|
// 通用终止
|
stop() {
|
// 终止前事件
|
const reValue = this.onStopBefore([this.formData])
|
if (reValue === false) return
|
|
this.$confirm('确定要进行终止操作吗, 是否继续?', '终止操作', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
})
|
.then(() => {
|
_stop()
|
})
|
.catch(() => {
|
this.$message({
|
type: 'info',
|
message: '已取消终止'
|
})
|
})
|
|
const _stop = () => {
|
var idField = this.dataOptions.idField
|
var idValue = this.formData[this.dataOptions.idField]
|
var tableName = this.dataOptions.tableView
|
var folder = this.dataOptions.folder
|
var url = '/api/common/stop'
|
this.initLoading = true
|
var params = {
|
idField: idField,
|
idValues: [idValue],
|
tableName: tableName,
|
modelName: tableName,
|
folder: folder
|
}
|
this.common.ajax(
|
url,
|
params,
|
res => {
|
this.common.showMsg(res)
|
if (res.result) {
|
var ref = this.findRef(this.dataListRef)
|
ref.loadData()
|
this.isShowDialog = false
|
}
|
this.initLoading = false
|
},
|
true
|
)
|
}
|
},
|
// 通用审核
|
auditing() {
|
if (this.formData.auditing === 2) {
|
this.$message.error('已审核的单子不允许重复审核')
|
return
|
}
|
this.$confirm('审核后将无法进行修改, 是否继续?', '审核操作', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
})
|
.then(() => {
|
_auditing()
|
})
|
.catch(() => {
|
this.$message({
|
type: 'info',
|
message: '取消审核'
|
})
|
})
|
|
const _auditing = () => {
|
var DBServer = 'Sys'
|
var url = '/api/common/batchAuditing'
|
this.initLoading = true
|
var idValue = this.formData[this.dataOptions.idField]
|
var params = Object.assign({}, this.dataOptions, {
|
DBServer: DBServer,
|
idValues: [idValue],
|
auditing: 2
|
})
|
this.common.ajax(
|
url,
|
params,
|
res => {
|
this.common.showMsg(res)
|
if (res.result) {
|
var ref = this.findRef(this.dataListRef)
|
ref.loadData()
|
this.isShowDialog = false
|
}
|
this.initLoading = false
|
},
|
true
|
)
|
}
|
},
|
// 复制
|
copy() {
|
this.$confirm('确定要复制此单据吗?', '复制操作', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
})
|
.then(() => {
|
_copy()
|
})
|
.catch(() => {
|
this.$message({
|
type: 'info',
|
message: '取消复制'
|
})
|
})
|
|
const _copy = () => {
|
var idField = this.dataOptions.idField
|
var idValue = this.formData[this.dataOptions.idField]
|
var where = {}
|
where[idField] = idValue
|
var url = '/api/common/copy'
|
this.initLoading = true
|
// 明细表
|
const detailTableList = this.detailFields.map(item => {
|
const opts = item.options
|
opts.subTableView = item.subTableView
|
return opts
|
})
|
var params = Object.assign({}, this.dataOptions, {
|
idValue: idValue,
|
where: where,
|
detailTableList: detailTableList
|
})
|
|
this.common.ajax(
|
url,
|
params,
|
res => {
|
this.common.showMsg(res)
|
if (res.result) {
|
var ref = this.findRef(this.dataListRef)
|
ref.loadData()
|
this.$emit('on-copy-after', idValue)
|
this.config.visible = false
|
}
|
this.initLoading = false
|
},
|
true
|
)
|
}
|
},
|
// 编辑窗体关闭前事件
|
onBeforeClose(done) {
|
// 将明细分页码初始化为1
|
this.detailFields.forEach(item => {
|
item.options.pageIndex = 1
|
})
|
const reVal = this.beforeClose()
|
if (reVal) {
|
done()
|
}
|
},
|
// 批量导入对话框
|
importDialog(btnOpts) {
|
this.batchImport.visible = true
|
this.batchImport.label = btnOpts.label
|
this.batchImport.options = btnOpts.options
|
this.batchImport.options.fId = this.dataOptions.idValue // 外键ID
|
},
|
// 批量导出对话框
|
exportDialog(btnOpts) {
|
this.batchExport.visible = true
|
this.batchExport.label = btnOpts.label
|
this.batchExport.options = btnOpts.options
|
// 初始化模板
|
this.$nextTick(() => {
|
this.$refs['export-dialog'].getTemplateList()
|
})
|
},
|
// 批量导入
|
importData(exportInfo_Id, vueData_Id) {
|
// 刷新数据
|
this.editData(this.dataOptions.idValue)
|
},
|
// 批量导出
|
exportData(exportInfo_Id, vueData_Id) {
|
var where = this.dataOptions.idField + '=' + this.dataOptions.idValue
|
var url = '/api/common/ExportDataVue'
|
var detailInfo = this.detailFields[0]
|
var tableName = detailInfo.subTableView
|
var masterTableName = this.dataOptions.tableName || this.dataOptions.tableView
|
|
var params = {
|
projectName: this.dataOptions.projectName,
|
masterTableName: masterTableName,
|
masterIdField: this.dataOptions.idField,
|
tableName: tableName,
|
tableView: tableName,
|
idField: detailInfo.options.idField,
|
where: where,
|
sortName: detailInfo.options.idField,
|
exportInfo_Id: exportInfo_Id,
|
vueData_Id: vueData_Id,
|
isDetail: true // 标注为表名导出
|
}
|
this.initLoading = true
|
var callback = res => {
|
this.common.showMsg(res)
|
if (res.result) {
|
window.open(this.common.domain + res.data)
|
}
|
this.initLoading = false
|
}
|
this.common.ajax(url, params, callback, true)
|
},
|
// 明细单元格单击事件
|
onDetailCellClick(detail, row, col, cell, event) {
|
this.$set(detail, 'currentRow', row)
|
this.$emit('on-detail-cell-click', detail, row, col, cell, event)
|
},
|
// 明细当前行改变
|
onDetailCurrentChange(detail, currentRow, oldCurrentRow) {
|
this.$set(detail, 'currentRow', currentRow)
|
},
|
// 获得焦点
|
onKeyup(ref, val, event, field, tableData) {
|
this.$emit('on-key-up', ref, val, event, field, tableData)
|
},
|
// 获得焦点
|
onRowChange(ref, selectedRow, field) {
|
this.$emit('on-row-change', ref, selectedRow, field)
|
},
|
// 下拉框项单击事件
|
onItemClick(ref, val, itemData, field, formData) {
|
this.$emit('on-item-click', ref, val, itemData, field, formData)
|
},
|
// 下拉框项单击事件
|
editorContainerClick() {
|
this.detailFields.forEach(detail => {
|
this.$set(detail, 'currentRow', null)
|
this.$refs['detail-table-' + detail.subTableView][0].setCurrentRow(null)
|
})
|
},
|
// 明细标题点击事件
|
detailHeaderClick(column, event, detail) {
|
if (event.target.innerText === '#') {
|
this.tableAttr.showAttrDialog = true
|
this.tableAttr.dataOptions = {
|
tableView: detail.subTableView,
|
idField: detail.options.idField,
|
router: this.dataOptions.router,
|
menu_Id: this.dataOptions.menu_Id,
|
linkColumn: null,
|
sortName: detail.options.orderBy
|
}
|
this.tableAttr.fields = detail.fields.map(item => {
|
if (!item.width) {
|
item.width = 'auto'
|
}
|
return item
|
})
|
}
|
},
|
// 窗口打开时
|
opened() {
|
if (Array.isArray(this.$refs.editorInput)) {
|
this.$refs.editorInput.forEach(input => {
|
input.init()
|
})
|
}
|
},
|
// 获得分组fields
|
getGroupFields(tabGroupName) {
|
const fields = this.masterFields.filter(item => {
|
if (tabGroupName === '[未分组]') {
|
return !item.tabGroupName
|
} else {
|
return item.tabGroupName === tabGroupName
|
}
|
})
|
|
return fields
|
},
|
// 设置扩展字段数据值
|
setExtendFields() {
|
// 获得扩展字段
|
var getExpandField = function(expandFields, fields, dataInfo) {
|
fields.forEach(item => {
|
if (item.type === 'grid') {
|
item.columns.forEach(colItem => {
|
getExpandField(expandFields, colItem.fields, dataInfo)
|
})
|
} else if (item.type === 'inline-group') {
|
getExpandField(expandFields, item.fields, dataInfo)
|
// } else if (item.type === "detail-grid") {
|
// getExpandField(item.fields);
|
} else {
|
if (item.options && item.options.isExpandField) {
|
expandFields[item.options.prop] = dataInfo[item.options.prop]
|
} else if (item.isExpandField) {
|
// 明细下拉框ID
|
expandFields[item.prop] = dataInfo[item.prop]
|
}
|
}
|
})
|
}
|
|
// 主表字段
|
var expandFields = {}
|
getExpandField(expandFields, this.fields, this.formData)
|
if (!this.common.isEmptyObject(expandFields)) {
|
this.formData.expandFields = JSON.stringify(expandFields)
|
} else {
|
this.formData.expandFields = null
|
}
|
|
// 明细表字段
|
if (this.detailFields.length) {
|
for (const detailInfo of this.detailFields) {
|
const detailRows = this.getDetailDataList(detailInfo)
|
for (const row of detailRows) {
|
const expandFields = {}
|
getExpandField(expandFields, detailInfo.fields, row)
|
if (!this.common.isEmptyObject(expandFields)) {
|
row.expandFields = JSON.stringify(expandFields)
|
} else {
|
row.expandFields = null
|
}
|
}
|
}
|
}
|
},
|
// 表单验证
|
validate() {
|
if (this.$refs['editor-form']) {
|
this.$refs['editor-form'].validate()
|
}
|
},
|
// 树形下拉框获得点击项
|
onTreeNodeClick(data, node, el, labels, values, field) {
|
var the = this
|
// 仅选择叶节点
|
if (!node.isLeaf && field.options.onlySelectLeaf) return
|
|
var key = field.options.prop
|
// 将下拉框中的值赋给表单
|
if (Object.keys(data).findIndex(item => item === key) >= 0) {
|
Object.keys(data).forEach((key, index) => {
|
if (['value', 'label', 'hasChild', 'hasFactChild', 'state', 'attributes'].indexOf(key) < 0) {
|
the.$set(the.formData, key, data[key])
|
}
|
})
|
} else {
|
the.$set(the.formData, key, data[key])
|
}
|
this.$emit('on-tree-node-click', data, node, el, labels, values, field)
|
}
|
}
|
}
|
</script>
|
|
<style rel="stylesheet/scss" lang="scss" scoped>
|
.editor-container {
|
.splitter-title {
|
background-color: #f2f6fc;
|
padding: 0px 10px;
|
margin-bottom: 10px;
|
border-bottom: #dcdfe6 2px double;
|
position: relative;
|
.title {
|
padding: 10px 3px;
|
border-bottom: #036fba 3px solid;
|
font-size: 16px;
|
display: inline-block;
|
position: relative;
|
bottom: -2px;
|
}
|
}
|
|
.editor-detail {
|
border-top: 1px solid #ebeef5;
|
.detail-tool {
|
margin-bottom: 0px;
|
padding: 10px 0;
|
.el-button--mini {
|
padding: 7px 7px;
|
}
|
.tool-group + .tool-group {
|
margin-left: 10px;
|
}
|
.el-button--medium {
|
padding: 10px 10px;
|
}
|
}
|
+ .editor-detail {
|
margin-top: 20px;
|
}
|
}
|
|
/deep/ .el-input__inner {
|
padding: 0 5px;
|
}
|
|
/deep/ .el-input-number.is-controls-right .el-input__inner {
|
padding-left: 5px;
|
padding-right: 40px;
|
}
|
|
/deep/ .el-input--prefix .el-input__inner {
|
padding: 0 5px 0 25px;
|
}
|
/deep/ td {
|
padding: 3px 0;
|
}
|
|
/deep/ .col-container {
|
.el-input--suffix .el-input__inner {
|
padding: 0 5px;
|
}
|
/deep/ .el-input--prefix .el-input__inner {
|
padding: 0 5px 0 25px;
|
}
|
.cell {
|
padding-left: 5px;
|
padding-right: 5px;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
}
|
.el-input-number.is-controls-right .el-input__inner {
|
padding-left: 5px;
|
padding-right: 30px;
|
}
|
}
|
|
/deep/ .el-input__prefix {
|
left: 0;
|
}
|
|
/deep/ .el-input__suffix {
|
right: 0;
|
}
|
|
.footer {
|
text-align: center;
|
padding: 30px 0 0;
|
a.create {
|
display: block;
|
color: #036fba;
|
text-decoration: underline;
|
padding: 20px;
|
}
|
.el-button {
|
padding: 15px 50px;
|
font-size: 20px;
|
background-color: #036fba;
|
}
|
}
|
}
|
</style>
|
|
<style rel="stylesheet/scss" lang="scss">
|
.editor-dialog {
|
.el-dialog__body {
|
padding: 10px 20px 10px 10px;
|
}
|
.pagination-container {
|
margin-top: 10px;
|
}
|
}
|
</style>
|