|
|
@@ -43,6 +43,13 @@
|
|
|
:item-size="64"
|
|
|
key-field="__vsKey"
|
|
|
:buffer="200"
|
|
|
+ :style="{
|
|
|
+ height:
|
|
|
+ Math.min(
|
|
|
+ (props.row.qualitySampleTemplateList || []).length * 64,
|
|
|
+ 400
|
|
|
+ ) + 'px'
|
|
|
+ }"
|
|
|
v-if="(props.row.qualitySampleTemplateList || []).length"
|
|
|
>
|
|
|
<template #default="{ item }">
|
|
|
@@ -311,12 +318,55 @@
|
|
|
scrollBound: false, // 滚动监听是否已绑定
|
|
|
resizeObserver: null, // 监听 dialog body 大小变化
|
|
|
isFullscreen: false, // 当前是否处于全屏
|
|
|
- DEFAULT_TABLE_HEIGHT: 560, // 默认(非全屏)表格高度
|
|
|
- tableHeight: 560, // 当前表格高度(全屏时由 recomputeTableHeight 重算)
|
|
|
+ DEFAULT_TABLE_HEIGHT: 560, // 默认(非全屏)表格最大高度
|
|
|
+ MAX_TABLE_HEIGHT: 560, // 硬上限:非全屏和全屏都受此限制
|
|
|
+ _fullscreenTableHeight: 560, // 全屏时由 recomputeTableHeight 重算(dialog body 高度)
|
|
|
PRELOAD_COUNT: 3 // 预加载样品数(打开弹框时立即加载,滚动时永驻内存不卸载)
|
|
|
};
|
|
|
},
|
|
|
- computed: {},
|
|
|
+ computed: {
|
|
|
+ // 表格高度:
|
|
|
+ // - 非全屏:取"内容自然高度"和默认上限的较小者
|
|
|
+ // - 全屏:取 dialog body 高度(recomputeTableHeight 重算)
|
|
|
+ // - 两种情况都受 MAX_TABLE_HEIGHT 硬上限约束(避免 dialog body 很高时表格过大)
|
|
|
+ tableHeight() {
|
|
|
+ const cap = Math.min(
|
|
|
+ this.isFullscreen
|
|
|
+ ? this._fullscreenTableHeight
|
|
|
+ : this.DEFAULT_TABLE_HEIGHT,
|
|
|
+ this.MAX_TABLE_HEIGHT
|
|
|
+ );
|
|
|
+ // 最小 200,避免空数据/异常情况下表格太矮
|
|
|
+ return Math.max(200, Math.min(cap, this.naturalContentHeight));
|
|
|
+ },
|
|
|
+ // 估算 tableData 实际占的高度(el-table 的 :height 需要精确数字)
|
|
|
+ // 注意:内层 RecycleScroller 现在是动态高度(按模板数自适应,封顶 400),
|
|
|
+ // 这里要保持一致,否则估算会比实际大、表格会撑到 cap 而不是收缩
|
|
|
+ naturalContentHeight() {
|
|
|
+ const TABLE_HEADER = 44; // el-table 表头
|
|
|
+ const MAIN_ROW = 48; // 主行
|
|
|
+ const EXPAND_HEADER = 40; // virtual-table-header(包含 padding)
|
|
|
+ const EXPAND_WRAPPER_PAD = 20; // virtual-expand-wrapper 的上下 padding
|
|
|
+ const EXPAND_EMPTY = 56; // "暂无检测项" 占位(padding 20 + 文本)
|
|
|
+ const SCROLLER_MAX = 400; // RecycleScroller 高度封顶
|
|
|
+ const SCROLLER_ITEM = 64; // 单个模板行高度
|
|
|
+
|
|
|
+ let h = TABLE_HEADER;
|
|
|
+ for (const row of this.tableData) {
|
|
|
+ h += MAIN_ROW;
|
|
|
+ const key = row.sampleCode || row.__rowKey;
|
|
|
+ const expanded = this.expandedKeys.includes(key);
|
|
|
+ if (expanded) {
|
|
|
+ const tplLen = (row.qualitySampleTemplateList || []).length;
|
|
|
+ h += EXPAND_HEADER + EXPAND_WRAPPER_PAD;
|
|
|
+ h += tplLen > 0
|
|
|
+ ? Math.min(tplLen * SCROLLER_ITEM, SCROLLER_MAX)
|
|
|
+ : EXPAND_EMPTY;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return h;
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
created() {},
|
|
|
beforeDestroy() {
|
|
|
@@ -370,7 +420,6 @@
|
|
|
this.bindScrollListener();
|
|
|
// 重置全屏状态并重新计算表格高度(防止上次打开残留全屏)
|
|
|
this.isFullscreen = false;
|
|
|
- this.tableHeight = this.DEFAULT_TABLE_HEIGHT;
|
|
|
this.observeBodyResize();
|
|
|
});
|
|
|
},
|
|
|
@@ -417,14 +466,12 @@
|
|
|
});
|
|
|
},
|
|
|
|
|
|
- // 重新计算表格高度:全屏时填满 dialog body,非全屏回到默认值
|
|
|
+ // 重新计算表格高度:仅全屏时需要——把 dialog body 高度写进 _fullscreenTableHeight;
|
|
|
+ // 非全屏由 computed tableHeight 直接用 DEFAULT_TABLE_HEIGHT,无需重算
|
|
|
recomputeTableHeight() {
|
|
|
+ if (!this.isFullscreen) return;
|
|
|
const tableEl = this.$refs.mainTable && this.$refs.mainTable.$el;
|
|
|
if (!tableEl) return;
|
|
|
- if (!this.isFullscreen) {
|
|
|
- this.tableHeight = this.DEFAULT_TABLE_HEIGHT;
|
|
|
- return;
|
|
|
- }
|
|
|
// 全屏:沿 DOM 找到 .el-dialog,再取 .el-dialog__body 的内容区高度
|
|
|
// (不用 .ele-modal-wrap 这个 class——实际类名是 ele-modal-wrap-fullscreen)
|
|
|
const dialog = tableEl.closest('.el-dialog');
|
|
|
@@ -434,7 +481,7 @@
|
|
|
const style = getComputedStyle(body);
|
|
|
const padTop = parseFloat(style.paddingTop) || 0;
|
|
|
const padBottom = parseFloat(style.paddingBottom) || 0;
|
|
|
- this.tableHeight = body.clientHeight - padTop - padBottom;
|
|
|
+ this._fullscreenTableHeight = body.clientHeight - padTop - padBottom;
|
|
|
},
|
|
|
|
|
|
// 监听 dialog body 尺寸变化(拖拽 / resize / 全屏切换都会触发)
|
|
|
@@ -720,7 +767,7 @@
|
|
|
}
|
|
|
|
|
|
.virtual-scroller {
|
|
|
- height: 400px;
|
|
|
+ /* 高度由 :style 动态控制(按模板数量自适应,封顶 400) */
|
|
|
border: 1px solid #ebeef5;
|
|
|
border-top: none;
|
|
|
background: #fff;
|