From a8fd89f0a85af0c13bbde0ae8ee8fad84ec8e6f7 Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期二, 01 九月 2026 12:21:47 +0800
Subject: [PATCH] 优化数据修订详情展示

---
 src/views/DataRevision.vue |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/views/DataRevision.vue b/src/views/DataRevision.vue
index 5b8abb8..f117eff 100644
--- a/src/views/DataRevision.vue
+++ b/src/views/DataRevision.vue
@@ -2,13 +2,13 @@
 import { onMounted, reactive, ref } from 'vue'
 import { ElMessage } from 'element-plus'
 import { useRoute, useRouter } from 'vue-router'
-import { formatRevisionTime, getDataRevisionActions, revisionDataTypeLabels, revisionOperationLabels, type DataRevisionAction, type RevisionDataType, type RevisionOperationType } from '@/api/dataRevisions'
+import { formatRevisionScope, formatRevisionTime, getDataRevisionActions, revisionDataTypeLabels, revisionOperationLabels, type DataRevisionAction, type RevisionDataType, type RevisionOperationType } from '@/api/dataRevisions'
 interface FilterState { test: string; dataType: RevisionDataType | ''; operationType: RevisionOperationType | ''; dateRange: [string, string] | null }
 const route = useRoute(); const router = useRouter(); const initialTest = String(route.query.testId || route.query.testName || '')
 const initialDataType = ['REALTIME', 'STEP', 'CYCLE'].includes(String(route.query.dataType)) ? String(route.query.dataType) as RevisionDataType : ''
 const filters = reactive<FilterState>({ test: initialTest, dataType: initialDataType, operationType: '', dateRange: null }); const applied = ref<FilterState>({ ...filters })
 const records = ref<DataRevisionAction[]>([]); const total = ref(0); const currentPage = ref(1); const pageSize = ref(10); const loading = ref(false); const loadError = ref('')
-const dataTypeLabels = revisionDataTypeLabels; const operationLabels = revisionOperationLabels; const formatTime = formatRevisionTime
+const dataTypeLabels = revisionDataTypeLabels; const operationLabels = revisionOperationLabels; const formatTime = formatRevisionTime; const formatScope = formatRevisionScope
 function localDayBoundary(date: string, dayOffset = 0) { const value = new Date(`${date}T00:00:00`); value.setDate(value.getDate() + dayOffset); return value.toISOString() }
 async function loadRecords(showResult = false) { loading.value = true; loadError.value = ''; const query = applied.value; const keyword = query.test.trim(); try { const result = await getDataRevisionActions({ pageNum: currentPage.value, pageSize: pageSize.value, testId: /^\d+$/.test(keyword) ? Number(keyword) : undefined, testName: keyword && !/^\d+$/.test(keyword) ? keyword : undefined, dataType: query.dataType || undefined, operationType: query.operationType || undefined, beginCreatedAt: query.dateRange ? localDayBoundary(query.dateRange[0]) : undefined, endCreatedAt: query.dateRange ? localDayBoundary(query.dateRange[1], 1) : undefined }); records.value = result.rows; total.value = result.total; if (showResult) ElMessage.success(`已找到 ${result.total} 条修订行为`) } catch (error) { records.value = []; total.value = 0; loadError.value = error instanceof Error ? error.message : '数据修订行为加载失败' } finally { loading.value = false } }
 function applySearch() { applied.value = { test: filters.test, dataType: filters.dataType, operationType: filters.operationType, dateRange: filters.dateRange ? [...filters.dateRange] as [string, string] : null }; currentPage.value = 1; void loadRecords(true) }
@@ -18,5 +18,5 @@
 function handlePageChange(page: number) { currentPage.value = page; void loadRecords() }; function handleSizeChange(size: number) { pageSize.value = size; currentPage.value = 1; void loadRecords() }
 onMounted(loadRecords)
 </script>
-<template><div class="data-revision-page"><section class="filter-panel"><header class="section-heading"><div><i></i><strong>查询条件</strong><span>FILTER CONDITIONS</span></div><small>共 {{ total }} 条行为</small></header><div class="filter-grid"><label><span>测试</span><el-input v-model="filters.test" clearable placeholder="测试ID或名称" @keyup.enter="applySearch" /></label><label><span>数据类型</span><el-select v-model="filters.dataType" clearable placeholder="全部"><el-option label="实时" value="REALTIME" /><el-option label="工步" value="STEP" /><el-option label="循环" value="CYCLE" /></el-select></label><label><span>操作类型</span><el-select v-model="filters.operationType" clearable placeholder="全部"><el-option label="编辑" value="EDIT" /><el-option label="导入" value="IMPORT" /><el-option label="删除" value="DELETE" /></el-select></label><label><span>操作时间</span><el-date-picker v-model="filters.dateRange" type="daterange" value-format="YYYY-MM-DD" start-placeholder="开始日期" end-placeholder="结束日期" range-separator="至" unlink-panels /></label><div class="filter-actions"><button class="primary-button" type="button" :disabled="loading" @click="applySearch"><el-icon><Search /></el-icon>查询</button><button class="secondary-button" type="button" :disabled="loading" @click="resetSearch"><el-icon><RefreshLeft /></el-icon>重置</button></div></div></section><section class="result-panel"><div class="result-toolbar"><div><i></i><strong>数据修订行为</strong><span>{{ total }} RESULTS · 按操作时间倒序</span></div><span v-if="loadError" class="load-error">{{ loadError }}</span></div><div v-loading="loading" class="table-wrap"><table><thead><tr><th>行为ID</th><th>测试</th><th>数据类型</th><th>操作类型</th><th>操作范围</th><th>操作人</th><th>操作时间</th><th>原因</th><th class="action-column">操作</th></tr></thead><tbody><tr v-for="item in records" :key="item.actionId"><td class="id-cell">#{{ item.actionId }}</td><td><strong>{{ item.testName }}</strong><small>#{{ item.testId }}</small></td><td><span class="type-tag">{{ dataTypeLabels[item.dataType] }}</span></td><td><span class="operation-tag" :class="item.operationType.toLowerCase()">{{ operationLabels[item.operationType] }}</span></td><td :title="item.scopeSummary">{{ item.scopeSummary }}</td><td>{{ item.operatorName }}</td><td>{{ formatTime(item.createdAtUtc) }}</td><td :title="item.reason">{{ item.reason }}</td><td class="action-column"><div class="row-actions"><button type="button" @click="viewRecord(item)">查看</button><button type="button" @click="returnToTest(item)">回到测试</button></div></td></tr><tr v-if="!loading && !records.length"><td colspan="9" class="empty-cell">{{ loadError || '暂无符合条件的数据修订行为' }}</td></tr></tbody></table></div><footer class="pagination-bar"><span>显示 {{ records.length }} 条,共 {{ total }} 条</span><el-pagination :current-page="currentPage" :page-size="pageSize" :page-sizes="[10, 20, 50]" :total="total" :disabled="loading" layout="sizes, prev, pager, next" background @current-change="handlePageChange" @size-change="handleSizeChange" /></footer></section></div></template>
+<template><div class="data-revision-page"><section class="filter-panel"><header class="section-heading"><div><i></i><strong>查询条件</strong><span>FILTER CONDITIONS</span></div><small>共 {{ total }} 条行为</small></header><div class="filter-grid"><label><span>测试</span><el-input v-model="filters.test" clearable placeholder="测试ID或名称" @keyup.enter="applySearch" /></label><label><span>数据类型</span><el-select v-model="filters.dataType" clearable placeholder="全部"><el-option label="实时" value="REALTIME" /><el-option label="工步" value="STEP" /><el-option label="循环" value="CYCLE" /></el-select></label><label><span>操作类型</span><el-select v-model="filters.operationType" clearable placeholder="全部"><el-option label="编辑" value="EDIT" /><el-option label="导入" value="IMPORT" /><el-option label="删除" value="DELETE" /></el-select></label><label><span>操作时间</span><el-date-picker v-model="filters.dateRange" type="daterange" value-format="YYYY-MM-DD" start-placeholder="开始日期" end-placeholder="结束日期" range-separator="至" unlink-panels /></label><div class="filter-actions"><button class="primary-button" type="button" :disabled="loading" @click="applySearch"><el-icon><Search /></el-icon>查询</button><button class="secondary-button" type="button" :disabled="loading" @click="resetSearch"><el-icon><RefreshLeft /></el-icon>重置</button></div></div></section><section class="result-panel"><div class="result-toolbar"><div><i></i><strong>数据修订行为</strong><span>{{ total }} RESULTS · 按操作时间倒序</span></div><span v-if="loadError" class="load-error">{{ loadError }}</span></div><div v-loading="loading" class="table-wrap"><table><thead><tr><th>行为ID</th><th>测试</th><th>数据类型</th><th>操作类型</th><th>操作范围</th><th>操作人</th><th>操作时间</th><th>原因</th><th class="action-column">操作</th></tr></thead><tbody><tr v-for="item in records" :key="item.actionId"><td class="id-cell">#{{ item.actionId }}</td><td><strong>{{ item.testName }}</strong><small>#{{ item.testId }}</small></td><td><span class="type-tag">{{ dataTypeLabels[item.dataType] }}</span></td><td><span class="operation-tag" :class="item.operationType.toLowerCase()">{{ operationLabels[item.operationType] }}</span></td><td :title="formatScope(item.scopeSummary)">{{ formatScope(item.scopeSummary) }}</td><td>{{ item.operatorName }}</td><td>{{ formatTime(item.createdAtUtc) }}</td><td :title="item.reason">{{ item.reason }}</td><td class="action-column"><div class="row-actions"><button type="button" @click="viewRecord(item)">查看</button><button type="button" @click="returnToTest(item)">回到测试</button></div></td></tr><tr v-if="!loading && !records.length"><td colspan="9" class="empty-cell">{{ loadError || '暂无符合条件的数据修订行为' }}</td></tr></tbody></table></div><footer class="pagination-bar"><span>显示 {{ records.length }} 条,共 {{ total }} 条</span><el-pagination :current-page="currentPage" :page-size="pageSize" :page-sizes="[10, 20, 50]" :total="total" :disabled="loading" layout="sizes, prev, pager, next" background @current-change="handlePageChange" @size-change="handleSizeChange" /></footer></section></div></template>
 <style scoped>.data-revision-page{width:100%}.primary-button,.secondary-button{height:34px;display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:0 13px;border:1px solid transparent;border-radius:3px;font-size:13px;cursor:pointer}.primary-button{color:#fff;background:var(--blue)}.secondary-button{color:#52606d;background:#fff;border-color:var(--line-strong)}button:disabled{opacity:.55}.filter-panel,.result-panel{background:#fff;border:1px solid #d8e1e9}.filter-panel{margin-bottom:16px}.section-heading,.result-toolbar{display:flex;align-items:center;justify-content:space-between;padding:0 16px;background:var(--surface-soft);border-bottom:1px solid var(--line)}.section-heading{height:44px}.result-toolbar{height:50px}.section-heading>div,.result-toolbar>div{display:flex;align-items:center;gap:8px}.section-heading i,.result-toolbar i{width:3px;height:16px;background:#2b78a3}.section-heading strong,.result-toolbar strong{color:var(--ink);font-size:15px}.section-heading span,.result-toolbar span,.section-heading small{color:#81909d;font-size:10px}.filter-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px 18px;padding:16px}.filter-grid label{min-width:0;display:grid;grid-template-columns:70px minmax(0,1fr);align-items:center;gap:8px}.filter-grid label>span{color:#52606d;font-size:12px}.filter-grid :deep(.el-select),.filter-grid :deep(.el-date-editor){width:100%}.filter-actions{grid-column:4;display:flex;justify-content:flex-end;gap:8px}.load-error{color:#b34f4f!important}.table-wrap{overflow-x:auto}table{width:100%;min-width:1380px;table-layout:fixed;border-collapse:collapse;color:#52606d;font-size:12px}th,td{height:50px;padding:0 12px;border-right:1px solid #dde7f0;border-bottom:1px solid #dde7f0;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}th{height:40px;background:#eaf4ff;border-color:#c7e0ff;font-weight:600}th:nth-child(1){width:85px}th:nth-child(2){width:190px}th:nth-child(3),th:nth-child(4){width:90px}th:nth-child(5){width:250px}th:nth-child(6){width:100px}th:nth-child(7){width:165px}th:nth-child(8){width:250px}th:nth-child(9){width:145px}td strong,td small{display:block}td strong{color:#26333f}td small{margin-top:3px;color:#8795a3}.id-cell{font-family:'Cascadia Mono',Consolas,monospace}.type-tag,.operation-tag{display:inline-flex;padding:3px 8px;border:1px solid #c9d9e7;background:#f5f8fb}.operation-tag.edit{color:#176fcb;background:#edf6ff;border-color:#b8d9fb}.operation-tag.import{color:#23865e;background:#edf9f3;border-color:#b8dfcd}.operation-tag.delete{color:#b34f4f;background:#fff1f1;border-color:#e9bcbc}.action-column{position:sticky;right:0;z-index:2;background:#fff;box-shadow:inset 1px 0 0 #b4c7d9,-8px 0 14px rgba(23,49,74,.1)}th.action-column{z-index:3;background:#eaf4ff}.row-actions{display:flex;justify-content:center;gap:12px}.row-actions button{border:0;color:var(--blue);background:transparent;cursor:pointer}.empty-cell{height:160px;color:#8795a3;text-align:center}.pagination-bar{min-height:58px;display:flex;align-items:center;justify-content:space-between;gap:16px;padding:8px 14px 8px 16px}.pagination-bar>span{color:#7b8794;font-size:11px}@media(max-width:1100px){.filter-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.filter-actions{grid-column:2}}@media(max-width:680px){.filter-grid{grid-template-columns:1fr}.filter-actions{grid-column:auto}.filter-actions button{flex:1}.pagination-bar{align-items:flex-start;flex-direction:column;overflow-x:auto}}</style>

--
Gitblit v1.7.1