emis-frontend/src/components/XdTable/index.vue
2024-08-06 17:03:30 +08:00

1398 lines
50 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="xd-table" :id="tableId">
<div class="table-operate-btn-content" v-show="showOperateButton">
<slot name="operateBtnContent">
<div class="operate-btn-content">
<slot name="toolbar">
<div />
</slot>
<div class="top-right-btn" v-show="showRightButton">
<el-row>
<el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top">
<el-button size="mini" circle icon="el-icon-search" @click="toggleSearch()" />
</el-tooltip>
<el-tooltip class="item" effect="dark" content="刷新" placement="top">
<el-button size="mini" circle icon="el-icon-refresh" @click="refresh()" />
</el-tooltip>
<el-tooltip class="item" effect="dark" content="间距" placement="top">
<el-dropdown size="mini" @command="(command) => handleAdjustTableSize(command)">
<el-button size="mini" circle style="margin-left: 10px;" class="icon iconfont icon-hangjianju" />
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="small" >中等</el-dropdown-item>
<el-dropdown-item command="mini" >紧凑</el-dropdown-item>
<el-dropdown-item command="medium" >宽松</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-tooltip>
<el-tooltip class="item" effect="dark" content="显隐列" placement="top" v-if="canHideColumns">
<el-popover
placement="bottom-end"
popper-class="table-cloumn-setting-popper"
trigger="click"
:show-arrow="false"
>
<div class="setting-row-content">
<div style="text-align:right;display: inline-flex;width:240px;border-bottom: 1px solid #d5d4d438;padding: 0px 0px 10px 0px;">
<div style="text-align: left;width: 55%;">
<el-select
v-model="curentTbShowTpl"
size="mini"
clearable
filterable
allow-create
default-first-option
placeholder="模版名称"
@blur="onTplSelectInputBlur($event)"
:style="{width: '100%'}"
@change="changeTbShowTpl"
:disabled="!isNeedDbSaveTpl"
>
<el-option
v-for="(item, index) in storeTplList"
:key="index"
:label="item.tplName"
:value="item.tplCode"
/>
</el-select>
</div>
<div style="text-align: right;width: 45%;line-height: 30px;display:inline-flex">
<el-button type="text" size="mini" style="padding: 7px 5px;" @click="savaTbShowTpl" :disabled="!isNeedDbSaveTpl">保存</el-button>
<!-- <el-button type="text" size="mini" style="padding: 7px 5px;" icon="el-icon-refresh" @click="delStorage" ></el-button> -->
<el-button type="text" size="mini" style="padding: 7px 5px;" icon="el-icon-setting" @click="setTbShowTpl" :disabled="!isNeedDbSaveTpl"></el-button>
</div>
</div>
<div style="">
<div style="width:50%">
<el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox>
</div>
<el-scrollbar style="height: calc(100vh - 200px);box-sizing: border-box;" >
<draggable v-model="storageList"
ghostClass="drag-ghost"
chosenClass="drag-chosen"
:animation="500"
handle=".el-icon-s-operation"
@end="updateTable"
>
<div v-for="col in storageList" :key="col.label" class="setting-row">
<i class="el-icon-s-operation icon iconfont icon-ui_drag_horizontally" />
<el-checkbox v-model="col.show" class="label" @change="showOrHidden($event,col)">{{ col.label }}</el-checkbox>
</div>
</draggable>
</el-scrollbar>
</div>
</div>
<el-button style="margin-left: 10px;" slot="reference" size="mini" circle icon="el-icon-menu" />
</el-popover>
</el-tooltip>
</el-row>
</div>
</div>
</slot>
</div>
<div>
<orig-table ref="table" :key="refreshKeyId" :config="config" v-dragColumn v-dragSelect class="xd-tb-wrapper" />
<!-- 统计数据 -->
<div v-if="showStatInfo" style="display: inline-flex; width: 100%;">
<div style="width:40%" >
<div class="pagination-container"><slot name="statInfo" /></div>
</div>
<div v-if="showPagination" style="width:60%;overflow: hidden;" >
<pagination
v-show="total>0 "
:total="total"
:page-sizes="[10,20,50,100,300,500,1000,2000,5000]"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
:page-size="queryParams.pageSize"
@pagination="queryTable"
/>
</div>
</div>
<div v-else >
<div v-if="showPagination">
<pagination
v-show="total>0 "
:total="total"
:page-sizes="[5,10,20,50,100,300,500,1000,2000,5000]"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
:page-size="queryParams.pageSize"
@pagination="queryTable"
/>
</div>
</div>
</div>
<!-- 数据框选复制 -->
<div id="contextMenu" class="menuDiv" v-show="contextVisible">
<ul class="el-dropdown-menu el-popper el-dropdown-menu--medium"
style="transform-origin: center top; z-index: 2009;width: 180px;"
x-placement="bottom-end">
<li class="el-dropdown-menu__item" @click.stop="handleCopySelect($event)" > <span >复制</span></li>
<li class="el-dropdown-menu__item" @click.stop="handleSelectCurrentColumn($event)" > <span >选中当前列</span></li>
<li class="el-dropdown-menu__item" > <span @click="handleSelectCurrentRow(null,$event)">选中当前行</span></li>
</ul>
</div>
<el-dialog title="设置模板" :visible.sync="openTbShowTplDlg" width="50%">
<el-form ref="form" :model="form" size="small" :rules="rules" label-width="100px" :disabled="!isNeedDbSaveTpl">
<el-row :gutter="0" style="display: flex;flex-wrap: wrap;">
<el-col :span="12">
<el-form-item label="模板名称" prop="tplCode">
<el-select
ref="refNewTplCode"
v-model="form.tplCode"
size="mini"
clearable
filterable
allow-create
placeholder="选择模版"
:style="{width: '100%'}"
@change="changeSaveTbShowTpl"
>
<el-option
v-for="(item, index) in storeTplList"
:key="index"
:label="item.tplName"
:value="item.tplCode"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="默认此模板" prop="blDefault">
<el-radio-group v-model="form.blDefault">
<el-radio :label="1" value="1">是</el-radio>
<el-radio :label="0" value="0">否</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer" style="text-align: center;margin-bottom:20px">
<el-button size="mini" @click="delStorage">重置</el-button>
<el-button size="mini" @click="delTbShowTpl">删除该模版</el-button>
<el-button type="primary" size="mini" @click="savaTbShowTpl">保 存</el-button>
<el-button size="mini" @click="openTbShowTplDlg = false">关 闭</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listSysCustomizeTpl, delSysCustomizeTpl, addSysCustomizeTpl, updateSysCustomizeTpl } from "@/api/system/sysCustomizeTpl";
import { genJsSeqNo } from "@/utils/custom";
import clip from '@/utils/clipboard'
import Sortable from 'sortablejs'
import draggable from 'vuedraggable'
import origTable from './table.jsx'
const components = { origTable, draggable }
export default {
name: 'XdTable',
components,
props: {
id: {
type: String,
},
showSearch: {
type: Boolean,
default: true,
},
showStatInfo: {
type: Boolean,
default: true,
},
canHideColumns: {
type: Boolean,
default: true,
},
storageName: {
type: String,
required: false
},
queryParams:{
type: Object,
default: null,
},
total:{
type: Number,
default: 0,
},
showRightButton:{
type: Boolean,
default: true,
},
showPagination:{
type: Boolean,
default: true,
},
showOperateButton:{
type: Boolean,
default: true,
},
showCustomizeTpl:{
type: Boolean,
default: true,
},
},
// 框选的指令
directives: {
dragSelect: {
// 指令的定义
inserted: function (el, binding, vnode) {
var oDiv = el;
var tbBodyDiv=oDiv.getElementsByClassName("el-table__body-wrapper")[0];
//监听用户鼠标事件
tbBodyDiv.onmousedown = function (ev) {
var evt = window.event || arguments[0];
var flag = true;
// 鼠标右键菜单,并且记录当前位置
if(evt.button == 2){
flag=false;
if(vnode.context.multipleSelection&&vnode.context.multipleSelection.length>0){
vnode.context.currentOdiv=oDiv;
// vnode.context.currentOdiv=tbBodyDiv;
vnode.context.currentCell=evt.target;
showContextMenu(evt);
const currentCellInfo=getCellPosition(evt.target);
vnode.context.currentCellInfo=currentCellInfo;
}
return;
}
// 只有鼠标左键按下时有效
if(evt.button != 0){
return;
}
// addCtrlCKeyDown(oDiv,evt)
vnode.context.multipleSelection=[];
//初始化不显示
vnode.context.contextVisible=false;
const refTableObj=vnode.context.getInstance();
// 增加图层
var xdTableObj = document.getElementById(vnode.context.tableId);
var tbBody1=xdTableObj.getElementsByClassName("el-table__body-wrapper")[0];
var selDiv = document.createElement("div");
selDiv.style.cssText = "position:absolute;width:0px;height:0px;font-size:0px;margin:0px;padding:0px;border:2px solid #409eff;background-color:#d9ecff;z-index:1000;filter:alpha(opacity:60);opacity:0.6;display:none;";
selDiv.id = "selectDiv-"+vnode.context.tableId;
tbBody1.appendChild(selDiv);
// 表格对象
const tableDom=vnode.context.$refs.table.$refs.elTable.$el;
//用来存储列表 单元格和行
var selList = [];
var selRowList = [];
//获得指令下的dom对应的表格
var fileNodes = oDiv.getElementsByTagName("td");
var countI = 0;
// 获得鼠标 X,Y
var startX = (evt.x || evt.clientX);
var startY = (evt.y || evt.clientY);
//重置选中单元格css
for (var i = 0; i < fileNodes.length; i++) {
if (fileNodes[i].className.indexOf("el-table__cell") != -1) {
fileNodes[i].classList.remove("seled");
selList.push(fileNodes[i]);
}
}
var fileRowNodes = oDiv.getElementsByTagName("tr");
for (var i = 0; i < fileRowNodes.length; i++) {
if (fileRowNodes[i].className.indexOf("el-table__row") != -1) {
fileRowNodes[i].className = "el-table__row";
selRowList.push(fileRowNodes[i]);
}
}
setMouseCellSelect(evt.target,selRowList);
// setMouseRowSelect(evt.target);
var _x = null;
var _y = null;
// vnode.context.clearEventBubble(evt);
// //打开开关
vnode.context.mouseflag = true;
// //鼠标拖动时画框
document.onmousemove = function (ev) {
evt = window.event || arguments[0];
_x = (evt.x || evt.clientX);
_y = (evt.y || evt.clientY);
//为了确定是点击事件还是移动事件
// if(Math.abs(_x - startX)<5 && Math.abs(_y - startY)<5){
// return;
// }
if(flag){
flag = false;
}
if (vnode.context.mouseflag) {
if (selDiv.style.display == "none") {
selDiv.style.display = "";
}
// 获取表格的位置
let tbPosRect2=getTablePosition(tableDom);
var tbBody2=oDiv.getElementsByClassName("el-table__body-wrapper")[0];
var tbHeader2=oDiv.getElementsByClassName("el-table__header-wrapper")[0];
selDiv.style.left = Math.min(_x, startX)-tbPosRect2.left+tbBody2.scrollLeft + "px";
//表头的高度
selDiv.style.top = Math.min(_y, startY)-tbPosRect2.top - tbHeader2.offsetHeight+tbBody2.scrollTop+ "px";
selDiv.style.width = Math.abs(_x - startX) + "px";
selDiv.style.height = Math.abs(_y - startY) + "px";
// 核心,判断选择的区域
var _l = selDiv.offsetLeft, _t = selDiv.offsetTop;
var _w = selDiv.offsetWidth, _h = selDiv.offsetHeight;
if(_y>(tbPosRect2.y+tbPosRect2.height)){
tbBody2.scrollBy(0, 60);
}
// else if(_y<(tbPosRect2.y-tbHeader2.offsetHeight)){
// tbBody2.scrollBy(0, 0-60);
// }
// 单元格
for (var i = 0; i < selList.length; i++) {
var sl = selList[i].offsetWidth + selList[i].offsetLeft;
var st = selList[i].offsetHeight + selList[i].offsetTop;
if(sl > _l && st > _t && selList[i].offsetLeft < _l + _w && selList[i].offsetTop < _t + _h) {
// 选择列不允许选择
if(selList[i].className.indexOf("--selection") != -1 ){
continue;
}
if (selList[i].className.indexOf("seled") == -1) {
selList[i].className = selList[i].className + " seled";
const cellInfo=getCellPosition(selList[i]);
vnode.context.multipleSelection.push(cellInfo);
}
}
}
// 行
for (var i = 0; i < selRowList.length; i++) {
var sl = selRowList[i].offsetWidth + selRowList[i].offsetLeft;
var st = selRowList[i].offsetHeight + selRowList[i].offsetTop;
if (sl > _l && st > _t && selRowList[i].offsetLeft < _l + _w && selRowList[i].offsetTop < _t + _h) {
if (selRowList[i].className.indexOf("rowSeled") == -1) {
selRowList[i].className = selRowList[i].className + " rowSeled";
refTableObj.toggleRowSelection(vnode.context.tableData[i],true)
//把选中的都存入到table标签中的已选中
// if(vnode.context.tableData[i]){
// vnode.context.multipleRowSelection.push(vnode.context.tableData[i]);
// }
}
} else {
if (selRowList[i].className.indexOf("rowSeled") != -1 ) {
selRowList[i].className = "el-table__row";
refTableObj.toggleRowSelection(vnode.context.tableData[i],false);
// vnode.context.multipleSelection.forEach((ele,i)=>{
// //这里没用对象是否相等用的是传入table中的唯一的myKey字段
// if(ele[vnode.context.myKey]==vnode.context.tableData[i][vnode.context.myKey] ){
// vnode.context.multipleSelection.splice(i,1);
// }
// })
}
}
}
}
// vnode.context.clearEventBubble(evt);
};
function showContextMenu(event){
var xdTableObj = document.getElementById(vnode.context.tableId);
xdTableObj.addEventListener("contextmenu", function(event) {
vnode.context.clearEventBubble(event)
var menu = xdTableObj.querySelector("#contextMenu");
// console.log("====>xdTableObj====>",xdTableObj);
// console.log("====>menu====>",menu);
let tbPosRect=getTablePosition(xdTableObj);
menu.style.left = (event.clientX-tbPosRect.left+5) + "px";
menu.style.top = (event.clientY-tbPosRect.top-35) + "px";
menu.style.display = "block";
menu.style.zIndex = 3000;
vnode.context.contextVisible=true;
event.preventDefault();
});
}
// function addCtrlCKeyDown(oDiv,event){
// let that=this;
// vnode.context.clearEventBubble(event)
// oDiv.addEventListener('keydown', function(e) {
// e = e||window.event;
// if(e.ctrlKey&&e.code=="KeyC"){
// vnode.context.handleCopySelect(e);
// return false;
// }
// });
// }
function cancelContextMenu() {
document.oncontextmenu = new Function("event.returnValue=true");
}
// 获取el-table元素的位置信息
function getTablePosition(tbDom) {
const tableRect = tbDom.getBoundingClientRect();
return tableRect;
}
function getCellXY(cell) {
try{
while(cell.tagName !== 'TD'){
cell = cell.parentElement;
}
// // console.log("xdtable==>",cell);
const cellRect = cell.getBoundingClientRect();
return { x:cellRect.x,y:cellRect.y,width:cellRect.width,height:cellRect.height};
}catch(e){
return { left:-1,top:-1,width:-1,height:-1};
}
}
function setMouseCellSelect(cell,selRowList) {
try{
while(cell.tagName !== 'TD'){
cell = cell.parentElement;
}
if(cell.className.indexOf("--selection") != -1 ){
return;
}
// 选中和取消选中
if(cell.className.indexOf("seled") != -1 ){
// cell.classList.remove("seled");
// vnode.context.multipleSelection=[];
}
else{
cell.className = cell.className + " seled";
}
const cellInfo=getCellPosition(cell);
vnode.context.multipleSelection=[];
vnode.context.multipleSelection.push(cellInfo);
// 行样式设置
// const refTableObj=vnode.context.getInstance();
// let rowIndex = cell.rowIndex;
// // selRowList[i].className = selRowList[i].className + " rowSeled";
// refTableObj.toggleRowSelection(vnode.context.tableData[rowIndex],true)
}catch(e){
}
}
// 获取鼠标位置的单元格
function getCellPosition(cell) {
try{
while(cell.tagName !== 'TD'){
cell = cell.parentElement;
}
const rowIndex = cell.parentElement.rowIndex;
const cellIndex = cell.cellIndex;
const text = cell.innerText;
return { row:rowIndex,col: cellIndex ,text:text};
}catch(e){
return { rowIndex:-1,cellIndex:-1};
}
}
//在鼠标抬起后做的重置
document.onmouseup = function () {
//把鼠标移动事初始化
document.onmousemove=null;
var xdTableObj = document.getElementById(vnode.context.tableId);
var selDiv=document.getElementById("selectDiv-"+vnode.context.tableId);
if (selDiv) {
xdTableObj.getElementsByClassName("el-table__body-wrapper")[0].removeChild(selDiv);
}
selList = null, _x = null, _y = null, selDiv = null, startX = null, startY = null, evt = null;
vnode.context.mouseflag = false;
vnode.context.handleBatchSelect();
// cancelContextMenu();
};
};
}
},
dragColumn: {
update: function (el, binding, vnode) {
var oDiv = el;
vnode.context.$nextTick(() => {
vnode.context.setHeaderSortable();
})
}
}
},
data() {
return {
refreshKeyId:Math.random().toString(36).substring(3,10),
tableId:this.id?this.id:"XdTable"+Math.random().toString(36).substring(3,10),
// 弹出层标题
title: "显示/隐藏",
// 是否显示弹出层
open: false,
showTable: false,
popVisible:false,
isMouseDown: true, // 是否需要(允许)处理鼠标的移动事件
tbSize:"",
name: '',
config: {
children: [],
attrs: {size:"small"},
listeners: {
},
key: ''
},
tableData:[],
dropCol:[],
sortable:null,
isDragging: false,
startRowIndex: -1,
endRowIndex: -1,
//指令中确定的时候是鼠标按下事件
mouseflag: false,
//选中的数组
multipleSelection: [],
multipleRowSelection:[],
//控制右键菜单弹出显示
contextVisible:false,
//分页当前的页数
currentPage:1 ,
//当前右键点击的列
currentRow:[],
//当前滚动的距离,
targetScroll:0,
//鼠标滑动选中
isSelecting: false, // 是否正在进行选择操作
selectionStart:{rowIndex:-1,cellIndex:-1}, // 选择操作起始单元格位置
selectionEnd:{rowIndex:-1,cellIndex:-1}, // 选择操作结束单元格位置
currentCellInfo:null,
currentSelectStr:null,
currentOdiv:null,
currentCell:null,
checkAll: false, //招标阶段 是否全选
isIndeterminate: false, //全选复选框标识
// 表格个性化记忆配置
isNeedDbSaveTpl:false,
fullUrl:null,
pageId:null,
saveStorageName:this.storageName,
storeTplList:[],
storageList: [],
openTbShowTplDlg:false,
curentTbShowTpl:null,
form:{},
rules: {
tplName: [
{ required: true, message: "模版名称必填", trigger: "blur" }
],
}
}
},
watch: {
'$attrs': {
handler(newV) {
this.$set(this.config, 'attrs', newV)
this.tableData=this.config.attrs.data;
},
deep: true,
immediate: true
},
},
mounted() {
// console.log("===>xdtabe mounted==111->");
if(this.saveStorageName&&this.saveStorageName!=undefined&&this.saveStorageName!=''){
this.isNeedDbSaveTpl=true;
}else{
this.fullUrl=window.location.origin + window.location.pathname + window.location.search + window.location.hash;
this.pageId=this.MD5(this.fullUrl);
this.saveStorageName=this.pageId;
// // console.log("===> this.fullUrl==>", this.fullUrl,this.saveStorageName)
this.isNeedDbSaveTpl=false;
}
// 初始化默认模版到本地
this.initDefaultTplList();
this.initStorage()
this.updateTable()
this.initSort();
this.initKeyDown();
this.tableDom=this.getTableDom();
},
methods: {
getInstance() {
// const ref = this.$children.find(i => i.$options._componentTag === 'el-table')
// return ref
return this.$refs.table.$refs?.elTable
},
getUUID() {
return Math.random().toString(36).substring(3,10);
},
clearSelection(){
this.$nextTick(()=>{
this.$refs.table.$refs.elTable.clearSelection();
});
},
initKeyDown(){
let that=this;
document.addEventListener('keydown', function(e) {
e = e||window.event;
if(e.ctrlKey&&e.code=="KeyC"){
that.handleCopySelect(e);
return false;
}
});
},
onTplSelectInputBlur(e) {
if (e.target.value.trim()!== '') {
//e.target.value就是录入的内容
this.curentTbShowTpl = e.target.value;
this.form.tplName = e.target.value;
// 如果是对象,要使用this.$set方法
// this.$set('typeObj', 'name', e.target.value)
}
},
setTbShowTpl(){
this.openTbShowTplDlg=true;
},
changeSaveTbShowTpl(val){
if(val){
const tplItem = this.storeTplList.find(d => d.tplCode === val)
if(tplItem){
this.form=Object.assign({},tplItem);
}else{
this.form.id=null;
this.form.tplName=val;
}
}else{
this.form = {
id: null,
tplCode: null,
tplName: null,
tplType: null,
tagId: null,
blDefault: null,
tplData: null,
}
this.resetForm("form");
this.form.blDefault='1';
}
},
changeTbShowTpl(val){
if(val){
if(this.storeTplList&&this.storeTplList.length>0){
const tplItem = this.storeTplList.find(d => d.tplCode === val)
// // console.log("===>changeTbShowTpl==111->",tplItem);
this.form=Object.assign({},tplItem);
if(this.form.tplData){
let tplColList=JSON.parse(this.form.tplData);
// 保存模版数据到本地
this.storeTplToLocal(tplColList);
this.initStorage();
this.updateTable();
}
}
}else{
this.form = {
id: null,
tplCode: null,
tplName: null,
tplType: null,
tagId: null,
blDefault: null,
tplData: null,
}
window.localStorage.removeItem('tableStorage');
this.reInitList();
}
},
async initDefaultTplList() {
if(!this.isNeedDbSaveTpl){
return;
}
let queryParams = {
tagId:this.saveStorageName
};
// console.log("===>initDefaultTplList=1111=>");
this.storeTplList=[];
// 获取模版列表
let res=await listSysCustomizeTpl(queryParams)
if(res.rows&&res.rows.length>0){
this.storeTplList=res.rows;
// 设置默认模版
const selTplItem=this.storeTplList.find(item=>item.blDefault == '1' );
if(selTplItem){
this.form=selTplItem;
this.curentTbShowTpl=selTplItem.tplCode;
const tplColList=JSON.parse(this.form.tplData);
// console.log("===>initDefaultTplList=2222=>",tplColList);
// 存储到本地tpl
this.storeTplToLocal(tplColList);
}
}
},
// 矫正模版数据
savaTbShowTpl(){
if(!this.form.tplName){
// this.form.tplName='默认'
this.$modal.msgError("模版名称必填");
return;
}
// 判断模版是否存在,若存在则覆盖
const tmpTplItem=this.storeTplList.find(item=>item.tplName == this.form.tplName );
if(tmpTplItem){
this.form=tmpTplItem;
}
if (this.form.id != null) {
this.curentTbShowTpl=this.form.tplCode;
this.form.tagId=this.saveStorageName;
this.form.tplData=JSON.stringify(this.storageList);
updateSysCustomizeTpl(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.openTbShowTplDlg=false;
this.initDefaultTplList();
this.curentTbShowTpl=this.form.tplCode;
});
} else {
this.form.tplCode=genJsSeqNo();
this.form.tagId=this.saveStorageName;
this.form.tplData=JSON.stringify(this.storageList);
addSysCustomizeTpl(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.openTbShowTplDlg=false;
this.initDefaultTplList();
this.curentTbShowTpl=this.form.tplCode;
});
}
},
delTbShowTpl(){
const ids = this.form.id;
if(!ids || ids==undefined){
this.$modal.msgSuccess("未选择模版");
return;
}
this.$modal.confirm('是否确认删除').then(function() {
return delSysCustomizeTpl(ids);
}).then(() => {
this.curentTbShowTpl=null;
this.initDefaultTplList();
this.openTbShowTplDlg=false;
this.changeTbShowTpl(null);
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
// 获取导出参数
getExportParam(){
// header:[],filter:[]
var header = [];
var filter = [];
this.storageList.forEach(item => {
if (item.show) {
header.push(item.label);
filter.push(item.prop)
}
})
let params={
header: header,
filter: filter
}
return params;
},
// 鼠标框选----------
//当批量选中结束调用
handleBatchSelect(){
let vList = [];
// 按行列排序
if(this.multipleSelection&&this.multipleSelection.length>0){
this.multipleSelection.sort(function(a,b){
if(a.row === b.row){//如果row相同,按照col的升序
return a.col-b.col
}else{
return a.row-b.row
}
})
let selStr="";
let currentRow=-1;
this.multipleSelection.forEach(item=>{
if(currentRow!=-1 && currentRow!=item.row){
// 去除末尾的\t
selStr=this.trimTabChar(selStr,'\t','');
selStr=selStr+"\n";
}
let str=item.text;
if(!str || str==''){
str='';
}
selStr = selStr+str+"\t";
currentRow=item.row;
});
selStr=this.trimTabChar(selStr,'\t','');
// // console.log("=selStr==>",selStr);
this.currentSelectStr=selStr;
}
// this.$emit('handleSelect',this.multipleSelection)
},
getCellInfo(cell) {
try{
while(cell.tagName !== 'TD'){
cell = cell.parentElement;
}
const rowIndex = cell.parentElement.rowIndex;
const cellIndex = cell.cellIndex;
const text = cell.innerText;
return { row:rowIndex,col: cellIndex ,text:text};
}catch(e){
return { rowIndex:-1,cellIndex:-1};
}
},
// 复制选中数据
handleCopySelect(event) {
this.contextVisible=false;
if(this.currentSelectStr){
if (navigator.clipboard && window.isSecureContext) {
// navigator clipboard 向剪贴板写文本
this.$modal.msgSuccess('复制成功')
return navigator.clipboard.writeText(this.currentSelectStr)
} else {
// 创建text area
const textArea = document.createElement('textarea')
textArea.value = this.currentSelectStr
// 使text area不在viewport,同时设置不可见
document.body.appendChild(textArea)
textArea.focus()
textArea.select()
this.$modal.msgSuccess('复制成功')
return new Promise((res, rej) => {
// 执行复制命令并移除文本框
document.execCommand('copy') ? res() : rej()
textArea.remove()
})
}
}
},
// 选择整行
handleSelectCurrentRow(evt){
this.contextVisible=false;
var fileNodes = this.currentOdiv.getElementsByTagName("td");
if(this.currentCellInfo){
this.multipleSelection=[];
for (var i = 0; i < fileNodes.length; i++) {
const selItem=fileNodes[i];
if (selItem.className.indexOf("el-table__cell") != -1 && selItem.parentElement.rowIndex == this.currentCellInfo.row ) {
selItem.className = selItem.className + " seled";
const cellInfo=this.getCellInfo(selItem);
this.multipleSelection.push(cellInfo);
}else{
selItem.classList.remove("seled");
}
}
}
},
// 选择整列
handleSelectCurrentColumn(evt){
this.contextVisible=false;
var fileNodes = this.currentOdiv.getElementsByTagName("td");
if(this.currentCellInfo){
this.multipleSelection=[];
for (var i = 0; i < fileNodes.length; i++) {
const selItem=fileNodes[i];
if (selItem.className.indexOf("el-table__cell") != -1 && selItem.cellIndex == this.currentCellInfo.col ) {
selItem.className = selItem.className + " seled";
const cellInfo=this.getCellInfo(selItem);
this.multipleSelection.push(cellInfo);
}else{
selItem.classList.remove("seled");
}
}
}
},
trimTabChar(str,char, type) {
if (char) {
if (type == 'left') {
return str.replace(new RegExp('^\\'+char+'+', 'g'), '');
} else if (type == 'right') {
return str.replace(new RegExp('\\'+char+'+$', 'g'), '');
}
return str.replace(new RegExp('^\\'+char+'+|\\'+char+'+$', 'g'), '');
}
return str.replace(/^\s+|\s+$/g, '');
},
// ---------------
//清除默认事件
clearEventBubble(evt) {
if (evt.stopPropagation)
evt.stopPropagation();
else
evt.cancelBubble = true;
if (evt.preventDefault)
evt.preventDefault();
else
evt.returnValue = false;
},
getTableDom() {
return this.$refs.table.$refs.elTable.$el;
},
getTablePosition() {
return this.tableDom.getBoundingClientRect();
},
handleCopy(text, event) {
clip(text, event)
},
setHeaderSortable(){
let that=this;
this.$nextTick(function () {
const wrapperTr = document.querySelector('#'+that.tableId+' .el-table__header-wrapper > table > thead > tr');
// // console.log("===>wrapperTr==>",wrapperTr);
if(wrapperTr){
Sortable.create(wrapperTr, {
animation: 100,
delay: 50,
dragClass: "dragClass",
ghostClass: "ghostClass",
chosenClass: "chosenClass",
onStart: () => {
},
// 结束拖动事件
onEnd: ({ newIndex, oldIndex }) => {
let arr = that.storageList;
const currCol = arr.splice(oldIndex-1, 1)[0];
arr.splice(newIndex-1, 0, currCol);
that.storageList = arr;
that.updateTable();
// this.refreshKeyId=Math.random().toString(36).substring(3,10);
// const currCol = vnode.context.storageList.splice(oldIndex-1, 1)[0];
// vnode.context.storageList.splice(newIndex-1, 0, currCol);
// vnode.context.updateTable();
},
});
}
})
},
// 定义方法 isEqual 来比较两个选中数据对象是否相同
isEqual(data1, data2) {
return (
data1.rowId === data2.rowId &&
data1.column === data2.column &&
data1.sampleTime === data2.sampleTime &&
data1.factor === data2.factor
);
},
// 重新初始化
reInitList() {
let list=[];
this.$vnode.componentOptions.children.forEach(node => {
// 以prop为准,因为可能会改文本
if (!(!node.componentOptions || node.componentOptions.propsData.type) && list.findIndex(i => i.prop === node.componentOptions.propsData.prop) < 0) {
// 非插槽且 不是特殊类型的 找不到就加上
const propsData = JSON.parse(JSON.stringify(node.componentOptions.propsData))
if (propsData.fixed === undefined || propsData.fixed === false) {
propsData.fixed = false
} else {
propsData.fixed = propsData.fixed ? propsData.fixed : 'left'
}
list.push({
fixed: false, // 默认新增的都是不固定
show: true, // 默认新增的都是显示的
...propsData
})
}
})
this.storeTplToLocal(list)
this.initStorage()
this.updateTable()
this.initSort();
},
download(){
this.$emit("download");
},
initSort() {
},
// 查询
queryTable(){
this.$emit("queryTable");
},
// 显示搜索
toggleSearch() {
this.$emit("update:showSearch", !this.showSearch);
},
// 刷新
refresh() {
this.$emit("queryTable");
},
// 打开显隐列
showColumn() {
this.open = true;
},
delStorage() {
this.$confirm('是否恢复默认设置?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
const storage = window.localStorage.getItem('tableStorage') ? JSON.parse(window.localStorage.getItem('tableStorage')) : {}
storage[this.saveStorageName] = []
window.localStorage.setItem('tableStorage', JSON.stringify(storage))
this.changeSaveTbShowTpl(null);
this.reInitList();
})
},
handleCheckAllChange(isCheckAll){
if(isCheckAll){
this.storageList.forEach(col=>{
col.show = true
});
}else{
this.storageList.forEach((col,index)=>{
if(index!=0){
col.show = false;
}
});
}
this.updateTable();
},
showOrHidden(val, clo) {
if (!val && this.storageList.filter(i => i.show).length === 0) {
this.$message.warning('列表最少显示一列')
this.$nextTick(() => {
clo.show = true
})
return
}
this.updateTable()
},
setFixed(value, clo) {
if (clo.fixed === value) {
clo.fixed = false
} else {
clo.fixed = value
}
this.updateTable()
},
// 更多操作触发
handleAdjustTableSize(command) {
//size:mini/small/medium;
// // console.log(this.config);
switch (command) {
case "small":
this.config.attrs.size='small';
break;
case "mini":
this.config.attrs.size='mini';
break;
case "medium":
this.config.attrs.size='medium';
break;
default:
break;
}
this.updateTable();
},
// 初始化缓存配置
initStorage() {
this.storageList = []
let list = [];
const storage = window.localStorage.getItem('tableStorage') ? JSON.parse(window.localStorage.getItem('tableStorage')) : {}
if(this.showCustomizeTpl && this.saveStorageName!=undefined && this.saveStorageName!=''){
list = storage[this.saveStorageName] ? storage[this.saveStorageName] : []
}
// 不管是否初次还是要做一下处理,万一页面有修改,做一下更新,以最新的node节点数组为准
this.$vnode.componentOptions.children.forEach(node => {
// 以prop为准,因为可能会改文本
if (!(!node.componentOptions || node.componentOptions.propsData.type) && list.findIndex(i => i.prop === node.componentOptions.propsData.prop) < 0) {
// 非插槽且 不是特殊类型的 找不到就加上
const propsData = JSON.parse(JSON.stringify(node.componentOptions.propsData))
if (propsData.fixed === undefined || propsData.fixed === false) {
propsData.fixed = false
} else {
propsData.fixed = propsData.fixed ? propsData.fixed : 'left'
}
list.push({
fixed: false, // 默认新增的都是不固定
show: true, // 默认新增的都是显示的
...propsData
})
}
})
// 必须在节点数组存在的才有意义
list = list.filter(item => this.$vnode.componentOptions.children.find(n => {
return n.componentOptions && n.componentOptions.propsData.label && item.prop === n.componentOptions.propsData.prop
}))
// 去除重复数据
let map = new Map();
let list2 = []; // 数组用于返回结果
for (let i = 0; i < list.length; i++) {
if(map.has(list[i].prop)) { // 如果有该key值
map.set(list[i].prop, true);
} else {
map.set(list[i].prop, false); // 如果没有该key值
// 必须要存在 列名称才处理
if(list[i].label){
list2.push(list[i]);
}
}
}
list=list2;
console.log("===>list=1111=>",list);
this.storageList = list
},
// 根据缓存的数组进行渲染表格
updateTable() {
// 特殊类型
const childrenNodes = this.$vnode.componentOptions.children.filter(node => node.componentOptions && node.componentOptions.propsData.type)
this.storageList.forEach(item => {
if (item.show) {
const node = this.$vnode.componentOptions.children.find(n => n.componentOptions && n.componentOptions.propsData.prop === item.prop)
if (node) {
let nodeItem=node.componentOptions.propsData;
if(item.label != nodeItem.label){
item.label=nodeItem.label;
}
node.componentOptions.propsData.fixed = item.fixed
childrenNodes.push(node)
}
}
})
this.config.children = childrenNodes
this.config.attrs = this.$attrs
this.config.listeners = this.$listeners;
// 通过key值触发表格刷新,避免拖拽由于数组长度一致导致diff算法无法识别
// this.config.key = Math.random() + ''
// 控制下表格重新刷新
this.getInstance()?.doLayout()
if(this.showCustomizeTpl){
this.storeTplToLocal(this.storageList);
}else{
// 清除本地缓存
// window.localStorage.removeItem('tableStorage')
}
},
storeTplToLocal(tplColList){
const storage = window.localStorage.getItem('tableStorage') ? JSON.parse(window.localStorage.getItem('tableStorage')) : {}
storage[this.saveStorageName] = tplColList
window.localStorage.setItem('tableStorage', JSON.stringify(storage))
},
/** 导出excel文件操作 */
exportData(fileName,dataList,formatJson,loadingInstance){
const curList =dataList
import('@/vendor/Export2Excel').then(excel => {
const exportParam=this.getExportParam();
const tHeader = exportParam.header;
const filterVal = exportParam.filter;
const data = formatJson(filterVal, curList, selData)
excel.export_json_to_excel({
header: tHeader,
data,
filename: fileName,
autoWidth: true
})
loadingInstance.close()
})
},
}
}
</script>
<style lang="scss" scoped>
.table-cloumn-setting-popper{
.setting-row-content{
max-height: 600px;
overflow-y: auto;
//overflow-y: hidden;
.setting-row{
height: 30px;
line-height: 30px;
.el-icon-s-operation{
cursor: move;
font-size: 16px;
margin-right: 8px;
}
.label{
margin-right: 8px;
}
.btn{
padding: 4px!important;
}
}
}
}
.xd-table{
width:100%;
height:100%;
position: relative;
.el-icon-setting{
position: absolute;
right: 7px;
top: 5px;
cursor: pointer;
}
.table-operate-btn-content{
// width: calc(100% - 40px);
width: 100%;
// min-height: 28px; // 给一个最低的高度,防止没有插槽,右侧icon被吞
min-height: 40px; // 给一个最低的高度,防止没有插槽,右侧icon被吞
.operate-btn-content {
display: flex;
justify-content: space-between;
align-items: center;
min-height: 28px;
padding-bottom: 6px;
}
}
.parent:has(.child){
background-color: #eee;
}
}
.pagination-container{
padding: 0px 20px !important;
}
.menuDiv {
position: absolute;
background-color: #fff;
width: 100px;
/*height: 106px;*/
}
:deep .seled{
background-color: #51dd397d !important;
color: black;
font-weight: 600;
}
:deep .rowSeled{
background-color: #ffa5a55e !important;
color: black;
font-weight: 600;
}
.xd-tb-wrapper :deep .el-table__body tr:hover > td {
background-color: #ffa5a55e !important;
}
.xd-tb-wrapper{
-webkit-user-select: none; /* Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none;
}
.drag-ghost { background-color: #e7e7e77d; }
.drag-chosen { background-color: #e7e7e77d; }
// 拖拽
.dragClass {
background: rgba($color: #41c21a, $alpha: 0.5) !important;
}
// 停靠
.ghostClass {
background: rgba($color: #6cacf5, $alpha: 0.5) !important;
}
// 选择
.chosenClass:hover > td {
background: rgba($color: #f56c6c, $alpha: 0.5) !important;
}
.el-table__body tr.current-row > td {
background-color: #78f709 !important;
}
.el-table--enable-row-hover .el-table__body tr:hover > td {
background-color: #f6d604 !important;
cursor:pointer;
}
</style>