fix: 修复ResultModal数据提取时的agent调用错误

详细说明:
- 修复getProjectInfo函数中seq.agent()的类型错误
- 添加兼容性处理,支持函数和对象两种数据格式
- 解决选择订单班后点击按钮导致页面崩溃的问题
- 修改文件: WorkflowPageV4.tsx (第934行)
- 影响模块: ResultModal数据显示系统

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Yep_Q
2025-10-10 14:25:07 +08:00
parent 6f1a9a577c
commit 125a134902
40 changed files with 7501 additions and 876 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,179 @@
<title>光伏晶硅电池片印后AOI检测与分拣单元 - 能源订单班</title>
<link rel="stylesheet" href="css/styles.css">
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.min.js"></script>
<!-- Mermaid 图表库 -->
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
mermaid.initialize({
startOnLoad: true,
theme: 'dark',
themeVariables: {
primaryColor: '#f59e0b',
primaryTextColor: '#e8f5e9',
primaryBorderColor: '#d97706',
lineColor: '#f59e0b',
secondaryColor: '#d97706',
tertiaryColor: '#0a1a0f',
background: '#0d1f13',
mainBkg: '#12231e',
secondBkg: '#1a352a',
border1: '#f59e0b',
border2: '#d97706',
note: '#1a352a',
text: '#e8f5e9',
critical: '#ef4444',
done: '#4a9d5f',
activeText: '#ffffff',
activeBorder: '#f59e0b',
activeBkg: '#d97706',
labelColor: '#e8f5e9',
errorBkgColor: '#ef4444',
errorTextColor: '#ffffff',
fontSize: '16px',
fontFamily: 'Inter, sans-serif'
}
});
// 监听主题切换
const updateMermaidTheme = (isDark) => {
const theme = isDark ? {
theme: 'dark',
themeVariables: {
primaryColor: '#f59e0b',
primaryTextColor: '#e8f5e9',
primaryBorderColor: '#d97706',
lineColor: '#f59e0b',
secondaryColor: '#d97706',
tertiaryColor: '#0a1a0f',
background: '#0d1f13',
mainBkg: '#12231e',
secondBkg: '#1a352a',
border1: '#f59e0b',
border2: '#d97706',
note: '#1a352a',
text: '#e8f5e9',
critical: '#ef4444',
done: '#4a9d5f',
activeText: '#ffffff',
activeBorder: '#f59e0b',
activeBkg: '#d97706',
labelColor: '#e8f5e9',
fontSize: '16px',
fontFamily: 'Inter, sans-serif'
}
} : {
theme: 'default',
themeVariables: {
primaryColor: '#f59e0b',
primaryTextColor: '#0a1a0f',
primaryBorderColor: '#d97706',
lineColor: '#f59e0b',
secondaryColor: '#d97706',
tertiaryColor: '#f8faf7',
background: '#ffffff',
mainBkg: '#f8faf7',
secondBkg: '#ffffff',
border1: '#f59e0b',
border2: '#d97706',
note: '#ffffff',
text: '#0a1a0f',
critical: '#ef4444',
done: '#4a9d5f',
activeText: '#0a1a0f',
activeBorder: '#f59e0b',
activeBkg: '#d97706',
labelColor: '#0a1a0f',
fontSize: '16px',
fontFamily: 'Inter, sans-serif'
}
};
mermaid.initialize(theme);
// 重新渲染所有 Mermaid 图表
document.querySelectorAll('.mermaid-container').forEach(container => {
const code = container.dataset.mermaidCode;
if (code) {
mermaid.render('mermaid-' + Date.now(), code).then(result => {
container.innerHTML = result.svg;
});
}
});
};
// 导出到全局以供主题切换使用
window.updateMermaidTheme = updateMermaidTheme;
</script>
<style>
.mermaid-interactive-container {
position: relative;
width: 100%;
min-height: 500px;
background: var(--bg-card);
backdrop-filter: blur(15px);
-webkit-backdrop-filter: blur(15px);
border-radius: var(--radius-xl);
border: 2px solid var(--border-light);
box-shadow: var(--shadow-md);
padding: var(--spacing-lg);
overflow: hidden;
}
.mermaid-container {
width: 100%;
height: 100%;
overflow: auto;
position: relative;
}
.mermaid-container svg {
max-width: 100%;
height: auto;
}
.mermaid-controls {
position: absolute;
top: var(--spacing-md);
right: var(--spacing-md);
display: flex;
gap: var(--spacing-sm);
z-index: 10;
}
.mermaid-control-btn {
background: var(--bg-card);
border: 1px solid var(--border-light);
border-radius: var(--radius-md);
padding: var(--spacing-sm);
cursor: pointer;
transition: all var(--transition-base);
color: var(--text-light);
display: flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
}
.mermaid-control-btn:hover {
background: var(--hover-bg);
border-color: var(--accent-gold);
transform: translateY(-2px);
box-shadow: var(--shadow-md);
}
.mermaid-control-btn i {
width: 18px;
height: 18px;
}
.image-caption {
text-align: center;
margin-top: var(--spacing-md);
color: var(--text-gray);
font-size: var(--text-sm);
font-weight: var(--font-medium);
}
</style>
</head>
<body class="dark-theme">
<!-- 主题切换按钮 -->
@@ -208,82 +381,43 @@
<!-- 增强数据可视化展示 -->
<div class="stats-enhanced" style="margin-top: var(--spacing-xl);">
<!-- 环形进度条统计 -->
<div class="stat-circle-item scroll-reveal-scale">
<div class="circle-progress" data-progress="100">
<svg viewBox="0 0 120 120">
<circle class="circle-bg" cx="60" cy="60" r="52"></circle>
<circle class="circle-fill" cx="60" cy="60" r="52"
style="--progress: 100"></circle>
</svg>
<div class="circle-text">
<div class="circle-value">3600</div>
<div class="circle-unit">片/时</div>
</div>
<!-- 现代化图标统计 -->
<div class="stat-modern-item scroll-reveal-scale">
<div class="stat-icon-wrapper" style="background: linear-gradient(135deg, #1976d2 0%, #0d47a1 100%);">
<i data-lucide="gauge" style="width: 32px; height: 32px; color: white;"></i>
</div>
<div class="stat-label">设计产能</div>
<div class="stat-modern-value">3600<span class="stat-modern-unit">片/时</span></div>
<div class="stat-modern-label">设计产能</div>
</div>
<div class="stat-circle-item scroll-reveal-scale">
<div class="circle-progress" data-progress="99.7">
<svg viewBox="0 0 120 120">
<circle class="circle-bg" cx="60" cy="60" r="52"></circle>
<circle class="circle-fill" cx="60" cy="60" r="52"
style="--progress: 99.7"></circle>
</svg>
<div class="circle-text">
<div class="circle-value">99.7</div>
<div class="circle-unit">%</div>
</div>
<div class="stat-modern-item scroll-reveal-scale">
<div class="stat-icon-wrapper" style="background: linear-gradient(135deg, #00bcd4 0%, #0097a7 100%);">
<i data-lucide="check-circle" style="width: 32px; height: 32px; color: white;"></i>
</div>
<div class="stat-label">检出率</div>
<div class="stat-modern-value">99.7<span class="stat-modern-unit">%</span></div>
<div class="stat-modern-label">检出率</div>
</div>
<div class="stat-circle-item scroll-reveal-scale">
<div class="circle-progress" data-progress="99.5">
<svg viewBox="0 0 120 120">
<circle class="circle-bg" cx="60" cy="60" r="52"></circle>
<circle class="circle-fill" cx="60" cy="60" r="52"
style="--progress: 99.5"></circle>
</svg>
<div class="circle-text">
<div class="circle-value">0.5</div>
<div class="circle-unit">%</div>
</div>
<div class="stat-modern-item scroll-reveal-scale">
<div class="stat-icon-wrapper" style="background: linear-gradient(135deg, #4caf50 0%, #2e7d32 100%);">
<i data-lucide="alert-triangle" style="width: 32px; height: 32px; color: white;"></i>
</div>
<div class="stat-label">误检率</div>
<div class="stat-modern-value">0.5<span class="stat-modern-unit">%</span></div>
<div class="stat-modern-label">误检率</div>
</div>
<div class="stat-circle-item scroll-reveal-scale">
<div class="circle-progress" data-progress="85">
<svg viewBox="0 0 120 120">
<circle class="circle-bg" cx="60" cy="60" r="52"></circle>
<circle class="circle-fill" cx="60" cy="60" r="52"
style="--progress: 85"></circle>
</svg>
<div class="circle-text">
<div class="circle-value detection-time">300</div>
<div class="circle-unit">ms</div>
</div>
<div class="stat-modern-item scroll-reveal-scale">
<div class="stat-icon-wrapper" style="background: linear-gradient(135deg, #ff9800 0%, #f57c00 100%);">
<i data-lucide="clock" style="width: 32px; height: 32px; color: white;"></i>
</div>
<div class="stat-label">检测时间</div>
<div class="stat-modern-value">300<span class="stat-modern-unit">ms</span></div>
<div class="stat-modern-label">检测时间</div>
</div>
</div>
</div>
</div>
</section>
<!-- 视觉分隔区 1 -->
<div class="visual-divider" style="background-image: url('data/订单班文档资料/能源/notion文稿/image/输送与治具.jpg');">
<div class="divider-content">
<div class="divider-icon">
<i data-lucide="zap"></i>
</div>
<h3>智能化生产线</h3>
<p>PLC + 机器视觉 + 机器人协同工作</p>
</div>
</div>
<!-- Section 2: PLC控制逻辑与I/O配置 -->
<section class="section">
<div class="container">
@@ -303,11 +437,6 @@
<p>采用西门子TIA Portal V17开发,基于IEC 61131-3标准的SCL+梯形图混合编程。系统划分为6个核心功能模块:启动安全链、物料检测、AOI检测触发、机器人抓取交互、MES数据上传、异常处理。使用DB块结构化数据存储,通过Profinet实时通讯(500ms循环周期)实现PLC-机器人-视觉系统的无缝协同。</p>
</div>
<div class="image-container" style="margin-bottom: var(--spacing-xl);">
<img data-src="data/订单班文档资料/能源/notion文稿/image/Mermaid流程图.jpg" alt="控制流程图" loading="lazy">
<div class="image-caption">系统控制流程Mermaid图</div>
</div>
<!-- 左右交替图文布局 -->
<div class="split-layout">
<!-- 左侧图片 -->
@@ -347,11 +476,103 @@
</ul>
</div>
<!-- 右侧图片 -->
<div class="split-layout-image scroll-reveal-right">
<img data-src="data/订单班文档资料/能源/notion文稿/image/Mermaid流程图.jpg" alt="PLC控制流程" loading="lazy">
<div class="split-overlay">
<div class="split-badge">13路输出</div>
<!-- 右侧Mermaid交互图表 -->
<div class="split-layout-image scroll-reveal-right" style="position: relative; overflow: visible;">
<div class="mermaid-interactive-container" style="height: 100%; margin: 0;">
<!-- Mermaid控制按钮 -->
<div class="mermaid-controls">
<button class="mermaid-control-btn" onclick="mermaidZoomIn(this)" title="放大">
<i data-lucide="zoom-in"></i>
</button>
<button class="mermaid-control-btn" onclick="mermaidZoomOut(this)" title="缩小">
<i data-lucide="zoom-out"></i>
</button>
<button class="mermaid-control-btn" onclick="mermaidReset(this)" title="重置">
<i data-lucide="refresh-cw"></i>
</button>
<button class="mermaid-control-btn" onclick="mermaidFullscreen(this)" title="全屏">
<i data-lucide="maximize"></i>
</button>
</div>
<!-- Mermaid图表容器 -->
<div class="mermaid-container" data-mermaid-code="graph TB
Start([系统启动]) --> SafetyCheck{安全链检测<br/>FB100}
SafetyCheck -->|安全链OK| MaterialDetect[物料检测<br/>FB200<br/>I0.3-I0.5传感器]
SafetyCheck -->|安全链异常| ErrorHandle[异常处理<br/>FB600]
MaterialDetect -->|检测到物料| ConveyorControl[输送带控制<br/>Q0.0启动]
ConveyorControl --> PositionClamp[定位夹持<br/>Q0.1-Q0.2]
PositionClamp --> AOITrigger[AOI检测触发<br/>FB300<br/>Q0.3相机触发]
AOITrigger --> VisionProcess{视觉系统<br/>In-Sight D900}
VisionProcess -->|检测完成<br/>I0.6| ResultReceive[接收检测结果<br/>OK/RW/NG]
VisionProcess -->|检测异常<br/>I0.7| ErrorHandle
ResultReceive --> RobotInteract[机器人交互<br/>FB400<br/>Q0.5-Q0.7]
RobotInteract -->|等待机器人<br/>I1.0就绪| RobotGrab[机器人抓取<br/>I1.1完成]
RobotGrab --> MESUpload[MES数据上传<br/>FB500<br/>Q1.4握手]
MESUpload --> NextCycle{继续循环?}
NextCycle -->|是| MaterialDetect
NextCycle -->|否| End([流程结束])
ErrorHandle -->|报警<br/>Q1.3蜂鸣器| AlarmLight[故障指示<br/>Q1.1红灯]
AlarmLight --> ManualReset{手动复位?}
ManualReset -->|复位<br/>I1.5| SafetyCheck
ManualReset -->|急停<br/>I0.0-I0.2| EmergencyStop[紧急停止<br/>切断所有输出]
style Start fill:#4a9d5f,stroke:#2d7a3f,color:#fff
style End fill:#4a9d5f,stroke:#2d7a3f,color:#fff
style SafetyCheck fill:#f59e0b,stroke:#d97706,color:#fff
style VisionProcess fill:#f59e0b,stroke:#d97706,color:#fff
style NextCycle fill:#f59e0b,stroke:#d97706,color:#fff
style ManualReset fill:#f59e0b,stroke:#d97706,color:#fff
style ErrorHandle fill:#ef4444,stroke:#dc2626,color:#fff
style EmergencyStop fill:#ef4444,stroke:#dc2626,color:#fff
style AlarmLight fill:#ef4444,stroke:#dc2626,color:#fff">
<pre class="mermaid">
graph TB
Start([系统启动]) --> SafetyCheck{安全链检测<br/>FB100}
SafetyCheck -->|安全链OK| MaterialDetect[物料检测<br/>FB200<br/>I0.3-I0.5传感器]
SafetyCheck -->|安全链异常| ErrorHandle[异常处理<br/>FB600]
MaterialDetect -->|检测到物料| ConveyorControl[输送带控制<br/>Q0.0启动]
ConveyorControl --> PositionClamp[定位夹持<br/>Q0.1-Q0.2]
PositionClamp --> AOITrigger[AOI检测触发<br/>FB300<br/>Q0.3相机触发]
AOITrigger --> VisionProcess{视觉系统<br/>In-Sight D900}
VisionProcess -->|检测完成<br/>I0.6| ResultReceive[接收检测结果<br/>OK/RW/NG]
VisionProcess -->|检测异常<br/>I0.7| ErrorHandle
ResultReceive --> RobotInteract[机器人交互<br/>FB400<br/>Q0.5-Q0.7]
RobotInteract -->|等待机器人<br/>I1.0就绪| RobotGrab[机器人抓取<br/>I1.1完成]
RobotGrab --> MESUpload[MES数据上传<br/>FB500<br/>Q1.4握手]
MESUpload --> NextCycle{继续循环?}
NextCycle -->|是| MaterialDetect
NextCycle -->|否| End([流程结束])
ErrorHandle -->|报警<br/>Q1.3蜂鸣器| AlarmLight[故障指示<br/>Q1.1红灯]
AlarmLight --> ManualReset{手动复位?}
ManualReset -->|复位<br/>I1.5| SafetyCheck
ManualReset -->|急停<br/>I0.0-I0.2| EmergencyStop[紧急停止<br/>切断所有输出]
style Start fill:#4a9d5f,stroke:#2d7a3f,color:#fff
style End fill:#4a9d5f,stroke:#2d7a3f,color:#fff
style SafetyCheck fill:#f59e0b,stroke:#d97706,color:#fff
style VisionProcess fill:#f59e0b,stroke:#d97706,color:#fff
style NextCycle fill:#f59e0b,stroke:#d97706,color:#fff
style ManualReset fill:#f59e0b,stroke:#d97706,color:#fff
style ErrorHandle fill:#ef4444,stroke:#dc2626,color:#fff
style EmergencyStop fill:#ef4444,stroke:#dc2626,color:#fff
style AlarmLight fill:#ef4444,stroke:#dc2626,color:#fff
</pre>
</div>
<div class="split-overlay" style="pointer-events: none;">
<div class="split-badge">交互式流程图</div>
</div>
</div>
</div>
</div>
@@ -467,20 +688,12 @@
</div>
</section>
<!-- 视觉分隔区 2 -->
<div class="visual-divider" style="background-image: url('data/订单班文档资料/能源/notion文稿/image/工业机器人图片.jpg');">
<div class="divider-content">
<div class="divider-icon">
<i data-lucide="bot"></i>
</div>
<h3>精密机器人分拣</h3>
<p>±0.02mm定位精度 · ≤0.8秒单次节拍</p>
</div>
</div>
<!-- Section 3: 机器人编程与分拣逻辑 -->
<section class="section">
<div class="container">
<section class="section" style="background-image: url('data/订单班文档资料/能源/notion文稿/image/工业机器人图片.jpg'); background-size: cover; background-position: center; background-attachment: fixed; position: relative;">
<!-- 半透明遮罩层 -->
<div style="position: absolute; inset: 0; background: linear-gradient(135deg, rgba(10, 26, 15, 0.92) 0%, rgba(13, 31, 19, 0.88) 100%); backdrop-filter: blur(3px);"></div>
<div class="container" style="position: relative; z-index: 1;">
<div class="section-header">
<img src="agent-avatars/机器人调试工程师.jpg" alt="机器人调试工程师" class="agent-avatar">
<div class="agent-info">
@@ -497,92 +710,67 @@
<p>基于ABB RobotStudio离线编程,使用RAPID语言开发拾取-判断-分拣主程序。系统通过真空吸盘拾取电池片(负压-60kPa),根据PLC传输的检测结果(OK/RW/NG)执行对应分拣路径。采用多点轨迹规划优化节拍(单次循环≤0.8秒),使用WorldZone碰撞检测保障安全,通过TCP精度补偿实现±0.02mm重复定位精度。</p>
</div>
<div class="image-container" style="margin-bottom: var(--spacing-xl);">
<img data-src="data/订单班文档资料/能源/notion文稿/image/光伏面板生成画面.jpg" alt="光伏面板分拣场景" loading="lazy">
<div class="image-caption">机器人分拣路径三维仿真</div>
</div>
<!-- Timeline时间轴布局 -->
<div class="timeline-container">
<h3 class="timeline-title"><i data-lucide="git-branch"></i> 分拣逻辑流程</h3>
<div class="timeline">
<!-- 机器人工作流程可视化 -->
<div class="robot-workflow-visual" style="margin-bottom: var(--spacing-2xl);">
<div style="display: grid; grid-template-columns: repeat(6, 1fr); gap: var(--spacing-md); margin-bottom: var(--spacing-xl);">
<!-- 步骤1 -->
<div class="timeline-item scroll-reveal">
<div class="timeline-marker">
<i data-lucide="play"></i>
</div>
<div class="timeline-content">
<div class="timeline-step">步骤 1</div>
<h4>等待PLC就绪信号</h4>
<p>检测DI1=1,确认系统准备就绪</p>
<div class="timeline-badge">初始化</div>
<div class="workflow-step">
<div class="workflow-icon" style="background: linear-gradient(135deg, #4a9d5f, #2d7a3f);">
<i data-lucide="play" style="width: 32px; height: 32px;"></i>
</div>
<div class="workflow-number">01</div>
<h4>等待就绪</h4>
<p>DI1信号检测</p>
</div>
<!-- 步骤2 -->
<div class="timeline-item scroll-reveal">
<div class="timeline-marker">
<i data-lucide="hand"></i>
</div>
<div class="timeline-content">
<div class="timeline-step">步骤 2</div>
<h4>移动至拾取点</h4>
<p>机器人移动→开启真空→检测吸附成功</p>
<div class="timeline-badge">拾取</div>
<div class="workflow-step">
<div class="workflow-icon" style="background: linear-gradient(135deg, #f59e0b, #d97706);">
<i data-lucide="hand" style="width: 32px; height: 32px;"></i>
</div>
<div class="workflow-number">02</div>
<h4>移动拾取</h4>
<p>300mm/s速度</p>
</div>
<!-- 步骤3 -->
<div class="timeline-item scroll-reveal">
<div class="timeline-marker">
<i data-lucide="search"></i>
</div>
<div class="timeline-content">
<div class="timeline-step">步骤 3</div>
<h4>读取检测结果</h4>
<p>从PLC读取DI2-DI3编码,获取质量判定</p>
<div class="timeline-badge">判断</div>
<div class="workflow-step">
<div class="workflow-icon" style="background: linear-gradient(135deg, #3b82f6, #2563eb);">
<i data-lucide="search" style="width: 32px; height: 32px;"></i>
</div>
<div class="workflow-number">03</div>
<h4>读取结果</h4>
<p>DI2-DI3编码</p>
</div>
<!-- 步骤4 -->
<div class="timeline-item scroll-reveal">
<div class="timeline-marker">
<i data-lucide="git-branch"></i>
</div>
<div class="timeline-content">
<div class="timeline-step">步骤 4</div>
<h4>分支判断路径</h4>
<p>OK→托盘1 | RW→托盘2 | NG→废料箱</p>
<div class="timeline-badge">分拣</div>
<div class="workflow-step">
<div class="workflow-icon" style="background: linear-gradient(135deg, #8b5cf6, #7c3aed);">
<i data-lucide="git-branch" style="width: 32px; height: 32px;"></i>
</div>
<div class="workflow-number">04</div>
<h4>路径判断</h4>
<p>OK/RW/NG分支</p>
</div>
<!-- 步骤5 -->
<div class="timeline-item scroll-reveal">
<div class="timeline-marker">
<i data-lucide="box"></i>
</div>
<div class="timeline-content">
<div class="timeline-step">步骤 5</div>
<h4>到达目标位置</h4>
<p>精确定位→关闭真空→等待释放确认</p>
<div class="timeline-badge">放置</div>
<div class="workflow-step">
<div class="workflow-icon" style="background: linear-gradient(135deg, #ec4899, #db2777);">
<i data-lucide="box" style="width: 32px; height: 32px;"></i>
</div>
<div class="workflow-number">05</div>
<h4>精确放置</h4>
<p>±0.02mm精度</p>
</div>
<!-- 步骤6 -->
<div class="timeline-item scroll-reveal">
<div class="timeline-marker">
<i data-lucide="rotate-ccw"></i>
</div>
<div class="timeline-content">
<div class="timeline-step">步骤 6</div>
<h4>返回原点并循环</h4>
<p>发送完成信号DO1=1,准备下一次循环</p>
<div class="timeline-badge">完成</div>
<div class="workflow-step">
<div class="workflow-icon" style="background: linear-gradient(135deg, #10b981, #059669);">
<i data-lucide="rotate-ccw" style="width: 32px; height: 32px;"></i>
</div>
<div class="workflow-number">06</div>
<h4>返回循环</h4>
<p>DO1反馈信号</p>
</div>
</div>
</div>
@@ -719,17 +907,6 @@
</div>
</section>
<!-- 视觉分隔区 3 -->
<div class="visual-divider" style="background-image: url('data/订单班文档资料/能源/notion文稿/image/光伏面板室外场景图片.jpg');">
<div class="divider-content">
<div class="divider-icon">
<i data-lucide="camera"></i>
</div>
<h3>深度学习视觉检测</h3>
<p>99.7%检出率 · 0.05mm缺陷可检出</p>
</div>
</div>
<!-- Section 4: 视觉标定与性能验证 -->
<section class="section">
<div class="container">
@@ -926,8 +1103,9 @@
<div class="grid grid-3">
<div class="card">
<div class="card-header" style="order: 1;">
<h3 class="card-title">⚡ 核心技术</h3>
<div class="card-header" style="order: 1; background-image: url('https://images.unsplash.com/photo-1581092160562-40aa08e78837?w=800&q=80'); background-size: cover; background-position: center; position: relative; min-height: 200px; display: flex; align-items: center; justify-content: center;">
<div style="position: absolute; inset: 0; background: linear-gradient(135deg, rgba(13, 71, 161, 0.92) 0%, rgba(25, 118, 210, 0.88) 100%); z-index: 0;"></div>
<h3 class="card-title" style="position: relative; z-index: 1; color: white; text-shadow: 0 2px 8px rgba(0,0,0,0.3);">⚡ 核心技术</h3>
</div>
<div class="card-body" style="order: 2;">
<ul class="feature-list">
@@ -944,8 +1122,9 @@
</div>
<div class="card">
<div class="card-header" style="order: 1;">
<h3 class="card-title">📊 性能指标</h3>
<div class="card-header" style="order: 1; background-image: url('https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=800&q=80'); background-size: cover; background-position: center; position: relative; min-height: 200px; display: flex; align-items: center; justify-content: center;">
<div style="position: absolute; inset: 0; background: linear-gradient(135deg, rgba(0, 188, 212, 0.92) 0%, rgba(0, 151, 167, 0.88) 100%); z-index: 0;"></div>
<h3 class="card-title" style="position: relative; z-index: 1; color: white; text-shadow: 0 2px 8px rgba(0,0,0,0.3);">📊 性能指标</h3>
</div>
<div class="card-body" style="order: 2;">
<ul class="feature-list">
@@ -962,8 +1141,9 @@
</div>
<div class="card">
<div class="card-header" style="order: 1;">
<h3 class="card-title">🎯 应用成果</h3>
<div class="card-header" style="order: 1; background-image: url('https://images.unsplash.com/photo-1504384308090-c894fdcc538d?w=800&q=80'); background-size: cover; background-position: center; position: relative; min-height: 200px; display: flex; align-items: center; justify-content: center;">
<div style="position: absolute; inset: 0; background: linear-gradient(135deg, rgba(76, 175, 80, 0.92) 0%, rgba(46, 125, 50, 0.88) 100%); z-index: 0;"></div>
<h3 class="card-title" style="position: relative; z-index: 1; color: white; text-shadow: 0 2px 8px rgba(0,0,0,0.3);">🎯 应用成果</h3>
</div>
<div class="card-body" style="order: 2;">
<ul class="feature-list">
@@ -988,5 +1168,70 @@
</section>
<script src="js/main.js"></script>
<!-- Mermaid交互控制脚本 -->
<script>
// Mermaid图表缩放控制
let mermaidScales = new Map();
function mermaidZoomIn(btn) {
const container = btn.closest('.mermaid-interactive-container');
const mermaidDiv = container.querySelector('.mermaid-container');
const currentScale = mermaidScales.get(mermaidDiv) || 1;
const newScale = Math.min(currentScale + 0.2, 3);
mermaidScales.set(mermaidDiv, newScale);
mermaidDiv.style.transform = `scale(${newScale})`;
mermaidDiv.style.transformOrigin = 'top left';
}
function mermaidZoomOut(btn) {
const container = btn.closest('.mermaid-interactive-container');
const mermaidDiv = container.querySelector('.mermaid-container');
const currentScale = mermaidScales.get(mermaidDiv) || 1;
const newScale = Math.max(currentScale - 0.2, 0.5);
mermaidScales.set(mermaidDiv, newScale);
mermaidDiv.style.transform = `scale(${newScale})`;
mermaidDiv.style.transformOrigin = 'top left';
}
function mermaidReset(btn) {
const container = btn.closest('.mermaid-interactive-container');
const mermaidDiv = container.querySelector('.mermaid-container');
mermaidScales.set(mermaidDiv, 1);
mermaidDiv.style.transform = 'scale(1)';
mermaidDiv.scrollTop = 0;
mermaidDiv.scrollLeft = 0;
}
function mermaidFullscreen(btn) {
const container = btn.closest('.mermaid-interactive-container');
if (!document.fullscreenElement) {
container.requestFullscreen().catch(err => {
console.log(`Error attempting to enable fullscreen: ${err.message}`);
});
btn.querySelector('i').setAttribute('data-lucide', 'minimize');
lucide.createIcons();
} else {
document.exitFullscreen();
btn.querySelector('i').setAttribute('data-lucide', 'maximize');
lucide.createIcons();
}
}
// 监听全屏变化事件
document.addEventListener('fullscreenchange', function() {
document.querySelectorAll('.mermaid-control-btn').forEach(btn => {
const icon = btn.querySelector('i');
if (btn.getAttribute('title') === '全屏') {
if (document.fullscreenElement) {
icon.setAttribute('data-lucide', 'minimize');
} else {
icon.setAttribute('data-lucide', 'maximize');
}
}
});
lucide.createIcons();
});
</script>
</body>
</html>

View File

@@ -279,14 +279,21 @@ function initThemeToggle() {
if (themeToggleBtn) {
themeToggleBtn.addEventListener('click', () => {
document.body.classList.toggle('dark-theme');
const isDark = document.body.classList.contains('dark-theme');
// 保存用户偏好
if (document.body.classList.contains('dark-theme')) {
if (isDark) {
localStorage.setItem('theme', 'dark');
} else {
localStorage.setItem('theme', 'light');
}
// 更新Mermaid图表主题
if (typeof window.updateMermaidTheme === 'function') {
window.updateMermaidTheme(isDark);
}
// 重新初始化图标以确保正确显示
if (typeof lucide !== 'undefined') {
lucide.createIcons();