refactor: fullscreen iframe layout - 3D model as background with overlay panels

This commit is contained in:
Cui Hongwei
2026-06-24 14:50:50 +08:00
parent e12a7b0828
commit 833e256e6b

View File

@@ -21,110 +21,106 @@
<div class="leftLine"></div>
<div class="rightLine"></div>
<main class="qa-dashboard">
<section class="qa-main-grid">
<div class="qa-column qa-column-left">
<section class="qa-panel qa-panel--combined">
<div class="left-title-header">
<span class="left-title-text">线体联动监控</span>
</div>
<div class="qa-panel-body qa-scroll">
<div v-for="row in lineMonitorRows" :key="row.name" class="monitor-card">
<div class="monitor-head">
<div class="monitor-title">
<strong>{{ row.name }}</strong>
<p>{{ row.summary }}</p>
</div>
<span class="status-pill" :class="`status-pill--${row.type}`">{{ row.status }}</span>
</div>
<div class="main-content">
<iframe v-if="iframeAddress" allowtransparency="true" class="model-bg-frame" :src="iframeAddress" title="三维模型"></iframe>
<div v-else class="model-placeholder">等待配置三维模型地址</div>
<div class="monitor-main">
<div class="monitor-task">
<span>任务流向</span>
<strong>{{ row.start }} -> {{ row.end }}</strong>
<p>{{ row.recipe }} / {{ row.pallet }} / {{ row.part }}</p>
</div>
<div class="monitor-signals">
<div v-for="signal in row.signals" :key="signal.label" class="signal-item">
<span class="dot" :class="`dot--${signal.color}`"></span>
<span>{{ signal.label }}</span>
</div>
</div>
<div class="left-box qa-scroll">
<section class="qa-panel qa-panel--combined">
<div class="left-title-header">
<span class="left-title-text">线体联动监控</span>
</div>
<div class="qa-panel-body qa-scroll">
<div v-for="row in lineMonitorRows" :key="row.name" class="monitor-card">
<div class="monitor-head">
<div class="monitor-title">
<strong>{{ row.name }}</strong>
<p>{{ row.summary }}</p>
</div>
<span class="status-pill" :class="`status-pill--${row.type}`">{{ row.status }}</span>
</div>
<div class="monitor-flow">
<span class="monitor-flow-label">反馈流程</span>
<div class="steps">
<span v-for="step in row.steps" :key="step.label" class="step" :class="`step--${step.state}`">
{{ step.label }}
</span>
<div class="monitor-main">
<div class="monitor-task">
<span>任务流向</span>
<strong>{{ row.start }} -> {{ row.end }}</strong>
<p>{{ row.recipe }} / {{ row.pallet }} / {{ row.part }}</p>
</div>
<div class="monitor-signals">
<div v-for="signal in row.signals" :key="signal.label" class="signal-item">
<span class="dot" :class="`dot--${signal.color}`"></span>
<span>{{ signal.label }}</span>
</div>
</div>
</div>
</div>
</section>
</div>
<section class="qa-model-panel">
<iframe v-if="iframeAddress" allowtransparency="true" class="model-frame" :src="iframeAddress" title="三维模型"></iframe>
<div v-else class="model-placeholder">等待配置三维模型地址</div>
<div class="monitor-flow">
<span class="monitor-flow-label">反馈流程</span>
<div class="steps">
<span v-for="step in row.steps" :key="step.label" class="step" :class="`step--${step.state}`">
{{ step.label }}
</span>
</div>
</div>
</div>
</div>
</section>
</div>
<div class="right-box qa-scroll">
<section class="qa-panel">
<div class="right-title-header">
<span class="right-title-text">加工设备状态</span>
</div>
<div class="qa-panel-body qa-scroll">
<div
v-for="item in equipmentList"
:key="item.name"
class="equipment-row"
:class="{ 'equipment-row--alarm': item.type === 'alarm' }"
>
<strong class="equipment-name">{{ item.name }}</strong>
<div class="equipment-program">
<span>目标</span>
<b>{{ item.target }}</b>
</div>
<div class="equipment-program">
<span>实际</span>
<b>{{ item.actual }}</b>
</div>
<div class="equipment-tags">
<span v-for="tag in item.tags" :key="tag.text" class="status-pill status-pill--compact" :class="`status-pill--${tag.type}`">
{{ tag.text }}
</span>
</div>
<span class="status-pill equipment-status" :class="`status-pill--${item.type}`">{{ item.status }}</span>
</div>
</div>
</section>
<div class="qa-column qa-column-right">
<section class="qa-panel">
<div class="right-title-header">
<span class="right-title-text">加工设备状态</span>
</div>
<div class="qa-panel-body qa-scroll">
<div
v-for="item in equipmentList"
:key="item.name"
class="equipment-row"
:class="{ 'equipment-row--alarm': item.type === 'alarm' }"
>
<strong class="equipment-name">{{ item.name }}</strong>
<div class="equipment-program">
<span>目标</span>
<b>{{ item.target }}</b>
<section class="qa-panel">
<div class="right-title-header">
<span class="right-title-text">辅助设备状态</span>
</div>
<div class="qa-panel-body qa-scroll">
<div class="assist-grid">
<div v-for="item in assistList" :key="item.name" class="assist-card">
<div class="assist-title">
<strong>{{ item.name }}</strong>
<span class="status-pill" :class="`status-pill--${item.type}`">{{ item.status }}</span>
</div>
<div class="equipment-program">
<span>实际</span>
<b>{{ item.actual }}</b>
</div>
<div class="equipment-tags">
<div class="assist-flow">
<span v-for="tag in item.tags" :key="tag.text" class="status-pill status-pill--compact" :class="`status-pill--${tag.type}`">
{{ tag.text }}
</span>
</div>
<span class="status-pill equipment-status" :class="`status-pill--${item.type}`">{{ item.status }}</span>
</div>
</div>
</section>
</div>
</section>
</div>
<section class="qa-panel">
<div class="right-title-header">
<span class="right-title-text">辅助设备状态</span>
</div>
<div class="qa-panel-body qa-scroll">
<div class="assist-grid">
<div v-for="item in assistList" :key="item.name" class="assist-card">
<div class="assist-title">
<strong>{{ item.name }}</strong>
<span class="status-pill" :class="`status-pill--${item.type}`">{{ item.status }}</span>
</div>
<div class="assist-flow">
<span v-for="tag in item.tags" :key="tag.text" class="status-pill status-pill--compact" :class="`status-pill--${tag.type}`">
{{ tag.text }}
</span>
</div>
</div>
</div>
</div>
</section>
</div>
</section>
<section class="qa-bottom-grid">
<div class="bottom-box">
<section class="qa-panel">
<div class="center-title-header">
<span>物料库位矩阵</span>
@@ -171,8 +167,8 @@
</div>
</div>
</section>
</section>
</main>
</div>
</div>
</div>
</template>
@@ -463,41 +459,89 @@ body,
background-image: url("/png/右边条.png");
}
.qa-dashboard {
.main-content {
position: absolute;
z-index: 2;
left: 64px;
right: 64px;
top: 100px;
bottom: 26px;
display: grid;
grid-template-rows: minmax(0, 1fr) 248px;
}
.model-bg-frame {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
border: 0;
background: transparent;
z-index: 1;
}
.model-placeholder {
position: absolute;
inset: 0;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
color: #77d9ff;
font-size: 24px;
background: radial-gradient(circle at center, rgba(37, 111, 184, 0.24), rgba(4, 12, 28, 0.92));
}
.left-box {
position: absolute;
top: 0;
left: 0;
width: 360px;
bottom: 260px;
z-index: 10;
overflow-y: auto;
}
.right-box {
position: absolute;
top: 0;
right: 0;
width: 360px;
bottom: 260px;
z-index: 10;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 12px;
}
.qa-main-grid {
.bottom-box {
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 248px;
z-index: 10;
display: grid;
grid-template-columns: 360px minmax(0, 1fr) 360px;
grid-template-columns: 1.2fr 1fr 1fr;
gap: 12px;
}
.left-box .qa-panel {
height: 100%;
display: flex;
flex-direction: column;
}
.right-box .qa-panel:first-child {
flex: 1;
min-height: 0;
}
.qa-column {
min-height: 0;
display: grid;
gap: 12px;
.right-box .qa-panel:last-child {
flex-shrink: 0;
height: 236px;
}
.qa-column-left {
grid-template-rows: minmax(0, 1fr);
}
.qa-column-right {
grid-template-rows: minmax(0, 1fr) 236px;
}
.qa-panel,
.qa-model-panel {
.qa-panel {
min-height: 0;
overflow: hidden;
border: 1px solid rgba(91, 180, 255, 0.36);
@@ -611,32 +655,6 @@ body,
background: rgba(255, 255, 255, 0.06);
}
.qa-model-panel {
position: relative;
background: rgba(8, 18, 32, 0.22);
}
.model-frame,
.model-placeholder {
position: absolute;
inset: 0;
}
.model-frame {
width: 100%;
height: 100%;
border: 0;
background: transparent;
}
.model-placeholder {
display: flex;
align-items: center;
justify-content: center;
color: #77d9ff;
font-size: 24px;
background: radial-gradient(circle at center, rgba(37, 111, 184, 0.24), rgba(4, 12, 28, 0.92));
}
.monitor-card,
.equipment-row,
@@ -842,13 +860,6 @@ body,
margin-bottom: 10px;
}
.qa-bottom-grid {
display: grid;
grid-template-columns: 1.2fr 1fr 1fr;
gap: 12px;
min-height: 0;
}
.storage-groups {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));