<template> <div class="bus-table-com"> <split-pane v-if="basicConfig && basicConfig.treeKeyName && basicConfig.treeModelName" :min-percent="18" :default-percent="22" split="vertical" class="detail-pane" > <template slot="paneL"> <div class="left-box"> <dee-static-cmp :cmp-options="{value:basicConfig ? basicConfig.treeKeyName : '', typeName: basicConfig ? basicConfig.treeModelName : ''}" @nodeClick="nodeClick" @handerTreeFun="handerTreeFun" /> </div> </template> <template slot="paneR"> <div class="right-box"> <div v-if="basicConfig && basicConfig.searchLayoutType" ref="searchBox"> <dee-static-cmp :cmp-options="{value:basicConfig ? basicConfig.searchLayoutType : '', typeName:typeName}" @searchEvent="searchEvent" /> </div> <div :style="{height: tableHeight}" class="dee-table-cmt" :class="[tableConfig.header&&tableConfig.header.toolList&&tableConfig.header.toolList.length?'':'only-settings-bar']"> <dee-table ref="deeTable" style="height:100%" :caculate-hight="tableHeight" :data="cacheTableData | capitalize(filterWorld, tableColumns)" :columns="tableColumns" :index-row="indexRow" v-bind="tableDefs" :pagination="pageDefs" :edit-table="true" :parent-object="cmpOptions && cmpOptions.parentObject" :options="tableOptions" :more-check="basicConfig ? basicConfig.moreCheck || showSelectRow : showSelectRow || false" @selection-change="selectionChange" @row-click="handleRowClick" @pageChange="pageChange" @clickRowFun="clickRowFun" @scrollToBottom="(e)=>{$emit('scrollToBottom',e)}" > <template slot="header"> <dee-tools v-if="tableConfig.header&&tableConfig.header.toolList&&tableConfig.header.toolList.length" ref="deeTools" :permissions="permissions" :tools="tableConfig.header&&tableConfig.header.toolList |btnfilterFn(btnsFilter, $utils.filterBlackAndWhite)" mode="normal" :perm-enable="!!permissions" :collapse="false" :params="paramsObj.selection" @handerToolFun="handerToolFun" v-on="toolEvent" @tb-add="addApprovalObjectList" @tb-remove="removeApprovalObjectList" /> <div v-if="showConfig" class="table-config-bar"> <el-input v-model="filterWorld" size="mini" clearable placeholder="请输入查询" > <i slot="prefix" class="el-input__icon el-icon-search" /> </el-input> <i v-show="modelName" class="icon-btn el-icon-setting" title="显示列配置" @click="dialogVisibleTable = true" /> <i v-show="tableConfig&&tableConfig.tableColumns" class="icon-btn el-icon-s-unfold" title="导出" @click="export_excel" /> </div> </template> </dee-table> <dee-dialog v-if="dialogVisibleTable" width="700px" :title="'设置列表显示字段'" :dialog-visible="dialogVisibleTable" @handleClose="dialogVisibleTable=false"> <div class="column-config-box"> <div class="left"> <div class="title"> <el-checkbox v-model="isCheckAll" @change="onCheckAll">全选</el-checkbox> </div> <div style="padding:0 10px;">> <el-checkbox-group v-model="checkList" @change="changeVisibleColumn"> <el-checkbox v-for="item in tableColumnsCopy" :key="item.key" v-model="item.defaultItem" :label="item.key" :disabled="item.fixedItem">{{ item.title }}</el-checkbox> </el-checkbox-group> </div> </div> <div class="right"> <div class="title"> 当前选定字段及排序 </div> <draggable class="vacant-draggable-area" :list="showTableColumnsCopy" style="width: 90%;padding-left: 5%" group="block" > <el-tag v-for="(tag, index) in showTableColumnsCopy" :key="tag.key" :closable="!tag.fixedItem" type="info" size="small" @close="removeVisibleColumn(index)" > {{ parseInt(index+1) +'.' + tag.title }} </el-tag> </draggable> </div> </div> <div slot="footer" class="dialogBtn"> <el-button type="primary" size="small" @click="saveConfig(false)">保存</el-button> <el-button size="small" @click="dialogVisibleTable=false">取消</el-button> </div> </dee-dialog> <component :is="componentName" v-if="showDialog" :width="width" title="dialogTitle" :model-name="serachModel" :version-control="versionControl" :show-dialog="showDialog" @close="()=>{showDialog = false}" @selection="selection" /> </div> </div> </template> </split-pane> <div v-else style="height:100%"> <div v-if="basicConfig && basicConfig.searchLayoutType" ref="searchBox"> <dee-static-cmp :cmp-options="{value:basicConfig ? basicConfig.searchLayoutType : '', typeName:typeName}" @searchEvent="searchEvent" /> </div> <div :style="{height: tableHeight}" class="dee-table-cmt" :class="[tableConfig.header&&tableConfig.header.toolList&&tableConfig.header.toolList.length?'':'only-settings-bar']"> <dee-table ref="deeTable" style="height:100%" :caculate-hight="tableHeight" :data="cacheTableData | capitalize(filterWorld, tableColumns)" :columns="tableColumns" :index-row="indexRow" v-bind="tableDefs" :pagination="pageDefs" :parent-object="cmpOptions && cmpOptions.parentObject" :options="tableOptions" :more-check="basicConfig ? basicConfig.moreCheck || showSelectRow : showSelectRow || false" @selection-change="selectionChange" @row-click="handleRowClick" @pageChange="pageChange" @clickRowFun="clickRowFun" @scrollToBottom="(e)=>{$emit('scrollToBottom',e)}" > <template slot="header"> <dee-tools v-if="tableConfig.header&&tableConfig.header.toolList&&tableConfig.header.toolList.length" ref="deeTools" :permissions="permissions" :tools="tableConfig.header&&tableConfig.header.toolList |btnfilterFn(btnsFilter, $utils.filterBlackAndWhite)" mode="normal" :perm-enable="!!permissions" :collapse="false" :params="paramsObj.selection" :hide-tool-keys="hideToolKeys" @handerToolFun="handerToolFun" v-on="toolEvent" @tb-add="addApprovalObjectList" @tb-remove="removeApprovalObjectList" /> <div v-if="showConfig" class="table-config-bar"> <el-input v-model="filterWorld" size="mini" clearable placeholder="请输入查询" > <i slot="prefix" class="el-input__icon el-icon-search" /> </el-input> <i v-show="modelName" class="icon-btn el-icon-setting" title="显示列配置" @click="dialogVisibleTable = true" /> <i v-show="tableConfig&&tableConfig.tableColumns" class="icon-btn el-icon-s-unfold" title="导出" @click="export_excel" /> </div> </template> </dee-table> <dee-dialog v-if="dialogVisibleTable" width="700px" :title="'设置列表显示字段'" :dialog-visible="dialogVisibleTable" @handleClose="dialogVisibleTable=false"> <div class="column-config-box"> <div class="left"> <div class="title"> <el-checkbox v-model="isCheckAll" @change="onCheckAll">全选</el-checkbox> </div> <div style="padding:0 10px;"> <el-checkbox-group v-model="checkList" @change="changeVisibleColumn"> <el-checkbox v-for="item in tableColumnsCopy" :key="item.key" v-model="item.defaultItem" :label="item.key" :disabled="item.fixedItem">{{ item.title }}</el-checkbox> </el-checkbox-group> </div> </div> <div class="right"> <div class="title"> 当前选定字段及排序 </div> <draggable class="vacant-draggable-area" :list="showTableColumnsCopy" style="width: 90%;padding-left: 5%" group="block" > <el-tag v-for="(tag, index) in showTableColumnsCopy" :key="tag.key" :closable="!tag.fixedItem" type="info" size="small" @close="removeVisibleColumn(index)" > {{ parseInt(index+1) +'.' + tag.title }} </el-tag> </draggable> </div> </div> <div slot="footer" class="dialogBtn"> <el-button type="primary" size="small" @click="saveConfig(false)">保存</el-button> <el-button size="small" @click="dialogVisibleTable=false">取消</el-button> </div> </dee-dialog> <component :is="componentName" v-if="showDialog" :width="width" title="dialogTitle" :model-name="serachModel" :version-control="versionControl" :show-dialog="showDialog" @close="()=>{showDialog = false}" @selection="selection" /> </div> </div> </div> </template> <script> import allComps from '@/customCompontents/index' import columnsConfig from './columnsConfig' import elementResizeDetectorMaker from 'element-resize-detector' import { post } from '@/utils/http' export default { name: 'DeeTableCmt', filters: { btnfilterFn: (list, filters, filterBlackAndWhite) => { return filterBlackAndWhite(list, 'key', filters) } }, mixins: [ columnsConfig ], props: { hideToolKeys: { type: Array, default: () => [] }, typeName: { type: String, default: () => 'client' }, basicData: { type: Object, default: () => null }, cmpOptions: { type: Object, default: () => null }, toolEvent: { type: Object, default: () => { return {} } }, tableData: { type: Array, default: () => [] }, toolbarListeners: { type: Object, default: () => {} }, tableOptions: { type: Object, default: () => {} }, basicConfig: { type: Object, default: () => {} }, tableConfig: { type: Object, default: () => {} }, indexRow: { type: Object, default: () => { return { title: '序号', width: '80', align: 'center' } } }, showSelectRow: { type: Boolean, default: () => false }, showConfig: { type: Boolean, default: () => true }, tableDefs: { type: Object, default: () => { return { } } }, isPreview: { type: Boolean, defaut: () => false }, pageDefs: { type: Object, default: () => null }, permissions: { type: [Array, Object], default: () => null }, tableFilter: { type: [Array, Object], default: () => null }, paginationType: { type: String, default: () => 'client' }, btnsFilter: { type: String, default: () => '' } }, data() { return { keyWord: '', tableHeight: '100%', searchItems: [], serachModel: '', versionControl: false, width: '50%', componentName: '', showDialog: false, linkName: '', dialogTitle: '添加审批对象', selectedData: [], selectionRows: [], paramsObj: { selection: [] } } }, computed: { cacheTableData() { if (!this.tableData || !Array.isArray(this.tableData)) { return [] } if (this.paginationType === 'client' && this.pageDefs) { const start = (this.pageDefs.currentPage - 1) * this.pageDefs.pageSize const end = start + this.pageDefs.pageSize return this.tableData.slice(start, end) } return this.tableData }, tableColumns() { const middleEditRows = [] if (this.tableConfig.rowBtns && this.tableConfig.rowBtns.length) { this.tableConfig.rowBtns.forEach((el) => { middleEditRows.push({ operation: el.name, icon: el.icon, ...el, btnvalue: el.key, showFun: (row) => { // 配置权限 if (row.permissions) { if (typeof row.permissions[0] === 'string') { const perm = row.permissions.find(r => r.includes(el.key)) if (!perm) { return false } } else { const perm = row.permissions.find(r => r.keyName.includes(el.key)) if (perm) { if (!perm.hadPage) { return false } } } } // 已有判断 if (el.showFun) { let fun = null try { // eslint-disable-next-line no-eval fun = eval(`(${el.showFun})`) } catch { fun = null } if (fun && fun(row)) { return true } return false } // // 默认显示 return true }, handleClick: (row, index) => { this.$emit('tableRowBtnClick', { row, index, btnvalue: el.btnValue, bo: el }) } }) }) } const middlColums = [] this.showTableColumns.forEach(col => { let _col = {} _col = Object.assign({}, { ...col }) if (col.component) { _col.component = Object.assign({}, { ...col.component, show: true }) } middlColums.push(_col) }) middlColums.forEach(col => { if (col.component && col.component.render) { try { // eslint-disable-next-line no-eval const fun = eval(`(${col.component.render})`) col.component.render = fun.bind(this) } catch (error) { console.log(error) } } else if (col.formatterKey === 'render' && col.component && col.component.formatter) { try { // eslint-disable-next-line no-eval const fun = eval(`(${col.component.render})`) col.component.render = fun.bind(this) } catch (error) { console.log(error) } } else if (col.formatterKey === 'formatter' && col.component && col.component.formatter) { try { // eslint-disable-next-line no-eval const fun = eval(`(${col.component.formatter})`) this.$set(col, 'formatter', fun.bind(this)) } catch (error) { console.log(error) } } else if (col.formatter) { try { // eslint-disable-next-line no-eval const fun = eval(` (${col.formatter})`) this.$set(col, 'formatter', fun.bind(this)) } catch (error) { console.log(error) } } else if (col.component && col.component.name) { try { const cmp = allComps[col.component.name] if (cmp) { this.$set(col.component, 'name', cmp) } else { this.$set(col.component, 'name', col.component.name) } if (col.component.props) { // const prop = eval(` (${col.component.props})`) const prop = this.resolveRegexpJSON(col.component.props) if (prop) { this.$set(col.component, 'props', prop) } } } catch (error) { console.log(error) } } }) const bsaeWidth = this.basicConfig && this.basicConfig.tableType === 'treeTable' ? 80 : 20 if (middleEditRows.length > 0) { if (this.basicConfig && this.basicConfig.tableType === 'treeTable') { middlColums.splice(1, 0, { title: '操作', 'width': bsaeWidth + 25 * (middleEditRows.length + 1), key: 'id', component: { show: true, name: 'EditTableRow', props: { btns: middleEditRows } } }) } else { middlColums.splice(0, 0, { title: '操作', 'width': bsaeWidth + 25 * (middleEditRows.length + 1), key: 'id', component: { show: true, name: 'EditTableRow', props: { btns: middleEditRows } } }) } return middlColums.map(col => { if (this.tableOptions && this.tableOptions.align) { col.align = this.tableOptions.align } if (this.tableOptions && this.tableOptions['header-align']) { col['header-align'] = this.tableOptions['header-align'] } return col }) } else { return middlColums.map(col => { if (this.tableOptions && this.tableOptions.align) { col.align = this.tableOptions.align } if (this.tableOptions && this.tableOptions['header-align']) { col['header-align'] = this.tableOptions['header-align'] } return col }) } } }, watch: { basicData: { immediate: true, deep: true, handler: function(val) { if (val && val.id) { this.initDataFun() } } } }, // 生命周期 - 创建完成(访问当前this实例) created() { if (this.isPreview) { this.tableData.push({ show: true }) } if (this.basicConfig && this.basicConfig.isInitLoadData) { this.$emit('refreshGetData', { data: { items: [] }}) } }, // 生命周期 - 挂载完成(访问DOM元素) mounted() { if (this.$refs.searchBox) { this.watchSize() } }, methods: { resolveRegexpJSON(props) { let prop = props || '' let error try { // eslint-disable-next-line no-eval prop = eval(` (${prop})`) } catch (e) { error = e } if (error) { try { error = null prop = prop.replaceAll(/''/g, '"') // eslint-disable-next-line no-eval prop = eval(` (${prop})`) } catch (e) { error = e } } if (error) { console.log(error) } return prop }, watchSize() { const _this = this var erd = elementResizeDetectorMaker() erd.listenTo(this.$refs.searchBox, (element) => { // 这里的this.$refs.fan指定要监听的元素对象,对应的是<div ref="fan"></div> _this.$nextTick(() => { // 这里填写监听改变后的操作 _this.tableHeight = `calc(100% - ${element.offsetHeight}px)` }) }) }, searchEvent(items) { this.searchItems = [] this.keyWord = '' if (items) { for (const a in items) { if (a === 'keyWord') { this.keyWord = items[a] } else if (items[a].value !== '' && items[a].value !== null && items[a].value !== undefined) { this.searchItems.push(items[a]) } } } if (this.pageDefs) { this.pageDefs.currentPage = 1 } this.$emit('refreshGetData', { data: { items: this.searchItems }, keyWord: this.keyWord }) }, nodeClick(data, treeData) { this.$emit('nodeClick', data, treeData) }, handerTreeFun(item, data, node) { this.$emit('handerTreeFun', item, data, node) }, clickRowFun(scope, item) { this.$emit('clickRowFun', { row: scope.row, item, pageConfig: this.basicConfig }) }, addApprovalObjectList({ rows, bo }) { if (this.basicConfig.tableType === 'approvalObj') { this.serachModel = bo.serachModel this.versionControl = bo.serachModelVersionControl this.dialogTitle = '添加审批对象' this.componentName = 'deeAddModelCaseDialog' this.showDialog = true } }, removeApprovalObjectList({ rows, bo }) { if (this.basicConfig.tableType === 'approvalObj') { this.$utils.showConfirm( `你是否确定删除选中的数据`, '提示', 'warning', '确定', '取消', () => { const deleteParams = { 'id': this.basicData.id, 'operator': 'NO_CHANGE' } const deleteArray = [] rows.forEach(el => { deleteArray.push({ 'operator': 'REMOVE', 'id': el.id }) }) deleteParams[this.basicConfig.approvalObjName] = deleteArray post(`/${this.$utils.getModelName4dxClassName(this.basicData.dxClassname)}/recursion`, deleteParams).then(res => { this.$message.success('删除成功') this.initDataFun() }) } ) } }, selection(rows) { this.showDialog = false const params = { id: this.basicData.id, operator: 'NO_CHANGE' } params[this.basicConfig.approvalObjName] = [] rows.forEach(el => { params[this.basicConfig.approvalObjName].push( { 'operator': 'ADD', target: el } ) }) post(`/${this.$utils.getModelName4dxClassName(this.basicData.dxClassname)}/recursion`, params).then(res => { this.showDialog = false this.$message.success('添加成功') this.initDataFun() }) }, formatterPropsFun(openProp) { if (openProp) { const openPropArr = [] let monmentText = '' let bracesNumber = 0 const textArr = openProp.split('') for (let index = 0; index < textArr.length; index++) { const element = textArr[index] if (element === '(') { ++bracesNumber } if (element === ')') { --bracesNumber } if ((element === ',' || index === textArr.length - 1) && bracesNumber === 0) { if (index === textArr.length - 1 && element !== ',') { monmentText += element } openPropArr.push(monmentText) monmentText = '' } else { monmentText += element } } const resultArr = [] openPropArr.forEach(el => { var regex = /\((.+?)\)/ var a = regex.test(el) if (a) { const openProps = this.formatterPropsFun(el.slice(el.indexOf('(') + 1, -1)) resultArr.push({ 'name': el.replace(/\((.+?)\)/, ''), 'pageFrom': 1, 'pageSize': 1000, openProps }) } else { resultArr.push({ 'name': el, 'pageFrom': 1, 'pageSize': 1000 }) } }) return resultArr } else { return [] } }, initDataFun() { this.editObjName = this.basicConfig.approvalObjName if (this.basicConfig.tableType === 'approvalObj') { if (this.basicConfig.approvalObjShowType === 'business') { this.$set(this.tableData, 0, this.basicData) } else { const params = { openProps: this.basicConfig.openProp ? this.formatterPropsFun(this.basicConfig.openProp) : {}, 'pageFrom': 1, 'pageSize': 1000, 'searchItems': { 'items': [{ 'fieldName': 'id', 'operator': 'EQ', 'value': this.basicData.id }], 'operator': 'AND', 'children': [] } } post(`/${this.$utils.getModelName4dxClassName(this.basicData.dxClassname)}/find/recursion`, params).then(res => { if (res.items.content[0]) { res.items.content[0][this.basicConfig.approvalObjName].forEach((el) => ( this.tableData.push(el) )) } }).catch(response => { }) } } }, tableFilterFun(data, filter) { if (!filter || filter.length === 0) { return data } return data }, handerToolFun(btnValue, bo) { if (bo && bo.toPathRoute) { let pageUrl = bo.toPathRoute if (this.selectedData) { pageUrl = this.$utils.attachTemplateDoubleToDataParamsArray(bo.toPathRoute, this.selectedData) } this.$router.push({ path: pageUrl, query: { fromPage: this.$route.path }}) } if (btnValue === 'defaultRemove') { if (this.selectedData.length === 0) { return } this.$confirm('是否确定删除选中的对象?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { const ids = this.selectedData.map(el => { return el.id }) this.$api.batchDelete(this.modelName, ids).then(res => { this.$utils.showMessageSuccess('删除成功!') this.$emit('freshRewriting', { data: { items: this.searchItems }}) }) }).catch(() => { this.$message.info('已取消删除') }) } this.$emit('tableToolHandler', { key: { btnValue }, el: this }) }, tableRowBtnClick(val) { this.$emit('tableRowBtnClick', { ...val, el: this }) }, selectionChange(val) { this.selectedData = val this.$refs.deeTools && this.$refs.deeTools.setSelectRow(val) this.$emit('selectionChange', val) }, pageChange() { this.$emit('pageChange', this.pageDefs) if (this.paginationType === 'server') { this.$emit('refresh', this.pageDefs) this.$emit('freshRewriting', this.pageDefs) return } }, handleRowClick(row) { this.$emit('rowClick', row, this.basicConfig) }, getTableData() { this.$emit('refresh') } } } </script> <style lang="scss"> /* @import url(); 引入css类 */ .bus-table-com{ height: 100%; .right-box { height: 100%; padding: 10px; border: 1px solid #d9d9d9; box-sizing: border-box; background-color: #fff; } } .dee-table-cmt{ .dee-table-header{ height: 24px; position: relative; display:flex; justify-content: space-between; } &.only-settings-bar .dee-table-header{ justify-content: flex-end; } .table-config-bar{ display: flex; align-items: center; .icon-btn { font-size:18px; margin-left: 6px; cursor: pointer; color:#2f90e2; } } .column-config-box{ display: flex; height: 400px; .title { font-size:14px; padding: 0 10px 4px; margin-bottom: 10px; height:20px; border-bottom: 1px solid #d8d8d8; } .left{ width: 440px; height: 100%; box-sizing: border-box; border-right: 1px solid #d8d8d8; .el-checkbox{ margin-bottom: 10px; } } .right{ width: 200px; height: 100%; box-sizing: border-box; .el-tag{ display: block; margin-bottom: 10px; .el-icon-close{ float:right; right:6px; top:6px; } } } } } </style>