Commit ee2976ed authored by Data Governance Dev's avatar Data Governance Dev

feat(idcard-table): 大表分页显示 + 轮询不卡

需求:大表(5000+ 行)一次渲染卡浏览器;轮询时整表重渲染卡顿

改动(IdCardTable.vue):
- 模板:truncateAt 截断提示 → el-pagination 分页器
  · pageSizes: [25, 50, 100, 250]
  · 仅 rows.length > pageSize 时显示(避免小表无意义 UI)
- script:
  · currentPage = ref(1), pageSize = ref(25)
  · displayedRows 改成 pageSize 切片(替换 truncateAt 切片)
  · watch(props.rows) → currentPage 重置(防御性)
- style: 分页器靠右

轮询不卡的原理(三件套):
1. IdCardTool.vue: renderedTableNames Set 去重 → 已存在表不重复 push
2. violationsByTable.value.push(t) 只新增不替换 → 现有 IdCardTable 实例不动
3. :rows="t.bad_rows" 是稳定 prop 引用 → Vue 不重渲染现有表格

导出功能不变:仍导出 props.rows(不受分页影响)

详细 work-log 见 work-logs/2026-08-17.md 主题 19
parent 0320cbc0
...@@ -166,9 +166,19 @@ ...@@ -166,9 +166,19 @@
</template> </template>
</el-table> </el-table>
<div v-if="rows.length > truncateAt" class="idcard-table__trunc"> <!-- 分页器(2026-08-17 主题 19):大表 5000+ 行一次渲染会卡,
⚠ 仅展示前 {{ truncateAt }} 行(防爆上限;实际违规行 {{ rows.length }} 条) 改成翻页只渲染当前页,避免轮询触发整表重渲染时浏览器卡死 -->
</div> <el-pagination
v-if="rows.length > pageSize"
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:page-sizes="[25, 50, 100, 250]"
:total="rows.length"
layout="total, sizes, prev, pager, next, jumper"
class="idcard-table__pagination"
small
background
/>
</template> </template>
<script setup> <script setup>
...@@ -204,6 +214,19 @@ const props = defineProps({ ...@@ -204,6 +214,19 @@ const props = defineProps({
}, },
}) })
/* ── 分页(2026-08-17 主题 19)── */
const currentPage = ref(1)
const pageSize = ref(25)
/* rows 变化时(如流式 push 新表进来)把 currentPage 重置回第 1 页,
避免「之前在第 5 页但新表只有 30 行」变成空白页 */
watch(
() => props.rows,
() => {
currentPage.value = 1
},
)
/* 字段名 → 元数据查找表(O(1)) */ /* 字段名 → 元数据查找表(O(1)) */
const colMap = computed(() => { const colMap = computed(() => {
const m = new Map() const m = new Map()
...@@ -234,7 +257,10 @@ const dataColumns = computed(() => { ...@@ -234,7 +257,10 @@ const dataColumns = computed(() => {
return explicit.filter((n) => seen.has(n)) return explicit.filter((n) => seen.has(n))
}) })
const displayedRows = computed(() => props.rows.slice(0, props.truncateAt)) const displayedRows = computed(() => {
const start = (currentPage.value - 1) * pageSize.value
return props.rows.slice(start, start + pageSize.value)
})
function commentOf(colName) { function commentOf(colName) {
return colMap.value.get(colName)?.column_comment || '' return colMap.value.get(colName)?.column_comment || ''
...@@ -670,4 +696,11 @@ function applyHeaderStyle(ws, cols) { ...@@ -670,4 +696,11 @@ function applyHeaderStyle(ws, cols) {
background: #fdf6ec; background: #fdf6ec;
border-radius: 4px; border-radius: 4px;
} }
/* 分页器 —— 仅在 rows.length > pageSize 时显示,靠右 */
.idcard-table__pagination {
display: flex;
justify-content: flex-end;
margin-top: 8px;
}
</style> </style>
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment