This commit is contained in:
2026-05-15 15:20:31 +08:00
parent 5e8062f1d2
commit 6bd595bd63
2 changed files with 150 additions and 58 deletions
+24
View File
@@ -1318,6 +1318,16 @@ optgroup {
border-radius: var(--radius-lg); border-radius: var(--radius-lg);
} }
.viewer-section-hero {
border-color: var(--primary-200);
box-shadow: var(--shadow-md);
}
.viewer-frame-hero {
height: 680px;
background: var(--bg-secondary);
}
/* ================================ /* ================================
结果网格 结果网格
================================ */ ================================ */
@@ -1381,6 +1391,12 @@ optgroup {
border-top: 1px solid var(--border-light); border-top: 1px solid var(--border-light);
} }
.mechanism-actions {
margin-top: var(--space-4);
display: flex;
justify-content: flex-end;
}
.mechanism-note-list { .mechanism-note-list {
margin: 0; margin: 0;
padding-left: 1.1rem; padding-left: 1.1rem;
@@ -1428,6 +1444,10 @@ optgroup {
color: var(--primary-700); color: var(--primary-700);
} }
.mechanism-modal {
max-width: 860px;
}
.single-scheme-grid { .single-scheme-grid {
grid-template-columns: 1fr !important; grid-template-columns: 1fr !important;
} }
@@ -2962,6 +2982,10 @@ select.form-input {
.advanced-param-grid { .advanced-param-grid {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
.viewer-frame-hero {
height: 520px;
}
} }
/* ================================ /* ================================
+126 -58
View File
@@ -1425,6 +1425,7 @@ const ResultView = {
error: '', error: '',
selectedSchemeId: null, selectedSchemeId: null,
previewStatus: 'idle', previewStatus: 'idle',
activeMechanismDetail: null,
camLoading: false, camLoading: false,
camError: '', camError: '',
camPlan: null, camPlan: null,
@@ -1547,10 +1548,10 @@ const ResultView = {
}); });
const resultAnchorLinks = [ const resultAnchorLinks = [
{ id: 'candidate-schemes', label: '方案' }, { id: 'candidate-schemes', label: '方案' },
{ id: 'preview-3d', label: '预览' },
{ id: 'engineering-summary', label: '工程摘要' }, { id: 'engineering-summary', label: '工程摘要' },
{ id: 'side-actions', label: '抽芯建议' }, { id: 'side-actions', label: '抽芯建议' },
{ id: 'dfm-check', label: 'DFM' }, { id: 'dfm-check', label: 'DFM' },
{ id: 'preview-3d', label: '预览' },
{ id: 'export-cam', label: '导出/CAM' }, { id: 'export-cam', label: '导出/CAM' },
{ id: 'analysis-details', label: '分析详情' }, { id: 'analysis-details', label: '分析详情' },
{ id: 'diagnostic-info', label: '诊断' } { id: 'diagnostic-info', label: '诊断' }
@@ -1621,6 +1622,21 @@ const ResultView = {
const keys = Object.keys(size); const keys = Object.keys(size);
return keys.map(key => `${key}:${Number(size[key]).toFixed(1)} mm`).join(' / '); return keys.map(key => `${key}:${Number(size[key]).toFixed(1)} mm`).join(' / ');
}; };
const formatMechanismType = (type) => {
if (type === 'slider') return '滑块抽芯';
if (type === 'lifter') return '斜顶抽芯';
return type || '机构';
};
const openMechanismDetail = (type, index, item) => {
state.activeMechanismDetail = {
type,
index,
item,
};
};
const closeMechanismDetail = () => {
state.activeMechanismDetail = null;
};
const exportCAD = async (format) => { const exportCAD = async (format) => {
try { try {
@@ -1728,6 +1744,9 @@ const ResultView = {
formatTiming, formatTiming,
formatVector, formatVector,
formatMechanismSize, formatMechanismSize,
formatMechanismType,
openMechanismDetail,
closeMechanismDetail,
primaryRecommendation, primaryRecommendation,
sortedRecommendations, sortedRecommendations,
selectedDfmCount, selectedDfmCount,
@@ -1908,6 +1927,35 @@ const ResultView = {
</div> </div>
</div> </div>
<div id="preview-3d" v-if="selectedHtmlFile" class="viewer-section viewer-section-hero">
<div class="summary-header">
<h3>3D 预览</h3>
<span class="badge badge-info">重点区域</span>
</div>
<div v-if="state.previewStatus === 'error'" class="inline-alert inline-alert-warning" style="margin-bottom: var(--space-3);">
<div class="inline-alert-title">预览加载失败</div>
<div class="inline-alert-message">HTML 已生成但加载异常,请检查该链接是否可访问:{{ selectedHtmlFile }}</div>
</div>
<iframe
:key="selectedHtmlFile"
:src="selectedHtmlFile"
class="viewer-frame viewer-frame-hero"
@load="onPreviewLoad"
@error="onPreviewError"
></iframe>
</div>
<div id="preview-3d" v-else class="viewer-section viewer-section-hero">
<div class="summary-header">
<h3>3D 预览</h3>
<span class="badge badge-warning">未生成</span>
</div>
<div class="inline-alert inline-alert-warning">
<div class="inline-alert-title">预览未生成</div>
<div class="inline-alert-message">当前任务没有返回 HTML 预览链接,属于未生成状态。</div>
</div>
</div>
<div id="candidate-schemes" v-if="candidateSchemes.length" class="viewer-section"> <div id="candidate-schemes" v-if="candidateSchemes.length" class="viewer-section">
<h3>候选分模方案</h3> <h3>候选分模方案</h3>
<div class="inline-note">先切换并确认推荐方案,再进入后续工程判断、导出与 CAM。</div> <div class="inline-note">先切换并确认推荐方案,再进入后续工程判断、导出与 CAM。</div>
@@ -2144,28 +2192,9 @@ const ResultView = {
<span class="info-label">驱动方式</span> <span class="info-label">驱动方式</span>
<span class="info-value">{{ item.actuation || 'N/A' }}</span> <span class="info-value">{{ item.actuation || 'N/A' }}</span>
</div> </div>
<div class="info-item">
<span class="info-label">导滑方式</span>
<span class="info-value">{{ item.guide_type || 'N/A' }}</span>
</div>
<div class="info-item">
<span class="info-label">锁紧方式</span>
<span class="info-value">{{ item.locking_mechanism || 'N/A' }}</span>
</div>
<div class="info-item">
<span class="info-label">机构尺寸</span>
<span class="info-value">{{ formatMechanismSize(item.block_size) }}</span>
</div>
<div class="info-item">
<span class="info-label">机构位置</span>
<span class="info-value">{{ formatVector(item.location) }}</span>
</div>
</div> </div>
<div class="mechanism-notes" v-if="item.manufacturing_notes?.length"> <div class="mechanism-actions">
<div class="mechanism-subtitle">注意事项</div> <button class="btn-sm btn-secondary" @click="openMechanismDetail('slider', idx, item)">查看详情</button>
<ul class="mechanism-note-list">
<li v-for="(note, noteIdx) in item.manufacturing_notes" :key="'slider-note-' + idx + '-' + noteIdx">{{ note }}</li>
</ul>
</div> </div>
</div> </div>
</div> </div>
@@ -2193,20 +2222,9 @@ const ResultView = {
<span class="info-label">导向方式</span> <span class="info-label">导向方式</span>
<span class="info-value">{{ item.guide_type || 'N/A' }}</span> <span class="info-value">{{ item.guide_type || 'N/A' }}</span>
</div> </div>
<div class="info-item">
<span class="info-label">机构尺寸</span>
<span class="info-value">{{ formatMechanismSize(item.block_size) }}</span>
</div>
<div class="info-item">
<span class="info-label">机构位置</span>
<span class="info-value">{{ formatVector(item.location) }}</span>
</div>
</div> </div>
<div class="mechanism-notes" v-if="item.manufacturing_notes?.length"> <div class="mechanism-actions">
<div class="mechanism-subtitle">注意事项</div> <button class="btn-sm btn-secondary" @click="openMechanismDetail('lifter', idx, item)">查看详情</button>
<ul class="mechanism-note-list">
<li v-for="(note, noteIdx) in item.manufacturing_notes" :key="'lifter-note-' + idx + '-' + noteIdx">{{ note }}</li>
</ul>
</div> </div>
</div> </div>
</div> </div>
@@ -2249,29 +2267,6 @@ const ResultView = {
</div> </div>
</div> </div>
<div id="preview-3d" v-if="selectedHtmlFile" class="viewer-section">
<h3>3D 预览</h3>
<div v-if="state.previewStatus === 'error'" class="inline-alert inline-alert-warning" style="margin-bottom: var(--space-3);">
<div class="inline-alert-title">预览加载失败</div>
<div class="inline-alert-message">HTML 已生成但加载异常,请检查该链接是否可访问:{{ selectedHtmlFile }}</div>
</div>
<iframe
:key="selectedHtmlFile"
:src="selectedHtmlFile"
class="viewer-frame"
@load="onPreviewLoad"
@error="onPreviewError"
></iframe>
</div>
<div id="preview-3d" v-else class="viewer-section">
<h3>3D 预览</h3>
<div class="inline-alert inline-alert-warning">
<div class="inline-alert-title">预览未生成</div>
<div class="inline-alert-message">当前任务没有返回 HTML 预览链接,属于未生成状态。</div>
</div>
</div>
<div id="export-cam" class="viewer-section"> <div id="export-cam" class="viewer-section">
<h3>导出与 CAM</h3> <h3>导出与 CAM</h3>
<div class="result-card" style="margin-bottom: var(--space-4);"> <div class="result-card" style="margin-bottom: var(--space-4);">
@@ -2563,6 +2558,79 @@ const ResultView = {
</div> </div>
</div> </div>
</details> </details>
<div v-if="state.activeMechanismDetail" class="modal-overlay" @click.self="closeMechanismDetail">
<div class="modal-content mechanism-modal">
<div class="modal-header">
<h3>{{ formatMechanismType(state.activeMechanismDetail.type) }} {{ state.activeMechanismDetail.index + 1 }}</h3>
<button class="modal-close" @click="closeMechanismDetail">&times;</button>
</div>
<div class="modal-body">
<div class="result-card">
<div class="info-list">
<div class="info-item">
<span class="info-label">机构类型</span>
<span class="info-value">{{ formatMechanismType(state.activeMechanismDetail.type) }}</span>
</div>
<div class="info-item">
<span class="info-label">机构位置</span>
<span class="info-value">{{ formatVector(state.activeMechanismDetail.item.location) }}</span>
</div>
<div class="info-item" v-if="state.activeMechanismDetail.type === 'slider'">
<span class="info-label">抽芯方向</span>
<span class="info-value">{{ formatVector(state.activeMechanismDetail.item.slide_direction) }}</span>
</div>
<div class="info-item" v-if="state.activeMechanismDetail.type === 'slider'">
<span class="info-label">抽芯行程</span>
<span class="info-value">{{ state.activeMechanismDetail.item.slide_stroke || 'N/A' }} mm</span>
</div>
<div class="info-item" v-if="state.activeMechanismDetail.type === 'slider'">
<span class="info-label">抽芯角度</span>
<span class="info-value">{{ state.activeMechanismDetail.item.slide_angle || 'N/A' }}°</span>
</div>
<div class="info-item" v-if="state.activeMechanismDetail.type === 'slider'">
<span class="info-label">驱动方式</span>
<span class="info-value">{{ state.activeMechanismDetail.item.actuation || 'N/A' }}</span>
</div>
<div class="info-item" v-if="state.activeMechanismDetail.type === 'slider'">
<span class="info-label">导滑方式</span>
<span class="info-value">{{ state.activeMechanismDetail.item.guide_type || 'N/A' }}</span>
</div>
<div class="info-item" v-if="state.activeMechanismDetail.type === 'slider'">
<span class="info-label">锁紧方式</span>
<span class="info-value">{{ state.activeMechanismDetail.item.locking_mechanism || 'N/A' }}</span>
</div>
<div class="info-item" v-if="state.activeMechanismDetail.type === 'lifter'">
<span class="info-label">斜顶角度</span>
<span class="info-value">{{ state.activeMechanismDetail.item.lifter_angle || 'N/A' }}°</span>
</div>
<div class="info-item" v-if="state.activeMechanismDetail.type === 'lifter'">
<span class="info-label">斜顶行程</span>
<span class="info-value">{{ state.activeMechanismDetail.item.lifter_stroke || 'N/A' }} mm</span>
</div>
<div class="info-item" v-if="state.activeMechanismDetail.type === 'lifter'">
<span class="info-label">导向方式</span>
<span class="info-value">{{ state.activeMechanismDetail.item.guide_type || 'N/A' }}</span>
</div>
<div class="info-item" v-if="state.activeMechanismDetail.type === 'lifter'">
<span class="info-label">回位方式</span>
<span class="info-value">{{ state.activeMechanismDetail.item.return_mechanism || 'N/A' }}</span>
</div>
<div class="info-item">
<span class="info-label">机构尺寸</span>
<span class="info-value">{{ formatMechanismSize(state.activeMechanismDetail.item.block_size) }}</span>
</div>
</div>
</div>
<div class="result-card" v-if="state.activeMechanismDetail.item.manufacturing_notes?.length">
<h4>注意事项</h4>
<ul class="mechanism-note-list">
<li v-for="(note, noteIdx) in state.activeMechanismDetail.item.manufacturing_notes" :key="'active-note-' + noteIdx">{{ note }}</li>
</ul>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
` `