feat: add ReportLogViewer component for displaying logs and model comparison, along with a new CAD store.

This commit is contained in:
sladro 2026-03-02 18:55:01 +08:00
parent aa9d283706
commit 15ec017e60
2 changed files with 245 additions and 18 deletions

View File

@ -202,27 +202,79 @@
</div>
<!-- 手动/混合模式内容 -->
<!-- 手动/离线文件对比模式内容 -->
<div v-else class="manual-comparison">
<div class="upload-panels">
<div class="upload-box baseline-source">
<div class="status-indicator">
<i class="fas fa-desktop text-primary"></i>
<div class="live-flow-container">
<!-- 步骤 1: 捕获基准 -->
<div class="flow-step" :class="{ 'step-active': cadStore.manualComparisonState.step === 1, 'step-done': cadStore.manualComparisonState.step > 1 }">
<div class="step-header">
<div class="step-num">1</div>
<h3>记录当前模型基准状态</h3>
</div>
<div class="step-content">
<el-button v-if="cadStore.manualComparisonState.step === 1" type="primary" :loading="isCapturingManualBaseline" @click="captureManualBaseline" class="live-btn">
<i class="fas fa-crosshairs"></i> 读取当前 CAD 模型参数作为基准
</el-button>
<div v-else class="captured-data card-panel">
<h4><i class="fas fa-cube text-info"></i> 基准原始模型</h4>
<ul class="data-list">
<li><span class="lbl">模型文件:</span> <span class="val">{{ cadStore.manualComparisonState.baselineData?.name }}</span></li>
<li><span class="lbl">内存占用:</span> <span class="val">{{ cadStore.manualComparisonState.baselineData?.mem }}</span></li>
<li><span class="lbl">面片数量:</span> <span class="val">{{ cadStore.manualComparisonState.baselineData?.poly }}</span></li>
<li><span class="lbl">特征数量:</span> <span class="val">{{ cadStore.manualComparisonState.baselineData?.features }}</span></li>
</ul>
</div>
</div>
<p class="source-title">当前 CAD 打开模型</p>
<p class="source-desc">将自动抓取当前插件会话中的模型参数作为基准</p>
</div>
<div class="vs-icon">VS</div>
<div class="upload-box target">
<i class="fas fa-file-upload"></i>
<p>请选择比对目标离线文件 (.prt, .ifc, .rvt...)</p>
<el-button size="small" type="primary">选择本地文件</el-button>
<!-- 步骤 2: 填写离线文件路径并比对 -->
<div class="flow-step" :class="{ 'step-active': cadStore.manualComparisonState.step === 2, 'step-done': cadStore.manualComparisonState.step > 2 }">
<div class="step-header">
<div class="step-num">2</div>
<h3>自动打开离线文件并比对</h3>
</div>
<div class="step-content">
<div v-if="cadStore.manualComparisonState.step === 2" class="wait-msg">
<i class="fas fa-info-circle"></i> 请填写需要对比的离线文件绝对路径 (支持 .rvt, .rfa, .prt, .asm 等格式)
</div>
<div v-if="cadStore.manualComparisonState.step === 2" style="display: flex; gap: 10px; margin-top: 15px;">
<el-input v-model="cadStore.manualComparisonState.targetFilePath" placeholder="例如: D:\models\example.prt" style="flex: 1;" clearable />
<el-button type="success" :loading="isCapturingManualResult" @click="captureManualResult" plain>
<i class="fas fa-folder-open"></i> 自动打开并读取参数
</el-button>
</div>
<transition name="el-zoom-in-top">
<div v-if="cadStore.manualComparisonState.step === 3" class="comparison-results mt-4">
<div class="comparison-columns mt-4">
<div class="comp-col source-col">
<h4><i class="fas fa-cube"></i> 基准状态</h4>
<ul class="prop-list">
<li><span class="prop-label">内存占用</span> <span class="prop-value">{{ cadStore.manualComparisonState.baselineData?.mem }}</span></li>
<li><span class="prop-label">面片数量</span> <span class="prop-value">{{ cadStore.manualComparisonState.baselineData?.poly }}</span></li>
<li><span class="prop-label">特征总数</span> <span class="prop-value">{{ cadStore.manualComparisonState.baselineData?.features }}</span></li>
</ul>
</div>
<div class="vs-divider">VS</div>
<div class="comp-col target-col">
<h4><i class="fas fa-leaf text-success"></i> 离线文件读取状态</h4>
<ul class="prop-list">
<li><span class="prop-label">文件名称</span> <span class="prop-value text-success">{{ cadStore.manualComparisonState.resultData?.name }}</span></li>
<li><span class="prop-label">内存占用</span> <span class="prop-value text-success">{{ cadStore.manualComparisonState.resultData?.mem }}</span></li>
<li><span class="prop-label">面片数量</span> <span class="prop-value text-success">{{ cadStore.manualComparisonState.resultData?.poly }}</span></li>
<li><span class="prop-label">特征总数</span> <span class="prop-value text-success">{{ cadStore.manualComparisonState.resultData?.features }}</span></li>
</ul>
</div>
</div>
<div class="mt-4 flex-center">
<el-button plain @click="resetManualFlow">开启新一轮比对</el-button>
</div>
</div>
</transition>
</div>
</div>
</div>
<div class="manual-actions">
<el-button type="success" icon="el-icon-video-play" size="large">开始混合比对分析</el-button>
</div>
</div>
</div>
</el-tab-pane>
@ -253,6 +305,8 @@ const comparisonMode = ref('live')
const isCapturingBaseline = ref(false)
const isCapturingResult = ref(false)
const isCapturingManualBaseline = ref(false)
const isCapturingManualResult = ref(false)
const cadStore = useCADStore()
@ -404,6 +458,161 @@ const resetLiveFlow = () => {
cadStore.resetLiveComparison()
}
const captureManualBaseline = async () => {
const connectedCAD = cadStore.currentCAD
if (!connectedCAD) {
ElMessage.warning('请先连接并打开对应的 CAD 插件和模型')
return
}
isCapturingManualBaseline.value = true
try {
let result;
let stats = {
mem: 'API暂未支持',
poly: 'API暂未支持',
features: 'API暂未支持'
}
if (connectedCAD.id === 'creo') {
result = await creoApi.getCurrentModel()
try {
const statResult = await creoApi.getHierarchyStatistics()
if (statResult.success && statResult.data?.data?.statistics) {
let totalFeatures = 0
Object.values(statResult.data.data.statistics).forEach(v => totalFeatures += v)
if(totalFeatures > 0) stats.features = `${totalFeatures} +`
}
} catch(e) { }
} else if (connectedCAD.id === 'revit') {
result = await revitApi.getCurrentModel()
} else if (connectedCAD.id === 'pdms') {
result = await pdmsApi.getCurrentModel()
}
if (result && result.success) {
const respData = result.data?.data || {}
let fileName = '当前活动模型'
if (connectedCAD.id === 'creo' && respData.fileName) fileName = respData.fileName
else if (connectedCAD.id === 'revit' && respData.project?.name) fileName = respData.project.name
else if (connectedCAD.id === 'pdms' && respData.ProjectInfo?.ProjectName) fileName = respData.ProjectInfo.ProjectName
if (respData.fileSize) stats.mem = respData.fileSize
if (respData.memoryUsage) stats.mem = respData.memoryUsage
if (respData.polygonCount) stats.poly = respData.polygonCount
if (respData.featureCount) stats.features = respData.featureCount
if (respData.componentCount) stats.features = respData.componentCount
if (connectedCAD.id === 'revit' && respData.project) {
if (respData.project.fileSizeDisplay) stats.mem = respData.project.fileSizeDisplay
if (respData.project.polygonCount !== undefined) stats.poly = respData.project.polygonCount
if (respData.project.featureCount !== undefined) stats.features = respData.project.featureCount
}
cadStore.manualComparisonState.baselineData = {
name: fileName,
mem: stats.mem,
poly: stats.poly,
features: stats.features
}
cadStore.manualComparisonState.step = 2
ElMessage.success('基准状态参数读取成功')
} else {
throw new Error(result?.error || '未能获取到开启的模型信息')
}
} catch (error) {
ElMessage.error(`获取基准数据失败: ${error.message}`)
} finally {
isCapturingManualBaseline.value = false
}
}
const captureManualResult = async () => {
const filePath = cadStore.manualComparisonState.targetFilePath
if (!filePath || filePath.trim() === '') {
ElMessage.warning('请填写离线模型的绝对路径')
return
}
const ext = filePath.split('.').pop().toLowerCase()
let apiToUse = null
let cadType = ''
if (['rvt', 'rfa'].includes(ext)) {
apiToUse = revitApi
cadType = 'revit'
} else if (['prt', 'asm'].includes(ext)) {
apiToUse = creoApi
cadType = 'creo'
} else {
ElMessage.warning(`暂不支持的离线文件后缀: .${ext},目前自动打开支持 .rvt, .rfa, .prt, .asm`)
return
}
isCapturingManualResult.value = true
try {
// apiToUse 访
// 线
const openRes = await apiToUse.openModelFile(filePath)
if (!openRes || !openRes.success) {
throw new Error(openRes?.error || '打开离线模型文件失败')
}
let result = await apiToUse.getCurrentModel()
let stats = { mem: 'API暂未支持', poly: 'API暂未支持', features: 'API暂未支持' }
if (cadType === 'creo') {
try {
const statResult = await creoApi.getHierarchyStatistics()
if (statResult.success && statResult.data?.data?.statistics) {
let totalFeatures = 0
Object.values(statResult.data.data.statistics).forEach(v => totalFeatures += v)
if(totalFeatures > 0) stats.features = `${totalFeatures} +`
}
} catch(e) { }
}
if (result && result.success) {
const respData = result.data?.data || {}
//
let fileName = filePath.split('\\').pop().split('/').pop()
if (respData.fileSize) stats.mem = respData.fileSize
if (respData.memoryUsage) stats.mem = respData.memoryUsage
if (respData.polygonCount) stats.poly = respData.polygonCount
if (respData.featureCount) stats.features = respData.featureCount
if (respData.componentCount) stats.features = respData.componentCount
if (cadType === 'revit' && respData.project) {
if (respData.project.fileSizeDisplay) stats.mem = respData.project.fileSizeDisplay
if (respData.project.polygonCount !== undefined) stats.poly = respData.project.polygonCount
if (respData.project.featureCount !== undefined) stats.features = respData.project.featureCount
}
cadStore.manualComparisonState.resultData = {
name: fileName,
mem: stats.mem,
poly: stats.poly,
features: stats.features
}
cadStore.manualComparisonState.step = 3
ElMessage.success('离线模型已成功打开并读取参数')
} else {
throw new Error(result?.error || '未能获取到离线模型信息')
}
} catch (error) {
ElMessage.error(`获取离线模型数据失败: ${error.message}`)
} finally {
isCapturingManualResult.value = false
}
}
const resetManualFlow = () => {
cadStore.resetManualComparison()
}
//
const mockReports = [
{

View File

@ -97,13 +97,20 @@ export const useCADStore = defineStore('cad', () => {
draggedFile.value = file
}
// 实时穿透对比状态 (全局保留)
const liveComparisonState = ref({
step: 1, // 1: 准备抓取基准, 2: 已抓取基准(等待抓取结果), 3: 完成对比
baselineData: null,
resultData: null
})
// 离线文件对比状态
const manualComparisonState = ref({
step: 1, // 1: 准备抓取基准, 2: 填写并打开离线文件, 3: 完成对比
baselineData: null,
targetFilePath: '',
resultData: null
})
// 重置实时穿透对比状态
const resetLiveComparison = () => {
liveComparisonState.value = {
@ -113,6 +120,15 @@ export const useCADStore = defineStore('cad', () => {
}
}
const resetManualComparison = () => {
manualComparisonState.value = {
step: 1,
baselineData: null,
targetFilePath: '',
resultData: null
}
}
return {
// 状态
cadConnections,
@ -129,6 +145,8 @@ export const useCADStore = defineStore('cad', () => {
setCurrentProjectName,
setDraggedFile,
liveComparisonState,
resetLiveComparison
resetLiveComparison,
manualComparisonState,
resetManualComparison
}
})