123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988 |
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>数控车床振幅监测系统</title>
- <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
- <style>
- :root {
- --primary-color: #0066cc;
- --secondary-color: #00b6c1;
- --warning-color: #ff9800;
- --danger-color: #f44336;
- --success-color: #4caf50;
- --dark-bg: #1a2a3a;
- --card-bg: rgba(255, 255, 255, 0.1);
- }
-
- * {
- margin: 0;
- padding: 0;
- box-sizing: border-box;
- font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
- }
-
- body {
- background: linear-gradient(135deg, var(--dark-bg) 0%, #0d1721 100%);
- color: #fff;
- min-height: 100vh;
- padding: 20px;
- }
-
- .container {
- max-width: 1800px;
- margin: 0 auto;
- }
-
- header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 20px 0;
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
- margin-bottom: 30px;
- }
-
- .logo {
- display: flex;
- align-items: center;
- gap: 15px;
- }
-
- .logo h1 {
- font-size: 28px;
- font-weight: 700;
- background: linear-gradient(90deg, var(--secondary-color), #6ec1e4);
- -webkit-background-clip: text;
- background-clip: text;
- -webkit-text-fill-color: transparent;
- }
-
- .logo .tagline {
- font-size: 18px;
- color: #aaa;
- margin-top: 5px;
- }
-
- .system-stats {
- display: flex;
- gap: 25px;
- }
-
- .stat-card {
- background: var(--card-bg);
- border-radius: 12px;
- padding: 15px 25px;
- min-width: 200px;
- text-align: center;
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
- border: 1px solid rgba(255, 255, 255, 0.05);
- }
-
- .stat-card h3 {
- font-size: 14px;
- font-weight: 500;
- margin-bottom: 10px;
- color: #ccc;
- }
-
- .stat-card .value {
- font-size: 26px;
- font-weight: 700;
- margin-bottom: 5px;
- }
-
- .stat-card .highlight {
- color: var(--secondary-color);
- font-weight: 700;
- }
-
- .alert-indicator {
- position: absolute;
- top: 10px;
- right: 10px;
- width: 12px;
- height: 12px;
- border-radius: 50%;
- background-color: var(--success-color);
- box-shadow: 0 0 10px var(--success-color);
- transition: all 0.3s ease;
- }
-
- .alert-indicator.warning {
- background-color: var(--warning-color);
- box-shadow: 0 0 10px var(--warning-color);
- }
-
- .alert-indicator.danger {
- background-color: var(--danger-color);
- box-shadow: 0 0 10px var(--danger-color);
- animation: pulse 1.5s infinite;
- }
-
- @keyframes pulse {
- 0% { opacity: 1; }
- 50% { opacity: 0.4; }
- 100% { opacity: 1; }
- }
-
- .dashboard {
- display: grid;
- grid-template-columns: 1fr 1fr;
- gap: 25px;
- margin-bottom: 30px;
- }
-
- .card {
- background: var(--card-bg);
- border-radius: 15px;
- padding: 25px;
- box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
- border: 1px solid rgba(255, 255, 255, 0.05);
- position: relative;
- overflow: hidden;
- }
-
- .card-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 20px;
- }
-
- .card-title {
- font-size: 20px;
- font-weight: 600;
- color: #fff;
- }
-
- .chart-container {
- height: 400px;
- width: 100%;
- }
-
- .dashboard-row {
- display: grid;
- grid-template-columns: 1fr 1fr;
- gap: 25px;
- margin-bottom: 30px;
- }
-
- .cost-comparison {
- display: grid;
- grid-template-columns: 1fr 1fr;
- gap: 20px;
- margin-top: 20px;
- }
-
- .cost-card {
- background: rgba(0, 0, 0, 0.3);
- border-radius: 10px;
- padding: 15px;
- text-align: center;
- }
-
- .cost-card h4 {
- font-size: 16px;
- margin-bottom: 10px;
- color: #ccc;
- }
-
- .cost-value {
- font-size: 24px;
- font-weight: 700;
- }
-
- .import-value {
- color: #ff6b6b;
- }
-
- .our-value {
- color: var(--secondary-color);
- }
-
- .key-metrics {
- display: grid;
- grid-template-columns: repeat(3, 1fr);
- gap: 15px;
- margin-top: 20px;
- }
-
- .metric-card {
- background: rgba(0, 0, 0, 0.3);
- border-radius: 10px;
- padding: 15px;
- text-align: center;
- }
-
- .metric-card h4 {
- font-size: 14px;
- margin-bottom: 10px;
- color: #ccc;
- }
-
- .metric-value {
- font-size: 22px;
- font-weight: 700;
- }
-
- .controls {
- display: flex;
- gap: 15px;
- margin-top: 20px;
- }
-
- .btn {
- background: var(--primary-color);
- color: white;
- border: none;
- padding: 10px 20px;
- border-radius: 6px;
- cursor: pointer;
- font-size: 16px;
- font-weight: 500;
- transition: all 0.3s ease;
- flex: 1;
- }
-
- .btn:hover {
- background: #004d99;
- transform: translateY(-2px);
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
- }
-
- .btn.secondary {
- background: rgba(255, 255, 255, 0.1);
- }
-
- .btn.secondary:hover {
- background: rgba(255, 255, 255, 0.2);
- }
-
- .btn.warning {
- background: var(--warning-color);
- }
-
- .btn.warning:hover {
- background: #e68a00;
- }
-
- .status-bar {
- display: flex;
- align-items: center;
- gap: 15px;
- margin-top: 20px;
- padding: 10px 15px;
- background: rgba(0, 0, 0, 0.3);
- border-radius: 8px;
- }
-
- .status-indicator {
- width: 12px;
- height: 12px;
- border-radius: 50%;
- background: var(--success-color);
- }
-
- .status-text {
- font-size: 16px;
- }
-
- .status-indicator.warning {
- background: var(--warning-color);
- }
-
- .status-indicator.danger {
- background: var(--danger-color);
- }
-
- footer {
- text-align: center;
- padding: 30px 0;
- color: #777;
- font-size: 14px;
- border-top: 1px solid rgba(255, 255, 255, 0.1);
- margin-top: 40px;
- }
-
- .alert-notification {
- position: fixed;
- top: 20px;
- right: 20px;
- background: var(--danger-color);
- color: white;
- padding: 20px 30px;
- border-radius: 10px;
- box-shadow: 0 10px 30px rgba(244, 67, 54, 0.3);
- animation: slideIn 0.5s ease;
- z-index: 1000;
- display: flex;
- align-items: center;
- gap: 15px;
- max-width: 400px;
- }
-
- @keyframes slideIn {
- from { transform: translateX(100%); opacity: 0; }
- to { transform: translateX(0); opacity: 1; }
- }
-
- .alert-icon {
- font-size: 28px;
- }
-
- .alert-content h3 {
- font-size: 18px;
- margin-bottom: 5px;
- }
-
- .alert-content p {
- font-size: 14px;
- opacity: 0.9;
- }
-
- .close-alert {
- background: none;
- border: none;
- color: white;
- font-size: 20px;
- cursor: pointer;
- margin-left: 10px;
- }
- </style>
- </head>
- <body>
- <div class="container">
- <header>
- <div class="logo">
- <div>
- <h1>数控车床振幅监测系统</h1>
- <div class="tagline">工业监测领域的"歼-20"方案</div>
- </div>
- </div>
-
- <div class="system-stats">
- <div class="stat-card">
- <h3>当前状态</h3>
- <div class="value" id="system-status">运行中</div>
- <div class="highlight" id="uptime">正常运行: 32小时</div>
- </div>
-
- <div class="stat-card">
- <h3>检测响应速度</h3>
- <div class="value"><span id="response-time">8</span>ms</div>
- <div class="highlight">↑德国方案150倍</div>
- </div>
-
- <div class="stat-card">
- <h3>误报率</h3>
- <div class="value"><span id="error-rate">0.8</span>%</div>
- <div class="highlight">↓德国方案86%</div>
- </div>
- </div>
- </header>
-
- <div class="dashboard">
- <div class="card">
- <div class="card-header">
- <h2 class="card-title">实时振动波形</h2>
- <div class="alert-indicator" id="vibration-alert"></div>
- </div>
- <div class="chart-container" id="vibration-chart"></div>
- <div class="status-bar">
- <div class="status-indicator" id="status-indicator"></div>
- <div class="status-text" id="status-text">系统运行正常</div>
- </div>
- </div>
-
- <div class="card">
- <div class="card-header">
- <h2 class="card-title">成本控制与性能对比</h2>
- </div>
- <div class="chart-container" id="cost-chart"></div>
-
- <div class="cost-comparison">
- <div class="cost-card">
- <h4>单通道成本 (德国方案)</h4>
- <div class="cost-value import-value">¥10,284</div>
- </div>
- <div class="cost-card">
- <h4>单通道成本 (本系统)</h4>
- <div class="cost-value our-value">¥1,920</div>
- </div>
- </div>
-
- <div class="key-metrics">
- <div class="metric-card">
- <h4>成本节约</h4>
- <div class="metric-value" style="color: var(--secondary-color);">92%</div>
- </div>
- <div class="metric-card">
- <h4>响应提升</h4>
- <div class="metric-value" style="color: var(--secondary-color);">150倍</div>
- </div>
- <div class="metric-card">
- <h4>误报率降低</h4>
- <div class="metric-value" style="color: var(--secondary-color);">86%</div>
- </div>
- </div>
- </div>
- </div>
-
- <div class="dashboard-row">
- <div class="card">
- <div class="card-header">
- <h2 class="card-title">刀具寿命预测</h2>
- <div class="alert-indicator" id="tool-alert"></div>
- </div>
- <div class="chart-container" id="tool-chart"></div>
- <div class="controls">
- <button class="btn">导出报告</button>
- <button class="btn secondary">维护计划</button>
- <button class="btn warning">更换刀具</button>
- </div>
- </div>
-
- <div class="card">
- <div class="card-header">
- <h2 class="card-title">异常事件分析</h2>
- </div>
- <div class="chart-container" id="event-chart"></div>
- </div>
- </div>
-
- <footer>
- <p>国产化高精度振动监测系统 © 2025 | 技术指标:微秒级采样(100kHz) | AI动态阈值算法(误报率0.8%) | 响应延迟<10ms</p>
- </footer>
- </div>
-
- <div class="alert-notification" id="alert-notification" style="display: none;">
- <div class="alert-icon">⚠️</div>
- <div class="alert-content">
- <h3>振动异常报警!</h3>
- <p>检测到异常振动幅度超过阈值,请立即检查设备!</p>
- </div>
- <button class="close-alert" onclick="closeAlert()">×</button>
- </div>
- <script>
- // 初始化图表
- const vibrationChart = echarts.init(document.getElementById('vibration-chart'));
- const costChart = echarts.init(document.getElementById('cost-chart'));
- const toolChart = echarts.init(document.getElementById('tool-chart'));
- const eventChart = echarts.init(document.getElementById('event-chart'));
-
- // 振动图表配置
- const vibrationOption = {
- backgroundColor: 'transparent',
- grid: {
- top: 30,
- right: 30,
- bottom: 40,
- left: 50
- },
- tooltip: {
- trigger: 'axis'
- },
- legend: {
- data: ['振动幅度', '动态阈值'],
- textStyle: {
- color: '#ccc'
- },
- top: 0
- },
- xAxis: {
- type: 'category',
- data: [],
- axisLine: {
- lineStyle: {
- color: '#666'
- }
- },
- axisLabel: {
- color: '#999'
- }
- },
- yAxis: {
- type: 'value',
- name: '振幅 (g)',
- nameTextStyle: {
- color: '#999'
- },
- axisLine: {
- lineStyle: {
- color: '#666'
- }
- },
- axisLabel: {
- color: '#999'
- },
- splitLine: {
- lineStyle: {
- color: 'rgba(255, 255, 255, 0.05)'
- }
- }
- },
- series: [
- {
- name: '振动幅度',
- type: 'line',
- smooth: true,
- data: [],
- lineStyle: {
- width: 3,
- color: '#00b6c1'
- },
- itemStyle: {
- color: '#00b6c1'
- },
- areaStyle: {
- color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
- { offset: 0, color: 'rgba(0, 182, 193, 0.7)' },
- { offset: 1, color: 'rgba(0, 182, 193, 0.1)' }
- ])
- },
- symbol: 'none'
- },
- {
- name: '动态阈值',
- type: 'line',
- smooth: true,
- data: [],
- lineStyle: {
- width: 2,
- color: '#ff9800',
- type: 'dashed'
- },
- itemStyle: {
- color: '#ff9800'
- },
- symbol: 'none'
- }
- ],
- animation: false
- };
-
- // 成本对比图表配置
- const costOption = {
- backgroundColor: 'transparent',
- tooltip: {
- trigger: 'axis',
- axisPointer: {
- type: 'shadow'
- }
- },
- legend: {
- data: ['德国方案', '本系统'],
- textStyle: {
- color: '#ccc'
- },
- top: 0
- },
- grid: {
- top: 40,
- right: 30,
- bottom: 40,
- left: 50
- },
- xAxis: {
- type: 'category',
- data: ['单通道成本', '误报率', '响应延迟'],
- axisLine: {
- lineStyle: {
- color: '#666'
- }
- },
- axisLabel: {
- color: '#999',
- interval: 0
- }
- },
- yAxis: [
- {
- type: 'value',
- name: '成本 (元)',
- min: 0,
- max: 12000,
- axisLine: {
- lineStyle: {
- color: '#666'
- }
- },
- axisLabel: {
- color: '#999',
- formatter: '{value}'
- },
- splitLine: {
- lineStyle: {
- color: 'rgba(255, 255, 255, 0.05)'
- }
- }
- },
- {
- type: 'value',
- name: '比率/毫秒',
- min: 0,
- max: 6,
- axisLine: {
- lineStyle: {
- color: '#666'
- }
- },
- axisLabel: {
- color: '#999',
- formatter: function(value) {
- if (value < 1) return value * 100 + '%';
- return value + 'ms';
- }
- }
- }
- ],
- series: [
- {
- name: '德国方案',
- type: 'bar',
- barWidth: 30,
- itemStyle: {
- color: '#ff6b6b'
- },
- data: [10284, 0.058, 1.2]
- },
- {
- name: '本系统',
- type: 'bar',
- barWidth: 30,
- itemStyle: {
- color: '#00b6c1'
- },
- data: [1920, 0.008, 0.008]
- }
- ]
- };
-
- // 刀具寿命图表配置
- const toolOption = {
- backgroundColor: 'transparent',
- tooltip: {
- trigger: 'axis'
- },
- legend: {
- data: ['刀具磨损度'],
- textStyle: {
- color: '#ccc'
- },
- top: 0
- },
- grid: {
- top: 30,
- right: 30,
- bottom: 40,
- left: 50
- },
- xAxis: {
- type: 'category',
- data: [],
- axisLine: {
- lineStyle: {
- color: '#666'
- }
- },
- axisLabel: {
- color: '#999'
- }
- },
- yAxis: {
- type: 'value',
- name: '磨损度 (%)',
- min: 0,
- max: 100,
- axisLine: {
- lineStyle: {
- color: '#666'
- }
- },
- axisLabel: {
- color: '#999'
- },
- splitLine: {
- lineStyle: {
- color: 'rgba(255, 255, 255, 0.05)'
- }
- }
- },
- series: [
- {
- name: '刀具磨损度',
- type: 'line',
- data: [],
- smooth: true,
- lineStyle: {
- width: 3,
- color: '#ff9800'
- },
- itemStyle: {
- color: '#ff9800'
- },
- areaStyle: {
- color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
- { offset: 0, color: 'rgba(255, 152, 0, 0.5)' },
- { offset: 1, color: 'rgba(255, 152, 0, 0.1)' }
- ])
- },
- markLine: {
- silent: true,
- lineStyle: {
- color: '#f44336',
- width: 2,
- type: 'dashed'
- },
- data: [
- {
- yAxis: 85,
- label: {
- formatter: '更换阈值',
- position: 'start'
- }
- }
- ]
- }
- }
- ]
- };
-
- // 异常事件图表配置
- const eventOption = {
- backgroundColor: 'transparent',
- tooltip: {
- trigger: 'axis'
- },
- legend: {
- data: ['异常事件'],
- textStyle: {
- color: '#ccc'
- },
- top: 0
- },
- grid: {
- top: 30,
- right: 30,
- bottom: 40,
- left: 50
- },
- xAxis: {
- type: 'category',
- data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
- axisLine: {
- lineStyle: {
- color: '#666'
- }
- },
- axisLabel: {
- color: '#999'
- }
- },
- yAxis: {
- type: 'value',
- name: '事件次数',
- axisLine: {
- lineStyle: {
- color: '#666'
- }
- },
- axisLabel: {
- color: '#999'
- },
- splitLine: {
- lineStyle: {
- color: 'rgba(255, 255, 255, 0.05)'
- }
- }
- },
- series: [
- {
- name: '异常事件',
- type: 'bar',
- barWidth: 30,
- itemStyle: {
- color: '#00b6c1'
- },
- data: [2, 0, 1, 3, 1, 0, 0]
- }
- ]
- };
-
- // 应用图表配置
- vibrationChart.setOption(vibrationOption);
- costChart.setOption(costOption);
- toolChart.setOption(toolOption);
- eventChart.setOption(eventOption);
-
- // 窗口大小调整时重新渲染图表
- window.addEventListener('resize', function() {
- vibrationChart.resize();
- costChart.resize();
- toolChart.resize();
- eventChart.resize();
- });
-
- // 模拟实时数据
- let timeCounter = 0;
- let vibrationData = [];
- let thresholdData = [];
- let toolWearData = [];
- let isAlertActive = false;
-
- // 动态阈值算法
- function calculateDynamicThreshold(data) {
- // 简单实现:基于历史数据的均值和标准差
- if (data.length < 20) return 0.8;
-
- const recentData = data.slice(-20);
- const sum = recentData.reduce((a, b) => a + b, 0);
- const mean = sum / recentData.length;
-
- const squareDiffs = recentData.map(value => Math.pow(value - mean, 2));
- const variance = squareDiffs.reduce((a, b) => a + b, 0) / recentData.length;
- const stdDev = Math.sqrt(variance);
-
- return mean + 4 * stdDev; // 4倍标准差作为阈值
- }
-
- // 生成模拟数据
- function generateData() {
- timeCounter++;
-
- // 生成振动数据(模拟微秒级采样)
- const baseValue = Math.sin(timeCounter * 0.2) * 0.8;
- const noise = (Math.random() - 0.5) * 0.3;
- let amplitude = baseValue + noise;
-
- // 0.1%概率产生异常
- if (Math.random() < 0.001) {
- amplitude = 2.5 + Math.random() * 1.0; // 异常值范围2.5-3.5
- }
-
- vibrationData.push(amplitude);
- if (vibrationData.length > 200) vibrationData.shift();
-
- // 计算动态阈值
- const threshold = calculateDynamicThreshold(vibrationData);
- thresholdData.push(threshold);
- if (thresholdData.length > 200) thresholdData.shift();
-
- // 更新刀具磨损数据
- const wear = Math.min(85, 20 + timeCounter * 0.05);
- toolWearData.push(wear);
- if (toolWearData.length > 20) toolWearData.shift();
-
- // 更新图表
- const xAxisData = Array.from({length: vibrationData.length}, (_, i) => i);
- vibrationChart.setOption({
- xAxis: {
- data: xAxisData
- },
- series: [
- { data: vibrationData },
- { data: thresholdData }
- ]
- });
-
- // 更新刀具寿命图表
- const toolXAxisData = Array.from({length: toolWearData.length}, (_, i) => i);
- toolChart.setOption({
- xAxis: {
- data: toolXAxisData
- },
- series: [
- { data: toolWearData }
- ]
- });
-
- // 检查是否需要报警
- const statusIndicator = document.getElementById('status-indicator');
- const statusText = document.getElementById('status-text');
- const alertIndicator = document.getElementById('vibration-alert');
-
- if (amplitude > threshold) {
- statusIndicator.className = 'status-indicator danger';
- statusText.textContent = '检测到异常振动!';
- alertIndicator.className = 'alert-indicator danger';
-
- if (!isAlertActive) {
- showAlert();
- isAlertActive = true;
- }
- } else if (amplitude > threshold * 0.8)
- {
- statusIndicator.className = 'status-indicator'
- statusIndicator.className = 'status-indicator warning';
- statusText.textContent = '振动接近阈值,请注意!';
- alertIndicator.className = 'alert-indicator warning';
- isAlertActive = false;
- }
- else
- {
- statusIndicator.className = 'status-indicator';
- statusText.textContent = '系统运行正常';
- alertIndicator.className = 'alert-indicator';
- isAlertActive = false;
- }
- }
-
- // 显示报警通知
- function showAlert() {
- const alertNotification = document.getElementById('alert-notification');
- alertNotification.style.display = 'flex';
-
- // 播放警报声
- const audioContext = new (window.AudioContext || window.webkitAudioContext)();
- const oscillator = audioContext.createOscillator();
- const gainNode = audioContext.createGain();
-
- oscillator.connect(gainNode);
- gainNode.connect(audioContext.destination);
-
- oscillator.type = 'sine';
- oscillator.frequency.setValueAtTime(440, audioContext.currentTime);
- oscillator.frequency.setValueAtTime(880, audioContext.currentTime + 0.1);
-
- gainNode.gain.setValueAtTime(0.3, audioContext.currentTime);
-
- oscillator.start();
- oscillator.stop(audioContext.currentTime + 0.5);
-
- // 背景闪烁效果
- let flashCount = 0;
- const flashInterval = setInterval(() => {
- document.body.style.backgroundColor = flashCount % 2 === 0 ? 'rgba(244, 67, 54, 0.2)' : '';
- flashCount++;
-
- if (flashCount > 10) {
- clearInterval(flashInterval);
- document.body.style.backgroundColor = '';
- }
- }, 200);
- }
-
- // 关闭报警通知
- function closeAlert() {
- document.getElementById('alert-notification').style.display = 'none';
- }
-
- // 每秒生成4次数据(模拟100kHz采样率)
- setInterval(generateData, 250);
-
- // 更新运行时间
- let uptime = 0;
- setInterval(() => {
- uptime++;
- const hours = Math.floor(uptime / 3600);
- const minutes = Math.floor((uptime % 3600) / 60);
- const seconds = uptime % 60;
- document.getElementById('uptime').textContent =
- `正常运行: ${hours}小时${minutes}分${seconds}秒`;
- }, 1000);
- </script>
- </body>
- </html>
|