Element UI设置列表时间倒序/正序排序展示

在ElementUI的el-table组件中,通过设置:sortable为true开启列排序,并使用:sort-by属性配合负号(-)指定降序排列,例如-paixuDate,确保日期数据以时间戳形式存储以保证正确排序。

在 Element UI 的 el-table 中,可以通过设置 :sort-by 属性来指定表格列的排序属性。那么,如果要按时间倒序排序,只需要将 :sort-by 属性设置为日期字段名,同时在这个字段前加上符号“-”,表示降序排列。

因此,可以按以下步骤实现将 el-table-column 根据时间倒序排序:

  1. 在 el-table-column 上设置 :sortable 属性为 true,开启该列排序功能。

html复制代码

<el-table-column label="待排序日期" align="center" prop="paixuDate" :sortable="true"/>

  1. 在 el-table-column 上设置 :sort-by 属性为降序排序的日期字段名(即带有“-”的日期字段名)。

html复制代码

<el-table-column label="待排序日期" align="center" prop="paixuDate" :sortable="true" :sort-by="'-paixuDate'"/>

这样就可以实现对 el-table-column 按时间倒序排序了。最后,需要注意的是,使用 Element UI 的 el-table 进行排序时,日期数据需要以时间戳形式进行排序,否则会出现不正确的排序结果。

<template> <div> <div class="table-container"> <el-table :data="filteredTableData" :default-sort="{ prop: 'cityName', order: 'ascending' }" @sort-change="handleSortChange" element-loading-text="数据加载中..." class="custom-header-table" :row-class-name="rowClassName"> <el-table-column class="className" v-for="column in tableColumns" :key="column.prop || column.label" :label="column.label" :fixed="column.fixed" :align="column.align" :sortable="column.sortable" :sort-method="column.sortable ? createSorter(column.prop) : null"> <!-- 父列:只作为容器,不显示数据 --> <template v-if="column.children && column.children.length > 0"> <el-table-column v-for="child in column.children" :key="child.prop" :prop="child.prop" :label="child.label" :sortable="child.sortable" :align="child.align || 'right'" class="className" :sort-method="child.sortable ? createSorter(child.prop) : null"> <template slot-scope="{ row }"> <span class="text-right cell-clickable" @click.stop="handleCellClick(row, child, row[child.prop], child.type)"> {{ row[child.prop] + "%" }} </span> </template> </el-table-column> </template> <!-- 普通列:显示数据 --> <template slot-scope="{ row }" v-if="!column.children || column.children.length === 0"> <!-- 单元格点击事件 --> <span class="cell-clickable" @click.stop="handleCellClick(row, column, row[column.prop], column.type)"> {{ row && column.prop !== undefined ? (column.prop.endsWith('Rate') ? row[column.prop] + '%' : row[column.prop]) : '--' }} </span> </template> </el-table-column> <el-table-column class="className" v-for="column in tableColumns" :key="column.prop || column.label" :label="column.label" :fixed="column.fixed" :align="column.align" :sortable="column.sortable" :sort-method="column.sortable ? createSorter(column.prop) : null"> <!-- 父列:只作为容器,不显示数据 --> <template v-if="column.children && column.children.length > 0"> <el-table-column v-for="child in column.children" :key="child.prop" :prop="child.prop" :label="child.label" :sortable="child.sortable" :align="child.align || 'right'" class="className" :sort-method="child.sortable ? createSorter(child.prop) : null"> <template slot-scope="{ row }"> <span class="text-right cell-clickable" @click.stop="handleCellClick(row, child, row[child.prop], child.type)"> {{ row[child.prop] + "%" }} </span> </template> </el-table-column> </template> <!-- 普通列:显示数据 --> <template slot-scope="{ row }" v-if="!column.children || column.children.length === 0"> <!-- 单元格点击事件 --> <span class="cell-clickable" @click.stop="handleCellClick(row, column, row[column.prop], column.type)"> {{ row && column.prop !== undefined ? (column.prop.endsWith('Rate') ? row[column.prop] + '%' : row[column.prop]) : '--' }} </span> </template> </el-table-column> </el-table> </div> <!-- 单元格详情弹窗 --> <el-dialog :title="dialogConfig.title" :visible.sync="showCellDialog" width="60%" :close-on-click-modal="false" class="cell-detail-dialog"> <div class="cell-dialog-content"> <div class="info-section"> <div class="info-item"> <span class="info-label">数据来源:</span> <span class="info-value">{{ dialogConfig.dataSources }}</span> </div> <div class="info-item"> <span class="info-label">统计口径:</span> <span class="info-value">{{ dialogConfig.statisticalCaliber }}</span> </div> <div class="info-item"> <span class="info-label">指标值:</span> <span class="info-value highlight">{{ selectedCell.cellValue }}</span> </div> </div> <div class="table-section"> <div class="table-header"> <h3 class="table-title">失分项目明细</h3> <el-button type="primary" @click="exportCellValue" size="small" icon="el-icon-download"> 导出数据 </el-button> </div> <el-table :data="pagedDetialTable" stripe border v-loading="detailTableLoading" element-loading-text="明细数据加载中..." style="width: 100%"> <el-table-column type="index" :index="indexMethod" label="号" width="60" align="center"> </el-table-column> <el-table-column prop="productCode" label="项目编号" width="140"> </el-table-column> <el-table-column prop="productName" label="项目名称" min-width="200"> <template slot-scope="{ row }"> <el-tooltip effect="dark" :content="row.productName" placement="top"> <span class="product-name">{{ row.productName }}</span> </el-tooltip> </template> </el-table-column> <el-table-column prop="area" label="区域" width="100" align="center"> </el-table-column> <el-table-column prop="createTime" label="创建时间" width="160" align="center"> </el-table-column> </el-table> </div> <!-- 分页控件 --> <div class="pagination-container" v-if="detialTable.length > pageSize"> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage" :page-sizes="[5, 10, 15, 20]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="detialTable.length"> </el-pagination> </div> </div> <div slot="footer" class="dialog-footer"> <el-button @click="showCellDialog = false">关闭</el-button> </div> </el-dialog> </div> </template> <script> import { detailConfig, getDataRevenueDetialInfo } from '../Mock/revenueEnvironment'; export default { name: 'RevenueEnvironmentTable', props: { tableData: { type: Array, required: true, default: () => [] }, tableColumns: { type: Array, required: true, default: () => [ ] }, queryTime: { required: true, }, }, data() { return { searchQuery: '', detailTableLoading: false, // 新增:单元格弹窗相关状态 showCellDialog: false, dialogConfig: detailConfig.dialogConfig, selectedCell: { row: {}, column: {}, cellValue: '', cityName: '', columnName: '', columnProp: '', }, detialTable: [], currentPage: 1, pageSize: 5, dataSourceKey: '', statisticalCaliberKey: '', currentSortOrder: 'ascending' // 默认升 }; }, computed: { //数据的过滤 这里是作为后续的拓展 filteredTableData() { // 分离数据:非平均行和平均行 const nonAverageData = this.tableData.filter(row => !row.isProvinceAverage); // const nonAverageData = this.tableData; // 对非平均行进行搜索过滤(后续扩展搜索功能) let filteredNonAverage = nonAverageData; if (this.searchQuery) { const query = this.searchQuery.toLowerCase(); filteredNonAverage = nonAverageData.filter(item => item.cityName.toLowerCase().includes(query) ); } // 返回结果:过滤后的非平均行 + 计算的平均行(如果存在) const result = [...filteredNonAverage]; if (this.provinceAverage) { result.push(this.provinceAverage); } return result; }, /** * 计算全省平均率 * @returns {Object|null} 包含全省平均数据的对象 */ provinceAverage() { if (!this.tableData || this.tableData.length === 0) { return null; } // 从 tableColumns 中动态获取所有需要计算平均率的字段 const rateFields = this.getRateFields(); // console.log(rateFields); const averageData = { cityName: '全省平均', isProvinceAverage: true // 标记为平均行,用于样式区分 }; // 计算每个百分比字段的平均值 rateFields.forEach(field => { let sum = 0; let count = 0; this.tableData.forEach(item => { const value = Number(item[field]); if (!isNaN(value) && value >= 0) { sum += value; count++; } }); // 计算平均值,对avgDays字段特殊处理 if (field === 'avgDays') { // 对天数字段进行四舍五入取整 averageData[field] = count > 0 ? Math.round(sum / count).toString() : '0'; } else { // 其他字段保留2位小数 averageData[field] = count > 0 ? (sum / count).toFixed(2) : '0.00'; } }); return averageData; }, //弹框内容的分页 pagedDetialTable() { const start = (this.currentPage - 1) * this.pageSize; const end = start + this.pageSize; return this.detialTable.slice(start, end); }, }, methods: { //自定义排序 el排序失效 customSort(a, b, prop) { // 如果其中一个是平均行,不参与排序比较 // 二选1 // if (a.isProvinceAverage || b.isProvinceAverage) { // return 0; // } console.log("a", a); console.log("b", b); console.log("prop", prop); // 处理平均行逻辑 if (a.isProvinceAverage && b.isProvinceAverage) { console.log("排序结果: 两行都是平均行,相等"); return 0; } if (a.isProvinceAverage) { console.log("排序结果: a 是平均行,排在 b 后面"); return 1; } if (b.isProvinceAverage) { console.log("排序结果: b 是平均行,a 排在 b 前面"); return -1; } // 以下为非平均行的排序逻辑 const aVal = a[prop]; const bVal = b[prop]; // 处理空值 if (aVal === null || aVal === undefined || aVal === '') return 1; if (bVal === null || bVal === undefined || bVal === '') return -1; // 处理数字和百分比数据 let numA, numB; if (typeof aVal === 'string' && aVal.includes('%')) { // 百分比数据:提取数字部分 numA = parseFloat(aVal.replace('%', '')); numB = parseFloat(bVal.replace('%', '')); } else { // 普通数字数据 numA = parseFloat(aVal); numB = parseFloat(bVal); } // 处理转换失败的情况 if (isNaN(numA)) return 1; if (isNaN(numB)) return -1; const result = numA - numB; console.log(`最终排序结果: ${a.cityName} vs ${b.cityName} = ${result}`); return result; }, handleSortChange({ prop, order }) { this.currentSortProp = prop; this.currentSortOrder = order || 'ascending'; }, /** * 生成排序方法 */ createSorter(prop) { return (a, b) => { // 获取当前排序方向 const sortOrder = this.currentSortOrder; // 处理平均行逻辑 if (a.isProvinceAverage && b.isProvinceAverage) { console.log("排序结果: 两行都是平均行,相等"); return 0; } if (a.isProvinceAverage) { // 时平均行最大(返回1),反时平均行最小(返回-1) // 这样无论,平均行都在底部 console.log("排序结果: a 是平均行,排在 b 后面"); return sortOrder === 'ascending' ? 1 : -1; } if (b.isProvinceAverage) { // 时平均行最大(返回-1),反时平均行最小(返回1) console.log("排序结果: b 是平均行,a 排在 b 前面"); return sortOrder === 'ascending' ? -1 : 1; } // 以下为非平均行的排序逻辑 const aVal = a[prop]; const bVal = b[prop]; // 处理空值 if (aVal === null || aVal === undefined || aVal === '') return 1; if (bVal === null || bVal === undefined || bVal === '') return -1; // 处理数字和百分比数据 let numA, numB; if (typeof aVal === 'string' && aVal.includes('%')) { numA = parseFloat(aVal.replace('%', '')); numB = parseFloat(bVal.replace('%', '')); } else { numA = parseFloat(aVal); numB = parseFloat(bVal); } // 处理转换失败的情况 if (isNaN(numA)) return 1; if (isNaN(numB)) return -1; const result = numA - numB; // 根据排序方向调整结果 return sortOrder === 'descending' ? -result : result; }; }, 代码这里有问题,当的时候全省确实是在下方,但反的时候却在上方。
最新发布
10-23
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值