Commit f845f8b0 authored by 水玉婷's avatar 水玉婷
Browse files

feat:表格添加多列排序功能

parent 1f5f143c
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from 'vue'; import { computed, ref, reactive } from 'vue';
import { Table as ATable } from 'ant-design-vue'; import { Table as ATable } from 'ant-design-vue';
import { formatNumber } from './utils/utils'; import { formatNumber } from './utils/utils';
...@@ -47,6 +47,12 @@ const paginationState = ref({ ...@@ -47,6 +47,12 @@ const paginationState = ref({
pageSize: 15 pageSize: 15
}); });
// 排序状态
const sortState = reactive({
sortedData: [] as any[],
isSorted: false
});
// 处理表格变化事件(包括分页、排序等) // 处理表格变化事件(包括分页、排序等)
const handleTableChange = (pagination: any, filters: any, sorter: any) => { const handleTableChange = (pagination: any, filters: any, sorter: any) => {
// 处理分页变化 // 处理分页变化
...@@ -58,9 +64,75 @@ const handleTableChange = (pagination: any, filters: any, sorter: any) => { ...@@ -58,9 +64,75 @@ const handleTableChange = (pagination: any, filters: any, sorter: any) => {
}; };
} }
// 可以在这里添加排序变化的处理 // 处理排序变化(支持多列排序)
if (sorter) { if (sorter) {
// console.log('排序变化:', sorter);
// 更新排序状态
sortState.isSorted = true;
// 获取原始数据
let rawData: any[] = [];
if (Array.isArray(props.tableData.rows)) {
rawData = [...props.tableData.rows];
} else if (Array.isArray(props.tableData)) {
rawData = [...props.tableData];
}
// 应用排序
if (Array.isArray(sorter)) {
// 多列排序情况:按优先级顺序应用排序
sorter.forEach((sortItem) => {
if (sortItem.order) {
rawData.sort((a, b) => {
const aValue = getSortableValue(a, sortItem.field);
const bValue = getSortableValue(b, sortItem.field);
if (sortItem.order === 'ascend') {
return aValue - bValue;
} else {
return bValue - aValue;
}
});
}
});
} else if (sorter.order) {
// 单列排序情况
rawData.sort((a, b) => {
const aValue = getSortableValue(a, sorter.field);
const bValue = getSortableValue(b, sorter.field);
if (sorter.order === 'ascend') {
return aValue - bValue;
} else {
return bValue - aValue;
}
});
}
// 更新排序后的数据
sortState.sortedData = rawData;
}
};
// 获取可排序的值(用于数字字段)
const getSortableValue = (item: any, field: string) => {
if (item[field] && typeof item[field] === 'object' && item[field].value !== undefined) {
// 对于特殊格式的数据,使用value字段进行排序
return parseFloat(item[field].value) || 0;
} else {
// 普通字段直接使用
return parseFloat(item[field]) || 0;
}
};
// 获取字符串值(用于文字字段)
const getStringValue = (item: any, field: string): string => {
if (item[field] && typeof item[field] === 'object' && item[field].display !== undefined) {
// 对于特殊格式的数据,使用display字段进行排序
return String(item[field].display || '');
} else {
// 普通字段直接使用
return String(item[field] || '');
} }
}; };
...@@ -92,46 +164,58 @@ const props = withDefaults(defineProps<Props>(), { ...@@ -92,46 +164,58 @@ const props = withDefaults(defineProps<Props>(), {
const processedTableData = computed(() => { const processedTableData = computed(() => {
if (!props.tableData) return []; if (!props.tableData) return [];
// 如果有排序后的数据,使用排序后的数据
if (sortState.isSorted && sortState.sortedData.length > 0) {
return processRawData(sortState.sortedData);
}
// 处理传入完整数据结构的情况 // 处理传入完整数据结构的情况
if (Array.isArray(props.tableData.rows)) { if (Array.isArray(props.tableData.rows)) {
// 获取字段配置 return processRawData(props.tableData.rows);
const indexFields = props.tableData?.indexFields || [];
const dimFields = props.tableData?.dimFields || [];
const indexFieldsFormat = props.tableData?.indexFieldsFormat || [];
// 需要显示的字段:dimFields + indexFields
const fieldsToShow = [...dimFields, ...indexFields];
return props.tableData.rows.map(row => {
const processedRow: Record<string, any> = {};
// 处理每个字段
fieldsToShow.forEach(field => {
if (row.hasOwnProperty(field)) {
// 如果是indexFields字段,检查是否有对应的indexFieldsFormat字段
const fieldIndex = indexFields.indexOf(field);
if (fieldIndex !== -1 && indexFieldsFormat[fieldIndex] && row.hasOwnProperty(indexFieldsFormat[fieldIndex])) {
// 使用indexFieldsFormat的格式化值来显示,但保留原始值用于排序
processedRow[field] = {
display: row[indexFieldsFormat[fieldIndex]],
value: row[field]
};
} else {
// 其他字段直接使用原始值
processedRow[field] = row[field];
}
}
});
return processedRow;
});
} else if (Array.isArray(props.tableData)) { } else if (Array.isArray(props.tableData)) {
return props.tableData; return processRawData(props.tableData);
} }
return []; return [];
}); });
// 处理原始数据
const processRawData = (rawData: any[]) => {
if (!rawData || rawData.length === 0) return [];
// 获取字段配置
const indexFields = props.tableData?.indexFields || [];
const dimFields = props.tableData?.dimFields || [];
const indexFieldsFormat = props.tableData?.indexFieldsFormat || [];
// 需要显示的字段:dimFields + indexFields
const fieldsToShow = [...dimFields, ...indexFields];
return rawData.map((row: any) => {
const processedRow: Record<string, any> = {};
// 处理每个字段
fieldsToShow.forEach(field => {
if (row.hasOwnProperty(field)) {
// 如果是indexFields字段,检查是否有对应的indexFieldsFormat字段
const fieldIndex = indexFields.indexOf(field);
if (fieldIndex !== -1 && indexFieldsFormat[fieldIndex] && row.hasOwnProperty(indexFieldsFormat[fieldIndex])) {
// 使用indexFieldsFormat的格式化值来显示,但保留原始值用于排序
processedRow[field] = {
display: row[indexFieldsFormat[fieldIndex]],
value: row[field]
};
} else {
// 其他字段直接使用原始值
processedRow[field] = row[field];
}
}
});
return processedRow;
});
};
// 判断列是否为数字列 // 判断列是否为数字列
const isNumericColumn = (header: string) => { const isNumericColumn = (header: string) => {
// 使用indexFields来判断数字列 // 使用indexFields来判断数字列
...@@ -190,18 +274,29 @@ const tableColumns = computed(() => { ...@@ -190,18 +274,29 @@ const tableColumns = computed(() => {
width: getColumnWidth(header), width: getColumnWidth(header),
ellipsis: true, ellipsis: true,
...fixedConfig, ...fixedConfig,
sorter: isNumericColumn(header) ? (a, b) => { sorter: isSortColumn(header) ? {
// 对于indexFields字段,使用存储的原始值进行排序 compare: (a: any, b: any) => {
if (isIndexField && a[header] && a[header].value !== undefined) { // 对于数字字段
const aValue = parseFloat(a[header].value); if (isNumericColumn(header)) {
const bValue = parseFloat(b[header].value); // 对于indexFields字段,使用存储的原始值进行排序
return aValue - bValue; if (isIndexField && a[header] && a[header].value !== undefined) {
} else { const aValue = parseFloat(a[header].value);
// 其他字段直接使用当前字段排序 const bValue = parseFloat(b[header].value);
const aValue = parseFloat(a[header]); return aValue - bValue;
const bValue = parseFloat(b[header]); } else {
return aValue - bValue; // 其他数字字段直接使用当前字段排序
} const aValue = parseFloat(a[header]);
const bValue = parseFloat(b[header]);
return aValue - bValue;
}
} else {
// 对于文字字段,使用字符串排序
const aValue = getStringValue(a, header);
const bValue = getStringValue(b, header);
return aValue.localeCompare(bValue, 'zh-CN');
}
},
multiple: 1 // 所有列设置相同的优先级,测试排序行为
} : undefined } : undefined
}; };
}); });
...@@ -216,6 +311,12 @@ const isTextColumn = (header: string) => { ...@@ -216,6 +311,12 @@ const isTextColumn = (header: string) => {
return dimFields.includes(header); return dimFields.includes(header);
}; };
// 判断是否为可排序列(数字字段+文字字段里面包含名称的)
const isSortColumn = (header: string): boolean => {
// 数字字段 或者 (文本字段且包含"名称")
return isNumericColumn(header) || (isTextColumn(header) && header.toLowerCase().includes('名称'));
};
// 判断列是否为趋势列 // 判断列是否为趋势列
const isTrendColumn = (header: string) => { const isTrendColumn = (header: string) => {
return header.toLowerCase().includes('趋势') || header.toLowerCase().includes('trend'); return header.toLowerCase().includes('趋势') || header.toLowerCase().includes('trend');
...@@ -412,9 +513,8 @@ const getTableScroll = () => { ...@@ -412,9 +513,8 @@ const getTableScroll = () => {
/* 表格样式 */ /* 表格样式 */
:deep(.ant-table) { :deep(.ant-table) {
width: 100%; width: 100%;
.ant-table-thead > tr > th { .ant-table-thead > tr > th {
background:#D1E9FF; background:#D1E9FF !important;
color: #323232; color: #323232;
font-weight: 600; font-weight: 600;
padding: 6px 8px; padding: 6px 8px;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment