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

feat(web3): ResultTable 列宽可拖拽(参照 web2 el-table resizable)

web3 ResultTable 是自定义 table,el-table resizable 不能直接复用,自实现:

1. ResultTable.vue

   columnWidths reactive + startResize/onResizeMove/endResize

   拖拽状态不放 reactive(频繁写不触发响应式刷新整张表格)

   window mousemove/mouseup(用户拖快会脱出 th 丢失 mouseup)

   拖拽过程 document.body user-select=none + cursor col-resize

   onBeforeUnmount 清理监听 + 还原 body 样式

2. global.css

   .resize-handle 样式(透明 + hover 变蓝 409eff)

   table.dq-table 加 table-layout: fixed(auto 时 width 被无视)

   thead th 加 position: relative 让 handle absolute 定位

3. 踩坑:改 Vue setup 的 import 段要核对所有 export 符号

   我改 import 时删了 watch 符号,但 setup 里 line 248 的 watch() 还在用

   → 运行时 ReferenceError: watch is not defined 把页面打白

4. localStorage 列宽持久化没做(用户没要求;后续可加 key→width 存)
parent ef99984a
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
* row.errorCells?: [key1, key2] 哪些单元格高亮+tooltip * row.errorCells?: [key1, key2] 哪些单元格高亮+tooltip
* row.issues?: [{field, desc}] 备注列要展示的所有错误(每行末尾「备注」列展开) * row.issues?: [{field, desc}] 备注列要展示的所有错误(每行末尾「备注」列展开)
- 分页:2026-08-21 改用 el-pagination,pageSizes 默认 [25, 50, 100, 200],中间页用 pager 自带 ... 折叠 - 分页:2026-08-21 改用 el-pagination,pageSizes 默认 [25, 50, 100, 200],中间页用 pager 自带 ... 折叠
- 列宽可拖拽:2026-08-21 自实现(参照 web2 el-table resizable)
th / td 都按 col.key 设 width;th 右侧挂 resize handle;mousedown 启动拖拽
—— 不依赖 el-table,因为我们用的是自定义 dq-table
- 无「操作」列(plan §3 决策;后续如要加,应在父组件再套一层,不要塞回通用组件) - 无「操作」列(plan §3 决策;后续如要加,应在父组件再套一层,不要塞回通用组件)
单元格错误展示: 单元格错误展示:
...@@ -27,6 +30,7 @@ ...@@ -27,6 +30,7 @@
v-for="col in allColumns" v-for="col in allColumns"
:key="col.key" :key="col.key"
:class="{ 'col-reason': col.key === '__reason' }" :class="{ 'col-reason': col.key === '__reason' }"
:style="thStyle(col)"
> >
<template v-if="col.key === '__reason'"> <template v-if="col.key === '__reason'">
<span class="flag">!</span><span class="cn">备注</span> <span class="flag">!</span><span class="cn">备注</span>
...@@ -50,6 +54,11 @@ ...@@ -50,6 +54,11 @@
> >
<span class="rule-mark">⚠ {{ col.rules }}规则</span> <span class="rule-mark">⚠ {{ col.rules }}规则</span>
</el-tooltip> </el-tooltip>
<!-- 拖拽手柄:吸在 th 最右侧,鼠标移上去变 col-resize -->
<span
class="resize-handle"
@mousedown.prevent="startResize($event, col)"
></span>
</template> </template>
</th> </th>
</tr> </tr>
...@@ -60,6 +69,7 @@ ...@@ -60,6 +69,7 @@
v-for="col in allColumns" v-for="col in allColumns"
:key="col.key" :key="col.key"
:class="cellClass(row, col.key)" :class="cellClass(row, col.key)"
:style="tdStyle(col)"
> >
<!-- 备注列:所有 issues 列表 --> <!-- 备注列:所有 issues 列表 -->
<template v-if="col.key === '__reason'"> <template v-if="col.key === '__reason'">
...@@ -123,7 +133,7 @@ ...@@ -123,7 +133,7 @@
</template> </template>
<script setup> <script setup>
import { computed, ref, watch } from 'vue' import { computed, onBeforeUnmount, reactive, ref, watch } from 'vue'
const props = defineProps({ const props = defineProps({
columns: { type: Array, required: true }, // [{ key, cn, en, rules, ruleList? }] columns: { type: Array, required: true }, // [{ key, cn, en, rules, ruleList? }]
...@@ -142,6 +152,67 @@ const props = defineProps({ ...@@ -142,6 +152,67 @@ const props = defineProps({
}) })
const emit = defineEmits(['page-change']) const emit = defineEmits(['page-change'])
// ── 列宽拖拽(2026-08-21,参照 web2 el-table resizable 自实现)──
// 每列的宽度按 col.key 存;拖动时实时更新;卸载时摘掉 window 监听
const DEFAULT_WIDTH = 140 // 业务列默认宽
const REASON_WIDTH = 220 // 备注列默认宽(原本 min:200 max:260)
const MIN_WIDTH = 60 // 不让用户拖太窄把列头文字截没
const columnWidths = reactive({})
function widthOf(col) {
// 没设过就用默认;备注列用专用默认值(保持原 200~260px 区间)
if (columnWidths[col.key] != null) return columnWidths[col.key]
return col.key === '__reason' ? REASON_WIDTH : DEFAULT_WIDTH
}
function thStyle(col) {
// min-width 防文字溢出撑开;width 用户拖拽值;box-sizing 已由 table 控制
return { width: `${widthOf(col)}px`, minWidth: `${MIN_WIDTH}px` }
}
function tdStyle(col) {
// td 不加 min-width —— 列头锁了宽度后 td 自然跟着收敛
return { width: `${widthOf(col)}px` }
}
// 拖拽状态 —— 不放在 reactive 里(拖拽过程频繁写,不需要触发响应式刷新表格)
// 只需要在 mousedown/move/up 这三个事件里读 X / 写 columnWidths 即可
let resizing = null // { startX, startWidth, key }
function startResize(e, col) {
resizing = {
startX: e.clientX,
startWidth: widthOf(col),
key: col.key,
}
// 鼠标可能拖出 th 才松开,必须挂 window 而不是 th 本身
window.addEventListener('mousemove', onResizeMove)
window.addEventListener('mouseup', endResize)
// 防止拖拽过程中浏览器选中表格文字
document.body.style.userSelect = 'none'
document.body.style.cursor = 'col-resize'
}
function onResizeMove(e) {
if (!resizing) return
const dx = e.clientX - resizing.startX
const next = Math.max(MIN_WIDTH, resizing.startWidth + dx)
columnWidths[resizing.key] = next
}
function endResize() {
resizing = null
window.removeEventListener('mousemove', onResizeMove)
window.removeEventListener('mouseup', endResize)
document.body.style.userSelect = ''
document.body.style.cursor = ''
}
onBeforeUnmount(() => {
// 组件卸载时如果还在拖(极少见,比如拖拽中切路由),摘掉监听
endResize()
})
// 业务列 + 自动追加的「备注」列 // 业务列 + 自动追加的「备注」列
// 优先级: // 优先级:
// 1. props.visibleFields 非空 → 严格按它过滤(FieldConfigDrawer 出来的用户选择) // 1. props.visibleFields 非空 → 严格按它过滤(FieldConfigDrawer 出来的用户选择)
......
...@@ -105,6 +105,8 @@ table.dq-table { ...@@ -105,6 +105,8 @@ table.dq-table {
border-collapse: collapse; border-collapse: collapse;
font-size: 13px; font-size: 13px;
min-width: 900px; min-width: 900px;
/* 列宽拖拽必须 fixed:让 th 设的 width 真的生效(默认 auto 时按内容撑开) */
table-layout: fixed;
} }
table.dq-table thead th { table.dq-table thead th {
background: #fafafa; background: #fafafa;
...@@ -113,9 +115,26 @@ table.dq-table thead th { ...@@ -113,9 +115,26 @@ table.dq-table thead th {
color: #606266; color: #606266;
border-bottom: 1px solid #ebeef5; border-bottom: 1px solid #ebeef5;
white-space: nowrap; white-space: nowrap;
position: relative; /* 让 .resize-handle 能 absolute 定位到右边 */
} }
table.dq-table thead th .cn { color: #1f2937; font-size: 13px; } table.dq-table thead th .cn { color: #1f2937; font-size: 13px; }
table.dq-table thead th .en { color: #909399; font-size: 11px; margin-left: 4px; } table.dq-table thead th .en { color: #909399; font-size: 11px; margin-left: 4px; }
/* 列宽拖拽手柄(2026-08-21,参照 web2 el-table resizable 自实现)
平时 1px 透明竖条,hover 时变蓝提示可拖 */
table.dq-table thead th .resize-handle {
position: absolute;
top: 0;
right: 0;
width: 6px;
height: 100%;
cursor: col-resize;
background: transparent;
transition: background 0.15s;
}
table.dq-table thead th .resize-handle:hover,
table.dq-table thead th.col-resizing .resize-handle {
background: #409eff;
}
table.dq-table thead th .rule-mark { table.dq-table thead th .rule-mark {
color: #e6a23c; color: #e6a23c;
margin-left: 4px; margin-left: 4px;
......
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