470 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Vue
		
	
	
			
		
		
	
	
			470 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Vue
		
	
	
<template>
 | 
						|
  <div class="crud-opts">
 | 
						|
    <span class="crud-opts-left">
 | 
						|
      <!--左侧插槽-->
 | 
						|
      <slot name="left" />
 | 
						|
      <el-button
 | 
						|
        v-if="crud.optShow.add"
 | 
						|
        v-permission="permission.add"
 | 
						|
        class="filter-item"
 | 
						|
        size="mini"
 | 
						|
        type="primary"
 | 
						|
        icon="el-icon-plus"
 | 
						|
        @click="crud.toAdd"
 | 
						|
      >
 | 
						|
        新增
 | 
						|
      </el-button>
 | 
						|
      <el-button
 | 
						|
        v-if="crud.optShow.edit"
 | 
						|
        v-permission="permission.edit"
 | 
						|
        class="filter-item"
 | 
						|
        size="mini"
 | 
						|
        type="success"
 | 
						|
        icon="el-icon-edit"
 | 
						|
        :disabled="crud.selections.length !== 1"
 | 
						|
        @click="crud.toEdit(crud.selections[0])"
 | 
						|
      >
 | 
						|
        修改
 | 
						|
      </el-button>
 | 
						|
      <el-button
 | 
						|
        v-if="crud.optShow.del"
 | 
						|
        slot="reference"
 | 
						|
        v-permission="permission.del"
 | 
						|
        class="filter-item"
 | 
						|
        type="danger"
 | 
						|
        icon="el-icon-delete"
 | 
						|
        size="mini"
 | 
						|
        :loading="crud.delAllLoading"
 | 
						|
        :disabled="crud.selections.length === 0"
 | 
						|
        @click="toDelete(crud.selections)"
 | 
						|
      >
 | 
						|
        删除
 | 
						|
      </el-button>
 | 
						|
      <el-button
 | 
						|
        v-if="crud.optShow.download"
 | 
						|
        :loading="crud.downloadLoading"
 | 
						|
        :disabled="!crud.data.length"
 | 
						|
        class="filter-item"
 | 
						|
        size="mini"
 | 
						|
        type="warning"
 | 
						|
        icon="el-icon-download"
 | 
						|
        @click="crud.doExport"
 | 
						|
      >导出</el-button>
 | 
						|
      <!--右侧-->
 | 
						|
      <slot name="right" />
 | 
						|
    </span>
 | 
						|
    <el-button-group class="crud-opts-right">
 | 
						|
      <el-button
 | 
						|
        size="mini"
 | 
						|
        plain
 | 
						|
        type="info"
 | 
						|
        icon="el-icon-search"
 | 
						|
        @click="toggleSearch()"
 | 
						|
      />
 | 
						|
      <el-button
 | 
						|
        size="mini"
 | 
						|
        icon="el-icon-refresh"
 | 
						|
        @click="crud.refresh()"
 | 
						|
      />
 | 
						|
      <el-popover
 | 
						|
        placement="bottom-end"
 | 
						|
        width="150"
 | 
						|
        trigger="click"
 | 
						|
      >
 | 
						|
        <el-button
 | 
						|
          slot="reference"
 | 
						|
          size="mini"
 | 
						|
          icon="el-icon-s-grid"
 | 
						|
        >
 | 
						|
          <i
 | 
						|
            class="fa fa-caret-down"
 | 
						|
            aria-hidden="true"
 | 
						|
          />
 | 
						|
        </el-button>
 | 
						|
        <el-checkbox
 | 
						|
          v-model="allColumnsSelected"
 | 
						|
          :indeterminate="allColumnsSelectedIndeterminate"
 | 
						|
          @change="handleCheckAllChange"
 | 
						|
        >
 | 
						|
          全选
 | 
						|
        </el-checkbox>
 | 
						|
        <el-checkbox
 | 
						|
          v-for="item in tableColumns"
 | 
						|
          :key="item.property"
 | 
						|
          v-model="item.visible"
 | 
						|
          @change="handleCheckedTableColumnsChange(item)"
 | 
						|
        >
 | 
						|
          {{ item.label }}
 | 
						|
        </el-checkbox>
 | 
						|
      </el-popover>
 | 
						|
      <el-button
 | 
						|
        size="mini"
 | 
						|
        type="warning" plain
 | 
						|
        @click="postToTableConfig()"
 | 
						|
      ><span>保存</span></el-button>
 | 
						|
    </el-button-group>
 | 
						|
  </div>
 | 
						|
</template>
 | 
						|
<script>
 | 
						|
import CRUD, { crud } from '@crud/crud'
 | 
						|
import crudTableConfig from '@/api/tableConfig'
 | 
						|
import Sortable from 'sortablejs'
 | 
						|
 | 
						|
function sortWithRef(src, ref) {
 | 
						|
  const result = Object.assign([], ref)
 | 
						|
  let cursor = -1
 | 
						|
  src.forEach(e => {
 | 
						|
    const idx = result.indexOf(e)
 | 
						|
    if (idx === -1) {
 | 
						|
      cursor += 1
 | 
						|
      result.splice(cursor, 0, e)
 | 
						|
    } else {
 | 
						|
      cursor = idx
 | 
						|
    }
 | 
						|
  })
 | 
						|
  return result
 | 
						|
}
 | 
						|
 | 
						|
export default {
 | 
						|
  mixins: [crud()],
 | 
						|
  props: {
 | 
						|
    permission: {
 | 
						|
      type: Object,
 | 
						|
      default: () => { return {} }
 | 
						|
    },
 | 
						|
    ignoreColumns: {
 | 
						|
      type: Array,
 | 
						|
      default: () => { return [] }
 | 
						|
    },
 | 
						|
    tableKey: {
 | 
						|
      type: String,
 | 
						|
      default: () => { return '' }
 | 
						|
    }
 | 
						|
  },
 | 
						|
  data() {
 | 
						|
    return {
 | 
						|
      hiddenColumns:[],
 | 
						|
      table_configs:[],
 | 
						|
      table_configs_xs:[],
 | 
						|
      tableColumns: [],
 | 
						|
      allColumnsSelected: true,
 | 
						|
      allColumnsSelectedIndeterminate: false,
 | 
						|
      tableUnwatcher: null,
 | 
						|
      // 忽略下次表格列变动
 | 
						|
      ignoreNextTableColumnsChange: false
 | 
						|
    }
 | 
						|
  },
 | 
						|
  watch: {
 | 
						|
    'crud.props.table'() {
 | 
						|
      this.updateTableColumns()
 | 
						|
      this.tableColumns.forEach(column => {
 | 
						|
        //选中框
 | 
						|
 | 
						|
      })
 | 
						|
    },
 | 
						|
    'crud.props.table.store.states.columns'() {
 | 
						|
      this.updateTableColumns()
 | 
						|
    }
 | 
						|
  },
 | 
						|
  created() {
 | 
						|
    this.crud.updateProp('searchToggle', true)
 | 
						|
  },
 | 
						|
  mounted() {
 | 
						|
    //初始化数据
 | 
						|
    this.columnDrop();
 | 
						|
    setTimeout(() => {
 | 
						|
      // 方法区
 | 
						|
      this.initcolumn();
 | 
						|
    }, 200)
 | 
						|
 | 
						|
 | 
						|
  },
 | 
						|
  methods: {
 | 
						|
    initcolumn() {
 | 
						|
      this.updateTableColumns()
 | 
						|
      const strHidden = sessionStorage.getItem(this.tableKey)
 | 
						|
 | 
						|
      // 检查 sessionStorage 值是否存在
 | 
						|
      if (!strHidden) {
 | 
						|
        this.hiddenColumns = []
 | 
						|
        return
 | 
						|
      }
 | 
						|
 | 
						|
      // 安全解析 JSON 数据
 | 
						|
      try {
 | 
						|
        this.hiddenColumns = JSON.parse(strHidden) || []
 | 
						|
      } catch (error) {
 | 
						|
        this.hiddenColumns = []
 | 
						|
        return
 | 
						|
      }
 | 
						|
 | 
						|
      if (this.hiddenColumns.length > 0) {
 | 
						|
        const table = this.crud.props.table
 | 
						|
 | 
						|
        // 预先构建 label 到 column 的映射,提高查找效率
 | 
						|
        const labelToColumnMap = {}
 | 
						|
        if (table && table.$children) {
 | 
						|
          table.$children.forEach(child => {
 | 
						|
            if (child.label) {
 | 
						|
              labelToColumnMap[child.label] = child
 | 
						|
            }
 | 
						|
          })
 | 
						|
        }
 | 
						|
 | 
						|
        this.table_configs_xs.forEach((column, index) => {
 | 
						|
          const vm = labelToColumnMap[column.label]
 | 
						|
 | 
						|
          // 检查元素是否存在
 | 
						|
          if (!vm) {
 | 
						|
            return
 | 
						|
          }
 | 
						|
 | 
						|
          const columnConfig = vm.columnConfig
 | 
						|
 | 
						|
          // 检查 columnConfig 是否有效
 | 
						|
          if (!columnConfig) {
 | 
						|
            return
 | 
						|
          }
 | 
						|
 | 
						|
          if (vm.owner && vm.owner.store) {
 | 
						|
            vm.owner.store.commit('removeColumn', columnConfig, null)
 | 
						|
          }
 | 
						|
        })
 | 
						|
 | 
						|
        this.ignoreNextTableColumnsChange = false
 | 
						|
 | 
						|
        setTimeout(() => {
 | 
						|
          // 方法区
 | 
						|
          this.showcolumn()
 | 
						|
        }, 200)
 | 
						|
      }
 | 
						|
    },
 | 
						|
    showcolumn() {
 | 
						|
      console.log("------显示列------")
 | 
						|
      const strHidden=sessionStorage.getItem(this.tableKey)
 | 
						|
      this.hiddenColumns= JSON.parse(strHidden);
 | 
						|
      const table = this.crud.props.table
 | 
						|
      this.hiddenColumns.forEach((column,index) => {
 | 
						|
 | 
						|
        const vm = table.$children.find(e => e.prop === column.property)
 | 
						|
        const columnConfig = vm.columnConfig
 | 
						|
        console.log(columnConfig.label)
 | 
						|
        if(column.visible){
 | 
						|
          columnConfig.width=column.width
 | 
						|
          columnConfig.visible=column.visible
 | 
						|
          vm.owner.store.commit('insertColumn', columnConfig, index+1  , null)
 | 
						|
        }
 | 
						|
      })
 | 
						|
      console.log("------显示列完成------")
 | 
						|
      this. updateTableColumns();
 | 
						|
    },
 | 
						|
    //列拖拽
 | 
						|
    columnDrop() {
 | 
						|
      const wrapperTr = document.querySelector('.el-table__header-wrapper tr')
 | 
						|
      this.sortable = Sortable.create(wrapperTr, {
 | 
						|
        animation: 180,
 | 
						|
        delay: 0,
 | 
						|
        onEnd: evt => {
 | 
						|
          // 根据中文label进行拖拉
 | 
						|
          this.ColumnsDrop(evt.item.innerText,evt.newIndex)
 | 
						|
        }
 | 
						|
      })
 | 
						|
    },
 | 
						|
 | 
						|
    //新加方法
 | 
						|
    ColumnsDrop(oldText,newIndex) {
 | 
						|
      const table = this.crud.props.table
 | 
						|
      let myindex = -1 //空格
 | 
						|
      let oldIndex1 = 0
 | 
						|
      let  step = -1
 | 
						|
      let count = 0
 | 
						|
      //
 | 
						|
      this.tableColumns.some((column,index) => {
 | 
						|
        if(column.visible) {
 | 
						|
          count++
 | 
						|
        }
 | 
						|
      })
 | 
						|
      // 定位拖拉中文表头位置以及在该字段之前隐藏字段数量
 | 
						|
      this.tableColumns.some((column,index) => {
 | 
						|
        if(column.label === oldText) {
 | 
						|
          oldIndex1 = index
 | 
						|
          return true
 | 
						|
        }else{
 | 
						|
          // 空格在字段前面
 | 
						|
          if(step>index){
 | 
						|
            myindex++
 | 
						|
          }
 | 
						|
        }
 | 
						|
        step++
 | 
						|
      })
 | 
						|
      if (myindex === -1  ) {
 | 
						|
        myindex = 0
 | 
						|
      }
 | 
						|
      let item= this.tableColumns[oldIndex1]
 | 
						|
      const vm = table.$children.find(e => e.prop === item.property)
 | 
						|
      const columnConfig = vm.columnConfig
 | 
						|
      /*this.tableColumns.splice(oldIndex1-1, 1)
 | 
						|
      this.tableColumns.splice(myindex-1, 0, item)*/
 | 
						|
      if(oldIndex1 <newIndex){ // 从左至右拖动
 | 
						|
        vm.owner.store.commit('insertColumn', columnConfig, newIndex+myindex  , null)
 | 
						|
        vm.owner.store.commit('removeColumn', columnConfig, null)
 | 
						|
      }else { //从右至左拖动
 | 
						|
        vm.owner.store.commit('removeColumn', columnConfig, null)
 | 
						|
        vm.owner.store.commit('insertColumn', columnConfig, newIndex+myindex  , null)
 | 
						|
      }
 | 
						|
      // 列重新排序
 | 
						|
      this.ignoreNextTableColumnsChange = false
 | 
						|
    },
 | 
						|
    updateTableColumns() {
 | 
						|
      const table = this.crud.getTable()
 | 
						|
      table.doLayout()
 | 
						|
      if (!table) {
 | 
						|
        this.tableColumns = []
 | 
						|
        return
 | 
						|
      }
 | 
						|
      let cols = null
 | 
						|
      const columnFilter = e => e && (e.type === 'default' || e.type === 'index') && e.property && this.ignoreColumns.indexOf(e.property) === -1
 | 
						|
      const refCols = table.columns.filter(columnFilter)
 | 
						|
      if (this.ignoreNextTableColumnsChange) {
 | 
						|
        this.ignoreNextTableColumnsChange = false
 | 
						|
        return
 | 
						|
      }
 | 
						|
      this.ignoreNextTableColumnsChange = false
 | 
						|
      const columns = []
 | 
						|
      const fullTableColumns = table.$children.map(e => e.columnConfig).filter(columnFilter)
 | 
						|
      cols = sortWithRef(fullTableColumns, refCols)
 | 
						|
      cols.forEach(config => {
 | 
						|
 | 
						|
        const column = {
 | 
						|
          property: config.property,
 | 
						|
          label: config.label,
 | 
						|
          width: config.width,
 | 
						|
          visible: refCols.indexOf(config) !== -1
 | 
						|
        }
 | 
						|
        columns.push(column)
 | 
						|
      })
 | 
						|
      this.tableColumns = columns
 | 
						|
      this.table_configs_xs = columns
 | 
						|
    },
 | 
						|
    toDelete(datas) {
 | 
						|
      this.$confirm(`确认删除选中的${datas.length}条数据?`, '提示', {
 | 
						|
        confirmButtonText: '确定',
 | 
						|
        cancelButtonText: '取消',
 | 
						|
        type: 'warning'
 | 
						|
      }).then(() => {
 | 
						|
        this.crud.delAllLoading = true
 | 
						|
        this.crud.doDelete(datas)
 | 
						|
      }).catch(() => {
 | 
						|
      })
 | 
						|
    },
 | 
						|
    handleCheckAllChange(val) {
 | 
						|
      if (val === false) {
 | 
						|
        this.allColumnsSelected = true
 | 
						|
        return
 | 
						|
      }
 | 
						|
      this.tableColumns.forEach(column => {
 | 
						|
        if (!column.visible) {
 | 
						|
          column.visible = true
 | 
						|
          this.updateColumnVisible(column)
 | 
						|
        }
 | 
						|
      })
 | 
						|
      //this.postToTableConfig()
 | 
						|
      this.allColumnsSelected = val
 | 
						|
      this.allColumnsSelectedIndeterminate = false
 | 
						|
    },
 | 
						|
    handleCheckedTableColumnsChange(item) {
 | 
						|
      let totalCount = 0
 | 
						|
      let selectedCount = 0
 | 
						|
      this.tableColumns.forEach(column => {
 | 
						|
        ++totalCount
 | 
						|
        selectedCount += column.visible ? 1 : 0
 | 
						|
      })
 | 
						|
      if (selectedCount === 0) {
 | 
						|
        this.crud.notify('请至少选择一列', CRUD.NOTIFICATION_TYPE.WARNING)
 | 
						|
        this.$nextTick(function() {
 | 
						|
          item.visible = true
 | 
						|
        })
 | 
						|
        return
 | 
						|
      }
 | 
						|
      this.allColumnsSelected = selectedCount === totalCount
 | 
						|
      this.allColumnsSelectedIndeterminate = selectedCount !== totalCount && selectedCount !== 0
 | 
						|
      this.updateColumnVisible(item)
 | 
						|
      /*const columns = []
 | 
						|
      this.tableColumns.forEach(column => {
 | 
						|
        if(column.visible==false){
 | 
						|
          columns.push(column.property)
 | 
						|
        }
 | 
						|
        console.log("-"+column.property+"--"+column.visible)
 | 
						|
      })
 | 
						|
      const post_table_config = {
 | 
						|
        value: JSON.stringify(columns),
 | 
						|
        tableType: this.tableKey
 | 
						|
      }
 | 
						|
 | 
						|
      crudTableConfig.add(post_table_config)*/
 | 
						|
      //this.postToTableConfig();
 | 
						|
    },
 | 
						|
    postToTableConfig(){
 | 
						|
      this. updateTableColumns();
 | 
						|
      const columns = []
 | 
						|
      this.tableColumns.forEach(column => {
 | 
						|
        const table_config = {
 | 
						|
          property: column.property,
 | 
						|
          visible: column.visible,
 | 
						|
          width: column.width,
 | 
						|
          label: column.label
 | 
						|
        }
 | 
						|
        columns.push(table_config)
 | 
						|
      })
 | 
						|
      const post_table_config = {
 | 
						|
        value: JSON.stringify(columns),
 | 
						|
        tableType: this.tableKey
 | 
						|
      }
 | 
						|
 | 
						|
      this.crud.loading=true
 | 
						|
      crudTableConfig.add(post_table_config).then(res => {
 | 
						|
        setTimeout(() => {
 | 
						|
          // 方法区
 | 
						|
          this.crud.loading=false
 | 
						|
        }, 500)
 | 
						|
 | 
						|
      })
 | 
						|
 | 
						|
 | 
						|
      sessionStorage.setItem(this.tableKey, JSON.stringify(columns));
 | 
						|
    },
 | 
						|
    updateColumnVisible(item) {
 | 
						|
      const table = this.crud.props.table
 | 
						|
      const vm = table.$children.find(e => e.prop === item.property)
 | 
						|
      const columnConfig = vm.columnConfig
 | 
						|
      if (item.visible) {
 | 
						|
        // 找出合适的插入点
 | 
						|
        const columnIndex = this.tableColumns.indexOf(item)
 | 
						|
        vm.owner.store.commit('insertColumn', columnConfig, columnIndex+1, null)
 | 
						|
      } else {
 | 
						|
        vm.owner.store.commit('removeColumn', columnConfig, null)
 | 
						|
      }
 | 
						|
      this.ignoreNextTableColumnsChange = true
 | 
						|
    },
 | 
						|
    toggleSearch() {
 | 
						|
      this.crud.props.searchToggle = !this.crud.props.searchToggle
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
</script>
 | 
						|
 | 
						|
<style>
 | 
						|
.crud-opts {
 | 
						|
  padding: 4px 0;
 | 
						|
  display: -webkit-flex;
 | 
						|
  display: flex;
 | 
						|
  align-items: center;
 | 
						|
}
 | 
						|
.crud-opts .crud-opts-right {
 | 
						|
  margin-left: auto;
 | 
						|
}
 | 
						|
.crud-opts .crud-opts-right span {
 | 
						|
  float: left;
 | 
						|
}
 | 
						|
</style>
 |