feat: 新增PDMS模型简化、分析仪表盘和收缩包裹功能页面。
This commit is contained in:
parent
090cf8b3cb
commit
3cdb7298e6
@ -55,16 +55,24 @@
|
||||
<div class="status-badge" style="background: var(--color-success)">新功能</div>
|
||||
</div>
|
||||
|
||||
<!-- 可以预留其他PDMS处理工具位置 -->
|
||||
<div class="pdms-strategy-card disabled" data-strategy="piping-analysis">
|
||||
<div class="strategy-icon" style="background: var(--color-border-primary);">
|
||||
<i class="fas fa-drafting-compass"></i>
|
||||
<div
|
||||
class="pdms-strategy-card"
|
||||
data-strategy="simplify"
|
||||
@click="openSimplifyPage"
|
||||
>
|
||||
<div class="strategy-icon" style="background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);">
|
||||
<i class="fas fa-filter"></i>
|
||||
</div>
|
||||
<h5 style="color: var(--color-text-secondary);">管道专项分析 (开发中)</h5>
|
||||
<p style="color: var(--color-text-disabled);">
|
||||
针对管道模型进行碰撞检测及流体路径复杂性评估。
|
||||
<h5>模型简化 (Simplify)</h5>
|
||||
<p>
|
||||
按设备类型规律地批量删除内部多余的构件元件,大幅度实现快速轻量化。
|
||||
</p>
|
||||
<div class="features">
|
||||
<span>类型过滤</span>
|
||||
<span>结构精简</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -98,6 +106,10 @@ const openShrinkwrapPage = () => {
|
||||
emit('page-change', 'pdms-shrinkwrap')
|
||||
}
|
||||
|
||||
const openSimplifyPage = () => {
|
||||
emit('page-change', 'pdms-simplify')
|
||||
}
|
||||
|
||||
const refreshConnection = () => {
|
||||
ElNotification({
|
||||
title: '刷新连接',
|
||||
|
||||
@ -91,35 +91,35 @@
|
||||
<div class="success-header">
|
||||
<i class="fas fa-check-circle success-icon"></i>
|
||||
<h3>模型轻量化完成</h3>
|
||||
<p v-if="taskResult.dryRun" style="color:var(--color-warning);">(本次为模拟运行模式,未真实删除模型)</p>
|
||||
<p v-if="taskResult.DryRun" style="color:var(--color-warning);">(本次为模拟运行模式,未真实删除模型)</p>
|
||||
</div>
|
||||
|
||||
<div class="metrics-grid">
|
||||
<div class="metric-card">
|
||||
<div class="metric-icon"><i class="fas fa-trash-alt"></i></div>
|
||||
<div class="metric-info">
|
||||
<div class="metric-value highlight">{{ taskResult.removedCount || 0 }}</div>
|
||||
<div class="metric-value highlight">{{ taskResult.RemovedCount || 0 }}</div>
|
||||
<div class="metric-label">移除内部构件数</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="metric-card">
|
||||
<div class="metric-icon"><i class="fas fa-check"></i></div>
|
||||
<div class="metric-info">
|
||||
<div class="metric-value">{{ taskResult.keptCount || 0 }}</div>
|
||||
<div class="metric-value">{{ taskResult.KeptCount || 0 }}</div>
|
||||
<div class="metric-label">保留构件总数</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="metric-card">
|
||||
<div class="metric-icon"><i class="fas fa-search-plus"></i></div>
|
||||
<div class="metric-info">
|
||||
<div class="metric-value">{{ taskResult.totalVisited || 0 }}</div>
|
||||
<div class="metric-value">{{ taskResult.TotalVisited || 0 }}</div>
|
||||
<div class="metric-label">扫描构件总数</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="metric-card" v-if="taskResult.shellKeptCount !== undefined">
|
||||
<div class="metric-card" v-if="taskResult.ShellKeptCount !== undefined">
|
||||
<div class="metric-icon"><i class="fas fa-cube"></i></div>
|
||||
<div class="metric-info">
|
||||
<div class="metric-value">{{ taskResult.shellKeptCount }}</div>
|
||||
<div class="metric-value">{{ taskResult.ShellKeptCount }}</div>
|
||||
<div class="metric-label">壳体保留数</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -127,27 +127,27 @@
|
||||
|
||||
<div class="details-box">
|
||||
<h4>处理信息</h4>
|
||||
<p v-if="taskResult.message">{{ taskResult.message }}</p>
|
||||
<p v-if="taskResult.startedAt && taskResult.completedAt">
|
||||
执行时间: {{ formatTime(taskResult.startedAt) }} - {{ formatTime(taskResult.completedAt) }}
|
||||
<p v-if="taskResult.Message">{{ taskResult.Message }}</p>
|
||||
<p v-if="taskResult.StartedAt && taskResult.CompletedAt">
|
||||
执行时间: {{ formatTime(taskResult.StartedAt) }} - {{ formatTime(taskResult.CompletedAt) }}
|
||||
</p>
|
||||
|
||||
<!-- Zone summaries -->
|
||||
<div v-if="taskResult.zoneSummaries && Object.keys(taskResult.zoneSummaries).length > 0">
|
||||
<div v-if="taskResult.ZoneSummaries && Object.keys(taskResult.ZoneSummaries).length > 0">
|
||||
<h5 style="margin-top:20px; color: var(--color-text-primary);">Zone 处理汇总</h5>
|
||||
<ul>
|
||||
<li v-for="(count, zone) in taskResult.zoneSummaries" :key="zone">
|
||||
<li v-for="(count, zone) in taskResult.ZoneSummaries" :key="zone">
|
||||
<span style="color:var(--color-primary)">{{ zone }}</span> : {{ count }} 个移除
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Errors -->
|
||||
<div v-if="taskResult.errors && taskResult.errors.length > 0" class="error-message" style="margin-top:20px;">
|
||||
<div v-if="taskResult.Errors && taskResult.Errors.length > 0" class="error-message" style="margin-top:20px;">
|
||||
<p><i class="fas fa-exclamation-triangle"></i> 部分处理出错:</p>
|
||||
<ul>
|
||||
<li v-for="(err, idx) in taskResult.errors.slice(0, 5)" :key="idx">{{ err }}</li>
|
||||
<li v-if="taskResult.errors.length > 5">...以及其他 {{ taskResult.errors.length - 5 }} 个错误</li>
|
||||
<li v-for="(err, idx) in taskResult.Errors.slice(0, 5)" :key="idx">{{ err }}</li>
|
||||
<li v-if="taskResult.Errors.length > 5">...以及其他 {{ taskResult.Errors.length - 5 }} 个错误</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@ -222,11 +222,11 @@ const startTask = async () => {
|
||||
|
||||
try {
|
||||
const payload = {
|
||||
dryRun: formData.dryRun,
|
||||
padding: formData.padding,
|
||||
touchTolerance: formData.touchTolerance,
|
||||
zoneFilters: zoneFiltersInput.value ? zoneFiltersInput.value.split(',').map(s => s.trim()).filter(s => s) : [],
|
||||
keepTypes: formData.keepTypes
|
||||
DryRun: formData.dryRun,
|
||||
Padding: formData.padding,
|
||||
TouchTolerance: formData.touchTolerance,
|
||||
ZoneFilters: zoneFiltersInput.value ? zoneFiltersInput.value.split(',').map(s => s.trim()).filter(s => s) : [],
|
||||
KeepTypes: formData.keepTypes
|
||||
}
|
||||
|
||||
const res = await pdmsApi.executeShrinkwrap(payload)
|
||||
|
||||
581
src/components/pages/PdmsSimplifyPage.vue
Normal file
581
src/components/pages/PdmsSimplifyPage.vue
Normal file
@ -0,0 +1,581 @@
|
||||
<template>
|
||||
<div class="pdms-simplify pdms-theme">
|
||||
<div class="header-actions">
|
||||
<button class="icon-btn" @click="goBack" title="返回">
|
||||
<i class="fas fa-arrow-left"></i> 返回分析中心
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="optimization-header">
|
||||
<h2>
|
||||
<i class="fas fa-filter"></i>
|
||||
PDMS模型简化处理
|
||||
</h2>
|
||||
<p class="subtitle">按设备类型过滤批量删除内部构件,大幅度实现快速轻量化。</p>
|
||||
</div>
|
||||
|
||||
<!-- 任务参数设置区 -->
|
||||
<div class="settings-panel" v-if="taskStatus === 'idle' || taskStatus === 'failed'">
|
||||
<div class="setting-group checkbox-group">
|
||||
<label>保留类别 (Keep Types)</label>
|
||||
<div class="checkbox-options">
|
||||
<el-checkbox-group v-model="formData.keepTypes">
|
||||
<el-checkbox label="SITE">SITE (场地)</el-checkbox>
|
||||
<el-checkbox label="ZONE">ZONE (区域)</el-checkbox>
|
||||
<el-checkbox label="STRU">STRU (结构)</el-checkbox>
|
||||
<el-checkbox label="FRAME">FRAME (框架)</el-checkbox>
|
||||
<el-checkbox label="SHELL">SHELL (壳体)</el-checkbox>
|
||||
<el-checkbox label="PLAT">PLAT (平台)</el-checkbox>
|
||||
<el-checkbox label="WALL">WALL (墙体)</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="setting-group checkbox-group">
|
||||
<label>删除类别 (Remove Types)</label>
|
||||
<div class="checkbox-options">
|
||||
<el-checkbox-group v-model="formData.removeTypes">
|
||||
<el-checkbox label="PIPE">PIPE (管道)</el-checkbox>
|
||||
<el-checkbox label="BRAN">BRAN (分支)</el-checkbox>
|
||||
<el-checkbox label="ELBO">ELBO (弯头)</el-checkbox>
|
||||
<el-checkbox label="VALV">VALV (阀门)</el-checkbox>
|
||||
<el-checkbox label="FITT">FITT (管件)</el-checkbox>
|
||||
<el-checkbox label="NOZZ">NOZZ (管口)</el-checkbox>
|
||||
<el-checkbox label="EQUI">EQUI (设备)</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="setting-group parameters-group">
|
||||
<div class="param-item">
|
||||
<label>包围盒内部补白 (BoundingShell Padding)</label>
|
||||
<el-input-number v-model="formData.padding" :min="0" :step="10" />
|
||||
<p class="help-text">指定边界包围盒的填充间距,默认 0.0</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="setting-group">
|
||||
<label>区域过滤 (Zone Filters, 可选)</label>
|
||||
<el-input
|
||||
v-model="zoneFiltersInput"
|
||||
placeholder="输入要处理的ZONE路径(逗号分隔),为空则全量处理"
|
||||
></el-input>
|
||||
</div>
|
||||
|
||||
<div class="setting-group toggle-group">
|
||||
<label>安全设置</label>
|
||||
<div class="toggle-control">
|
||||
<span>开启模拟模式 (Dry Run)?仅模拟不真删</span>
|
||||
<el-switch v-model="formData.dryRun" active-color="#3b82f6" inactive-color="#ff4949"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="action-bar">
|
||||
<button class="primary-btn" @click="startTask" :disabled="isStarting">
|
||||
<i class="fas" :class="isStarting ? 'fa-spinner fa-spin' : 'fa-play'"></i>
|
||||
{{ isStarting ? '正在处理...' : '执行简化' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="errorMessage" class="error-message">
|
||||
<i class="fas fa-exclamation-triangle"></i> {{ errorMessage }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 任务执行中进度区 -->
|
||||
<div class="execution-panel" v-else-if="taskStatus === 'Processing'">
|
||||
<h3>
|
||||
<i class="fas fa-cog fa-spin"></i>
|
||||
正在处理PDMS模型,请耐心等待 (可能需要几分钟)...
|
||||
</h3>
|
||||
|
||||
<div class="progress-container">
|
||||
<div class="progress-bar">
|
||||
<div class="progress-fill active"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 任务结果区 -->
|
||||
<div class="result-panel" v-else-if="taskStatus === 'Completed' && taskResult">
|
||||
<div class="success-header">
|
||||
<i class="fas fa-check-circle success-icon"></i>
|
||||
<h3>模型简化完成</h3>
|
||||
<p v-if="taskResult.DryRun" style="color:var(--color-warning);">(本次为模拟运行模式,未真实删除模型)</p>
|
||||
</div>
|
||||
|
||||
<div class="metrics-grid">
|
||||
<div class="metric-card">
|
||||
<div class="metric-icon"><i class="fas fa-trash-alt"></i></div>
|
||||
<div class="metric-info">
|
||||
<div class="metric-value highlight">{{ taskResult.RemovedCount || 0 }}</div>
|
||||
<div class="metric-label">移除类别构件数</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="metric-card">
|
||||
<div class="metric-icon"><i class="fas fa-check"></i></div>
|
||||
<div class="metric-info">
|
||||
<div class="metric-value">{{ taskResult.KeptCount || 0 }}</div>
|
||||
<div class="metric-label">保留构件总数</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="metric-card">
|
||||
<div class="metric-icon"><i class="fas fa-search-plus"></i></div>
|
||||
<div class="metric-info">
|
||||
<div class="metric-value">{{ taskResult.TotalVisited || 0 }}</div>
|
||||
<div class="metric-label">扫描构件总数</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="details-box">
|
||||
<h4>处理信息</h4>
|
||||
<p v-if="taskResult.Message">{{ taskResult.Message }}</p>
|
||||
<p v-if="taskResult.StartedAt && taskResult.CompletedAt">
|
||||
执行时间: {{ formatTime(taskResult.StartedAt) }} - {{ formatTime(taskResult.CompletedAt) }}
|
||||
</p>
|
||||
|
||||
<!-- Zone summaries -->
|
||||
<div v-if="taskResult.ZoneSummaries && taskResult.ZoneSummaries.length > 0">
|
||||
<h5 style="margin-top:20px; color: var(--color-text-primary);">Zone 处理汇总</h5>
|
||||
<ul>
|
||||
<li v-for="(summary, idx) in taskResult.ZoneSummaries" :key="idx">
|
||||
{{ summary }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Removed Elements Summary -->
|
||||
<div v-if="taskResult.RemovedElements && taskResult.RemovedElements.length > 0">
|
||||
<h5 style="margin-top:20px; color: var(--color-text-primary);">移除元件示例</h5>
|
||||
<ul>
|
||||
<li v-for="(el, idx) in taskResult.RemovedElements.slice(0, 5)" :key="idx">
|
||||
{{ el }}
|
||||
</li>
|
||||
<li v-if="taskResult.RemovedElements.length > 5">...以及其他 {{ taskResult.RemovedElements.length - 5 }} 个元件</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Errors -->
|
||||
<div v-if="taskResult.Errors && taskResult.Errors.length > 0" class="error-message" style="margin-top:20px;">
|
||||
<p><i class="fas fa-exclamation-triangle"></i> 部分处理出错:</p>
|
||||
<ul>
|
||||
<li v-for="(err, idx) in taskResult.Errors.slice(0, 5)" :key="idx">{{ err }}</li>
|
||||
<li v-if="taskResult.Errors.length > 5">...以及其他 {{ taskResult.Errors.length - 5 }} 个错误</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="result-actions">
|
||||
<button class="primary-btn" @click="resetTask">
|
||||
<i class="fas fa-redo"></i> 再次处理
|
||||
</button>
|
||||
<button class="secondary-btn" @click="goBack">
|
||||
<i class="fas fa-home"></i> 返回分析中心
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ElNotification } from 'element-plus'
|
||||
import pdmsApi from '@/services/pdmsApi'
|
||||
|
||||
const emit = defineEmits(['page-change'])
|
||||
|
||||
// 状态定义
|
||||
const taskStatus = ref('idle')
|
||||
const isStarting = ref(false)
|
||||
const errorMessage = ref('')
|
||||
const taskResult = ref(null)
|
||||
|
||||
const zoneFiltersInput = ref("")
|
||||
|
||||
// 默认配置
|
||||
const DEFAULT_SIMPLIFY_CONFIG = {
|
||||
DRY_RUN: true,
|
||||
KEEP_TYPES: ["SITE", "ZONE", "STRU", "FRAME", "SHELL", "PLAT", "WALL"],
|
||||
REMOVE_TYPES: ["PIPE", "BRAN", "ELBO", "VALV", "FITT", "NOZZ", "EQUI"],
|
||||
PADDING: 0.0
|
||||
};
|
||||
|
||||
// 表单数据
|
||||
const formData = reactive({
|
||||
dryRun: DEFAULT_SIMPLIFY_CONFIG.DRY_RUN,
|
||||
keepTypes: [...DEFAULT_SIMPLIFY_CONFIG.KEEP_TYPES],
|
||||
removeTypes: [...DEFAULT_SIMPLIFY_CONFIG.REMOVE_TYPES],
|
||||
padding: DEFAULT_SIMPLIFY_CONFIG.PADDING
|
||||
})
|
||||
|
||||
const goBack = () => {
|
||||
emit('page-change', 'analysis-tools')
|
||||
}
|
||||
|
||||
const resetTask = () => {
|
||||
taskStatus.value = 'idle'
|
||||
taskResult.value = null
|
||||
errorMessage.value = ''
|
||||
}
|
||||
|
||||
const formatTime = (timeStr) => {
|
||||
if (!timeStr) return ""
|
||||
return new Date(timeStr).toLocaleString()
|
||||
}
|
||||
|
||||
const startTask = async () => {
|
||||
isStarting.value = true
|
||||
errorMessage.value = ''
|
||||
taskStatus.value = 'Processing'
|
||||
|
||||
try {
|
||||
const payload = {
|
||||
DryRun: formData.dryRun,
|
||||
ZoneFilters: zoneFiltersInput.value ? zoneFiltersInput.value.split(',').map(s => s.trim()).filter(s => s) : [],
|
||||
KeepTypes: formData.keepTypes,
|
||||
RemoveTypes: formData.removeTypes,
|
||||
BoundingShell: {
|
||||
Padding: formData.padding
|
||||
}
|
||||
}
|
||||
|
||||
const res = await pdmsApi.executeSimplify(payload)
|
||||
if (res.success && res.data && res.data.code === 0) {
|
||||
taskStatus.value = 'Completed'
|
||||
taskResult.value = res.data.data
|
||||
ElNotification({
|
||||
title: '处理完成',
|
||||
message: 'PDMS模型简化处理执行完毕。',
|
||||
type: 'success'
|
||||
})
|
||||
} else {
|
||||
taskStatus.value = 'failed'
|
||||
errorMessage.value = (res.data && res.data.message) || res.error || '执行简化失败,返回数据异常。'
|
||||
ElNotification({
|
||||
title: '处理失败',
|
||||
message: errorMessage.value,
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
taskStatus.value = 'failed'
|
||||
errorMessage.value = err.message || '网络请求错误'
|
||||
ElNotification({
|
||||
title: '处理失败',
|
||||
message: errorMessage.value,
|
||||
type: 'error'
|
||||
})
|
||||
} finally {
|
||||
isStarting.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* Copied from PdmsShrinkwrapPage styling */
|
||||
.pdms-simplify {
|
||||
background: linear-gradient(135deg, var(--color-bg-secondary) 0%, var(--color-bg-primary) 100%);
|
||||
border: 1px solid var(--color-border-primary);
|
||||
border-radius: 16px;
|
||||
padding: 24px;
|
||||
backdrop-filter: blur(20px);
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||||
animation: slideInUp 0.4s ease-out;
|
||||
color: var(--color-text-primary);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.icon-btn {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #3b82f6;
|
||||
font-size: 1.1em;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.icon-btn:hover {
|
||||
transform: translateX(-4px);
|
||||
color: #2563eb;
|
||||
}
|
||||
|
||||
.optimization-header {
|
||||
text-align: center;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.optimization-header h2 {
|
||||
color: #3b82f6;
|
||||
font-size: 1.8em;
|
||||
font-weight: 600;
|
||||
margin: 0 0 12px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.optimization-header .subtitle {
|
||||
color: var(--color-text-secondary);
|
||||
font-size: 1em;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.settings-panel {
|
||||
background: var(--color-bg-card);
|
||||
border-radius: 12px;
|
||||
padding: 32px;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
border: 1px solid var(--color-border-primary);
|
||||
}
|
||||
|
||||
.setting-group {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.setting-group > label {
|
||||
display: block;
|
||||
font-size: 1.1em;
|
||||
font-weight: 600;
|
||||
margin-bottom: 16px;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.parameters-group {
|
||||
display: flex;
|
||||
gap: 32px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.param-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.param-item label {
|
||||
font-weight: 500;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.param-item .help-text {
|
||||
font-size: 0.8em;
|
||||
color: var(--color-text-secondary);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.toggle-group {
|
||||
background: var(--color-bg-secondary);
|
||||
padding: 16px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.toggle-control {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.action-bar {
|
||||
text-align: center;
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
::v-deep(.el-checkbox-group) {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
::v-deep(.el-checkbox) {
|
||||
margin-right: 0;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.primary-btn {
|
||||
background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
padding: 14px 40px;
|
||||
font-size: 1.1em;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 4px 15px rgba(59, 130, 246, 0.4);
|
||||
transition: all 0.3s;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.primary-btn:hover:not(:disabled) {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(59, 130, 246, 0.6);
|
||||
}
|
||||
.primary-btn:disabled {
|
||||
opacity: 0.7;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.secondary-btn {
|
||||
background: var(--color-bg-secondary);
|
||||
color: var(--color-text-primary);
|
||||
border: 1px solid var(--color-border-primary);
|
||||
border-radius: 8px;
|
||||
padding: 14px 40px;
|
||||
font-size: 1.1em;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.secondary-btn:hover {
|
||||
background: var(--color-white-rgb-1);
|
||||
}
|
||||
|
||||
.error-message {
|
||||
margin-top: 20px;
|
||||
padding: 12px;
|
||||
background: rgba(255, 73, 73, 0.1);
|
||||
color: #ff4949;
|
||||
border-left: 4px solid #ff4949;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.execution-panel {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
}
|
||||
|
||||
.execution-panel h3 {
|
||||
color: #3b82f6;
|
||||
font-size: 1.6em;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.progress-container {
|
||||
max-width: 500px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
height: 8px;
|
||||
background: var(--color-border-primary);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress-fill {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #3b82f6, #60a5fa);
|
||||
width: 50%;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.progress-fill.active {
|
||||
animation: progressIndeterminate 2s infinite ease-in-out;
|
||||
transform-origin: 0% 50%;
|
||||
}
|
||||
|
||||
@keyframes progressIndeterminate {
|
||||
0% { transform: translateX(-100%) scaleX(0.2); }
|
||||
50% { transform: translateX(0) scaleX(1); }
|
||||
100% { transform: translateX(200%) scaleX(0.2); }
|
||||
}
|
||||
|
||||
.result-panel {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.success-header {
|
||||
text-align: center;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
.success-icon {
|
||||
font-size: 64px;
|
||||
color: #3b82f6;
|
||||
margin-bottom: 16px;
|
||||
text-shadow: 0 4px 15px rgba(59, 130, 246, 0.3);
|
||||
}
|
||||
.success-header h3 {
|
||||
font-size: 1.8em;
|
||||
color: var(--color-text-primary);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.metrics-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 24px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.metric-card {
|
||||
background: var(--color-bg-card);
|
||||
border: 1px solid var(--color-border-primary);
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
}
|
||||
.metric-icon {
|
||||
font-size: 32px;
|
||||
color: #3b82f6;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: rgba(59, 130, 246, 0.1);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.metric-info {
|
||||
flex: 1;
|
||||
}
|
||||
.metric-value {
|
||||
font-size: 1.8em;
|
||||
font-weight: 700;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
.metric-value.highlight {
|
||||
color: #3b82f6;
|
||||
}
|
||||
.metric-label {
|
||||
color: var(--color-text-secondary);
|
||||
font-size: 0.9em;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.details-box {
|
||||
background: var(--color-bg-card);
|
||||
border: 1px solid var(--color-border-primary);
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
.details-box h4 {
|
||||
margin: 0 0 20px 0;
|
||||
color: var(--color-text-primary);
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.result-actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
}
|
||||
</style>
|
||||
@ -129,12 +129,13 @@ const CAD_SOFTWARE_DEFINITIONS = {
|
||||
apiVersion: 'v1',
|
||||
priority: 3,
|
||||
description: '工厂设计管理',
|
||||
features: ['status', 'piping', 'shrinkwrap', 'openProject', 'openMdb', 'exportIfc'],
|
||||
features: ['status', 'piping', 'shrinkwrap', 'simplify', 'openProject', 'openMdb', 'exportIfc'],
|
||||
endpoints: {
|
||||
connect: '/test',
|
||||
status: '/api/status/model',
|
||||
piping: '/api/v1/piping',
|
||||
shrinkwrap: '/api/model/shrinkwrap',
|
||||
simplify: '/api/model/simplify',
|
||||
openProject: '/api/project/open',
|
||||
openMdb: '/api/mdb/open',
|
||||
exportIfc: '/api/export/ifc'
|
||||
|
||||
@ -15,6 +15,7 @@ export const PAGE_TYPES = {
|
||||
FILE_MANAGEMENT: 'file-management',
|
||||
REVIT_ENVELOPE_OPTIMIZATION: 'revit-envelope-optimization',
|
||||
PDMS_SHRINKWRAP: 'pdms-shrinkwrap',
|
||||
PDMS_SIMPLIFY: 'pdms-simplify',
|
||||
BATCH_JOB_MANAGER: 'batch-job-manager',
|
||||
REPORT_LOG_VIEWER: 'report-log-viewer',
|
||||
MULTI_ALGORITHM_FUSION: 'multi-algorithm-fusion'
|
||||
@ -26,5 +27,6 @@ export const CAD_REQUIRED_PAGES = [
|
||||
PAGE_TYPES.ANALYSIS_TOOLS,
|
||||
PAGE_TYPES.EXPORT_TOOLS,
|
||||
PAGE_TYPES.REVIT_ENVELOPE_OPTIMIZATION,
|
||||
PAGE_TYPES.PDMS_SHRINKWRAP
|
||||
PAGE_TYPES.PDMS_SHRINKWRAP,
|
||||
PAGE_TYPES.PDMS_SIMPLIFY
|
||||
]
|
||||
@ -53,6 +53,23 @@ class PdmsApiService {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行PDMS模型简化处理
|
||||
* @param {Object} params 简化参数
|
||||
* @returns {Promise<{success: boolean, data?: any, error?: string}>}
|
||||
*/
|
||||
async executeSimplify(params) {
|
||||
const url = buildApiUrl(this.softwareName, 'simplify')
|
||||
|
||||
return await apiClient.post(url, params, {
|
||||
timeout: 600000, // 超时600s
|
||||
operationContext: {
|
||||
software: 'PDMS',
|
||||
operation: '模型简化处理'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开 PDMS 项目
|
||||
* @param {Object} params - 项目参数 { ProjectName, UserName, Password }
|
||||
|
||||
@ -67,6 +67,7 @@ import GeometryOptimizationParams from '@/components/pages/GeometryOptimizationP
|
||||
import GeometryOptimizationResult from '@/components/pages/GeometryOptimizationResult.vue'
|
||||
import RevitEnvelopeOptimization from '@/components/pages/RevitEnvelopeOptimization.vue'
|
||||
import PdmsShrinkwrapPage from '@/components/pages/PdmsShrinkwrapPage.vue'
|
||||
import PdmsSimplifyPage from '@/components/pages/PdmsSimplifyPage.vue'
|
||||
import FileManagementPage from '@/components/pages/FileManagementPage.vue'
|
||||
import BatchJobManager from '@/components/pages/BatchJobManager.vue'
|
||||
import ReportLogViewer from '@/components/pages/ReportLogViewer.vue'
|
||||
@ -118,6 +119,7 @@ const pageComponentMap = {
|
||||
[PAGE_TYPES.FILE_MANAGEMENT]: FileManagementPage,
|
||||
[PAGE_TYPES.REVIT_ENVELOPE_OPTIMIZATION]: RevitEnvelopeOptimization,
|
||||
[PAGE_TYPES.PDMS_SHRINKWRAP]: PdmsShrinkwrapPage,
|
||||
[PAGE_TYPES.PDMS_SIMPLIFY]: PdmsSimplifyPage,
|
||||
[PAGE_TYPES.BATCH_JOB_MANAGER]: BatchJobManager,
|
||||
[PAGE_TYPES.REPORT_LOG_VIEWER]: ReportLogViewer,
|
||||
[PAGE_TYPES.MULTI_ALGORITHM_FUSION]: MultiAlgorithmFusion
|
||||
|
||||
Loading…
Reference in New Issue
Block a user