docking-vue/src/components/table/index.vue

142 lines
3.9 KiB
Vue
Raw Normal View History

2025-06-10 09:31:15 +08:00
<template>
<el-table
ref="tableRef"
size="small"
:data="data"
:border="border"
:stripe="stripe"
:height="height"
:max-height="maxHeight"
:highlight-current-row="highlightCurrentRow"
:row-key="getRowKey"
:row-class-name="rowClassName"
:row-style="rowStyle"
:show-header="showHeader"
:show-summary="showSummary"
:summary-method="summaryMethod"
:span-method="spanMethod"
:default-expand-all="defaultExpandAll"
:tree-props="treeProps"
:header-cell-style="headerCellStyle"
:cell-style="cellStyle"
2025-06-27 14:01:42 +08:00
:show-overflow-tooltip="showOverflowTooltip"
style="width: 100%"
2025-06-10 09:31:15 +08:00
@row-click="rowClick"
@row-dblclick="rowDblclick"
>
<el-table-column
v-if="showSelection"
type="selection"
2025-06-27 14:01:42 +08:00
:selectable="selectable"
2025-06-10 09:31:15 +08:00
reserve-selection
width="60"
2025-06-27 14:01:42 +08:00
:show-overflow-tooltip="false"
2025-06-10 09:31:15 +08:00
/>
2025-06-27 14:01:42 +08:00
<template v-if="showIndex">
<el-table-column v-if="showPagination" label="序号" width="60">
<template #default="{ $index }">
{{ serialNumber(pagination, $index) }}
</template>
</el-table-column>
<el-table-column
v-if="!showPagination"
label="序号"
width="60"
type="index"
/>
</template>
2025-06-10 09:31:15 +08:00
<slot></slot>
</el-table>
<div v-if="showPagination || slots.button" class="table_footer">
<div>
<slot name="button"></slot>
</div>
<app-pagination
v-if="showPagination"
v-model:pagination="pagination"
@get-data="emits('get-data')"
/>
</div>
</template>
<script setup>
import { useSlots, useTemplateRef } from "vue";
import AppPagination from "@/components/pagination/index.vue";
import { serialNumber } from "@/assets/js/utils.js";
const slots = useSlots();
defineOptions({
name: "AppTable",
});
const props = defineProps({
2025-07-21 11:32:02 +08:00
data: { type: Array, required: true },
showPagination: { type: Boolean, default: true },
showIndex: { type: Boolean, default: true },
showSelection: { type: Boolean, default: false },
stripe: { type: Boolean, default: true },
border: { type: Boolean, default: true },
showHeader: { type: Boolean, default: true },
highlightCurrentRow: { type: Boolean, default: false },
showSummary: { type: Boolean, default: false },
defaultExpandAll: { type: Boolean, default: false },
rowKey: { type: [String, Function] },
maxHeight: { type: [String, Number] },
height: { type: [String, Number] },
rowClassName: { type: Function },
rowStyle: { type: Function },
summaryMethod: { type: Function },
spanMethod: { type: Function },
selectable: { type: Function },
2025-06-10 09:31:15 +08:00
treeProps: {
type: Object,
default: () => ({ hasChildren: "hasChildren", children: "children" }),
},
2025-07-21 11:32:02 +08:00
headerCellStyle: { type: Object, default: () => ({}) },
cellStyle: { type: [Object, Function], default: () => ({}) },
showOverflowTooltip: { type: Boolean, default: true },
2025-06-10 09:31:15 +08:00
});
const pagination = defineModel("pagination", {
type: Object,
default: () => ({
currentPage: 1,
pageSize: 10,
total: 0,
}),
});
const emits = defineEmits(["get-data", "row-click", "row-dblclick"]);
const tableRef = useTemplateRef("tableRef");
const getRowKey = (row) => {
if (!props.rowKey) return;
if (typeof props.rowKey === "string") return row[props.rowKey];
else return props.rowKey(row);
};
const rowClick = (row, column, event) => {
emits("row-click", row, column, event);
};
const rowDblclick = (row, column, event) => {
emits("row-dblclick", row, column, event);
};
const getSelectionRows = () => {
return tableRef.value.getSelectionRows();
};
const clearSelection = () => {
return tableRef.value.clearSelection();
};
const toggleRowSelection = (value, selected = true) => {
tableRef.value.toggleRowSelection(value, selected);
};
defineExpose({
getSelectionRows,
clearSelection,
toggleRowSelection,
});
</script>
<style lang="scss" scoped>
.table_footer {
margin-top: 20px;
display: flex;
justify-content: space-between;
}
</style>