feat: 实现几何复杂度分析完整功能

- 修正API参数max_results为30符合需求
- 修复数据传递层级问题(result.data.data)
- 移除硬编码模拟数据,使用API真实数据
- 实现删除选定组件功能与智能分析一致
- 使用ElementPlus系统UI组件替换原生确认框
- 修复ESLint错误,清理未使用变量和函数
- 优化体积字段显示,0值显示为N/A

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
sladro 2025-09-18 11:43:31 +08:00
parent 7ea1014570
commit b2da2281f2
9 changed files with 74 additions and 136 deletions

View File

@ -148,6 +148,7 @@ const handleOperation = async () => {
- ✅ Revit建筑设计模型查看器RevitModelViewer
- ✅ 层级统计功能完整集成getHierarchyStatistics API + 层级删除配置页面)
- ✅ 层级删除功能完整实现deleteHierarchy API + 项目名称管理 + 成功提示)
- ✅ 几何复杂度分析API接入完整实现API调用 + 真实数据显示 + 组件删除功能)
## 页面添加标准流程

View File

@ -388,33 +388,6 @@ const refreshStats = () => {
}
//
const isRunning = (status) => {
return ['running', 'started', 'active', 'online', 'idle', 'ready', 'connected'].includes(status)
}
const getStatusText = (status) => {
const statusMap = {
'running': '运行中',
'stopped': '已停止',
'starting': '启动中...',
'stopping': '停止中...',
'restarting': '重启中...',
'started': '运行中',
'active': '运行中',
'online': '运行中',
'idle': '运行中',
'ready': '运行中',
'connected': '运行中',
'disconnected': '已停止',
'offline': '已停止',
'inactive': '已停止',
'terminated': '已停止',
'error': '错误',
'failed': '启动失败',
'unknown': '检测中...'
}
return statusMap[status] || '检测中...'
}
const getLogStatusText = (status) => {
const statusMap = {
@ -438,7 +411,7 @@ const formatTime = (timestamp) => {
minute: '2-digit',
second: '2-digit'
})
} catch (error) {
} catch {
return timestamp
}
}

View File

@ -228,7 +228,7 @@ const formatDateTime = (dateTimeString) => {
minute: '2-digit',
second: '2-digit'
})
} catch (error) {
} catch {
return dateTimeString
}
}

View File

@ -93,7 +93,7 @@ const handleHierarchyDeletion = async () => {
const handleGeometryComplexity = async () => {
const result = await creoApi.startGeometryComplexityAnalysis()
if (result.success) {
emit('show-geometry-complexity-result')
emit('show-geometry-complexity-result', result.data.data)
}
}
const handleGeometryOptimization = () => {

View File

@ -15,13 +15,13 @@
<h4><i class="fas fa-chart-pie"></i> 分析摘要</h4>
<div class="analysis-time">
<i class="fas fa-clock"></i>
完成时间: {{ analysisTime }}
完成时间: {{ analysisTimeFormatted }}
</div>
</div>
<div class="summary-stats">
<div class="stat-card">
<div class="stat-value">{{ mockData.length }}</div>
<div class="stat-value">{{ totalPartsAnalyzed }}</div>
<div class="stat-label">总零件数</div>
</div>
<div class="stat-card">
@ -44,7 +44,7 @@
<div class="complexity-parts-header">
<h4>
<i class="fas fa-list"></i>
几何复杂度分析结果 ({{ mockData.length }} 个零件)
几何复杂度分析结果 ({{ partsData.length }} 个零件)
</h4>
<div class="complexity-controls">
<button class="complexity-select-all" @click="selectAll">
@ -76,7 +76,7 @@
</thead>
<tbody id="complexity-parts-tbody">
<tr
v-for="(part, index) in mockData"
v-for="(part, index) in partsData"
:key="index"
class="complexity-part-row"
:class="{ selected: selectedParts.has(index + 1) }"
@ -151,101 +151,44 @@
<script setup>
import { ref, computed, onMounted } from 'vue'
import { ElMessageBox } from 'element-plus'
import { creoApi } from '@/services/creoApi'
// props
const props = defineProps({
analysisData: {
type: Object,
default: null
}
})
//
const selectedParts = ref(new Set())
const analysisTime = ref('')
//
const mockData = ref([
{
part_name: 'HOUSING_ASSEMBLY_001',
part_path: '/PROJECT/ASSEMBLY/HOUSING_ASSEMBLY_001.PRT',
file_size: '2.4 MB',
surface_count: 142,
feature_count: 23,
curved_surface_count: 18,
hole_count: 8,
fillet_count: 15,
complexity_score: 8.5,
complexity_level: 'Very High',
volume: 125400.50
},
{
part_name: 'BRACKET_SUPPORT_V2',
part_path: '/PROJECT/ASSEMBLY/BRACKET_SUPPORT_V2.PRT',
file_size: '1.8 MB',
surface_count: 98,
feature_count: 18,
curved_surface_count: 12,
hole_count: 6,
fillet_count: 11,
complexity_score: 7.2,
complexity_level: 'High',
volume: 89230.25
},
{
part_name: 'CONNECTOR_PLATE_A',
part_path: '/PROJECT/ASSEMBLY/CONNECTOR_PLATE_A.PRT',
file_size: '0.9 MB',
surface_count: 54,
feature_count: 12,
curved_surface_count: 6,
hole_count: 4,
fillet_count: 8,
complexity_score: 5.8,
complexity_level: 'Medium',
volume: 42150.75
},
{
part_name: 'BASE_FRAME_MAIN',
part_path: '/PROJECT/ASSEMBLY/BASE_FRAME_MAIN.PRT',
file_size: '3.2 MB',
surface_count: 186,
feature_count: 31,
curved_surface_count: 24,
hole_count: 12,
fillet_count: 19,
complexity_score: 9.1,
complexity_level: 'Very High',
volume: 198750.00
},
{
part_name: 'GUIDE_RAIL_SET',
part_path: '/PROJECT/ASSEMBLY/GUIDE_RAIL_SET.PRT',
file_size: '1.2 MB',
surface_count: 76,
feature_count: 15,
curved_surface_count: 8,
hole_count: 5,
fillet_count: 9,
complexity_score: 6.4,
complexity_level: 'Medium',
volume: 67890.30
},
{
part_name: 'SIMPLE_WASHER_001',
part_path: '/PROJECT/ASSEMBLY/SIMPLE_WASHER_001.PRT',
file_size: '0.1 MB',
surface_count: 8,
feature_count: 3,
curved_surface_count: 2,
hole_count: 1,
fillet_count: 2,
complexity_score: 2.1,
complexity_level: 'Low',
volume: 1250.45
}
])
// 使API
const partsData = computed(() => {
return props.analysisData?.parts || []
})
//
// - 使API
const averageComplexity = computed(() => {
const total = mockData.value.reduce((sum, part) => sum + part.complexity_score, 0)
return (total / mockData.value.length).toFixed(2)
return props.analysisData?.average_complexity?.toFixed(2) || '0.00'
})
const totalPartsAnalyzed = computed(() => {
return props.analysisData?.total_parts_analyzed || partsData.value.length
})
const analysisTimeFormatted = computed(() => {
if (props.analysisData?.analysis_time) {
return new Date(props.analysisData.analysis_time).toLocaleString('zh-CN')
}
return analysisTime.value
})
const highComplexityCount = computed(() => {
return mockData.value.filter(part => part.complexity_score >= 7.0).length
return partsData.value.filter(part => part.complexity_score >= 7.0).length
})
//
@ -258,6 +201,9 @@ const getComplexityClass = (score) => {
}
const formatVolume = (volume) => {
if (volume === 0 || volume === null || volume === undefined) {
return 'N/A'
}
return volume.toLocaleString('zh-CN', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
@ -266,7 +212,7 @@ const formatVolume = (volume) => {
const selectAll = () => {
selectedParts.value.clear()
for (let i = 1; i <= mockData.value.length; i++) {
for (let i = 1; i <= partsData.value.length; i++) {
selectedParts.value.add(i)
}
}
@ -284,15 +230,39 @@ const updateSelection = (event) => {
}
}
const deleteSelected = () => {
const deleteSelected = async () => {
if (selectedParts.value.size === 0) {
alert('请先选择要删除的零件')
return
}
const confirmed = confirm(`确定要删除选中的 ${selectedParts.value.size} 个零件吗?`)
if (confirmed) {
alert('删除功能仅为UI演示未实现实际删除逻辑')
await ElMessageBox.confirm(
`确定要删除选中的 ${selectedParts.value.size} 个零件吗?此操作不可撤销!`,
'删除确认',
{
confirmButtonText: '确定删除',
cancelButtonText: '取消',
type: 'warning'
}
)
//
const selectedPartIds = Array.from(selectedParts.value)
const componentPaths = []
selectedPartIds.forEach(partId => {
const part = partsData.value.find((p, index) => index + 1 === partId)
if (part && part.part_path) {
componentPaths.push(part.part_path)
}
})
if (componentPaths.length === 0) {
return
}
const result = await creoApi.deleteComponentsByPath(componentPaths, false)
if (result.success) {
selectedParts.value.clear()
}
}

View File

@ -133,13 +133,6 @@ const getLevelComponentCount = (level) => {
return hierarchyStatistics.value[level]
}
//
const getExecutionParams = () => {
return {
selectedLevel: selectedLevel.value
}
}
//
const initializeDefaultLevel = () => {
if (availableLevels.value.length > 0) {

View File

@ -2,7 +2,6 @@
// 包含拦截器、日志记录和后处理能力
import { getDefaultRequestConfig, getNotificationConfig } from '@/config/cad'
import cadConfig from '@/config/cad'
import { ElNotification, ElLoading } from 'element-plus'
import websocketService from './websocketService'

View File

@ -118,7 +118,7 @@ class CreoApiService {
return await apiClient.post(url, {
"software_type": SOFTWARE_TYPE,
"project_name": "Geometry Analysis",
"max_results": DEFAULT_MAX_RESULTS,
"max_results": 30,
"sort_order": "desc",
"complexity_threshold": 0.0,
"include_details": true

View File

@ -156,7 +156,7 @@
<!-- 几何复杂度分析结果页面 -->
<div v-else-if="currentPage === PAGE_TYPES.GEOMETRY_COMPLEXITY_RESULT" class="page-content">
<GeometryComplexityResult />
<GeometryComplexityResult :analysis-data="geometryComplexityData" />
</div>
<!-- 几何优化分析参数设置页面 -->
@ -291,6 +291,7 @@ const currentModelData = ref(null)
//
const shellAnalysisData = ref(null)
const hierarchyAnalysisData = ref(null)
const geometryComplexityData = ref(null)
//
const showInfoPanel = ref(false)
@ -320,7 +321,8 @@ const handleShowHierarchyAnalysisResult = (analysisData) => {
}
//
const handleShowGeometryComplexityResult = () => {
const handleShowGeometryComplexityResult = (data) => {
geometryComplexityData.value = data
currentPage.value = PAGE_TYPES.GEOMETRY_COMPLEXITY_RESULT
}