优化列表
This commit is contained in:
@@ -5,53 +5,53 @@
|
|||||||
<el-form-item v-for="col in filterableColumns" :key="col.dataIndex" :label="col.title">
|
<el-form-item v-for="col in filterableColumns" :key="col.dataIndex" :label="col.title">
|
||||||
<template v-if="col.filterType === 'text'">
|
<template v-if="col.filterType === 'text'">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="filters[col.dataIndex]"
|
v-model="filters[col.dataIndex]"
|
||||||
:placeholder="`搜索 ${col.title}`"
|
:placeholder="`搜索 ${col.title}`"
|
||||||
clearable
|
clearable
|
||||||
@change="handleFilterChange(col.dataIndex, filters[col.dataIndex])"
|
@change="handleFilterChange(col.dataIndex, filters[col.dataIndex])"
|
||||||
></el-input>
|
></el-input>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="col.filterType === 'number'">
|
<template v-else-if="col.filterType === 'number'">
|
||||||
<el-input-number
|
<el-input-number
|
||||||
v-model="filters[col.dataIndex]"
|
v-model="filters[col.dataIndex]"
|
||||||
:placeholder="`搜索 ${col.title}`"
|
:placeholder="`搜索 ${col.title}`"
|
||||||
:controls="false"
|
:controls="false"
|
||||||
clearable
|
clearable
|
||||||
@change="handleFilterChange(col.dataIndex, filters[col.dataIndex])"
|
@change="handleFilterChange(col.dataIndex, filters[col.dataIndex])"
|
||||||
></el-input-number>
|
></el-input-number>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="col.filterType === 'dateRange'">
|
<template v-else-if="col.filterType === 'dateRange'">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="filters[col.dataIndex]"
|
v-model="filters[col.dataIndex]"
|
||||||
type="datetimerange"
|
type="datetimerange"
|
||||||
range-separator="至"
|
range-separator="至"
|
||||||
start-placeholder="开始日期"
|
start-placeholder="开始日期"
|
||||||
end-placeholder="结束日期"
|
end-placeholder="结束日期"
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
@change="handleFilterChange(col.dataIndex, filters[col.dataIndex])"
|
@change="handleFilterChange(col.dataIndex, filters[col.dataIndex])"
|
||||||
></el-date-picker>
|
></el-date-picker>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="col.filterType === 'select'">
|
<template v-else-if="col.filterType === 'select'">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="filters[col.dataIndex]"
|
v-model="filters[col.dataIndex]"
|
||||||
:placeholder="`选择 ${col.title}`"
|
:placeholder="`选择 ${col.title}`"
|
||||||
clearable
|
clearable
|
||||||
@change="handleFilterChange(col.dataIndex, filters[col.dataIndex])"
|
@change="handleFilterChange(col.dataIndex, filters[col.dataIndex])"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="option in col.filterOptions"
|
v-for="option in col.filterOptions"
|
||||||
:key="option.value"
|
:key="option.value"
|
||||||
:label="option.text"
|
:label="option.text"
|
||||||
:value="option.value"
|
:value="option.value"
|
||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="col.filterType === 'boolean'">
|
<template v-else-if="col.filterType === 'boolean'">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="filters[col.dataIndex]"
|
v-model="filters[col.dataIndex]"
|
||||||
:placeholder="`选择 ${col.title}`"
|
:placeholder="`选择 ${col.title}`"
|
||||||
clearable
|
clearable
|
||||||
@change="handleFilterChange(col.dataIndex, filters[col.dataIndex])"
|
@change="handleFilterChange(col.dataIndex, filters[col.dataIndex])"
|
||||||
>
|
>
|
||||||
<el-option label="是" :value="true"></el-option>
|
<el-option label="是" :value="true"></el-option>
|
||||||
<el-option label="否" :value="false"></el-option>
|
<el-option label="否" :value="false"></el-option>
|
||||||
@@ -65,44 +65,46 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<el-table
|
<el-table
|
||||||
:data="data"
|
:data="data"
|
||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
border
|
border
|
||||||
style="width: 100%"
|
stripe
|
||||||
@sort-change="handleSortChange"
|
style="width: 100%"
|
||||||
|
@sort-change="handleSortChange"
|
||||||
>
|
>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
v-for="col in tableColumns"
|
v-for="col in tableColumns"
|
||||||
:key="col.key"
|
:key="col.key"
|
||||||
:prop="col.prop"
|
:prop="col.prop"
|
||||||
:label="col.title"
|
:label="col.title"
|
||||||
:sortable="col.sorter ? 'custom' : false"
|
:sortable="col.sorter ? 'custom' : false"
|
||||||
:formatter="col.formatter"
|
:formatter="col.formatter"
|
||||||
|
:min-width="col.minWidth"
|
||||||
>
|
>
|
||||||
<template v-if="col.render" #default="{ row }">
|
<template v-if="col.render" #default="{ row }">
|
||||||
<component :is="col.render(row)" />
|
<component :is="col.render(row)"/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<el-pagination
|
<el-pagination
|
||||||
@size-change="handleSizeChange"
|
@size-change="handleSizeChange"
|
||||||
@current-change="handleCurrentChange"
|
@current-change="handleCurrentChange"
|
||||||
:current-page="pagination.currentPage"
|
:current-page="pagination.currentPage"
|
||||||
:page-sizes="[10, 20, 50, 100]"
|
:page-sizes="[10, 20, 50, 100]"
|
||||||
:page-size="pagination.pageSize"
|
:page-size="pagination.pageSize"
|
||||||
layout="total, sizes, prev, pager, next, jumper"
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
:total="pagination.total"
|
:total="pagination.total"
|
||||||
background
|
background
|
||||||
style="margin-top: 20px; text-align: right;"
|
style="margin-top: 20px; text-align: right;"
|
||||||
></el-pagination>
|
></el-pagination>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, onMounted, watch, computed } from 'vue';
|
import {ref, reactive, onMounted, watch, computed} from 'vue';
|
||||||
import { ElMessage } from 'element-plus';
|
import {ElMessage} from 'element-plus';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
fetchData: {
|
fetchData: {
|
||||||
@@ -134,7 +136,7 @@ const filterableColumns = computed(() => {
|
|||||||
|
|
||||||
const tableColumns = computed(() => {
|
const tableColumns = computed(() => {
|
||||||
return props.columnsConfig.map(col => {
|
return props.columnsConfig.map(col => {
|
||||||
const newCol = { ...col };
|
const newCol = {...col};
|
||||||
newCol.prop = Array.isArray(col.dataIndex) ? col.dataIndex.join('.') : col.dataIndex;
|
newCol.prop = Array.isArray(col.dataIndex) ? col.dataIndex.join('.') : col.dataIndex;
|
||||||
return newCol;
|
return newCol;
|
||||||
});
|
});
|
||||||
@@ -182,7 +184,7 @@ const handleCurrentChange = (val) => {
|
|||||||
loadData();
|
loadData();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSortChange = ({ prop, order }) => {
|
const handleSortChange = ({prop, order}) => {
|
||||||
sortOrder.prop = prop;
|
sortOrder.prop = prop;
|
||||||
sortOrder.order = order;
|
sortOrder.order = order;
|
||||||
loadData();
|
loadData();
|
||||||
@@ -213,10 +215,12 @@ onMounted(() => {
|
|||||||
.generic-monitor-list {
|
.generic-monitor-list {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-form {
|
.filter-form {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-card {
|
.el-card {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { createApp } from 'vue';
|
|||||||
import { createRouter, createWebHistory } from 'vue-router';
|
import { createRouter, createWebHistory } from 'vue-router';
|
||||||
import ElementPlus from 'element-plus';
|
import ElementPlus from 'element-plus';
|
||||||
import 'element-plus/dist/index.css';
|
import 'element-plus/dist/index.css';
|
||||||
|
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'; // 导入 Element Plus 中文语言包
|
||||||
|
|
||||||
import App from './App.vue';
|
import App from './App.vue';
|
||||||
import Home from './components/Home.vue';
|
import Home from './components/Home.vue';
|
||||||
@@ -47,8 +48,8 @@ router.beforeEach((to, from, next) => {
|
|||||||
// 创建Vue应用实例
|
// 创建Vue应用实例
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
|
||||||
// 使用Element Plus组件库
|
// 全局配置 Element Plus 为中文
|
||||||
app.use(ElementPlus);
|
app.use(ElementPlus, { locale: zhCn });
|
||||||
|
|
||||||
// 使用路由
|
// 使用路由
|
||||||
app.use(router);
|
app.use(router);
|
||||||
|
|||||||
22
src/utils/format.js
Normal file
22
src/utils/format.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* 将 RFC3339 格式的日期时间字符串格式化为 'YYYY-MM-DD HH:mm:ss'
|
||||||
|
* @param {string | null | undefined} rfc3339String - 后端返回的日期时间字符串
|
||||||
|
* @returns {string} - 格式化后的字符串,如果输入无效则返回空字符串或提示
|
||||||
|
*/
|
||||||
|
export function formatRFC3339(rfc3339String) {
|
||||||
|
if (!rfc3339String) {
|
||||||
|
return '--'; // 或者返回空字符串 ''
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 例如: "2025-10-17T14:57:01.570169+08:00"
|
||||||
|
// 替换 'T' 为空格,并截取前 19 个字符即可得到 'YYYY-MM-DD HH:mm:ss'
|
||||||
|
return rfc3339String.replace('T', ' ').substring(0, 19);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error formatting date:', rfc3339String, error);
|
||||||
|
return rfc3339String; // 格式化失败时返回原始值
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 你未来还可以添加其他全局格式化函数
|
||||||
|
// export function formatCurrency(number) { ... }
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="device-command-log-view">
|
<div class="device-command-log-view">
|
||||||
<GenericMonitorList
|
<GenericMonitorList
|
||||||
:fetchData="fetchDeviceCommandLogs"
|
:fetchData="fetchDeviceCommandLogs"
|
||||||
:columnsConfig="deviceCommandLogColumns"
|
:columnsConfig="deviceCommandLogColumns"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import GenericMonitorList from '../../components/GenericMonitorList.vue';
|
import GenericMonitorList from '../../components/GenericMonitorList.vue';
|
||||||
import { getDeviceCommandLogs } from '../../api/monitor.js';
|
import {getDeviceCommandLogs} from '../../api/monitor.js';
|
||||||
|
import {formatRFC3339} from '../../utils/format.js'; // 导入全局格式化函数
|
||||||
|
|
||||||
// 适配通用组件的 fetchData prop
|
// 适配通用组件的 fetchData prop
|
||||||
const fetchDeviceCommandLogs = async (params) => {
|
const fetchDeviceCommandLogs = async (params) => {
|
||||||
@@ -26,12 +27,15 @@ const deviceCommandLogColumns = [
|
|||||||
key: 'device_id',
|
key: 'device_id',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
filterType: 'number', // 设置筛选类型为数字
|
filterType: 'number', // 设置筛选类型为数字
|
||||||
|
minWidth: 100, // 设置最小宽度
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '消息ID',
|
title: '消息ID',
|
||||||
dataIndex: 'message_id',
|
dataIndex: 'message_id',
|
||||||
key: 'message_id',
|
key: 'message_id',
|
||||||
filterType: 'text', // 设置筛选类型为文本
|
// 后端不支持此字段筛选,暂时移除
|
||||||
|
// filterType: 'text',
|
||||||
|
minWidth: 300, // UUID较长,设置较宽的最小宽度
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '发送时间',
|
title: '发送时间',
|
||||||
@@ -39,6 +43,8 @@ const deviceCommandLogColumns = [
|
|||||||
key: 'sent_at',
|
key: 'sent_at',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
filterType: 'dateRange', // 设置筛选类型为日期范围
|
filterType: 'dateRange', // 设置筛选类型为日期范围
|
||||||
|
formatter: (row, column, cellValue) => formatRFC3339(cellValue), // 使用全局格式化函数
|
||||||
|
minWidth: 180, // 设置最小宽度
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '接收成功',
|
title: '接收成功',
|
||||||
@@ -46,12 +52,15 @@ const deviceCommandLogColumns = [
|
|||||||
key: 'received_success',
|
key: 'received_success',
|
||||||
filterType: 'boolean', // 设置筛选类型为布尔值
|
filterType: 'boolean', // 设置筛选类型为布尔值
|
||||||
formatter: (row, column, cellValue) => (cellValue ? '是' : '否'),
|
formatter: (row, column, cellValue) => (cellValue ? '是' : '否'),
|
||||||
|
minWidth: 100, // 设置最小宽度
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '确认时间',
|
title: '确认时间',
|
||||||
dataIndex: 'acknowledged_at',
|
dataIndex: 'acknowledged_at',
|
||||||
key: 'acknowledged_at',
|
key: 'acknowledged_at',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
|
formatter: (row, column, cellValue) => formatRFC3339(cellValue), // 使用全局格式化函数
|
||||||
|
minWidth: 180, // 设置最小宽度
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user