123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- <template>
- <div class="hc-table-ref-box" :class="ui">
- <el-table ref="tableRef" hc :data="tableData" :height="heights" v-loading="isLoading" stripe :row-key="rowKey" :border="isBorder" :highlight-current-row="isCurrentRow" @selection-change="tableSelectionChange"
- @row-click="tableRowClick" @row-dblclick="tableRowDblClick" @row-contextmenu="tableRowContextmenu" @cell-click="tableCellClick" @cell-dblclick="tableCellDblClick"
- @cell-contextmenu="tableCellContextmenu" style="width: 100%;">
- <el-table-column type="selection" width="50" v-if="isCheck"/>
- <el-table-column type="index" prop="num" label="序号" width="80" v-if="isIndex && !isSlotNum">
- <template #default="scope">
- <div class="table-column-sort">
- <span class="mr-3">{{scope.$index + 1}}</span>
- <template v-if="isDataSort">
- <span class="text-link text-lg">
- <HcIcon name="arrow-up" @click="upSortClick(scope.$index)"/>
- </span>
- <span class="text-link text-lg">
- <HcIcon name="arrow-down" @click="downSortClick(scope.$index)"/>
- </span>
- </template>
- </div>
- </template>
- </el-table-column>
- <el-table-column type="index" prop="num" width="100" v-if="isIndex && isSlotNum">
- <template #header>
- <div class="table-column-header-num">
- <span class="mr-3">序号</span>
- <slot name='table-column-header-num'></slot>
- </div>
- </template>
- </el-table-column>
- <template v-for="item in columns">
- <el-table-column :prop="item.key" :label="item.name" :align="item.align ?? 'left'" :width="item.width ?? ''" :fixed="item.fixed ?? false">
- <template #default="scope" v-if="item.isSlot">
- <slot :name='item.key' :row="scope.row" :index="scope.$index"/>
- </template>
- </el-table-column>
- </template>
- </el-table>
- </div>
- </template>
- <script setup>
- import {ref,watch,nextTick,useSlots} from "vue";
- import Sortable from 'sortablejs'
- const props = defineProps({
- ui: {
- type: String,
- default: ''
- },
- column: {
- type: Array,
- default: () => ([])
- },
- datas: {
- type: Array,
- default: () => ([])
- },
- loading: {
- type: Boolean,
- default: false
- },
- isCheck: {
- type: Boolean,
- default: false
- },
- isIndex: {
- type: Boolean,
- default: true
- },
- rowKey: {
- type: String,
- default: 'id'
- },
- border: {
- type: Boolean,
- default: false
- },
- isRowDrop: {
- type: Boolean,
- default: false
- },
- isCurrentRow: {
- type: Boolean,
- default: false
- },
- heights: {
- type: String,
- default: '100%'
- },
- isSort: {
- type: Boolean,
- default: false
- },
- })
- //初始变量
- const tableRef = ref(null)
- const columns = ref(props.column)
- const tableData = ref(props.datas)
- const isLoading = ref(props.loading)
- const isBorder = ref(props.border)
- const isDataSort = ref(props.isSort)
- //监听
- watch(() => [
- props.datas,
- props.loading,
- props.border,
- props.isSort,
- ], ([datas, loading, border, isSort]) => {
- tableData.value = datas;
- isLoading.value = loading;
- isBorder.value = border;
- isDataSort.value = isSort;
- })
- //监听表头
- watch(() => [
- props.column
- ], ([column]) => {
- columns.value = column;
- setIsSlots()
- })
- //加载完成
- nextTick(()=>{
- setIsSlots()
- if (props.isRowDrop && props.ui) {
- tableRowDropInit(props.ui)
- }
- })
- //判断<slot>是否有传值
- const slots = useSlots()
- const isSlotNum = !!slots['table-column-header-num']
- const setIsSlots = () => {
- let arr = columns.value
- for (let i = 0; i < arr.length; i++) {
- arr[i].isSlot = !!slots[arr[i].key]
- }
- columns.value = arr
- }
- //事件
- const emit = defineEmits([
- 'selection-change', 'row-drop', 'row-sort',
- 'row-click', 'row-dblclick', 'row-contextmenu',
- 'cell-click', 'cell-dblclick', 'cell-contextmenu'
- ])
- //清空多选
- const clearSelection = () => {
- tableRef.value?.clearSelection()
- emit('selection-change', [])
- }
- //返回当前选中的行
- const getSelectionRows = () => {
- tableRef.value?.getSelectionRows()
- }
- //用于多选表格,切换某一行的选中状态, 如果使用了第二个参数,则可直接设置这一行选中与否
- const toggleRowSelection = (row, selected) => {
- tableRef.value?.toggleRowSelection(row, selected)
- }
- //多选
- const tableSelectionChange = (rows) => {
- let tableRows = rows.filter((item) => {
- return (item??'') !== '';
- })
- emit('selection-change', tableRows)
- }
- //拖动排序处理
- const tableRowDropInit = (ui) => {
- const tbody = document.querySelector(`.${ui} .el-table__body-wrapper tbody`)
- Sortable.create(tbody, {
- onEnd({ newIndex, oldIndex }) {
- const rows = tableData.value
- const currRow = rows.splice(oldIndex, 1)[0]
- rows.splice(newIndex, 0, currRow)
- tableData.value = rows
- emit('row-drop', rows)
- }
- })
- }
- //当某一行被点击时会触发该事件
- const tableRowClick = (row, column, event) => {
- emit('row-click', {row, column, event})
- }
- //当某一行被双击时会触发该事件
- const tableRowDblClick = (row, column, event) => {
- emit('row-dblclick', {row, column, event})
- }
- //当某一行被鼠标右键点击时会触发该事件
- const tableRowContextmenu = (row, column, event) => {
- emit('row-contextmenu', {row, column, event})
- }
- //当某个单元格被点击时会触发该事件
- const tableCellClick = (row, column, cell, event) => {
- emit('cell-click', {row, column, cell, event})
- }
- //当某个单元格被双击击时会触发该事件
- const tableCellDblClick = (row, column, cell, event) => {
- emit('cell-dblclick', {row, column, cell, event})
- }
- //当某个单元格被鼠标右键点击时会触发该事件
- const tableCellContextmenu = (row, column, cell, event) => {
- emit('cell-contextmenu', {row, column, cell, event})
- }
- //向上排序
- const upSortClick = (index) => {
- const data = tableData.value
- if(index !== 0) {
- const tmp = data.splice(index - 1,1);
- tableData.value.splice(index, 0, tmp[0]);
- emit('row-sort', tableData.value)
- } else {
- window?.$message?.warning('已经处于置顶,无法上移')
- }
- }
- //向下排序
- const downSortClick = (index) => {
- const indexs = index + 1
- const data = tableData.value
- if(indexs !== data.length) {
- const tmp = data.splice(indexs, 1);
- tableData.value.splice(index, 0, tmp[0]);
- emit('row-sort', tableData.value)
- } else {
- window?.$message?.warning('已经处于置底,无法下移')
- }
- }
- // 暴露出去
- defineExpose({
- clearSelection,
- getSelectionRows,
- toggleRowSelection
- })
- </script>
- <style lang="scss">
- .hc-table-ref-box {
- height: 100%;
- .el-scrollbar .el-scrollbar__bar.is-vertical {
- right: 0;
- }
- .el-scrollbar .el-scrollbar__bar.is-horizontal {
- bottom: 2px;
- }
- .el-table__body-wrapper tr td.el-table-fixed-column--left,
- .el-table__body-wrapper tr td.el-table-fixed-column--right,
- .el-table__body-wrapper tr th.el-table-fixed-column--left,
- .el-table__body-wrapper tr th.el-table-fixed-column--right,
- .el-table__footer-wrapper tr td.el-table-fixed-column--left,
- .el-table__footer-wrapper tr td.el-table-fixed-column--right,
- .el-table__footer-wrapper tr th.el-table-fixed-column--left,
- .el-table__footer-wrapper tr th.el-table-fixed-column--right,
- .el-table__header-wrapper tr td.el-table-fixed-column--left,
- .el-table__header-wrapper tr td.el-table-fixed-column--right,
- .el-table__header-wrapper tr th.el-table-fixed-column--left,
- .el-table__header-wrapper tr th.el-table-fixed-column--right {
- --el-bg-color: #ebeef0;
- }
- .table-column-header-num {
- position: relative;
- display: flex;
- align-items: center;
- }
- }
- </style>
|