增加列表排序
This commit is contained in:
@@ -43,10 +43,11 @@
|
|||||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||||
:row-class-name="tableRowClassName"
|
:row-class-name="tableRowClassName"
|
||||||
:highlight-current-row="false"
|
:highlight-current-row="false"
|
||||||
:scrollbar-always-on="true">
|
:scrollbar-always-on="true"
|
||||||
|
@sort-change="handleSortChange">
|
||||||
<el-table-column width="40"></el-table-column>
|
<el-table-column width="40"></el-table-column>
|
||||||
<el-table-column prop="id" label="设备ID" min-width="60" />
|
<el-table-column prop="id" label="设备ID" min-width="100" sortable="custom" />
|
||||||
<el-table-column prop="name" label="设备名称" min-width="120" />
|
<el-table-column prop="name" label="设备名称" min-width="120" sortable="custom" />
|
||||||
<el-table-column prop="type" label="设备类型" min-width="100">
|
<el-table-column prop="type" label="设备类型" min-width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ formatDeviceType(scope.row.type) }}
|
{{ formatDeviceType(scope.row.type) }}
|
||||||
@@ -92,6 +93,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tableData: [], // 树形表格数据
|
tableData: [], // 树形表格数据
|
||||||
|
originalTableData: [], // 存储原始未排序的树形数据
|
||||||
allDevices: [], // 存储所有设备用于构建树形结构
|
allDevices: [], // 存储所有设备用于构建树形结构
|
||||||
loading: false,
|
loading: false,
|
||||||
error: null,
|
error: null,
|
||||||
@@ -112,10 +114,9 @@ export default {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await deviceService.getDevices();
|
const data = await deviceService.getDevices();
|
||||||
// 保存所有设备数据
|
|
||||||
this.allDevices = data;
|
this.allDevices = data;
|
||||||
// 构建树形结构数据
|
|
||||||
this.tableData = this.buildTreeData(data);
|
this.tableData = this.buildTreeData(data);
|
||||||
|
this.originalTableData = [...this.tableData]; // 保存原始顺序
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.error = err.message || '未知错误';
|
this.error = err.message || '未知错误';
|
||||||
console.error('加载设备列表失败:', err);
|
console.error('加载设备列表失败:', err);
|
||||||
@@ -123,15 +124,37 @@ export default {
|
|||||||
this.loading = false;
|
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) {
|
buildTreeData(devices) {
|
||||||
// 先找出所有区域主控设备
|
|
||||||
const areaControllers = devices.filter(device => device.type === 'area_controller');
|
const areaControllers = devices.filter(device => device.type === 'area_controller');
|
||||||
|
|
||||||
// 为每个区域主控设备添加子设备列表
|
|
||||||
return areaControllers.map(controller => {
|
return areaControllers.map(controller => {
|
||||||
// 找到属于当前区域主控的所有普通设备
|
|
||||||
const children = devices.filter(device =>
|
const children = devices.filter(device =>
|
||||||
device.type === 'device' && device.parent_id === controller.id
|
device.type === 'device' && device.parent_id === controller.id
|
||||||
);
|
);
|
||||||
@@ -173,10 +196,8 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
editDevice(device) {
|
editDevice(device) {
|
||||||
// 处理设备数据,确保正确传递给表单
|
|
||||||
const processedDevice = { ...device };
|
const processedDevice = { ...device };
|
||||||
|
|
||||||
// 如果properties是字符串,则解析为对象
|
|
||||||
if (processedDevice.properties && typeof processedDevice.properties === 'string') {
|
if (processedDevice.properties && typeof processedDevice.properties === 'string') {
|
||||||
try {
|
try {
|
||||||
processedDevice.properties = JSON.parse(processedDevice.properties);
|
processedDevice.properties = JSON.parse(processedDevice.properties);
|
||||||
@@ -201,7 +222,6 @@ export default {
|
|||||||
|
|
||||||
await deviceService.deleteDevice(device.id);
|
await deviceService.deleteDevice(device.id);
|
||||||
this.$message.success('删除成功');
|
this.$message.success('删除成功');
|
||||||
// 重新加载设备列表
|
|
||||||
await this.loadDevices();
|
await this.loadDevices();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err !== 'cancel') {
|
if (err !== 'cancel') {
|
||||||
@@ -210,15 +230,12 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 设备操作成功回调
|
|
||||||
async onDeviceSuccess() {
|
async onDeviceSuccess() {
|
||||||
this.$message.success(this.isEdit ? '设备更新成功' : '设备添加成功');
|
this.$message.success(this.isEdit ? '设备更新成功' : '设备添加成功');
|
||||||
this.dialogVisible = false;
|
this.dialogVisible = false;
|
||||||
// 重新加载设备列表
|
|
||||||
await this.loadDevices();
|
await this.loadDevices();
|
||||||
},
|
},
|
||||||
|
|
||||||
// 为区域主控设备添加静态高亮样式
|
|
||||||
tableRowClassName({ row, rowIndex }) {
|
tableRowClassName({ row, rowIndex }) {
|
||||||
if (row.type === 'area_controller') {
|
if (row.type === 'area_controller') {
|
||||||
return 'current-row';
|
return 'current-row';
|
||||||
|
|||||||
@@ -33,30 +33,31 @@
|
|||||||
|
|
||||||
<el-table
|
<el-table
|
||||||
v-else
|
v-else
|
||||||
:data="plans"
|
:data="plans"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
class="plan-list-table"
|
class="plan-list-table"
|
||||||
:fit="true"
|
:fit="true"
|
||||||
:scrollbar-always-on="true">
|
:scrollbar-always-on="true"
|
||||||
<el-table-column prop="id" label="计划ID" min-width="60" />
|
@sort-change="handleSortChange">
|
||||||
<el-table-column prop="name" label="计划名称" min-width="120" />
|
<el-table-column prop="id" label="计划ID" min-width="100" sortable="custom" />
|
||||||
|
<el-table-column prop="name" label="计划名称" min-width="120" sortable="custom" />
|
||||||
<el-table-column prop="description" label="计划描述" min-width="150" />
|
<el-table-column prop="description" label="计划描述" min-width="150" />
|
||||||
<el-table-column prop="execution_type" label="执行类型" min-width="150">
|
<el-table-column prop="execution_type" label="执行类型" min-width="150" sortable="custom">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag v-if="scope.row.execution_type === 'manual'">手动</el-tag>
|
<el-tag v-if="scope.row.execution_type === 'manual'">手动</el-tag>
|
||||||
<el-tag v-else-if="scope.row.execute_num === 0" type="success">自动(无限执行)</el-tag>
|
<el-tag v-else-if="scope.row.execute_num === 0" type="success">自动(无限执行)</el-tag>
|
||||||
<el-tag v-else type="warning">自动({{ scope.row.execute_num }}次)</el-tag>
|
<el-tag v-else type="warning">自动({{ scope.row.execute_num }}次)</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="execute_count" label="已执行次数" min-width="100" />
|
<el-table-column prop="execute_count" label="已执行次数" min-width="120" sortable="custom" />
|
||||||
<el-table-column prop="status" label="状态" min-width="100">
|
<el-table-column prop="status" label="状态" min-width="100" sortable="custom">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag v-if="scope.row.status === 0" type="danger">禁用</el-tag>
|
<el-tag v-if="scope.row.status === 0" type="danger">禁用</el-tag>
|
||||||
<el-tag v-else-if="scope.row.status === 1" type="success">启用</el-tag>
|
<el-tag v-else-if="scope.row.status === 1" type="success">启用</el-tag>
|
||||||
<el-tag v-else type="info">执行完毕</el-tag>
|
<el-tag v-else type="info">执行完毕</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="cron_expression" label="下次执行时间" min-width="150">
|
<el-table-column prop="cron_expression" label="下次执行时间" min-width="150" sortable="custom">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ formatNextExecutionTime(scope.row.cron_expression) }}
|
{{ formatNextExecutionTime(scope.row.cron_expression) }}
|
||||||
</template>
|
</template>
|
||||||
@@ -103,6 +104,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
plans: [],
|
plans: [],
|
||||||
|
originalPlans: [], // Store the original unsorted list
|
||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
isEdit: false,
|
isEdit: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
@@ -131,6 +133,7 @@ export default {
|
|||||||
try {
|
try {
|
||||||
const response = await apiClient.plans.list();
|
const response = await apiClient.plans.list();
|
||||||
this.plans = response.data?.plans || [];
|
this.plans = response.data?.plans || [];
|
||||||
|
this.originalPlans = [...this.plans]; // Keep a copy of the original order
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.error = err.message || '未知错误';
|
this.error = err.message || '未知错误';
|
||||||
console.error('加载计划列表失败:', err);
|
console.error('加载计划列表失败:', err);
|
||||||
@@ -138,6 +141,46 @@ export default {
|
|||||||
this.loading = false;
|
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) {
|
formatNextExecutionTime(cronExpression) {
|
||||||
|
|||||||
Reference in New Issue
Block a user