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

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

parent 1f5f143c
......@@ -34,7 +34,7 @@
</template>
<script setup lang="ts">
import { computed, ref } from 'vue';
import { computed, ref, reactive } from 'vue';
import { Table as ATable } from 'ant-design-vue';
import { formatNumber } from './utils/utils';
......@@ -47,6 +47,12 @@ const paginationState = ref({
pageSize: 15
});
// 排序状态
const sortState = reactive({
sortedData: [] as any[],
isSorted: false
});
// 处理表格变化事件(包括分页、排序等)
const handleTableChange = (pagination: any, filters: any, sorter: any) => {
// 处理分页变化
......@@ -58,9 +64,75 @@ const handleTableChange = (pagination: any, filters: any, sorter: any) => {
};
}
// 可以在这里添加排序变化的处理
// 处理排序变化(支持多列排序)
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>(), {
const processedTableData = computed(() => {
if (!props.tableData) return [];
// 如果有排序后的数据,使用排序后的数据
if (sortState.isSorted && sortState.sortedData.length > 0) {
return processRawData(sortState.sortedData);
}
// 处理传入完整数据结构的情况
if (Array.isArray(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;
});
return processRawData(props.tableData.rows);
} else if (Array.isArray(props.tableData)) {
return props.tableData;
return processRawData(props.tableData);
}
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) => {
// 使用indexFields来判断数字列
......@@ -190,18 +274,29 @@ const tableColumns = computed(() => {
width: getColumnWidth(header),
ellipsis: true,
...fixedConfig,
sorter: isNumericColumn(header) ? (a, b) => {
// 对于indexFields字段,使用存储的原始值进行排序
if (isIndexField && a[header] && a[header].value !== undefined) {
const aValue = parseFloat(a[header].value);
const bValue = parseFloat(b[header].value);
return aValue - bValue;
} else {
// 其他字段直接使用当前字段排序
const aValue = parseFloat(a[header]);
const bValue = parseFloat(b[header]);
return aValue - bValue;
}
sorter: isSortColumn(header) ? {
compare: (a: any, b: any) => {
// 对于数字字段
if (isNumericColumn(header)) {
// 对于indexFields字段,使用存储的原始值进行排序
if (isIndexField && a[header] && a[header].value !== undefined) {
const aValue = parseFloat(a[header].value);
const bValue = parseFloat(b[header].value);
return aValue - bValue;
} else {
// 其他数字字段直接使用当前字段排序
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
};
});
......@@ -216,6 +311,12 @@ const isTextColumn = (header: string) => {
return dimFields.includes(header);
};
// 判断是否为可排序列(数字字段+文字字段里面包含名称的)
const isSortColumn = (header: string): boolean => {
// 数字字段 或者 (文本字段且包含"名称")
return isNumericColumn(header) || (isTextColumn(header) && header.toLowerCase().includes('名称'));
};
// 判断列是否为趋势列
const isTrendColumn = (header: string) => {
return header.toLowerCase().includes('趋势') || header.toLowerCase().includes('trend');
......@@ -412,9 +513,8 @@ const getTableScroll = () => {
/* 表格样式 */
:deep(.ant-table) {
width: 100%;
.ant-table-thead > tr > th {
background:#D1E9FF;
background:#D1E9FF !important;
color: #323232;
font-weight: 600;
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