From 35152ea3fe0eb84c15101f5ed09cb1d65b0b76a4 Mon Sep 17 00:00:00 2001
From: huang <1724659546@qq.com>
Date: Mon, 22 Sep 2025 16:27:27 +0800
Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=88=97=E8=A1=A8=E6=8E=92?=
=?UTF-8?q?=E5=BA=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/DeviceList.vue | 45 +++++++++++++++++---------
src/components/PlanList.vue | 59 ++++++++++++++++++++++++++++++-----
2 files changed, 82 insertions(+), 22 deletions(-)
diff --git a/src/components/DeviceList.vue b/src/components/DeviceList.vue
index 41c3b8ba..d4d341e0 100644
--- a/src/components/DeviceList.vue
+++ b/src/components/DeviceList.vue
@@ -43,10 +43,11 @@
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
:row-class-name="tableRowClassName"
:highlight-current-row="false"
- :scrollbar-always-on="true">
+ :scrollbar-always-on="true"
+ @sort-change="handleSortChange">
-
-
+
+
{{ formatDeviceType(scope.row.type) }}
@@ -92,6 +93,7 @@ export default {
data() {
return {
tableData: [], // 树形表格数据
+ originalTableData: [], // 存储原始未排序的树形数据
allDevices: [], // 存储所有设备用于构建树形结构
loading: false,
error: null,
@@ -112,10 +114,9 @@ export default {
try {
const data = await deviceService.getDevices();
- // 保存所有设备数据
this.allDevices = data;
- // 构建树形结构数据
this.tableData = this.buildTreeData(data);
+ this.originalTableData = [...this.tableData]; // 保存原始顺序
} catch (err) {
this.error = err.message || '未知错误';
console.error('加载设备列表失败:', err);
@@ -123,15 +124,37 @@ export default {
this.loading = false;
}
},
+
+ // 处理表格排序
+ handleSortChange({ prop, order }) {
+ if (!order) {
+ // 如果取消排序,则恢复原始顺序
+ this.tableData = [...this.originalTableData];
+ return;
+ }
+
+ const sortFactor = order === 'ascending' ? 1 : -1;
+
+ // 只对顶层项(区域主控)进行排序
+ this.tableData.sort((a, b) => {
+ const valA = a[prop];
+ const valB = b[prop];
+
+ if (valA < valB) {
+ return -1 * sortFactor;
+ }
+ if (valA > valB) {
+ return 1 * sortFactor;
+ }
+ return 0;
+ });
+ },
// 构建树形结构数据
buildTreeData(devices) {
- // 先找出所有区域主控设备
const areaControllers = devices.filter(device => device.type === 'area_controller');
- // 为每个区域主控设备添加子设备列表
return areaControllers.map(controller => {
- // 找到属于当前区域主控的所有普通设备
const children = devices.filter(device =>
device.type === 'device' && device.parent_id === controller.id
);
@@ -173,10 +196,8 @@ export default {
},
editDevice(device) {
- // 处理设备数据,确保正确传递给表单
const processedDevice = { ...device };
- // 如果properties是字符串,则解析为对象
if (processedDevice.properties && typeof processedDevice.properties === 'string') {
try {
processedDevice.properties = JSON.parse(processedDevice.properties);
@@ -201,7 +222,6 @@ export default {
await deviceService.deleteDevice(device.id);
this.$message.success('删除成功');
- // 重新加载设备列表
await this.loadDevices();
} catch (err) {
if (err !== 'cancel') {
@@ -210,15 +230,12 @@ export default {
}
},
- // 设备操作成功回调
async onDeviceSuccess() {
this.$message.success(this.isEdit ? '设备更新成功' : '设备添加成功');
this.dialogVisible = false;
- // 重新加载设备列表
await this.loadDevices();
},
- // 为区域主控设备添加静态高亮样式
tableRowClassName({ row, rowIndex }) {
if (row.type === 'area_controller') {
return 'current-row';
diff --git a/src/components/PlanList.vue b/src/components/PlanList.vue
index 22479be2..4916e974 100644
--- a/src/components/PlanList.vue
+++ b/src/components/PlanList.vue
@@ -33,30 +33,31 @@
-
-
+ :scrollbar-always-on="true"
+ @sort-change="handleSortChange">
+
+
-
+
手动
自动(无限执行)
自动({{ scope.row.execute_num }}次)
-
-
+
+
禁用
启用
执行完毕
-
+
{{ formatNextExecutionTime(scope.row.cron_expression) }}
@@ -103,6 +104,7 @@ export default {
data() {
return {
plans: [],
+ originalPlans: [], // Store the original unsorted list
dialogVisible: false,
isEdit: false,
loading: false,
@@ -131,6 +133,7 @@ export default {
try {
const response = await apiClient.plans.list();
this.plans = response.data?.plans || [];
+ this.originalPlans = [...this.plans]; // Keep a copy of the original order
} catch (err) {
this.error = err.message || '未知错误';
console.error('加载计划列表失败:', err);
@@ -138,6 +141,46 @@ export default {
this.loading = false;
}
},
+
+ // 处理表格排序
+ handleSortChange({ prop, order }) {
+ if (!order) {
+ // 恢复原始顺序
+ this.plans = [...this.originalPlans];
+ return;
+ }
+
+ const sortFactor = order === 'ascending' ? 1 : -1;
+
+ this.plans.sort((a, b) => {
+ let valA = a[prop];
+ let valB = b[prop];
+
+ // '下次执行时间' 列的特殊排序逻辑
+ if (prop === 'cron_expression') {
+ try {
+ const parser = cronParser.default || cronParser;
+ valA = valA ? parser.parse(valA).next().toDate().getTime() : 0;
+ } catch (e) {
+ valA = 0; // 无效的 cron 表达式排在前面
+ }
+ try {
+ const parser = cronParser.default || cronParser;
+ valB = valB ? parser.parse(valB).next().toDate().getTime() : 0;
+ } catch (e) {
+ valB = 0;
+ }
+ }
+
+ if (valA < valB) {
+ return -1 * sortFactor;
+ }
+ if (valA > valB) {
+ return 1 * sortFactor;
+ }
+ return 0;
+ });
+ },
// 格式化下次执行时间
formatNextExecutionTime(cronExpression) {