From bcc406d1a6491763b38d1f65fd9124e67b3a300e Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期二, 01 九月 2026 09:35:46 +0800
Subject: [PATCH] 将控制台编辑恢复到表格内
---
src/components/ConsoleDataListPanel.vue | 14 ++------------
1 files changed, 2 insertions(+), 12 deletions(-)
diff --git a/src/components/ConsoleDataListPanel.vue b/src/components/ConsoleDataListPanel.vue
index 5a9807c..3cbc5b9 100644
--- a/src/components/ConsoleDataListPanel.vue
+++ b/src/components/ConsoleDataListPanel.vue
@@ -60,20 +60,9 @@
<header class="section-heading"><div><i></i><strong>数据列表</strong><span>TEST DATA</span></div><nav class="data-tabs" aria-label="数据列表子页"><button v-for="tab in dataTabs" :key="tab.key" type="button" :class="{ active: activeTab === tab.key }" :aria-current="activeTab === tab.key ? 'page' : undefined" @click="changeTab(tab.key)">{{ tab.label }}</button></nav><small>{{ loading ? '加载中...' : `共 ${filteredRows.length} 条` }}</small></header>
<div class="filter-grid"><label><span>电池</span><el-select v-model="filters.batteryNo" clearable placeholder="全部"><el-option label="全部" value="" /><el-option v-for="item in batteryOptions" :key="item" :label="item" :value="item" /></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="至" /></label><label><span>循环</span><el-select v-model="filters.cycleNo" clearable placeholder="全部"><el-option label="全部" value="" /><el-option v-for="item in cycleOptions" :key="item" :label="`循环 ${item}`" :value="String(item)" /></el-select></label><label><span>实际工步</span><el-select v-model="filters.stepNo" clearable placeholder="全部"><el-option label="全部" value="" /><el-option v-for="item in stepOptions" :key="item[0]" :label="`${item[0]}-${item[1]}`" :value="String(item[0])" /></el-select></label><div class="filter-actions"><button class="primary-button" type="button" @click="applySearch"><el-icon><Search /></el-icon>查询</button><button class="secondary-button" type="button" @click="resetSearch"><el-icon><Refresh /></el-icon>重置</button></div></div>
<div class="data-toolbar"><div class="toolbar-group"><button class="primary-button" type="button" @click="goToImport"><el-icon><UploadFilled /></el-icon>导入</button><button class="primary-button" type="button" @click="downloadTemplate"><el-icon><Download /></el-icon>下载模板</button><button class="primary-button" type="button" @click="goToRevisions"><el-icon><Clock /></el-icon>修订记录</button><button v-if="!editing" class="primary-button" type="button" @click="openBatchEditor"><el-icon><EditPen /></el-icon>批量修改</button><template v-else><button class="primary-button" type="button" @click="saveBatchEdit"><el-icon><Check /></el-icon>保存修改</button><button class="secondary-button" type="button" @click="cancelBatchEdit">取消</button></template><button class="danger-button" type="button" :disabled="editing" @click="deleteSelected">删除</button></div><span v-if="loadError" class="load-error">{{ loadError }}</span><span v-else>{{ editing ? '编辑模式:仅允许修改当前页规定字段,保存后填写原因并一次提交' : `仅展示检测柜实际返回的 ${activeTab === 'realtime' ? 'record' : activeTab === 'step' ? 'step' : 'cycle'} 数据` }}</span><div class="toolbar-group"><button class="secondary-button" type="button" :disabled="loading || editing" @click="loadRecords"><el-icon><Refresh /></el-icon>刷新</button><button class="secondary-button" type="button" :disabled="editing" @click="downloadCsv"><el-icon><Download /></el-icon>下载</button></div></div>
- <div class="table-wrap"><table><thead><tr v-if="activeTab === 'realtime'"><th class="selection-column"><el-checkbox :model-value="allPageSelected" :indeterminate="somePageSelected" aria-label="选择本页" @change="(checked: string | number | boolean) => togglePageSelection(Boolean(checked))" /></th><th>记录编号</th><th>电池</th><th>循环号</th><th>实际工步号</th><th>实际工步名称</th><th>记录序号</th><th>记录时间</th><th>绝对时间</th><th>电压(V)</th><th>电流(A)</th><th>容量(Ah)</th><th>能量(Wh)</th></tr><tr v-else-if="activeTab === 'step'"><th class="selection-column"></th><th>工步记录</th><th>电池</th><th>循环号</th><th>实际工步号</th><th>实际工步名称</th><th>记录数量</th><th>开始时间</th><th>结束时间</th><th>容量(Ah)</th><th>能量(Wh)</th></tr><tr v-else><th class="selection-column"></th><th>循环记录</th><th>电池</th><th>循环号</th><th>充电容量(Ah)</th><th>放电容量(Ah)</th><th>充放电效率(%)</th><th>充电能量(Wh)</th><th>放电能量(Wh)</th></tr></thead><tbody><template v-for="row in pagedRows" :key="row.id"><tr v-if="activeTab === 'realtime'"><td class="selection-column"><el-checkbox :model-value="selectedIds.has(row.id)" :aria-label="`选择 ${row.recordNo}`" @change="(checked: string | number | boolean) => toggleRowSelection(row.id, Boolean(checked))" /></td><td class="record-code">{{ row.recordNo }}</td><td><strong>{{ row.batteryNo }}</strong></td><td>{{ row.cycleNo }}</td><td>{{ row.stepNo }}</td><td>{{ row.stepName }}</td><td>{{ row.sequenceId }}</td><td>{{ row.recordedAt }}</td><td>{{ row.absoluteTime }}</td><td>{{ row.voltage }}</td><td>{{ row.current }}</td><td>{{ row.capacity }}</td><td>{{ row.energy }}</td></tr><tr v-else-if="activeTab === 'step'"><td class="selection-column"><el-checkbox :model-value="selectedIds.has(row.id)" :aria-label="`选择 ${row.recordNo}`" @change="(checked: string | number | boolean) => toggleRowSelection(row.id, Boolean(checked))" /></td><td class="record-code">{{ row.recordNo }}</td><td><strong>{{ row.batteryNo }}</strong></td><td>{{ row.cycleNo }}</td><td>{{ row.stepNo }}</td><td>{{ row.stepName }}</td><td>{{ row.sequenceId }}</td><td>{{ row.recordedAt }}</td><td>{{ row.absoluteTime }}</td><td>{{ row.capacity }}</td><td>{{ row.energy }}</td></tr><tr v-else><td class="selection-column"><el-checkbox :model-value="selectedIds.has(row.id)" :aria-label="`选择 ${row.recordNo}`" @change="(checked: string | number | boolean) => toggleRowSelection(row.id, Boolean(checked))" /></td><td class="record-code">{{ row.recordNo }}</td><td><strong>{{ row.batteryNo }}</strong></td><td>{{ row.cycleNo }}</td><td>{{ row.chargeCapacity }}</td><td>{{ row.dischargeCapacity }}</td><td>{{ row.efficiency }}</td><td>{{ row.chargeEnergy }}</td><td>{{ row.dischargeEnergy }}</td></tr></template><tr v-if="!loading && !pagedRows.length"><td :colspan="activeTab === 'realtime' ? 13 : activeTab === 'step' ? 11 : 9" class="empty-cell">{{ loadError || '暂无检测柜记录' }}</td></tr></tbody></table></div>
+ <div class="table-wrap"><table><thead><tr v-if="activeTab === 'realtime'"><th class="selection-column"><el-checkbox :model-value="allPageSelected" :indeterminate="somePageSelected" aria-label="选择本页" @change="(checked: string | number | boolean) => togglePageSelection(Boolean(checked))" /></th><th>记录编号</th><th>电池</th><th>循环号</th><th>实际工步号</th><th>实际工步名称</th><th>记录序号</th><th>记录时间</th><th>绝对时间</th><th>电压(V)</th><th>电流(A)</th><th>容量(Ah)</th><th>能量(Wh)</th><th class="action-column">操作</th></tr><tr v-else-if="activeTab === 'step'"><th class="selection-column"></th><th>工步记录</th><th>电池</th><th>循环号</th><th>实际工步号</th><th>实际工步名称</th><th>记录数量</th><th>开始时间</th><th>结束时间</th><th>容量(Ah)</th><th>能量(Wh)</th><th class="action-column">操作</th></tr><tr v-else><th class="selection-column"></th><th>循环记录</th><th>电池</th><th>循环号</th><th>充电容量(Ah)</th><th>放电容量(Ah)</th><th>充放电效率(%)</th><th>充电能量(Wh)</th><th>放电能量(Wh)</th><th class="action-column">操作</th></tr></thead><tbody><template v-for="row in pagedRows" :key="row.id"><tr v-if="activeTab === 'realtime'"><td class="selection-column"><el-checkbox :model-value="selectedIds.has(row.id)" :aria-label="`选择 ${row.recordNo}`" @change="(checked: string | number | boolean) => toggleRowSelection(row.id, Boolean(checked))" /></td><td class="record-code">{{ row.recordNo }}</td><td><strong>{{ row.batteryNo }}</strong></td><td>{{ row.cycleNo }}</td><td>{{ row.stepNo }}</td><td>{{ row.stepName }}</td><td>{{ row.sequenceId }}</td><td>{{ row.recordedAt }}</td><td>{{ row.absoluteTime }}</td><td><el-input v-if="editing && draftRows[row.id]" v-model="draftRows[row.id].voltage" size="small" /><span v-else>{{ row.voltage }}</span></td><td><el-input v-if="editing && draftRows[row.id]" v-model="draftRows[row.id].current" size="small" /><span v-else>{{ row.current }}</span></td><td><el-input v-if="editing && draftRows[row.id]" v-model="draftRows[row.id].capacity" size="small" /><span v-else>{{ row.capacity }}</span></td><td><el-input v-if="editing && draftRows[row.id]" v-model="draftRows[row.id].energy" size="small" /><span v-else>{{ row.energy }}</span></td><td class="action-column"><div class="row-actions"><button type="button" @click="openRowEditor(row)">编辑</button><button class="delete-action" type="button" @click="deleteSelected([row.id])">删除</button></div></td></tr><tr v-else-if="activeTab === 'step'"><td class="selection-column"><el-checkbox :model-value="selectedIds.has(row.id)" :aria-label="`选择 ${row.recordNo}`" @change="(checked: string | number | boolean) => toggleRowSelection(row.id, Boolean(checked))" /></td><td class="record-code">{{ row.recordNo }}</td><td><strong>{{ row.batteryNo }}</strong></td><td>{{ row.cycleNo }}</td><td>{{ row.stepNo }}</td><td>{{ row.stepName }}</td><td>{{ row.sequenceId }}</td><td>{{ row.recordedAt }}</td><td>{{ row.absoluteTime }}</td><td><el-input v-if="editing && draftRows[row.id]" v-model="draftRows[row.id].capacity" size="small" /><span v-else>{{ row.capacity }}</span></td><td><el-input v-if="editing && draftRows[row.id]" v-model="draftRows[row.id].energy" size="small" /><span v-else>{{ row.energy }}</span></td><td class="action-column"><div class="row-actions"><button type="button" @click="openRowEditor(row)">编辑</button><button class="delete-action" type="button" @click="deleteSelected([row.id])">删除</button></div></td></tr><tr v-else><td class="selection-column"><el-checkbox :model-value="selectedIds.has(row.id)" :aria-label="`选择 ${row.recordNo}`" @change="(checked: string | number | boolean) => toggleRowSelection(row.id, Boolean(checked))" /></td><td class="record-code">{{ row.recordNo }}</td><td><strong>{{ row.batteryNo }}</strong></td><td>{{ row.cycleNo }}</td><td><el-input v-if="editing && draftRows[row.id]" v-model="draftRows[row.id].chargeCapacity" size="small" /><span v-else>{{ row.chargeCapacity }}</span></td><td><el-input v-if="editing && draftRows[row.id]" v-model="draftRows[row.id].dischargeCapacity" size="small" /><span v-else>{{ row.dischargeCapacity }}</span></td><td><el-input v-if="editing && draftRows[row.id]" v-model="draftRows[row.id].efficiency" size="small" /><span v-else>{{ row.efficiency }}</span></td><td><el-input v-if="editing && draftRows[row.id]" v-model="draftRows[row.id].chargeEnergy" size="small" /><span v-else>{{ row.chargeEnergy }}</span></td><td><el-input v-if="editing && draftRows[row.id]" v-model="draftRows[row.id].dischargeEnergy" size="small" /><span v-else>{{ row.dischargeEnergy }}</span></td><td class="action-column"><div class="row-actions"><button type="button" @click="openRowEditor(row)">编辑</button><button class="delete-action" type="button" @click="deleteSelected([row.id])">删除</button></div></td></tr></template><tr v-if="!loading && !pagedRows.length"><td :colspan="activeTab === 'realtime' ? 14 : activeTab === 'step' ? 12 : 10" class="empty-cell">{{ loadError || '暂无检测柜记录' }}</td></tr></tbody></table></div>
<footer class="pagination-bar"><span>显示 {{ pagedRows.length }} 条,共 {{ filteredRows.length }} 条</span><el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[20, 50, 100]" :total="filteredRows.length" layout="sizes, prev, pager, next" background /></footer>
<el-dialog v-model="editorVisible" title="提交数据修改" width="520px" align-center><div class="edit-form"><p>修改已暂存,请填写本次行为原因后一次提交。</p><label><span>修改字段</span><el-select v-model="editForm.field"><el-option v-for="item in fieldOptions" :key="String(item.value)" :label="item.label" :value="item.value" /></el-select></label><label><span>修改值</span><el-input v-model="editForm.value" inputmode="decimal" placeholder="请输入修改后的数值" /></label><label><span>修改原因</span><el-input v-model="editForm.remark" type="textarea" :rows="3" maxlength="120" show-word-limit placeholder="必填,将写入数据修订记录" /></label></div><template #footer><button class="secondary-button" type="button" @click="editorVisible=false">取消</button><button class="primary-button" type="button" @click="submitBatchEdit"><el-icon><Check /></el-icon>提交修改</button></template></el-dialog>
- <section v-if="editing" class="inline-editor">
- <header><strong>按格修改</strong><span>已开放当前数据页的可编辑字段,身份字段保持只读</span></header>
- <div v-for="row in pagedRows" :key="`edit-${row.id}`" class="inline-editor-row">
- <span class="record-code">{{ row.recordNo }}</span><span>{{ row.batteryNo }}</span><span>{{ row.cycleNo }}</span>
- <label v-for="field in fieldOptions" :key="String(field.value)"><small>{{ field.label }}</small><el-input v-model="draftRows[row.id][field.value as keyof DataRow]" size="small" /></label>
- <button class="row-action danger-text" type="button" @click="deleteSelected([row.id])">删除</button>
- </div>
- </section>
- <section v-else class="row-actions-panel">
- <div v-for="row in pagedRows" :key="`action-${row.id}`"><span class="record-code">{{ row.recordNo }}</span><button class="row-action" type="button" @click="openRowEditor(row)">编辑</button><button class="row-action danger-text" type="button" @click="deleteSelected([row.id])">删除</button></div>
- </section>
</section>
</template>
<style scoped>
@@ -81,6 +70,7 @@
.console-data-panel{min-width:0;border:1px solid #d8e1e9;background:#fff}.section-heading{position:relative;height:60px;display:flex;align-items:center;justify-content:space-between;padding:0 16px;border-bottom:1px solid var(--line);background:var(--surface-soft)}.section-heading>div{display:flex;align-items:center;gap:8px}.section-heading i{width:3px;height:16px;background:#2b78a3}.section-heading strong{color:var(--ink);font-size:14px}.section-heading span{color:#81909d;font-size:10px}.section-heading small{color:#647380;font-size:11px}.data-tabs{position:absolute;top:50%;left:50%;display:flex;justify-content:center;gap:8px;padding:0;border:0;background:transparent;transform:translate(-50%,-50%)}.data-tabs button{height:32px;min-width:78px;padding:0 18px;border:1px solid #cbd8e5;border-radius:4px;color:#52606d;background:#fff;box-shadow:0 1px 4px rgba(40,75,105,.08);font-size:13px;font-weight:600;cursor:pointer;transition:color .16s ease,background .16s ease,border-color .16s ease,box-shadow .16s ease}.data-tabs button:hover{color:#1677dd;border-color:#8ec4f4;box-shadow:0 3px 8px rgba(36,128,220,.14)}.data-tabs button.active{color:#fff;background:#1687ed;border-color:#1677dd;box-shadow:0 3px 8px rgba(26,112,220,.24)}.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:68px 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:-2/-1;display:flex;justify-content:flex-end;gap:8px}.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;white-space:nowrap}.primary-button{color:#fff;background:var(--blue)}.secondary-button{color:#52606d;background:#fff;border-color:var(--line-strong)}.secondary-button:disabled{opacity:.5;cursor:not-allowed}.data-toolbar{min-height:52px;display:flex;align-items:center;justify-content:space-between;gap:12px;margin:0 16px;border-top:1px solid #d8e1e9;color:#7b8794;font-size:11px}.data-toolbar>div{display:flex;gap:8px}.load-error{color:#b34f4f}.table-wrap{width:100%;overflow-x:auto}table{width:100%;min-width:1260px;table-layout:fixed;border-collapse:collapse;color:#52606d;font-size:12px}th,td{height:44px;padding:0 10px;border-right:1px solid #dde7f0;border-bottom:1px solid #dde7f0;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}th{height:40px;color:#52606d;background:#eaf4ff;border-color:#c7e0ff;font-weight:600}.record-code{font-family:'Cascadia Mono',Consolas,monospace;font-size:11px}.empty-cell{height:150px;color:#8795a3}.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}.pagination-bar :deep(.el-pagination){--el-pagination-button-bg-color:#edf4fa;--el-pagination-hover-color:var(--blue)}@media(max-width:900px){.filter-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.data-toolbar{align-items:flex-start;flex-direction:column;padding:10px 0}}@media(max-width:600px){.filter-grid{grid-template-columns:1fr;padding:14px 12px}.filter-actions{grid-column:auto}.filter-actions button{flex:1}.data-tabs{position:static;transform:none;gap:6px;padding:0 8px}.data-tabs button{min-width:0;flex:1;padding:0 12px}.data-toolbar{margin:0 12px}.pagination-bar{align-items:flex-start;flex-direction:column;overflow-x:auto}}
.toolbar-group{display:flex;align-items:center;gap:8px}.selection-column{width:46px;padding:0}.edit-form{display:grid;gap:14px}.edit-form label{display:grid;grid-template-columns:82px minmax(0,1fr);align-items:center;gap:10px}.edit-form label>span{color:#52606d;font-size:12px}.edit-form :deep(.el-select){width:100%}
.inline-editor,.row-actions-panel{margin:14px 16px;border:1px solid #cbddeb;background:#f8fbfe}.inline-editor>header{display:flex;align-items:center;gap:12px;padding:12px 14px;border-bottom:1px solid #d8e5ef}.inline-editor>header strong{color:#26333f;font-size:13px}.inline-editor>header span{color:#7b8794;font-size:11px}.inline-editor-row{display:flex;align-items:center;gap:10px;overflow-x:auto;padding:10px 12px;border-bottom:1px solid #e2ebf2;white-space:nowrap}.inline-editor-row>span{min-width:72px}.inline-editor-row label{display:grid;gap:4px;min-width:112px}.inline-editor-row label small{color:#71808d;font-size:10px}.inline-editor-row :deep(.el-input){width:112px}.row-actions-panel{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:8px;padding:10px 12px}.row-actions-panel>div{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:8px 10px;background:#fff;border:1px solid #e2ebf2}.row-action{padding:2px 6px;border:0;color:var(--blue);background:transparent;cursor:pointer;font-size:12px}.danger-text{color:#d94b4b}
+.action-column{position:sticky;right:0;z-index:2;width:112px;background:#fff;overflow:visible;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;align-items:center;justify-content:center;gap:12px}.row-actions button{border:0;color:var(--blue);background:transparent;font-size:12px;cursor:pointer}.row-actions .delete-action{color:#ad4a4a}
/* 三个数据子页使用连续分段控件,保持当前页在标题栏中央突出显示。 */
.data-tabs{width:228px;gap:0;padding:0;border:1px solid #2188f5;border-radius:5px;overflow:hidden;background:#fff;box-shadow:none}
.data-tabs button{flex:1;min-width:0;height:30px;padding:0 8px;border:0;border-radius:0;color:#2188f5;background:#fff;box-shadow:none;font-size:13px;font-weight:500}
--
Gitblit v1.7.1