|
@@ -4,7 +4,6 @@
|
|
|
v-bind="tableProps"
|
|
|
v-el-table-infinite-scroll="scrollOver"
|
|
|
:data="dealedTableData"
|
|
|
-
|
|
|
>
|
|
|
<el-table-column
|
|
|
v-if="sequence || customSequence"
|
|
@@ -33,14 +32,14 @@
|
|
|
:filter-options="filterOptionMap[column.columnName]"
|
|
|
:sortable="!!column.needSort"
|
|
|
filter-style="arrow"
|
|
|
- @update:changeValues="
|
|
|
- (sortRule) => {
|
|
|
- filterValuesChangeHandler(sortRule);
|
|
|
+ @update:filter-values="
|
|
|
+ filterValues => {
|
|
|
+ filterValuesChangeHandler(column.columnName, filterValues)
|
|
|
}
|
|
|
"
|
|
|
@update:sort-rule="
|
|
|
- (sortRule) => {
|
|
|
- sortRuleChangeHandler(column.columnName, sortRule);
|
|
|
+ sortRule => {
|
|
|
+ sortRuleChangeHandler(column.columnName, sortRule)
|
|
|
}
|
|
|
"
|
|
|
/>
|
|
@@ -53,126 +52,126 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import TableHeaderCell from "@/components/TableHeaderCell/index.vue";
|
|
|
-import type { CSSProperties, VNode } from "vue";
|
|
|
-import { TableColumnCtx } from "element-plus/es/components/table/src/table-column/defaults";
|
|
|
-import { CommonData, CommonTableColumn } from "~/common";
|
|
|
-import { Options, useTableFilterAndSort } from "@/hooks/useTableFilterAndSort";
|
|
|
-import { ElTable } from "element-plus";
|
|
|
-import { useTableSettingsStore } from "@/store/tableSettings";
|
|
|
+import TableHeaderCell from '@/components/TableHeaderCell/index.vue'
|
|
|
+import type { CSSProperties, VNode } from 'vue'
|
|
|
+import { TableColumnCtx } from 'element-plus/es/components/table/src/table-column/defaults'
|
|
|
+import { CommonData, CommonTableColumn } from '~/common'
|
|
|
+import { Options, useTableFilterAndSort } from '@/hooks/useTableFilterAndSort'
|
|
|
+import { ElTable } from 'element-plus'
|
|
|
+import { useTableSettingsStore } from '@/store/tableSettings'
|
|
|
|
|
|
type SummaryMethod<T> = (data: {
|
|
|
- columns: TableColumnCtx<T>[];
|
|
|
- data: T[];
|
|
|
-}) => string[];
|
|
|
-type ColumnCls<T> = string | ((data: { row: T; rowIndex: number }) => string);
|
|
|
+ columns: TableColumnCtx<T>[]
|
|
|
+ data: T[]
|
|
|
+}) => string[]
|
|
|
+type ColumnCls<T> = string | ((data: { row: T; rowIndex: number }) => string)
|
|
|
type ColumnStyle<T> =
|
|
|
| CSSProperties
|
|
|
- | ((data: { row: T; rowIndex: number }) => CSSProperties);
|
|
|
+ | ((data: { row: T; rowIndex: number }) => CSSProperties)
|
|
|
type CellCls<T> =
|
|
|
| string
|
|
|
| ((data: {
|
|
|
- row: T;
|
|
|
- rowIndex: number;
|
|
|
- column: TableColumnCtx<T>;
|
|
|
- columnIndex: number;
|
|
|
- }) => string);
|
|
|
+ row: T
|
|
|
+ rowIndex: number
|
|
|
+ column: TableColumnCtx<T>
|
|
|
+ columnIndex: number
|
|
|
+ }) => string)
|
|
|
type CellStyle<T> =
|
|
|
| CSSProperties
|
|
|
| ((data: {
|
|
|
- row: T;
|
|
|
- rowIndex: number;
|
|
|
- column: TableColumnCtx<T>;
|
|
|
- columnIndex: number;
|
|
|
- }) => CSSProperties);
|
|
|
+ row: T
|
|
|
+ rowIndex: number
|
|
|
+ column: TableColumnCtx<T>
|
|
|
+ columnIndex: number
|
|
|
+ }) => CSSProperties)
|
|
|
type Sort = {
|
|
|
- prop: string;
|
|
|
- order: "ascending" | "descending";
|
|
|
- init?: any;
|
|
|
- silent?: any;
|
|
|
-};
|
|
|
+ prop: string
|
|
|
+ order: 'ascending' | 'descending'
|
|
|
+ init?: any
|
|
|
+ silent?: any
|
|
|
+}
|
|
|
type TreeNode = {
|
|
|
- expanded?: boolean;
|
|
|
- loading?: boolean;
|
|
|
- noLazyChildren?: boolean;
|
|
|
- indent?: number;
|
|
|
- level?: number;
|
|
|
- display?: boolean;
|
|
|
-};
|
|
|
-type Layout = "fixed" | "auto";
|
|
|
+ expanded?: boolean
|
|
|
+ loading?: boolean
|
|
|
+ noLazyChildren?: boolean
|
|
|
+ indent?: number
|
|
|
+ level?: number
|
|
|
+ display?: boolean
|
|
|
+}
|
|
|
+type Layout = 'fixed' | 'auto'
|
|
|
type TableColumnProps<T> = {
|
|
|
- type?: string;
|
|
|
- index?: number | ((index: number) => number);
|
|
|
- columnKey?: string;
|
|
|
- width?: string | number;
|
|
|
- minWidth?: string | number;
|
|
|
- fixed?: boolean | string;
|
|
|
- renderHeader?: (data: { column: TableColumnCtx<T>; $index: number }) => VNode;
|
|
|
- resizable?: boolean;
|
|
|
+ type?: string
|
|
|
+ index?: number | ((index: number) => number)
|
|
|
+ columnKey?: string
|
|
|
+ width?: string | number
|
|
|
+ minWidth?: string | number
|
|
|
+ fixed?: boolean | string
|
|
|
+ renderHeader?: (data: { column: TableColumnCtx<T>; $index: number }) => VNode
|
|
|
+ resizable?: boolean
|
|
|
formatter?: (
|
|
|
row: T,
|
|
|
column: TableColumnCtx<T>,
|
|
|
cellValue: any,
|
|
|
index: number
|
|
|
- ) => VNode | string;
|
|
|
- showOverflowTooltip?: boolean;
|
|
|
- align?: string;
|
|
|
- headerAlign?: string;
|
|
|
- className?: string;
|
|
|
- labelClassName?: string;
|
|
|
- selectable?: (row: T, index: number) => boolean;
|
|
|
- reserveSelection?: boolean;
|
|
|
-};
|
|
|
+ ) => VNode | string
|
|
|
+ showOverflowTooltip?: boolean
|
|
|
+ align?: string
|
|
|
+ headerAlign?: string
|
|
|
+ className?: string
|
|
|
+ labelClassName?: string
|
|
|
+ selectable?: (row: T, index: number) => boolean
|
|
|
+ reserveSelection?: boolean
|
|
|
+}
|
|
|
|
|
|
const props = withDefaults(
|
|
|
defineProps<{
|
|
|
- data: CommonData[];
|
|
|
- size?: string;
|
|
|
- width?: string | number;
|
|
|
- height?: string | number;
|
|
|
- maxHeight?: string | number;
|
|
|
- fit?: boolean;
|
|
|
- stripe?: boolean;
|
|
|
- border?: boolean;
|
|
|
- rowKey?: string | ((row: CommonData) => string);
|
|
|
- showHeader?: boolean;
|
|
|
- showSummary?: boolean;
|
|
|
- sumText?: string;
|
|
|
- summaryMethod?: SummaryMethod<CommonData>;
|
|
|
- rowClassName?: ColumnCls<CommonData>;
|
|
|
- rowStyle?: ColumnStyle<CommonData>;
|
|
|
- cellClassName?: CellCls<CommonData>;
|
|
|
- cellStyle?: CellStyle<CommonData>;
|
|
|
- headerRowClassName?: ColumnCls<CommonData>;
|
|
|
- headerRowStyle?: ColumnStyle<CommonData>;
|
|
|
- headerCellClassName?: CellCls<CommonData>;
|
|
|
- headerCellStyle?: CellStyle<CommonData>;
|
|
|
- highlightCurrentRow?: boolean;
|
|
|
- currentRowKey?: string | number;
|
|
|
- emptyText?: string;
|
|
|
- expandRowKeys?: any[];
|
|
|
- defaultExpandAll?: boolean;
|
|
|
- defaultSort?: Sort;
|
|
|
- tooltipEffect?: string;
|
|
|
+ data: CommonData[]
|
|
|
+ size?: string
|
|
|
+ width?: string | number
|
|
|
+ height?: string | number
|
|
|
+ maxHeight?: string | number
|
|
|
+ fit?: boolean
|
|
|
+ stripe?: boolean
|
|
|
+ border?: boolean
|
|
|
+ rowKey?: string | ((row: CommonData) => string)
|
|
|
+ showHeader?: boolean
|
|
|
+ showSummary?: boolean
|
|
|
+ sumText?: string
|
|
|
+ summaryMethod?: SummaryMethod<CommonData>
|
|
|
+ rowClassName?: ColumnCls<CommonData>
|
|
|
+ rowStyle?: ColumnStyle<CommonData>
|
|
|
+ cellClassName?: CellCls<CommonData>
|
|
|
+ cellStyle?: CellStyle<CommonData>
|
|
|
+ headerRowClassName?: ColumnCls<CommonData>
|
|
|
+ headerRowStyle?: ColumnStyle<CommonData>
|
|
|
+ headerCellClassName?: CellCls<CommonData>
|
|
|
+ headerCellStyle?: CellStyle<CommonData>
|
|
|
+ highlightCurrentRow?: boolean
|
|
|
+ currentRowKey?: string | number
|
|
|
+ emptyText?: string
|
|
|
+ expandRowKeys?: any[]
|
|
|
+ defaultExpandAll?: boolean
|
|
|
+ defaultSort?: Sort
|
|
|
+ tooltipEffect?: string
|
|
|
spanMethod?: (data: {
|
|
|
- row: CommonData;
|
|
|
- rowIndex: number;
|
|
|
- column: TableColumnCtx<CommonData>;
|
|
|
- columnIndex: number;
|
|
|
+ row: CommonData
|
|
|
+ rowIndex: number
|
|
|
+ column: TableColumnCtx<CommonData>
|
|
|
+ columnIndex: number
|
|
|
}) =>
|
|
|
| number[]
|
|
|
| {
|
|
|
- rowspan: number;
|
|
|
- colspan: number;
|
|
|
+ rowspan: number
|
|
|
+ colspan: number
|
|
|
}
|
|
|
- | undefined;
|
|
|
- selectOnIndeterminate?: boolean;
|
|
|
- indent?: number;
|
|
|
+ | undefined
|
|
|
+ selectOnIndeterminate?: boolean
|
|
|
+ indent?: number
|
|
|
treeProps?: {
|
|
|
- hasChildren?: string;
|
|
|
- children?: string;
|
|
|
- };
|
|
|
- lazy?: boolean;
|
|
|
+ hasChildren?: string
|
|
|
+ children?: string
|
|
|
+ }
|
|
|
+ lazy?: boolean
|
|
|
load?: (
|
|
|
row: CommonData,
|
|
|
treeNode: TreeNode,
|
|
@@ -193,86 +192,86 @@ const props = withDefaults(
|
|
|
labelFormatter?: (label: string) => string
|
|
|
}>(),
|
|
|
{
|
|
|
- size: "default",
|
|
|
- height: "100%",
|
|
|
- maxHeight: "100%",
|
|
|
+ size: 'default',
|
|
|
+ height: '100%',
|
|
|
+ maxHeight: '100%',
|
|
|
stripe: true,
|
|
|
border: true,
|
|
|
fit: true,
|
|
|
showHeader: true,
|
|
|
labelFormatter: (label: string) => label,
|
|
|
}
|
|
|
-);
|
|
|
+)
|
|
|
|
|
|
const defaultSummaryMethod: SummaryMethod<CommonData> = ({ columns, data }) => {
|
|
|
- const sums: string[] = [];
|
|
|
+ const sums: string[] = []
|
|
|
columns.forEach((column, index) => {
|
|
|
const countColumn = tableColumns.value.find(
|
|
|
- (col) => column.property === col.columnName && col.needCount
|
|
|
- );
|
|
|
+ col => column.property === col.columnName && col.needCount
|
|
|
+ )
|
|
|
if (countColumn) {
|
|
|
const sumNumber = data.reduce((prev: number, curr: CommonData) => {
|
|
|
- const cellData = curr[column.property];
|
|
|
- if (countColumn.countMode === "all") {
|
|
|
- return prev + 1;
|
|
|
+ const cellData = curr[column.property]
|
|
|
+ if (countColumn.countMode === 'all') {
|
|
|
+ return prev + 1
|
|
|
}
|
|
|
- if (countColumn.countMode === "notNull") {
|
|
|
- return cellData ? prev + 1 : prev;
|
|
|
+ if (countColumn.countMode === 'notNull') {
|
|
|
+ return cellData ? prev + 1 : prev
|
|
|
}
|
|
|
- const value = Number(cellData);
|
|
|
+ const value = Number(cellData)
|
|
|
if (!Number.isNaN(value)) {
|
|
|
- prev += value;
|
|
|
+ prev += value
|
|
|
}
|
|
|
- return prev;
|
|
|
- }, 0);
|
|
|
- sums[index] = sumNumber.toString();
|
|
|
+ return prev
|
|
|
+ }, 0)
|
|
|
+ sums[index] = sumNumber.toString()
|
|
|
}
|
|
|
- });
|
|
|
- sums[0] = "合计:" + (sums[0] ?? "");
|
|
|
- return sums;
|
|
|
-};
|
|
|
+ })
|
|
|
+ sums[0] = '合计:' + (sums[0] ?? '')
|
|
|
+ return sums
|
|
|
+}
|
|
|
|
|
|
const tableProps = computed(() => {
|
|
|
- const rawProps = toRaw(props);
|
|
|
- const result: { [x: string]: any } = {};
|
|
|
+ const rawProps = toRaw(props)
|
|
|
+ const result: { [x: string]: any } = {}
|
|
|
Object.entries(rawProps).forEach(([key, value]) => {
|
|
|
if (
|
|
|
![
|
|
|
- "columnProps",
|
|
|
- "columns",
|
|
|
- "sequence",
|
|
|
- "customSequence",
|
|
|
- "filterSortOptions",
|
|
|
- "cacheKeys",
|
|
|
- "labelFormatter",
|
|
|
+ 'columnProps',
|
|
|
+ 'columns',
|
|
|
+ 'sequence',
|
|
|
+ 'customSequence',
|
|
|
+ 'filterSortOptions',
|
|
|
+ 'cacheKeys',
|
|
|
+ 'labelFormatter',
|
|
|
].includes(key) &&
|
|
|
- (value ?? "") !== ""
|
|
|
+ (value ?? '') !== ''
|
|
|
) {
|
|
|
- result[key] = value;
|
|
|
+ result[key] = value
|
|
|
}
|
|
|
- if (props.columns.some((column) => column.needCount)) {
|
|
|
- result.showSummary = true;
|
|
|
+ if (props.columns.some(column => column.needCount)) {
|
|
|
+ result.showSummary = true
|
|
|
}
|
|
|
if (!result.summaryMethod) {
|
|
|
- result.summaryMethod = defaultSummaryMethod;
|
|
|
+ result.summaryMethod = defaultSummaryMethod
|
|
|
}
|
|
|
- });
|
|
|
- return result;
|
|
|
-});
|
|
|
+ })
|
|
|
+ return result
|
|
|
+})
|
|
|
|
|
|
const computedColumnProps = computed(() => {
|
|
|
const defaultColumnProps: TableColumnProps<CommonData> = {
|
|
|
- align: "center",
|
|
|
- };
|
|
|
+ align: 'center',
|
|
|
+ }
|
|
|
return (column: CommonTableColumn & TableColumnProps<CommonData>) => ({
|
|
|
...defaultColumnProps,
|
|
|
...props.columnProps,
|
|
|
...column,
|
|
|
- });
|
|
|
-});
|
|
|
+ })
|
|
|
+})
|
|
|
|
|
|
-const tableColumns = ref<CommonTableColumn[]>([]);
|
|
|
-const tableData = ref<CommonData[]>([]);
|
|
|
+const tableColumns = ref<CommonTableColumn[]>([])
|
|
|
+const tableData = ref<CommonData[]>([])
|
|
|
watchEffect(() => {
|
|
|
tableColumns.value = props.columns.reduce(
|
|
|
(prevColumns: CommonTableColumn[], column) => {
|
|
@@ -281,18 +280,18 @@ watchEffect(() => {
|
|
|
label: column.columnLabel,
|
|
|
prop: column.columnName,
|
|
|
...column,
|
|
|
- });
|
|
|
+ })
|
|
|
}
|
|
|
- return prevColumns;
|
|
|
+ return prevColumns
|
|
|
},
|
|
|
[]
|
|
|
- );
|
|
|
- tableData.value = props.data;
|
|
|
-});
|
|
|
+ )
|
|
|
+ tableData.value = props.data
|
|
|
+})
|
|
|
|
|
|
const hasFixedColumn = computed(() =>
|
|
|
- tableColumns.value.some((column) => column.fixed)
|
|
|
-);
|
|
|
+ tableColumns.value.some(column => column.fixed)
|
|
|
+)
|
|
|
|
|
|
const {
|
|
|
filterOptionMap,
|
|
@@ -300,51 +299,49 @@ const {
|
|
|
sortRuleMap,
|
|
|
dealedTableData,
|
|
|
sortChangeHandler,
|
|
|
-} = useTableFilterAndSort(tableColumns, tableData, props.filterSortOptions);
|
|
|
+} = useTableFilterAndSort(tableColumns, tableData, props.filterSortOptions)
|
|
|
|
|
|
-const { saveTableFilterValues } = useTableSettingsStore();
|
|
|
+const { saveTableFilterValues } = useTableSettingsStore()
|
|
|
|
|
|
watch(
|
|
|
sortRuleMap,
|
|
|
- (map) => {
|
|
|
- emit("sortRuleChange", map);
|
|
|
+ map => {
|
|
|
+ emit('sortRuleChange', map)
|
|
|
},
|
|
|
{ deep: true }
|
|
|
-);
|
|
|
+)
|
|
|
|
|
|
const sortRuleChangeHandler = (columnName: string, sortRule: string) => {
|
|
|
- sortRuleMap[columnName] = sortRule;
|
|
|
- sortChangeHandler(columnName, sortRule);
|
|
|
-};
|
|
|
+ sortRuleMap[columnName] = sortRule
|
|
|
+ sortChangeHandler(columnName, sortRule)
|
|
|
+}
|
|
|
|
|
|
-const filterValuesChangeHandler = (sortRule: string[]) => {
|
|
|
- emit("filterChange", sortRule);
|
|
|
-};
|
|
|
+const filterValuesChangeHandler = (columnName: string, filterValues: string[]) => {
|
|
|
+ filterValueMap[columnName] = filterValues
|
|
|
+ emit('filterChange', filterValues)
|
|
|
+}
|
|
|
|
|
|
if (props.cacheKeys?.length) {
|
|
|
- watch(filterValueMap, (map) => {
|
|
|
- const values: { [x: string]: string[] } = {};
|
|
|
- props.cacheKeys!.forEach((columnName) => {
|
|
|
- values[columnName] = map[columnName];
|
|
|
- });
|
|
|
- saveTableFilterValues(values);
|
|
|
- });
|
|
|
+ watch(filterValueMap, map => {
|
|
|
+ const values: { [x: string]: string[] } = {}
|
|
|
+ props.cacheKeys!.forEach(columnName => {
|
|
|
+ values[columnName] = map[columnName]
|
|
|
+ })
|
|
|
+ saveTableFilterValues(values)
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
// 组件的inheritAttrs属性默认为true,此时组件上的属性(包括v-on)会被添加到根元素上
|
|
|
-const emit = defineEmits([
|
|
|
- 'sortRuleChange',
|
|
|
- 'scrollOver',
|
|
|
-])
|
|
|
+const emit = defineEmits(['filterChange', 'sortRuleChange', 'scrollOver'])
|
|
|
|
|
|
const scrollOver = () => {
|
|
|
- emit("scrollOver");
|
|
|
-};
|
|
|
+ emit('scrollOver')
|
|
|
+}
|
|
|
|
|
|
-const table = ref<InstanceType<typeof ElTable> | null>(null);
|
|
|
+const table = ref<InstanceType<typeof ElTable> | null>(null)
|
|
|
defineExpose({
|
|
|
table,
|
|
|
-});
|
|
|
+})
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
@@ -355,7 +352,7 @@ defineExpose({
|
|
|
&.cell-filter {
|
|
|
position: relative;
|
|
|
&::before {
|
|
|
- content: "";
|
|
|
+ content: '';
|
|
|
position: absolute;
|
|
|
width: 100%;
|
|
|
height: 100%;
|