<template> <div :id="elId" class="_hs_table" style="width:100%;height:100%"> <span class='toolsBox' v-show="configData.isShowTools"> <el-popover placement="top-start" width="200" trigger="hover" > <template v-for="(item,index) in tool_list"> <div class="closeAllItem" v-if="showItem(item)" :key="index"> <el-button type="text" :disabled="disabledItem(item)" size="mini" @click="itemClickAction(item)"> {{item.label}} </el-button> </div> </template> <el-button size="mini" type="primary" slot="reference" icon='el-icon-menu' circle></el-button> </el-popover> </span> <el-table v-if="isPicture==='0'" ref='hsTable' style="width:100%;overflow: auto;" :data="this.tableData" :style="tableStyle" :fit='true' :highlight-current-row=true :show-summary='showSummary' :header-row-style="setHeaderRowStyle" :header-cell-style="setHeaderCellStyle" :row-style="setRowStyle" :cell-style="setCellStyle" :max-height="maxHeight||maxHeight_" :border="configData.built_border" :show-header="!configData.hideHeader" :summary-method="getSummaries" @select-all='selectAll' @select='selectCheckBox' @row-click="tableRowClick" @cell-click='tableCellClick' @cell-mouse-enter='tableCellmouse' @cell-mouse-leave="tableCelleave" @cell-dblclick="cellDblclick" @sort-change='sortChange' @header-click="headerClick" @row-dblclick='tableRowDblclick' @selection-change='selectionChange' > <el-table-column v-if="configData.selection" type="selection" width="55"></el-table-column> <el-table-column v-if="configData.showIndex" label='序号' type="index" width="55"></el-table-column> <template v-if="columnsProp.length"> <template v-for='(column,index) in columnsProp'> <template v-if="!column.childs&&!column.isHide"> <el-table-column :key="index" :render-header='renderHeader' :width='minWidthFun(column,1)' :prop="column.prop||column.label" :show-overflow-tooltip='column.showOverflowTooltip' :label="column.label&&column.label.startsWith('img_')?column.label.substr(4):column.label" > <template slot-scope="scope"> <template v-if="column.prop.startsWith('img_')"> <el-image :src="scope.row[column.prop]" :fit="fit" :style="imgStyle"> </el-image> </template> <template v-else> <template v-if="!jumpDisable(scope.row,column.prop)"> <el-popover placement="top-start" width="400" @show='showpopover(scope.row,column.prop)' :close-delay='0' trigger="hover"> <el-table :data="tableDataDetail" :header-row-style="setCellHeaderRowStyle" :row-style="setCellRowStyle" style="width: 100%"> <el-table-column v-for="(prop,index) in tableHeader" :prop="prop" :label="prop" :key="index"> </el-table-column> </el-table> <div slot="reference">{{scope.row[column.prop]}}</div> </el-popover> </template> <template v-else> <template v-if="column.type==='checkBox'"> <i :class="rowCellBoolean(scope.row[column.prop])"></i> </template> <template v-else> <!-- <span @click="cellClickItem(scope.row[column.prop],column.action)">{{scope.row[column.prop]}}</span> --> <childItem :remoteMethod="remoteMethod" v-if="jumpItem(column.prop)" :item='jumpItem(column.prop)' :prop="column.prop" :formParms='scope.row' :allColumsConfig='allColumsConfig' :jsoneditorOpenAfter='jsoneditorOpenAfter' :readonly='readonly||dtlDialogFormDisAbled' > </childItem> </template> </template> </template> </template> </el-table-column> </template> <template v-else-if="column.childs&&column.childs.length"> <el-table-column :label="column.label" :key="index"> <template v-for="item in column.childs"> <el-table-column :width='minWidthFun(item,2)' :prop="item.prop||item.label" :render-header='renderHeader' :label="item.label.split('__')[1]||item.prop" :key="item.label" > <template slot-scope="scope"> <template v-if='!jumpDisable(scope.row,item.prop)'> <el-popover placement="top-start" width="400" @show='showpopover(scope.row,item.prop)' :close-delay='0' trigger="hover"> <el-table :data="tableDataDetail" :header-row-style="setCellHeaderRowStyle" :row-style="setCellRowStyle" style="width: 100%"> <el-table-column v-for="(props,index) in tableHeader" :prop="props" :label="props" :key="index"> </el-table-column> </el-table> <div slot="reference">{{scope.row[item.prop]}}</div> </el-popover> </template> <template v-else> <template v-if="item.type==='checkBox'"> <i :class="rowCellBoolean(scope.row[item.prop])"></i> </template> <template v-else> <div >{{scope.row[item.prop]}}</div> </template> </template> </template> </el-table-column> </template> </el-table-column> </template> </template> </template> <el-table-column v-if='configData.showHandle' label="操作" :width='configData.handleWidth' fixed="right"> <!-- <template slot-scope="scope"> <slot name="table_handle" :row='scope.row' :$index='scope.$index'></slot> </template> --> <!-- <template slot-scope="scope"> --> <template slot-scope="scope"> <template v-for="(item,index) in handleColumns_"> <el-button v-if="showItem(item,scope.row)" :disabled='disabledItem(item,scope.row)||dtlDialogFormDisAbled' :key="index" size="mini" :icon="item.icon" :type="item.type" @click="itemClickActionHandle(item,scope.$index,scope.row)"> {{item.label}}</el-button> </template> <template v-for="(item) in dtl_list"> <el-link :disabled="dtlDialogFormDisAbled" :key="item.label" type="primary" class="elLink" @click='linkDtl(item,scope.row)'>{{item.label}}</el-link> </template> </template> </el-table-column> </el-table> <div v-if="isPicture==='1'"> <div><img :src="imgUrl" style="width:100%;height:100%;"></div> </div> <div class="paginationBox"> <el-pagination v-if="paging" @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page.sync="paginationPage" :page-sizes="pageSizes" :page-size="paginationPageSize" layout="total, sizes, prev, pager, next, jumper" :total="paginationTotal"> </el-pagination> </div> <jsoneditor v-model='jsoneditorVisible' :elInfo='elInfo' :layout='layout' :allSourceData='allSourceData' :jsoneditorCloseAfter='jsoneditorCloseAfter' :jsoneditorOpenAfter='jsoneditorOpenAfter' :isEditColumns='isEditColumns||configData.isEditColumns' > </jsoneditor> <tableDeatil v-model='detailVisible' :cellDetailStyle='cellDetailStyle' :tableData='tableDataDetail'> </tableDeatil> <el-dialog title="详情" :visible.sync="dialogVisiblePage" width="90%" :before-close="handleClose" :close-on-click-modal='false' :append-to-body='true' > <iframe :src='pageSrc' style="width:100%;height:500px;padding-top:10px" sandbox="allow-same-origin allow-scripts allow-forms allow-top-navigation allow-popups"></iframe> </el-dialog> <tbaleColumsSet v-model="dialogVisibleTbaleColums" :tableDataColums='tableDataColums' :allSourceData='allSourceData' :elInfo='elInfo' @submit="submitTableColums" :isEditColumns='isEditColumns'></tbaleColumsSet> <dialogUpload @importSuccess='importSuccess' :entityConfig='entityConfig' :currentImportItem='currentImportItem' v-model="dialogUploadVisible" @submit="submitUpload"></dialogUpload> <dialogIframe :entityManger='entityManger' @importSuccess='importSuccess' :currentImportItem='currentImportItem' :entityConfig='entityConfig' v-model="dialogIframeVisible" :src='dialogIframeSrc'></dialogIframe> </div> </template> <script> import commonUtility from '../funTools/commonUtility' import uuidv1 from 'uuid/v1' import mes_style from './mes_style' import screen_style from './screen_style' import _ from 'lodash' import request from '../funTools/request' import tableDeatil from './tableDetail' import jsoneditor from '../common/jsoneditor' import childItem from './ItemComponentChild' import tbaleColumsSet from '../common/tbaleColumsSet' import dialogUpload from '../common/dialogTemplate/dialogUpload' import dialogIframe from '../common/dialogTemplate/dialogIframe' // const tableDeatil = r => require.ensure([], () => r(require('./tableDetail')), 'tableDeatil_') // const childItem = r => require.ensure([], () => r(require('./ItemComponentChild')), 'ItemComponentChild_') // const jsoneditor = r => require.ensure([], () => r(require('../common/jsoneditor')), 'jsoneditor_') // const dialogUpload = r => require.ensure([], () => r(require('../common/dialogTemplate/dialogUpload')), 'dialogUpload_') // const dialogIframe = r => require.ensure([], () => r(require('../common/dialogTemplate/dialogIframe')), 'dialogIframe_') // const tbaleColumsSet = r => require.ensure([], () => r(require('../common/tbaleColumsSet')), 'tbaleColumsSet_') export default { components: { jsoneditor, tableDeatil, childItem, tbaleColumsSet, dialogUpload, dialogIframe, }, name: 'hsTable', props: { remoteMethod: {}, importInfo: {// 导入信息 type: Array, default() { return [] } }, isEditColumns: {}, // 是否可编辑列 maxHeight: {}, height: {}, elInfo: {// 组件信息 type: Object, default() { return {} } }, allSourceData: {// 数据和配置 type: Object, default() { return { config: {}, sourceData: [], picture_url: '' } } }, isCarousel: { type: Boolean, default() { return true } }, params: { type: Object, default() { return { el: 'hsTable', page: 'page1', position: 'table1' } } }, layout: {}, jsoneditorCloseAfter: { type: Function }, jsoneditorOpenAfter: { type: Function }, getSourceData: {// 获取所有数据 type: Function }, toggleRow: {// 外部传入的当前行 }, entityConfig: {}, // 实体 readonly: {// 是否只读 }, handleColumns: {// 外部传入的操作列 type: Array, default() { return [] } }, dtl_list: {// 外部传入的操作列 type: Array, default() { return [] } }, fromWhere: {// 来自哪里的表格 列表 or 详情 default: 'list' }, entityManger: {}// 实体manger }, data() { return { imgUrl: '', elId: '', tableData: [], configData: { toolItems: [], handleColumns: [] }, jsoneditorVisible: false, tableStyle: '', imgStyle: '', pageArr: {}, page: 0, currentPage: 0, grouptableData: [], tableObj: {}, time: 0, timer: null, fit: 'fill', paging: null, paginationPage: 1, paginationPageSize: 50, detailVisible: false, detailVisible2: false, tableDataDetail: [], tableHeader: [], outBoxDom: null, maxHeight_: 'none', isPicture: '', columnsProp: [], visible2: false, cellDetailStyle: {}, paginationTotal: 0, total: {}, headerCellStyleSetting_: {}, columnsConfig: [], pageSizes: [10, 20, 50, 100, 200, 1000], subjoinStyle: { 'hyperlink': { 'text-decoration': 'underline', 'cursor': 'pointer' }, 'asyncQueryDetail': { 'text-decoration': 'underline', 'cursor': 'pointer' } }, dialogVisiblePage: false, pageSrc: '', handleWidth: 200, allColumsConfig: {}, dataChangeNumber: 0, tableDataColums: [], dialogVisibleTbaleColums: false, dialogUploadVisible: false, currentImportItem: null, dialogIframeSrc: '', dialogIframeVisible: false, tableDataFirst: null, // table[0]第一行数据 hsDyncProp: false, // 是否含有动态列 targetRowInner: {}, // 当前行 dtlDialogFormDisAbled: false } }, watch: { targetRowInner: { handler: function(newVal, oldVal) { this.$emit('setCurrentRow', newVal) }, deep: true }, toggleRow: { handler: function(newVal, oldVal) { this.setRowSelect(newVal) }, deep: true }, paging: { handler: function(newVal, oldVal) { if (!newVal) return const per_page = Array.isArray(newVal) ? parseInt(newVal[0].per_page) : parseInt(newVal.per_page) const list = [10, 20, 50, 100, 200, 1000] if (!list.includes(per_page)) { list.unshift(per_page) } this.pageSizes = list }, deep: true }, allSourceData: { handler: function(newVal, oldVal) { this.initTable(newVal) }, deep: true }, isCarousel: { handler: function(newVal, oldVal) { if (newVal && this.timer !== null) { this.timer = setInterval(this.changeTableDataFun, newVal) } else { clearInterval(this.timer)// 清除定时器 this.timer = null } }, deep: true }, time: { handler: function(newVal, oldVal) { if (newVal > 0 && this.isCarousel) { this.timer = setInterval(this.changeTableDataFun, newVal) } }, deep: true } }, computed: { handleColumns_: function() { const list1 = _.cloneDeep(this.handleColumns || []) const list2 = _.cloneDeep(this.configData.handleColumns || []) this.mergeData(list1, list2) list2.forEach(item => { const { click, isHide } = item const isHideType = typeof isHide === 'boolean' if (!isHideType) return switch (click) { case '$addRow': case '$deleteRow': if (this.fromWhere === 'hdrDtl') { if (this.readonly) { this.$set(item, 'disabled', true) } else { this.$set(item, 'disabled', false) } } if (this.readonly && this.fromWhere !== 'hdrDtl') { this.$set(item, 'disabled', true) } break } }) return list2 }, tool_list: function() { const newList = [] const newVal_ = _.cloneDeep(this.importInfo) const toolItems = _.cloneDeep(this.configData.toolItems || []) newList.push(...newVal_, ...toolItems) newList.forEach(item => { const { click, isHide } = item const isHideType = typeof isHide === 'boolean' switch (click) { case '$addRow': case '$deleteRow': if (this.fromWhere === 'hdrDtl') { if (this.readonly) { this.$set(item, 'disabled', true) } else if (isHide === undefined || isHideType) { this.$set(item, 'disabled', false) } } if (this.readonly && this.fromWhere !== 'hdrDtl') { this.$set(item, 'disabled', true) } break case '$excelImportItem': case '$dataImportItem': if (this.fromWhere === 'hdrDtl') { if (this.readonly) { this.$set(item, 'disabled', true) } else if (isHide === undefined || isHideType) { this.$set(item, 'disabled', false) } } break } }) return newList || [] }, showSummary: function() { const tkeys = Object.keys(this.total) const sumKey = this.columnsConfig.reduce((prve, curr) => { if (curr.summarizing) { prve.push(curr.prop) } return prve }, []) return !!tkeys.length || !!sumKey.length } }, created() { this.elId = uuidv1() // 获取随机id }, mounted() { this.initTable(this.allSourceData) this.$nextTick(() => { setTimeout(() => { this.showEditJsonDialog() }, 1000) }) }, destroyed() { if (this.outBoxDom) { this.outBoxDom.removeEventListener('mousedown', this.boxEventMouse) } this.chart = null }, beforeDestroy() { clearInterval(this.timer)// 清除定时器 if (this.chart) { this.chart.clear() } this.grouptableData = null this.chart = null this.timer = null this.time = 0 }, methods: { disabledItem(item, row) { const { disabled } = item const type = typeof disabled const data = { row, item } if (type === 'boolean') { return disabled } else if (type === 'function') { return disabled(data) } else { return false } }, showItem(item, row) { const { isHide } = item const type = typeof isHide const data = { row, item } if (type === 'boolean') { return !isHide } else if (type === 'function') { try { return !isHide(data) } catch (error) { console.log(error) const funName = '$' + isHide this.$message.error(`${funName} 有误`) } } else { return true } }, cumputedisabled(item) { return !!item.disabled }, linkDtl(item, row) { this.$emit('RowClick', { row: row }) const that = this setTimeout(() => { const tartItem = that.dtl_list.find(item__ => item__.url === item.url) this.$emit('linkDtl', tartItem, row) }, 100) }, mergeData(data1, data2, prop = 'click') { if (!Array.isArray(data1)) return if (!Array.isArray(data2)) return const list = [] data1.forEach(item => { let target = data2.find(_item => _item[prop] === item[prop]) if (target) { target = Object.assign(target, item) } else { list.push(item) } }) data2.push(...list) }, itemClickActionHandle(item, index, row) { const { click } = item const type = typeof click if (type === 'string' && click.startsWith('$')) { const item_ = Object.assign({}, item) item_.click = item_.click.substr(1) this.itemClick(item_, index) } else if (type === 'function') { click(row) } }, itemClickAction(item, index) { const { click } = item const type = typeof click if (type === 'string' && click.startsWith('$')) { const item_ = Object.assign({}, item) item_.click = item_.click.substr(1) this.itemClick(item_) } else if (type === 'function') { click(item) } }, itemClick(item, index) { const { click } = item switch (click) { case 'exportCurrPageData': this.exportExcel(1) break case 'exportAllPageData': this.exportExcel(2) break case 'tableColumnSet': this.tableColumnSet() break case 'dataImportItem': case 'excelImportItem': this.importItem(item) break case 'addRow': this.addRow(index) break case 'deleteRow': this.deleteRow(index) break case 'editRow': this.editRow(index) break } }, editRow(index) { const data = { row: this.tableData[index], index: index } this.$emit('editRow', data) }, addRow(index) { this.$emit('addRow', index) }, deleteRow(index) { if (typeof index === 'number') { this.tableData.splice(index, 1) } else { // 逆向循环删除数组某些项 var arr = this.tableData for (let i = arr.length - 1; i >= 0; i--) { if (arr[i].isSelected) { arr.splice(i, 1) } } } }, initTable(data) { const { config, sourceData } = data this.initTabelData(sourceData) this.initTabelconfig(config) }, getSessionInfo() { const { db_name, db_code } = commonUtility.parseUrlQueryString() const { appCode, pagename } = commonUtility.parseUrlQueryBIDyncAppcodePageName() const dbName = db_name || '' const obj = _.cloneDeep({ dbName, appCode, page: pagename, db_code }) return obj }, importSuccess(data) { this.$emit('importSuccess', data) this.dialogIframeVisible = false }, submitUpload(fileList) { const file = fileList[0] this.$emit('importItem', file.raw, this.currentImportItem) }, importItem(item) { this.currentImportItem = item this.$emit('setCurrentImportItem', item) const parms = item.parms if (!item.url) { // excel 导入 this.dialogUploadVisible = true } else { if (!item.import_name) { this.$message.error('请配置-import_name') return } // 数据导入 const href = location.href const startUrl = href.split('#')[0] let url = item.url if (item.url.includes('?')) { url = item.url + '&fromMenu=1' } else { url = item.url + '?fromMenu=1' } let parmsStr = '' for (const key in parms) { parmsStr += `&${key}=${parms[key]}` } const appInfo = this.getSessionInfo() const url_ = `${startUrl}#${url}` + `&db_name=${appInfo.dbName}` + parmsStr this.dialogIframeSrc = url_ this.dialogIframeVisible = true } }, getPageInfo(info = this.elInfo) { const data = { sControl: info.position } return request.getSql(data) }, async submitTableColums(data, flage) { const res = await this.getPageInfo() let paramsData = {} if (!res || (res && Array.isArray(res) && !res.length)) { const { config, sourceData } = this.allSourceData paramsData.json_config = JSON.stringify(config) paramsData.json_data = JSON.stringify(sourceData) paramsData.is_mock = 1 paramsData.query_sql = '' } else { paramsData = res[0] } const { query_sql, json_config, json_data, is_mock } = paramsData const json_config_ = JSON.parse(json_config) json_config_.columnsConfig = data const dataw = { sControl: this.elInfo.position, sConfig: json_config_, sData: JSON.parse(json_data), sQuerySql: query_sql, elInfo: this.elInfo, is_mock: is_mock ? 1 : 0 } request.runSave(dataw).then(res => { if (flage !== 'columnStyleSet') { this.dialogVisibleTbaleColums = false } this.configData.columnsConfig = data }) }, tableColumnSet() { const config = _.cloneDeep(this.configData) if (config && config.columnsConfig && config.columnsConfig.length) { this.tableDataColums = [...config.columnsConfig] } else { this.tableDataColums = [{}] } this.tableDataColums.forEach((item, index) => { if (item.childs) { this.tableDataColums.splice(index, 1, ...item.childs) } }) this.dialogVisibleTbaleColums = true }, selectionChange(data) { data.forEach(item => { this.$set(item, 'isSelected', true) }) this.$emit('selectionChange', data) }, jumpItem(prop) { const target = this.columnsConfig.find(item => item.prop === prop && !item.isHide) const target1 = this.columnsProp.find(item => item.prop === prop && !item.isHide) return target || target1 }, set_row_style(row) { if ( row.bill_status === '5' || row.usable === false || row.bUsable === false ) { return { 'text-decoration': 'line-through', color: '#afafaf' } } }, tableRowDblclick(row, column, event) { const disaledDblClick = this.configData.disaledDblClick if (!disaledDblClick) { this.$emit('tableRowDblclick', row) } }, selectAll(selection) { this.tableData.forEach(item => { this.$set(item, 'isSelected', !!selection.length) }) if (!selection.length) { // 清空时 去掉当前行 this.$refs.hsTable.setCurrentRow() } }, selectCheckBox(selection, row) { this.$set(row, 'isSelected', !row.isSelected) // 设置当前行是否高亮 if (!row.isSelected) { this.$refs.hsTable.setCurrentRow() this.targetRowInner = {} } else { this.$refs.hsTable.setCurrentRow(row) this.targetRowInner = row } }, async exportExcel(flage) { const data = this.tableData const columnsProp_ = [] this.columnsProp.forEach(item => { if (item.childs) { columnsProp_.push(...item.childs) } else { columnsProp_.push(item) } }) const tHeader = [] columnsProp_.forEach(item => { const str = `${item.label}=${item.prop}` tHeader.push(str) }) const exportExcelName = this.configData.exportExcelName || '表' if (flage === 2) { const result = await this.getSourceData({ param: { per_page: -1 }, elInfo: this.elInfo }) if (Array.isArray(result) && result.length) { let exportExcelData = [] if (result[0].json_data) { const json_data = typeof result[0].json_data === 'string' ? JSON.parse(result[0].json_data) : result[0].json_data exportExcelData = Array.isArray(json_data) ? json_data : json_data.table } else { exportExcelData = result } this.$utilsExcel.exportToExcel(tHeader, exportExcelData, exportExcelName) } else { this.$message.warning('暂无数据~') } } else { this.$utilsExcel.exportToExcel(tHeader, data, exportExcelName) } }, handleClose() { this.dialogVisiblePage = false }, headerClick(column, event) { const target = event.target const className = target.className const data = { prop: column.property, order: '' } if (className && className.includes('sort-caret')) { if (className.includes('ascending') && !target.className.includes('activeBottomSort')) { data.order = '1' target.className = target.className + ' activeBottomSort' target.nextSibling.className = target.nextSibling.className.replace('activeTopSort', '') } else if (className.includes('ascending') && target.className.includes('activeBottomSort')) { data.order = '' target.className = target.className.replace('activeBottomSort', '') } else if (className.includes('descending') && !target.className.includes('activeTopSort')) { data.order = '0' target.className = target.className + ' activeTopSort' target.previousSibling.className = target.previousSibling.className.replace('activeBottomSort', '') } else if (className.includes('descending') && target.className.includes('activeTopSort')) { data.order = '' target.className = target.className.replace('activeTopSort', '') } this.$emit('sortChange', data) } }, ascendingClick() { }, renderHeader(h, { column, $index }) { const { property, label } = column const target = this.columnsProp.find(item => { return item.prop === property && !item.isHide }) if (!target) { return label } let innerHtml = column.label if (target && target.isRequired) { innerHtml = '<i style="color:red;">*</i>' + innerHtml } if (target && target.isSort) { innerHtml += '<span class="caret-wrapper"><i class="sort-caret ascending"></i><i class="sort-caret descending"></i></span>' } return h( 'span', { domProps: { innerHTML: innerHtml }, on: { click: this.ascendingClick } }, [h('span')] ) }, sortChange(column) { const data = { prop: column.prop, order: column.order } this.$emit('sortChange', data) }, cellClickItem(value, action) { }, cellDblclick(row, column, cell, event) { // const { property } = column }, rowCellBoolean(value) { if (Number(value)) { return 'el-icon-check' } else { return 'el-icon-close' } }, getSummaries(param) { const { columns } = param const sums = [] const sumKey = this.columnsConfig.reduce((prve, curr) => { if (curr.summarizing) { prve.push(curr.prop) } return prve }, []) const sumObj = {} sumKey.forEach(key => { sumObj[key] = 0 this.tableData.forEach(item => { if (item[key]) { sumObj[key] += Number(item[key]) } }) }) const total_ = Object.assign(_.cloneDeep(this.total)) const tkeys = Object.keys(total_) columns.forEach((column, index) => { const { property } = column if (index === 0) { sums[index] = '合计' } else if (tkeys.length) { if (tkeys.includes(property)) { sums[index] = total_[property] } else { sums[index] = '' } } else if (sumKey.length) { if (sumKey.includes(property)) { sums[index] = sumObj[property] } else { sums[index] = '' } } }) return sums }, jumpDisable(row, key) { if (row[`_data_${key}`]) { return false } else { return true } }, showpopover(row, key, cell) { if (row[`_data_${key}`]) { const _data_value = row[`_data_${key}`] this.tableDataDetail = _data_value if (!this.tableDataDetail.length) return this.tableHeader = Object.keys(this.tableDataDetail[0]) } else { // this.tableDataDetail = [] } }, minWidthChildFun(label) { const l = label.length const f = 12 const minWidth = f * l // 加上一个文字长度 return minWidth }, minWidthFun(column, flage) { // 表示要自适应 const { width, label, prop: property } = column if (width) return width if (this.configData.isAdaptive) return if (!label) return const l = flage === 1 ? label.length : label.split('__')[1].length const f = 12 const sortList = this.columnsConfig.find(item => item.isSort && item.prop === property) let minWidth = f * (l + 2) if (sortList) { minWidth = f * (l + 4) } return minWidth }, initTabelData(sourceData) { if (sourceData && sourceData.picture_url && sourceData.picture_url !== '') { this.imgUrl = '/uploadAPI/file/' + sessionStorage.getItem('app_code') + '/' + this.allSourceData.picture_url this.isPicture = '1' } else { this.isPicture = '0' } if (sourceData) { if (Array.isArray(sourceData)) { this.tableData = sourceData this.paging = null this.total = {} } else { const total = sourceData.total || sourceData.set3 if (total) { if (Array.isArray(total)) { this.total = total[0] } else { this.total = total } } this.tableData = sourceData.table || sourceData.set1 || [] this.paging = sourceData.paging || sourceData.set2// 分页信息 if (this.paging) { if (Array.isArray(this.paging)) { this.paginationPage = parseInt(this.paging[0].page) // 当前页 this.paginationPageSize = parseInt(this.paging[0].per_page) // 分页条数 this.paginationTotal = parseInt(this.paging[0].total) } else { this.paginationPage = parseInt(this.paging.page) // 当前页 this.paginationPageSize = parseInt(this.paging.per_page) // 分页条数 this.paginationTotal = parseInt(this.paging.total) } } } } if (this.tableData.length) { const data0 = this.tableData[0] this.tableDataFirst = _.cloneDeep(data0) if (data0._id) { // 此时有动态列 且 此时数据为空 this.tableData.splice(0, 1) } } this.tableData.forEach(item => { for (const p in item) { if (p.includes('_data_')) { if (typeof item[p] === 'string') { item[p] = JSON.parse(item[p]) } } } }) }, initTabelconfig(config_) { const config = _.cloneDeep(config_) this.configData = this.getDefaultConfig(config) if (config && config.maxHeight) { this.maxHeight_ = config.maxHeight } const { columnsConfig, cellDetailStyle } = this.configData this.columnsConfig = columnsConfig || [] if (columnsConfig && columnsConfig.length) { this.columnsProp = [...columnsConfig] // 筛选出可显示的 const dyncProp = this.columnsProp.find(item => item.prop === '*') if (dyncProp) { this.hsDyncProp = true this.setHeaderAnynsProp(this.columnsProp) } else { this.hsDyncProp = false } } else { this.columnsProp = [...this.getAsyncProp(this.tableDataFirst)] } this.getHeaderCellStyle(this.tableData) this.columnsProp.forEach(item => { if (!item.showType || item.showType === 'text') { item.showOverflowTooltip = true } else { item.showOverflowTooltip = false } }) this.columnsProp = this.groupByProp(this.columnsProp) console.log(this.columnsConfig, ' this.columnsConfig') // 避免数据变更 再次发出请求 if (this.dataChangeNumber < 4) { this.dataChangeNumber++ // this.initTableColumnsControl() } if (this.hsDyncProp) { // 有动态列的时候 每次数据变得都得重新请求一次下拉数据 // this.initTableColumnsControl() } this.setCellDetailStyle(cellDetailStyle) this.dtlDialogFormDisAbled = this.disabledItem(this.configData) }, getHeaderCellStyle(datas) { if (!datas.length) return if (datas[0]._headerCellStyleSetting_) { const _headerCellStyleSetting_ = datas[0]._headerCellStyleSetting_ this.headerCellStyleSetting_ = _headerCellStyleSetting_ } }, setHeaderAnynsProp(data) { data.forEach((item, index) => { if (item.prop === '*') { // 获取所有的动态列 const anyncProp = this.getAsyncProp(this.tableDataFirst, data) anyncProp.forEach(item_ => { // item.showType = 'input' this.$set(item_, 'showType', item.showType) }) // 删除那一带*的行 替换成动态列 data.splice(index, 1, ...anyncProp) } }) }, getAsyncProp(tableDataFirst, columnsProp = []) { if (!tableDataFirst) return [] const props = Object.keys(tableDataFirst) // 已经手动设置存在的表表头 const constProps = [] if (columnsProp.length) { columnsProp.forEach(item => { if (item.prop !== '*') { constProps.push(item.prop) } }) } // 动态设置1维表头 const constProps_ = [] props.forEach(prop => { if (!prop.includes('__') && !prop.startsWith('_') && !prop.includes('_data_') && prop !== 'isSelected') { constProps_.push({ prop: prop, label: prop, 'showOverflowTooltip': true }) } else if (prop.includes('__')) { const one_title = prop.split('__')[0] const target = columnsProp.find(p => p.prop.split('__')[0] === one_title) if (target) return const one_title_list = props.filter(item => item.split('__')[0] === one_title) const one_title_list_prop = [] one_title_list.forEach(item => { one_title_list_prop.push({ prop: item, label: item, 'showOverflowTooltip': true }) }) const t = constProps_.find(item => item.prop === one_title) if (!t) { constProps_.push({ prop: one_title, label: one_title, childs: one_title_list_prop }) } } }) const result = constProps_.filter(item => !constProps.includes(item.prop)) return result || [] }, groupByProp(list) { const parms = [] list.forEach(item => { // const itemProp = item.prop // if (!itemProp) { // item.prop = item.label // } if (!item.prop) { item.prop = '' } const prop = item.prop.split('__')[0] if (item.prop.includes('__')) { // const prop = item.prop.split('__')[0] const t = parms.find(jtem => jtem.prop === prop) if (t) { t.childs.push(item) } else { const obj = { prop: '', label: '', childs: [] } obj.prop = prop obj.label = prop obj.childs.push(item) parms.push(obj) } } else { parms.push(item) } }) return parms }, tansFormAsyncProps(list) { const rasyncProps = _(list).groupBy(item => item.split('__')[0]).value() const Keys = Object.keys(rasyncProps) const result = [] Keys.forEach(k => { const obj = { prop: '', label: '', 'showOverflowTooltip': true, childs: [] } obj.prop = k obj.label = k rasyncProps[k].forEach(i => { obj.childs.push({ prop: i, label: i, 'showOverflowTooltip': true }) }) result.push(obj) }) return result }, getTableHeader(data = this.tableData) { if (!data.length) return [] const props = Object.keys(data[0]) let __list = [] const list = [] props.forEach((prop, index) => { if (prop.includes('__') && !prop.includes('_data_')) { __list.push(prop) delete props[index] } else if (!prop.startsWith('_') && !prop.includes('_data_') && prop !== 'isSelected') { list.push(prop) } }) if (__list.length) { __list = _(__list).groupBy(item => item.split('__')[0]).value() } list.push(__list) return list }, getDefaultConfig(config = {}) { let _config = {} if (config.hsConfig !== undefined && config.hsConfig.default_type + '' === '1') { // mes样式 _config = this.config_merge(mes_style, config) } else { // 大屏样式 _config = this.config_merge(screen_style, config) } if (_config.queryBiTheme) { sessionStorage['queryBiTheme_'] = JSON.stringify(_config.queryBiTheme) } return _config }, config_merge(defaultConfig, config) { if (!Object.keys(config).length) { return defaultConfig } const _defaultConfig = _.cloneDeep(defaultConfig) for (const key1 in _defaultConfig) { if (typeof _defaultConfig[key1] === 'object') { for (const key2 in _defaultConfig[key1]) { if (config[key1] !== undefined && config[key1][key2] !== undefined) { _defaultConfig[key1][key2] = config[key1][key2] } } } else if (Array.isArray(_defaultConfig[key1])) { _defaultConfig[key1] = config[key1] } else { if (config[key1] !== undefined) { _defaultConfig[key1] = config[key1] } } } Object.keys(config).forEach(item => { if (!(item in _defaultConfig)) { _defaultConfig[item] = config[item] } }) return _defaultConfig }, setRowSelect(row, f) { this.tableData.forEach(item => { if (item.isSelected) { this.$set(item, 'isSelected', false) } }) row.isSelected = true this.$refs.hsTable.clearSelection() this.$refs.hsTable.setCurrentRow(row) this.$refs.hsTable.toggleRowSelection(row) this.targetRowInner = row }, tableRowClick(row, column, event) { this.$emit('RowClick', { row: row, column: column, event: event }) }, // 单击某个单元格的时候 弹出明细 tableCellClick(row, column, cell, event) { this.setRowSelect(row) const key = column.label const { property } = column const target = this.columnsConfig.find(item => item.prop === property) if (target && (target.type === 'hyperlink' || target.type === 'asyncQueryDetail')) { let value_ = row[property] const otherConfig = target.otherConfig if (otherConfig && !otherConfig.startsWith('/') && !otherConfig.startsWith('http')) { value_ = row[target.otherConfig] } else if (otherConfig) { value_ = otherConfig } const reg = /\{(.*?)\}/g // /(?<=\{).*?(?=\})/g const queryList = value_.match(reg) || []// value_.match(/(?<=\{).*?(?=\})/g) || [] // value_.match(reg) || [] // queryList.forEach(p => { const p_ = p.replace('{', '').replace('}', '') const pt = row[p_] value_ = value_.replace(`{${p_}}`, pt) }) const origin = location.origin let url = value_ if (value_.startsWith('http')) { url = value_ } else if (value_.startsWith('/')) { url = origin + '/#' + value_ } if (target.type === 'hyperlink') { window.open(url, '_blank') } else if (target.type === 'asyncQueryDetail') { const property = column.property if (row[property]) { this.pageSrc = url this.dialogVisiblePage = true } } } if (row[`_data_${key}`]) { this.detailVisible = true const _data_value = row[`_data_${key}`] this.tableDataDetail = _data_value } else { this.$emit('CellClick', { row: row, column: column, cell: cell, event: event }) } }, // 鼠标移入事件 tableCellmouse(row, column, cell, event) { if (this.configData.hover) { const { hoverBackground } = this.configData.hover if (hoverBackground) { cell.parentNode.style.background = hoverBackground } } }, // 鼠标离开事件 tableCelleave(row, column, cell, event) { const { property } = column const { _styleCellSetting_, _styleRowSetting_ } = row const _styleRowSetting__ = _styleRowSetting_ || {} const cellStyel = {} if (_styleCellSetting_) { const keys = Object.keys(_styleCellSetting_) const targetKey = keys.find(k => k === property) if (targetKey) { Object.assign(cellStyel, _styleCellSetting_[property]) } } // this.detailVisible2 = false if (this.configData.hover) { const { leaveBackground } = this.configData.hover if (leaveBackground) { if (_styleRowSetting__.background) { cell.parentNode.style.background = _styleRowSetting__.background } else { cell.parentNode.style.background = leaveBackground } } } }, handleSizeChange(pageSize) { this.paginationPageSize = parseInt(pageSize) if (this.paginationPage !== 1) { this.paginationPage = 1 } this.$emit('paginationFun', { elInfo: this.elInfo, // 此处把组件信息返回出去 方便queryBi统一处理 pageSize: this.paginationPageSize, page: this.paginationPage }) }, // 当前页 change cb handleCurrentChange(currentPage) { this.paginationPage = parseInt(currentPage) this.$emit('paginationFun', { elInfo: this.elInfo, pageSize: this.paginationPageSize, page: this.paginationPage }) }, // 轮播table数据 changeTableDataFun() { if (this.currentPage === this.page) { this.currentPage = 0 } this.grouptableData = this.pageArr[this.currentPage] this.currentPage = this.currentPage + 1 }, boxEventMouse(event) { const that = this event.stopPropagation() if (event.shiftKey && event.altKey && !event.ctrlKey) { that.jsoneditorVisible = true } }, // 弹出可编辑的弹框 showEditJsonDialog() { this.outBoxDom = document.getElementById(this.elId) if (this.outBoxDom) { this.maxHeight_ = this.outBoxDom.offsetHeight this.outBoxDom.addEventListener('mousedown', this.boxEventMouse) } }, // 修改表头行的样式 setHeaderRowStyle(rowData) { const headerRowStyle = this.configData.headerRowStyle || {} return typeof headerRowStyle === 'string' ? JSON.parse(headerRowStyle) : headerRowStyle }, // 修改表头单元格样式 会合并行的样式 setHeaderCellStyle(rowData) { const { column } = rowData const headerCellStyle = this.configData.headerCellStyle || {} const { property } = column // 这是后台设置的表头单元格子数据 const commonStyle_ = this.headerCellStyleSetting_.commonStyle || {} const data_ = this.headerCellStyleSetting_.data || [] const target = data_.find(item => item.property === property) let targetStyle_ = {} if (target && target.style) { targetStyle_ = target.style } const commonStyle = headerCellStyle.commonStyle || {} const data = headerCellStyle.data || [] const targetProp = data.find(item => item.property === property) let targetPropStyle = {} if (targetProp && targetProp.style) { targetPropStyle = targetProp.style } const result = Object.assign(_.cloneDeep(commonStyle), _.cloneDeep(targetPropStyle), _.cloneDeep(commonStyle_), targetStyle_) return result }, setRowStyle(rowData) { const { rowStyle, onlyDataStyleRow } = this.configData const { rowIndex, row } = rowData const data_style = _.cloneDeep(this.set_row_style(row) || {})// 数据样式 const _styleRowSetting_ = row._styleRowSetting_ || {} const _styleRowSetting_P = typeof _styleRowSetting_ === 'string' ? JSON.parse(_styleRowSetting_) : _styleRowSetting_ // 如果设置了这个参数 仅仅数据样式生效 if (onlyDataStyleRow) { return Object.assign(_.cloneDeep(_styleRowSetting_P), _.cloneDeep(data_style)) } if (rowStyle) { // 合并本地默认样式+手动设置样式+后台返回样式 const { commonStyle, data } = rowStyle const data_ = data || [] let targetRowIndexStyle = {} const targetRow = data_.find(item => parseInt(item.rowIndex) === rowIndex) if (targetRow) { targetRowIndexStyle = targetRow.style } const result = Object.assign(_.cloneDeep(commonStyle), _.cloneDeep(targetRowIndexStyle), _.cloneDeep(_styleRowSetting_), _.cloneDeep(data_style)) return result } else { // 只有后台样式或者没有任何样式 const result = Object.assign(_.cloneDeep(_styleRowSetting_P), _.cloneDeep(data_style)) return result } }, setCellStyle(cellData) { const { column, columnIndex, row, rowIndex } = cellData const { property } = column // 对应的列名 // 后端返回的样式 const _styleCellSetting_ = row._styleCellSetting_ || {} // 对应行 所有列的样式汇总 // 前端config中设置的样式 const { onlyDataStyleCell, cellStyle, columnStyle } = this.configData let cellDataStyle = {}// 数据中的样式 let config_columnStyle = {} // config中的columnStyle的样式 let config_cellStyle = {}// config中的cellStyle的样式 let columnsConfig_columnStyle = {} // columnsConfig数据列配置中的columnStyle let columnsConfig_otherStyle = {} // 其他样式 const _styleCellSetting_P = typeof _styleCellSetting_ === 'string' ? JSON.parse(_styleCellSetting_) : _styleCellSetting_ const keys = Object.keys(_styleCellSetting_P) const targetKey = keys.find(k => k === property) // 附加样式 如超链接 配置中columnsConfig const otherStyle = this.columnsConfig.find(item => item.prop === property) if (otherStyle && (otherStyle.type === 'hyperlink' || otherStyle.type === 'asyncQueryDetail')) { columnsConfig_otherStyle = this.subjoinStyle[otherStyle.type] || {} } if (otherStyle && otherStyle.columnStyle) { columnsConfig_columnStyle = otherStyle.columnStyle || {} } if (targetKey) { cellDataStyle = _styleCellSetting_P[property] } if (onlyDataStyleCell) { // 仅仅 数据样式生效本地样式不生效 return cellDataStyle } if (columnStyle) { // config中的columnStyle的样式的时候 const { data, commonStyle: commonColumnStyle } = columnStyle const data_ = data const commonColumnStyle_ = _.cloneDeep(commonColumnStyle || {}) const targetColumn = data_.find(item => item.property === property) let targetColumnStyle = {} if (targetColumn && targetColumn.style) { targetColumnStyle = targetColumn.style } config_columnStyle = Object.assign(commonColumnStyle_, targetColumnStyle) } if (cellStyle) { const { commonStyle: commonCellStyle, data } = cellStyle const data_ = data || [] const commonCellStyle_ = _.cloneDeep(commonCellStyle || {}) let targetCellIndexStyle = {} const targetCell = data_.find(item => parseInt(item.rowIndex) === rowIndex && (item.property === property || parseInt(item.columnIndex) === columnIndex)) if (targetCell) targetCellIndexStyle = _.cloneDeep(targetCell.style || {}) config_cellStyle = Object.assign(commonCellStyle_, targetCellIndexStyle) } return Object.assign(config_columnStyle, config_cellStyle, cellDataStyle, columnsConfig_otherStyle, columnsConfig_columnStyle) }, alterConfigAction() { if (this.configData.tableStyle) { this.tableStyle = JSON.stringify(this.configData.tableStyle).replace(new RegExp('\"', 'g'), '').replace(new RegExp('{', 'g'), '').replace(new RegExp('\,', 'g'), ';').replace(new RegExp('}', 'g'), ';') } if (this.configData.imgStyle) { this.imgStyle = JSON.stringify(this.configData.imgStyle).replace(new RegExp('\"', 'g'), '').replace(new RegExp('{', 'g'), '').replace(new RegExp('\,', 'g'), ';').replace(new RegExp('}', 'g'), ';') } if (this.configData.gutter) { var tableId = document.getElementById(this.elId) if (!tableId) return var gutterArr = tableId.getElementsByClassName('gutter') if ((gutterArr && !gutterArr.length) || !gutterArr) return gutterArr[0].style.background = this.configData.gutter.background gutterArr[0].style.border = this.configData.gutter.border gutterArr[0].style.borderTop = this.configData.gutter.borderTop gutterArr[0].style.borderBottom = this.configData.gutter.borderBottom gutterArr[0].style.borderLeft = this.configData.gutter.borderLeft gutterArr[0].style.borderRight = this.configData.gutter.borderRight } }, setCellDetailStyle(data = {}) { // const { headerRowStyle, rowStyle } = data this.cellDetailStyle = data }, setCellHeaderRowStyle() { const { headerRowStyle } = this.cellDetailStyle return headerRowStyle || {} }, setCellRowStyle() { const { rowStyle } = this.cellDetailStyle return rowStyle || {} } } } </script> <style> .activeBottomSort{ border-bottom-color: #1f5ede !important; } .activeTopSort{ border-top-color: #1f5ede !important; } ._hs_table .el-table--border { border: 1px solid #EBEEF5 !important; } /* 禁止掉默认的hover事件 */ ._hs_table .el-table--striped .el-table__body tr.current-row > td, ._hs_table .el-table__body tr.hover-row.current-row > td, ._hs_table .el-table__body tr.hover-row.el-table__row--striped.current-row > td, ._hs_table .el-table__body tr.hover-row.el-table__row--striped > td, ._hs_table .el-table__body tr.hover-row > td { background-color: transparent !important; } ._hs_table .el-table--enable-row-hover .el-table__body tr:hover > td { background-color: transparent !important; } /* 去除表格边框线 */ ._hs_table .el-table::before, ._hs_table .el-table::after { height: 0 !important; } ._hs_table body .el-table th.gutter { display: table-cell !important; } .paginationBox{ display: flex; justify-content: flex-end; } /*滑块轨道*/ ._hs_table .el-table__body-wrapper::-webkit-scrollbar { width: 8px; height: 8px; } ._hs_table .el-table__body-wrapper::-webkit-scrollbar-thumb { background-color: #ddd; border-radius: 3px; } /*轨道*/ ._hs_table .el-table__body-wrapper::-webkit-scrollbar-track { box-shadow: none; -webkit-box-shadow: none; border-radius: 0; background: transparent; } ._hs_table .el-table::-webkit-scrollbar-track{ /*滚动条里面轨道*/ box-shadow: none; -webkit-box-shadow: none; border-radius: 0; background: transparent; } ._hs_table .el-table::-webkit-scrollbar-thumb { /*滚动条里面小方块*/ border-radius: 0; box-shadow: none; -webkit-box-shadow: none; opacity: 0.7; } .addtableFooterWrapper { margin-top: -57px; } .addtableBodyWrapper{ padding-bottom: 49px; } ._hs_table ::-webkit-scrollbar { width: 0px; background-color: transparent } .closeAllItem { padding: 3px; cursor: pointer; font-size: 10px; } .paginationBox .el-input__inner{ border: 1px solid #DCDFE6 !important; border-radius: 4px; background-color: #FFF; background-image: none; } .elLink{ margin: 0 3px; font-size: 12px; } .toolsBox{ float: right; top: 34px; position: relative; z-index: 1009; opacity: 0.8; } </style>