|
@@ -45,55 +45,60 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
<!-- 表格主体 -->
|
|
|
- <el-table
|
|
|
- ref="tableRef"
|
|
|
- v-bind="$attrs"
|
|
|
- :data="processTableData"
|
|
|
- :border="border"
|
|
|
- :row-key="rowKey"
|
|
|
- @selection-change="selectionChange"
|
|
|
- v-loading="loading"
|
|
|
- :scrollbar-always-on="true"
|
|
|
- v-horizontal-scroll="'always'"
|
|
|
- >
|
|
|
- <!-- 默认插槽 -->
|
|
|
- <slot />
|
|
|
- <template v-for="item in tableColumns" :key="item">
|
|
|
- <!-- selection || radio || index || expand || sort -->
|
|
|
- <el-table-column
|
|
|
- v-if="item.type && columnTypes.includes(item.type)"
|
|
|
- v-bind="item"
|
|
|
- :align="item.align ?? 'left'"
|
|
|
- :reserve-selection="item.type == 'selection'"
|
|
|
- >
|
|
|
- <template #default="scope">
|
|
|
- <!-- expand -->
|
|
|
- <template v-if="item.type == 'expand'">
|
|
|
- <component :is="item.render" v-bind="scope" v-if="item.render" />
|
|
|
- <slot v-else :name="item.type" v-bind="scope" />
|
|
|
- </template>
|
|
|
- <!-- radio -->
|
|
|
- <el-radio v-if="item.type == 'radio'" v-model="radio" :label="scope.row[rowKey]">
|
|
|
- <i></i>
|
|
|
- </el-radio>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <!-- other -->
|
|
|
- <TableColumn v-if="!item.type && item.prop && item.isShow" :column="item" col-setting="">
|
|
|
- <template v-for="slot in Object.keys($slots)" #[slot]="scope">
|
|
|
- <slot :name="slot" v-bind="scope" />
|
|
|
- </template>
|
|
|
- </TableColumn>
|
|
|
- </template>
|
|
|
- <!-- 插入表格最后一行之后的插槽 -->
|
|
|
- <template #append>
|
|
|
- <slot name="append" />
|
|
|
- </template>
|
|
|
- <!-- 无数据 -->
|
|
|
- <template #empty>
|
|
|
- <el-empty :image-size="120" />
|
|
|
- </template>
|
|
|
- </el-table>
|
|
|
+
|
|
|
+ <el-table
|
|
|
+ ref="tableRef"
|
|
|
+ v-bind="$attrs"
|
|
|
+ :data="processTableData"
|
|
|
+ :border="border"
|
|
|
+ :row-key="rowKey"
|
|
|
+ @selection-change="selectionChange"
|
|
|
+ :scrollbar-always-on="true"
|
|
|
+ v-horizontal-scroll="'always'"
|
|
|
+ v-loading="loading"
|
|
|
+ height="100%"
|
|
|
+ :key="Math.random()"
|
|
|
+ :row-style="{height: '24px'}"
|
|
|
+ :cell-style="{padding: '4px 0'}"
|
|
|
+ >
|
|
|
+ <!-- 默认插槽 -->
|
|
|
+ <slot />
|
|
|
+ <template v-for="item in tableColumns" :key="item">
|
|
|
+ <!-- selection || radio || index || expand || sort -->
|
|
|
+ <el-table-column
|
|
|
+ v-if="item.type && columnTypes.includes(item.type)"
|
|
|
+ v-bind="item"
|
|
|
+ :align="item.align ?? 'left'"
|
|
|
+ :reserve-selection="item.type == 'selection'"
|
|
|
+ >
|
|
|
+ <template #default="scope">
|
|
|
+ <!-- expand -->
|
|
|
+ <template v-if="item.type == 'expand'">
|
|
|
+ <component :is="item.render" v-bind="scope" v-if="item.render" />
|
|
|
+ <slot v-else :name="item.type" v-bind="scope" />
|
|
|
+ </template>
|
|
|
+ <!-- radio -->
|
|
|
+ <el-radio v-if="item.type == 'radio'" v-model="radio" :label="scope.row[rowKey]">
|
|
|
+ <i></i>
|
|
|
+ </el-radio>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <!-- other -->
|
|
|
+ <TableColumn v-if="!item.type && item.prop && item.isShow" :column="item" col-setting="">
|
|
|
+ <template v-for="slot in Object.keys($slots)" #[slot]="scope">
|
|
|
+ <slot :name="slot" v-bind="scope" />
|
|
|
+ </template>
|
|
|
+ </TableColumn>
|
|
|
+ </template>
|
|
|
+ <!-- 插入表格最后一行之后的插槽 -->
|
|
|
+ <template #append>
|
|
|
+ <slot name="append" />
|
|
|
+ </template>
|
|
|
+ <!-- 无数据 -->
|
|
|
+ <template #empty>
|
|
|
+ <el-empty :image-size="120" />
|
|
|
+ </template>
|
|
|
+ </el-table>
|
|
|
<!-- 分页组件 -->
|
|
|
<slot name="pagination">
|
|
|
<PaginationEl
|
|
@@ -111,7 +116,7 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts" name="ProTable">
|
|
|
-import { ref, provide, onMounted, unref, computed, reactive, PropType, watch } from 'vue';
|
|
|
+import {ref, provide, onMounted, unref, computed, reactive, PropType, watch, nextTick} from 'vue';
|
|
|
import { ElMessageBox, ElTable } from 'element-plus';
|
|
|
import { useSelection } from '@/hooks/useSelection';
|
|
|
import { ColumnProps, TypeProps } from '@/components/ProTable/interface';
|
|
@@ -119,6 +124,8 @@ import PaginationEl from './components/Pagination.vue';
|
|
|
import ColSetting from './components/ColSetting.vue';
|
|
|
import TableColumn from './components/TableColumn.vue';
|
|
|
import { downloadFileByStream } from '@/utils/tools';
|
|
|
+import { useResizeObserver } from '@vueuse/core'
|
|
|
+
|
|
|
|
|
|
// 接受父组件参数,配置默认值
|
|
|
const props = defineProps({
|
|
@@ -257,16 +264,25 @@ const { selectionChange, selectedList, selectedListIds, isSelected } = useSelect
|
|
|
|
|
|
// 清空选中数据列表
|
|
|
const clearSelection = () => tableRef.value!.clearSelection();
|
|
|
-
|
|
|
// 初始化表格数据 && 拖拽排序
|
|
|
-onMounted(() => {});
|
|
|
-
|
|
|
+onMounted(() => {
|
|
|
+ useResizeObserver(tableRef, () => {
|
|
|
+ tableRef.value.doLayout();
|
|
|
+ })
|
|
|
+});
|
|
|
// 处理表格数据
|
|
|
const processTableData = computed(() => {
|
|
|
if (!props.pagination) return props.data;
|
|
|
return props.data;
|
|
|
});
|
|
|
|
|
|
+// 监听 tableData 的变化来更新表格布局
|
|
|
+watch(processTableData, () => {
|
|
|
+ if (tableRef.value) {
|
|
|
+ tableRef.value.doLayout();
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
// 接收 columns 并设置为响应式
|
|
|
const tableColumns = ref(props.columns);
|
|
|
|
|
@@ -580,8 +596,16 @@ defineExpose({
|
|
|
});
|
|
|
</script>
|
|
|
<style scoped lang="scss">
|
|
|
+.pro-table-main{
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ height:calc(100% - 40px);
|
|
|
+ .el-table{
|
|
|
+ flex:1;
|
|
|
+ }
|
|
|
+}
|
|
|
.table-header {
|
|
|
- margin-bottom: 15px;
|
|
|
+ margin-bottom: 10px;
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
}
|