19、云端工业物联网生态组件 - 工厂能效与预测维护 - /数据与物联网组件/cloud-iiot-factory-analysis
76个工业组件库示例汇总
云端工业物联网生态组件 - 工厂能效与预测维护 (模拟)
概述
这是一个交互式的 Web 组件,旨在模拟一个云端工业物联网 (IIoT) 平台的核心界面,专注于工厂层面的能效分析和基于传感器数据的预测性维护概念。用户可以监控模拟的设备状态,查看全局或单个设备的能耗指标,并观察预测性维护警报的生成。
请注意:这是一个高度简化的前端模拟演示,不连接任何真实的云平台或物理设备。所有数据、状态变化、警报和预测都是在浏览器端模拟生成的。
主要功能
- 设备监控列表:
- 展示工厂内的模拟设备列表(如 CNC、冲压机、机器人臂等)。
- 显示每个设备的实时状态(在线、离线、警告、错误),状态会动态变化。
- 提供搜索功能,可以按设备名称、类型、位置或 ID 过滤列表。
- 全局 KPI 概览: 页眉实时显示工厂级的关键绩效指标 (KPI),包括:
- 总实时功率 (kW)
- 综合设备效率 (OEE %)
- 活跃的预测性维护警报数量
- 能效分析面板:
- 默认显示全局能耗信息。
- 当选择某个设备时,切换显示该单个设备的能耗信息。
- 展示关键指标:当前功率、今日累计能耗、本周累计能耗、能效指标 (kWh/件,模拟计算)。
- 包含模拟的实时功率趋势图和产线能耗占比饼图(占位符)。
- 预测性维护面板:
- 当选择某个设备时,显示该设备的预测性维护相关信息。
- 活跃警报列表: 显示针对该设备的警告(如传感器值偏高、RUL 低)或错误(传感器值异常)信息,包含警报级别、消息和时间戳。
- 关键传感器信息: 显示模拟的传感器类型(如振动、温度)、模拟的传感器数值趋势图(占位符)以及最重要的预估剩余使用寿命 (RUL) (小时)。
- 动态模拟:
- 设备状态(在线/离线/警告/错误)会基于模拟的传感器读数和随机事件动态变化。
- 能耗数据(功率、累计能耗)会根据设备状态和模拟逻辑实时更新。
- 预测性警报会根据模拟的传感器值和 RUL 阈值动态生成。
- 界面风格: 采用苹果科技风格,简洁、直观,三栏布局并支持响应式设计,适应不同屏幕尺寸。
如何使用
- 打开页面: 在浏览器中打开
index.html
。 - 查看全局状态: 默认加载后,页面显示工厂的全局 KPI 和全局能效数据。
- 监控设备: 在左侧"设备监控"列表中查看所有模拟设备及其当前状态。
- 搜索设备: 使用列表上方的搜索框输入关键字(名称、类型、位置、ID)来快速查找特定设备。
- 选择设备: 点击设备列表中的任意一项:
- 该项会高亮显示。
- 中间的"能效分析"面板会更新,显示该设备的能耗数据。
- 右侧的"预测性维护"面板会更新,显示该设备的活跃警报、传感器类型和预估 RUL。
- 取消选择: 再次点击已选中的设备项,将取消选择,面板恢复显示全局信息或占位符。
- 观察动态变化: 页面上的数据(KPI、设备状态、能耗、警报、RUL)会随时间自动更新,模拟工厂的动态运行。
模拟细节
- 设备数据: 组件初始化时会生成一组包含不同类型、位置和传感器配置的模拟设备。
- 状态变化: 设备的在线/离线状态会随机改变。警告/错误状态主要由模拟的传感器读数决定。当传感器读数超过预设的警告或错误阈值时,状态会改变;当读数回落后,有一定几率恢复为在线状态。
- 能耗模拟: 在线设备的功率会在一个基础值附近随机波动。累计能耗根据功率和时间间隔累加。生产件数也是随机模拟的,用于计算简单的能效指标。
- 传感器模拟: 每个设备关联一个模拟的关键传感器(类型随机)。其读数值会波动,且当 RUL 较低时,读数值偏高的可能性更大。
- RUL 模拟: 每个设备的 RUL 会随时间线性递减。这是预测性维护的核心输入之一。
- 警报生成: 当模拟的传感器值超过警告或错误阈值,或者 RUL 低于特定阈值(如 100 小时)时,会生成对应的预测性维护警报。
- OEE 模拟: 这是一个非常简化的 OEE 计算,主要基于在线设备比例、模拟的生产效率和有问题的设备比例。
文件结构
数据与物联网组件/cloud-iiot-factory-analysis/
├── index.html # 组件的 HTML 结构
├── styles.css # 组件的 CSS 样式 (苹果风格, 三栏响应式布局)
├── script.js # 组件的 JavaScript 逻辑 (模拟数据, 状态更新, 交互)
└── README.md # 本说明文件
技术栈
- HTML5
- CSS3 (使用了 CSS 变量, Grid 布局, Flexbox, 媒体查询)
- JavaScript (原生 JS, 无外部库依赖)
效果展示
源码
index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>云IIoT - 工厂能效与预测维护</title><link rel="stylesheet" href="styles.css"><!-- Placeholder for potential charting library -->
</head>
<body><div class="iiot-ecosystem-container"><header class="main-header"><h1>云端IIoT生态 - 工厂能效与预测维护</h1><div class="header-kpis"><div class="kpi-item"><span class="kpi-label">总实时功率 (kW)</span><span class="kpi-value" id="totalPower">--</span></div><div class="kpi-item"><span class="kpi-label">综合设备效率 (OEE %)</span><span class="kpi-value" id="overallOEE">--</span></div><div class="kpi-item"><span class="kpi-label">预测维护警报</span><span class="kpi-value alert" id="predictiveAlertsCount">0</span></div><div class="kpi-item"><span class="kpi-label">时间</span><span class="kpi-value" id="currentTime">--:--:--</span></div></div></header><main class="main-content"><!-- Column 1: Device List & Status --><aside class="device-list-panel"><h2><i class="icon icon-device"></i> 设备监控</h2><div class="toolbar"><input type="search" id="deviceSearch" placeholder="搜索设备..."></div><ul id="deviceList" class="device-list"><!-- Device items populated by JS --><li class="placeholder">加载设备列表中...</li></ul></aside><!-- Column 2: Energy Efficiency Analysis --><section class="energy-analysis-panel"><h2><i class="icon icon-energy"></i> 能效分析 (<span id="selectedDeviceEnergy">全局</span>)</h2><div class="analysis-grid"><div class="chart-widget"><h3>实时功率趋势 (kW)</h3><div class="chart-placeholder" id="powerTrendChart"><div class="fake-chart energy-trend"></div><span class="chart-axis-label y-axis">功率 (kW)</span><span class="chart-axis-label x-axis">时间</span></div></div><div class="stats-widget"><h3>关键指标</h3><div class="stats-list"><div class="stat-item"><span>当前功率 (kW):</span> <strong id="currentPower">--</strong></div><div class="stat-item"><span>今日累计能耗 (kWh):</span> <strong id="todayEnergy">--</strong></div><div class="stat-item"><span>本周累计能耗 (kWh):</span> <strong id="weekEnergy">--</strong></div><div class="stat-item"><span>能效指标 (kWh/件):</span> <strong id="efficiencyMetric">--</strong></div></div></div><div class="chart-widget"><h3>产线能耗占比 (%)</h3><div class="chart-placeholder" id="energyDistributionChart"><div class="fake-chart energy-pie"></div></div></div></div></section><!-- Column 3: Predictive Maintenance --><section class="predictive-maintenance-panel"><h2><i class="icon icon-predictive"></i> 预测性维护 (<span id="selectedDeviceMaintenance">--</span>)</h2><div class="maintenance-content"><div class="alerts-widget"><h3><i class="icon icon-alert"></i> 活跃警报</h3><ul id="alertList" class="alert-list"><li class="placeholder">无活跃警报</li><!-- Alerts populated by JS --></ul></div><div class="sensors-widget"><h3><i class="icon icon-sensor"></i> 关键传感器 (<span id="selectedSensorType">--</span>)</h3><div class="chart-placeholder" id="sensorTrendChart"><div class="fake-chart sensor-trend"></div><span class="chart-axis-label y-axis">数值</span><span class="chart-axis-label x-axis">时间</span></div><div class="sensor-details"><span>剩余寿命 (RUL): </span><strong id="rulEstimate">--</strong> 小时</div></div></div></section></main><footer class="main-footer"><p>© 2024 云端IIoT模拟系统. 概念演示.</p></footer></div><script src="script.js"></script>
</body>
</html>
styles.css
:root {--bg-color-light: #f9f9f9;--bg-color-container: #ffffff;--header-bg: #f5f5f7; /* Apple-like light grey */--panel-bg: #ffffff;--border-color: #e1e1e1;--text-primary: #1d1d1f;--text-secondary: #515154;--text-label: #6e6e73;--accent-blue: #007aff;--accent-green: #34c759;--accent-orange: #ff9500;--accent-red: #ff3b30;--kpi-value-color: var(--text-primary);--kpi-alert-color: var(--accent-red);--list-item-hover-bg: #f0f0f0;--list-item-selected-bg: #e8f3ff;--list-item-selected-text: var(--accent-blue);--input-bg: #f0f2f5;--input-border: transparent;--input-focus-border: var(--accent-blue);--placeholder-text: #aaaaaa;--chart-placeholder-bg: #f8f8f8;--chart-axis-color: #b0b0b0;--shadow-color: rgba(0, 0, 0, 0.05);--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;--border-radius: 8px;--border-radius-small: 4px;--transition-speed: 0.2s;
}* {box-sizing: border-box;margin: 0;padding: 0;
}body {font-family: var(--font-family);background-color: var(--bg-color-light);color: var(--text-primary);line-height: 1.4;overflow-x: hidden;
}.iiot-ecosystem-container {max-width: 1600px;margin: 1rem auto;background-color: var(--bg-color-container);border-radius: var(--border-radius);box-shadow: 0 4px 12px var(--shadow-color);overflow: hidden;display: flex;flex-direction: column;height: calc(100vh - 2rem); /* Limit height */min-height: 700px; /* Minimum reasonable height */
}/* Header */
.main-header {background-color: var(--header-bg);padding: 0.75rem 1.5rem;border-bottom: 1px solid var(--border-color);flex-shrink: 0;display: flex;justify-content: space-between;align-items: center;
}.main-header h1 {font-size: 1.3rem;font-weight: 600;color: var(--text-primary);
}.header-kpis {display: flex;align-items: center;gap: 1.5rem;
}.kpi-item {display: flex;flex-direction: column;align-items: flex-end;
}.kpi-label {font-size: 0.75rem;color: var(--text-label);margin-bottom: 0.1rem;
}.kpi-value {font-size: 1rem;font-weight: 600;color: var(--kpi-value-color);
}.kpi-value.alert {color: var(--kpi-alert-color);font-weight: 700;
}/* Main Content Layout */
.main-content {flex-grow: 1;padding: 1rem;overflow: hidden;display: grid;grid-template-columns: 300px 1fr 1fr; /* Device List | Energy | Predictive */gap: 1rem;
}/* Panels */
.device-list-panel,
.energy-analysis-panel,
.predictive-maintenance-panel {background-color: var(--panel-bg);/* border: 1px solid var(--border-color); */ /* Optional border */border-radius: var(--border-radius);padding: 1rem;display: flex;flex-direction: column;overflow: hidden;
}/* Panel Headers */
.device-list-panel h2,
.energy-analysis-panel h2,
.predictive-maintenance-panel h2 {font-size: 1.1rem;font-weight: 600;margin-bottom: 1rem;padding-bottom: 0.6rem;border-bottom: 1px solid var(--border-color);display: flex;align-items: center;color: var(--text-primary);flex-shrink: 0;
}.device-list-panel h2 .icon,
.energy-analysis-panel h2 .icon,
.predictive-maintenance-panel h2 .icon {margin-right: 0.6rem;color: var(--accent-blue);
}.energy-analysis-panel h2 span,
.predictive-maintenance-panel h2 span {font-weight: normal;font-size: 0.9em;color: var(--text-secondary);margin-left: 0.3rem;
}/* Device List Panel */
.device-list-panel .toolbar {margin-bottom: 0.75rem;flex-shrink: 0;
}#deviceSearch {width: 100%;padding: 0.5rem 0.75rem;font-size: 0.9rem;border: 1px solid var(--input-border);background-color: var(--input-bg);border-radius: var(--border-radius-small);outline: none;transition: border-color var(--transition-speed), box-shadow var(--transition-speed);
}#deviceSearch:focus {border-color: var(--input-focus-border);box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.2);
}.device-list {list-style: none;overflow-y: auto;flex-grow: 1;
}.device-item {padding: 0.75rem 0.5rem;margin-bottom: 0.2rem;border-radius: var(--border-radius-small);cursor: pointer;transition: background-color var(--transition-speed);display: flex;justify-content: space-between;align-items: center;font-size: 0.9rem;
}.device-item:hover {background-color: var(--list-item-hover-bg);
}.device-item.selected {background-color: var(--list-item-selected-bg);color: var(--list-item-selected-text);font-weight: 500;
}.device-item .device-name {font-weight: 500;
}.device-status {font-size: 0.8rem;padding: 0.15rem 0.4rem;border-radius: 10px;color: white;
}.device-status.online {background-color: var(--accent-green);
}.device-status.offline {background-color: var(--text-secondary);
}.device-status.warning {background-color: var(--accent-orange);
}.device-status.error {background-color: var(--accent-red);
}/* Energy Analysis Panel */
.energy-analysis-panel .analysis-grid {display: grid;grid-template-columns: 1fr; /* Single column for now, could be 2 */grid-template-rows: auto auto 1fr;gap: 1rem;flex-grow: 1;overflow-y: auto;
}.chart-widget, .stats-widget {background-color: #fff; /* Slightly different bg if needed *//* border: 1px solid var(--border-color); */border-radius: var(--border-radius-small);padding: 1rem;
}.chart-widget h3, .stats-widget h3 {font-size: 0.95rem;font-weight: 500;margin-bottom: 0.75rem;color: var(--text-label);
}.stats-list {display: flex;flex-direction: column;gap: 0.6rem;
}.stat-item {font-size: 0.9rem;display: flex;justify-content: space-between;
}.stat-item span {color: var(--text-secondary);
}.stat-item strong {font-weight: 600;color: var(--kpi-value-color);
}/* Predictive Maintenance Panel */
.predictive-maintenance-panel .maintenance-content {display: grid;grid-template-rows: auto 1fr; /* Alerts list then sensor */gap: 1rem;flex-grow: 1;overflow-y: auto;
}.alerts-widget, .sensors-widget {background-color: #fff;border-radius: var(--border-radius-small);padding: 1rem;
}.alerts-widget h3, .sensors-widget h3 {font-size: 0.95rem;font-weight: 500;margin-bottom: 0.75rem;color: var(--text-label);display: flex;align-items: center;
}.alerts-widget h3 .icon, .sensors-widget h3 .icon {margin-right: 0.4rem;font-size: 0.9em;
}.sensors-widget h3 span {font-weight: normal;font-size: 0.9em;color: var(--text-secondary);margin-left: 0.3rem;
}.alert-list {list-style: none;max-height: 150px; /* Limit alert list height */overflow-y: auto;
}.alert-item {padding: 0.5rem 0;border-bottom: 1px dashed var(--border-color);font-size: 0.85rem;display: flex;align-items: center;gap: 0.5rem;
}.alert-item:last-child {border-bottom: none;
}.alert-icon {flex-shrink: 0;font-size: 1.1em;
}
.alert-icon.warning { color: var(--accent-orange); }
.alert-icon.error { color: var(--accent-red); }.alert-message {flex-grow: 1;
}.alert-time {font-size: 0.75rem;color: var(--text-secondary);flex-shrink: 0;
}.sensors-widget {display: flex;flex-direction: column;
}.sensors-widget .chart-placeholder {flex-grow: 1; /* Let chart take available space */min-height: 150px;
}.sensor-details {margin-top: 0.75rem;font-size: 0.9rem;text-align: center;flex-shrink: 0;
}.sensor-details span {color: var(--text-secondary);
}.sensor-details strong {font-weight: 600;color: var(--accent-orange); /* Highlight RUL */
}/* Chart Placeholders */
.chart-placeholder {background-color: var(--chart-placeholder-bg);border-radius: var(--border-radius-small);display: flex;align-items: center;justify-content: center;position: relative;overflow: hidden;border: 1px solid var(--border-color);
}.chart-axis-label {position: absolute;font-size: 0.7rem;color: var(--chart-axis-color);transform: rotate(-90deg);white-space: nowrap;
}.chart-axis-label.y-axis {left: -10px;top: 50%;transform-origin: left top;
}.chart-axis-label.x-axis {bottom: -10px;left: 50%;transform: translateX(-50%);
}.fake-chart {width: 90%;height: 80%;position: relative;
}/* Different fake chart styles */
.fake-chart.energy-trend::after,
.fake-chart.sensor-trend::after {content: '';position: absolute;inset: 0;background: linear-gradient(to right, transparent, rgba(0, 122, 255, 0.1), rgba(52, 199, 89, 0.15), rgba(255, 149, 0, 0.1), transparent);animation: fakePulse 6s ease-in-out infinite;border-radius: 3px;
}.fake-chart.energy-pie {width: 60%;height: 0;padding-bottom: 60%; /* Make it square */border-radius: 50%;background: conic-gradient(var(--accent-blue) 0% 30%,var(--accent-green) 30% 55%,var(--accent-orange) 55% 75%,var(--text-secondary) 75% 100%);animation: fakeSpin 20s linear infinite;border: 3px solid var(--chart-placeholder-bg);
}@keyframes fakePulse {0%, 100% { transform: scaleY(0.6); opacity: 0.5; }50% { transform: scaleY(1); opacity: 0.8; }
}@keyframes fakeSpin {from { transform: rotate(0deg); }to { transform: rotate(360deg); }
}/* Generic Placeholder */
.placeholder {color: var(--placeholder-text);font-style: italic;text-align: center;padding: 1rem;font-size: 0.9rem;
}/* Footer */
.main-footer {background-color: var(--header-bg); /* Match header */padding: 0.6rem 1.5rem;text-align: center;font-size: 0.8rem;color: var(--text-secondary);border-top: 1px solid var(--border-color);flex-shrink: 0;
}/* Icons (Basic Placeholders) */
.icon::before {display: inline-block;font-weight: normal;font-style: normal;font-variant: normal;text-rendering: auto;-webkit-font-smoothing: antialiased;margin-right: 0.3em;/* Consider using a proper icon font like Font Awesome or Material Icons */
}
.icon-device::before { content: "📱"; }
.icon-energy::before { content: "⚡️"; }
.icon-predictive::before { content: "🔧"; }
.icon-alert::before { content: "⚠️"; } /* Warning triangle */
.icon-sensor::before { content: "🌡️"; } /* Thermometer */
.alert-icon.warning::before { content: "🔶"; } /* Orange Diamond */
.alert-icon.error::before { content: "🔴"; } /* Red Circle *//* Responsive Design */
@media (max-width: 1200px) {.main-content {grid-template-columns: 250px 1fr 1fr; /* Smaller sidebar */}.header-kpis { gap: 1rem; }.main-header h1 { font-size: 1.15rem; }.kpi-label { font-size: 0.7rem; }.kpi-value { font-size: 0.9rem; }
}@media (max-width: 992px) {.iiot-ecosystem-container {height: auto; /* Allow content to determine height */min-height: 100vh;margin: 0.5rem;}.main-content {grid-template-columns: 1fr; /* Stack columns */grid-template-rows: auto auto auto; /* Let rows size automatically */padding: 0.5rem;gap: 0.5rem;}.device-list-panel,.energy-analysis-panel,.predictive-maintenance-panel {padding: 0.75rem;overflow-y: visible; /* Allow panels to grow */}.device-list { max-height: 250px; } /* Limit list height on mobile */.alert-list { max-height: 120px; }.energy-analysis-panel .analysis-grid,.predictive-maintenance-panel .maintenance-content {overflow-y: visible;}.main-header {flex-direction: column;align-items: flex-start;gap: 0.5rem;padding: 0.75rem;}.header-kpis {width: 100%;justify-content: space-between;flex-wrap: wrap;gap: 0.5rem 1rem;}.kpi-item { align-items: flex-start; }
}@media (max-width: 576px) {.main-header h1 { font-size: 1rem; }.header-kpis { gap: 0.3rem 0.8rem; }.kpi-label { font-size: 0.65rem; }.kpi-value { font-size: 0.8rem; }.device-list-panel h2,.energy-analysis-panel h2,.predictive-maintenance-panel h2 {font-size: 1rem;}
}
script.js
// script.js - Cloud IIoT Factory Analysis Componentdocument.addEventListener('DOMContentLoaded', () => {// --- DOM Elements ---const totalPowerEl = document.getElementById('totalPower');const overallOEEEl = document.getElementById('overallOEE');const predictiveAlertsCountEl = document.getElementById('predictiveAlertsCount');const currentTimeEl = document.getElementById('currentTime');const deviceSearchInput = document.getElementById('deviceSearch');const deviceListUl = document.getElementById('deviceList');const selectedDeviceEnergyEl = document.getElementById('selectedDeviceEnergy');const currentPowerEl = document.getElementById('currentPower');const todayEnergyEl = document.getElementById('todayEnergy');const weekEnergyEl = document.getElementById('weekEnergy');const efficiencyMetricEl = document.getElementById('efficiencyMetric');const selectedDeviceMaintenanceEl = document.getElementById('selectedDeviceMaintenance');const alertListUl = document.getElementById('alertList');const selectedSensorTypeEl = document.getElementById('selectedSensorType');const rulEstimateEl = document.getElementById('rulEstimate');// Chart placeholders are mostly for styling in this versionconst powerTrendChartEl = document.getElementById('powerTrendChart');const energyDistributionChartEl = document.getElementById('energyDistributionChart');const sensorTrendChartEl = document.getElementById('sensorTrendChart');// --- Simulation State & Parameters ---let simulationTime = new Date();let selectedDeviceId = null; // null means global viewlet searchTerm = '';let factoryDevices = {}; // Store device datalet factoryState = {totalPower: 0,overallOEE: 0,alerts: [],todayEnergyGlobal: 0,weekEnergyGlobal: 0,};// Update intervals (in ms)const timeUpdateInterval = 1000;const dataUpdateInterval = 3000; // Update device data less frequentlyconst alertCheckInterval = 7000; // Check for new alerts periodically// --- Sample Data Generation ---function generateSampleDevices(count = 15) {const devices = {};const types = ['CNC机床', '冲压机', '注塑机', '机器人臂', '传送带', '压缩机'];const locations = ['A栋1楼', 'A栋2楼', 'B栋1楼', 'C栋动力房'];const sensorTypes = ['振动', '温度', '压力', '电流'];for (let i = 1; i <= count; i++) {const id = `DEV-${String(i).padStart(3, '0')}`;const type = types[Math.floor(Math.random() * types.length)];const location = locations[Math.floor(Math.random() * locations.length)];devices[id] = {id: id,name: `${type} #${i}`,type: type,location: location,status: 'offline', // Initial statuspower: 0, // kWtodayEnergy: 0, // kWhweekEnergy: 0, // kWhunitsProduced: 0,efficiencyMetric: null, // kWh/unitsensors: {type: sensorTypes[Math.floor(Math.random() * sensorTypes.length)],value: 0,thresholdWarning: 50 + Math.random() * 20,thresholdError: 80 + Math.random() * 15,rul: 1000 + Math.random() * 2000, // Remaining Useful Life in hours},alerts: [] // Active alerts for this device};}return devices;}// --- Initialization ---function initializeIIoTMonitor() {factoryDevices = generateSampleDevices();setupEventListeners();updateTime();setInterval(updateTime, timeUpdateInterval);// Start simulation loopsupdateFactoryData(); // Initial data loadsetInterval(updateFactoryData, dataUpdateInterval);setInterval(checkForNewAlerts, alertCheckInterval);renderDeviceList(); // Initial renderdisplayGlobalEnergyData(); // Show global initiallydisplayMaintenanceInfo(); // Show placeholder initiallyconsole.log("Cloud IIoT Monitor Initialized");}// --- Event Handlers ---function setupEventListeners() {deviceSearchInput.addEventListener('input', handleSearchInput);deviceListUl.addEventListener('click', handleDeviceSelect);}function handleSearchInput(event) {searchTerm = event.target.value.toLowerCase();renderDeviceList();}function handleDeviceSelect(event) {const listItem = event.target.closest('.device-item');if (listItem && listItem.dataset.id) {const deviceId = listItem.dataset.id;if (selectedDeviceId === deviceId) {// Clicked selected device again: Deselect and show globalselectedDeviceId = null;displayGlobalEnergyData();displayMaintenanceInfo(); // Clear maintenance panel or show global summary?} else {selectedDeviceId = deviceId;displayDeviceEnergyData(selectedDeviceId);displayMaintenanceInfo(selectedDeviceId);}renderDeviceList(); // Re-render to update selection highlight}}// --- Simulation & Data Update Logic ---function updateTime() {simulationTime = new Date();currentTimeEl.textContent = simulationTime.toLocaleTimeString('zh-CN');}function updateFactoryData() {let currentTotalPower = 0;let totalUnits = 0;let onlineDevices = 0;let devicesWithIssues = 0;Object.values(factoryDevices).forEach(device => {// Simulate status changesconst randStatus = Math.random();if (device.status === 'offline' && randStatus < 0.1) {device.status = 'online'; // Chance to come online} else if (device.status === 'online' && randStatus < 0.02) {device.status = 'offline'; // Chance to go offlinedevice.power = 0;} else if (device.status !== 'offline') {// Simulate power fluctuation for online/warning/error devicesconst basePower = (device.type === 'CNC机床' || device.type === '冲压机') ? 15 : 8;device.power = basePower + (Math.random() - 0.3) * 5;if (device.power < 0) device.power = 0;// Simulate energy consumptionconst energyConsumed = device.power * (dataUpdateInterval / (1000 * 3600)); // kWhdevice.todayEnergy += energyConsumed;device.weekEnergy += energyConsumed;factoryState.todayEnergyGlobal += energyConsumed;factoryState.weekEnergyGlobal += energyConsumed;// Simulate productionif (device.power > basePower * 0.5) {const units = Math.floor(Math.random() * 3);device.unitsProduced += units;totalUnits += units;if (device.unitsProduced > 0) {device.efficiencyMetric = device.todayEnergy / device.unitsProduced;}}onlineDevices++;}// Simulate sensor readings & RUL decreaseif (device.status !== 'offline') {device.sensors.rul -= (dataUpdateInterval / (1000 * 3600)); // Decrease RULif (device.sensors.rul < 0) device.sensors.rul = 0;const sensorRand = Math.random();// Fluctuate sensor value, more likely to increase if RUL is lowconst baseSensorValue = 20 + (1000 / (device.sensors.rul + 10)) * 2; // Higher base value for lower RULdevice.sensors.value = baseSensorValue + (sensorRand - 0.5 + (device.sensors.rul < 200 ? 0.2 : 0)) * 15;if (device.sensors.value < 0) device.sensors.value = 0;if (device.sensors.value > 100) device.sensors.value = 100;// Update status based on sensor thresholdsif (device.sensors.value >= device.sensors.thresholdError && device.status !== 'offline') {if (device.status !== 'error') device.status = 'error';devicesWithIssues++;} else if (device.sensors.value >= device.sensors.thresholdWarning && device.status !== 'offline') {if (device.status !== 'error' && device.status !== 'warning') device.status = 'warning';devicesWithIssues++;} else if (device.status === 'error' || device.status === 'warning') {// Chance to recover if value drops (less likely for error)if (Math.random() < (device.status === 'error' ? 0.05 : 0.2)) {device.status = 'online';}}}currentTotalPower += device.power;});factoryState.totalPower = currentTotalPower;// Simulate OEE (simple version based on online and issue states)const availability = onlineDevices / Object.keys(factoryDevices).length;const performance = totalUnits > 0 ? 0.8 + Math.random() * 0.15 : 0; // Simplified performanceconst quality = 1 - (devicesWithIssues / (onlineDevices + 0.1)); // Simplified qualityfactoryState.overallOEE = availability * performance * quality * 100;if (factoryState.overallOEE < 0) factoryState.overallOEE = 0;if (factoryState.overallOEE > 100) factoryState.overallOEE = 100;// Update header KPIstotalPowerEl.textContent = factoryState.totalPower.toFixed(1);overallOEEEl.textContent = factoryState.overallOEE.toFixed(1);// Re-render lists and panels if necessary (e.g., status changed)renderDeviceList();if (selectedDeviceId) {displayDeviceEnergyData(selectedDeviceId);displayMaintenanceInfo(selectedDeviceId);} else {displayGlobalEnergyData();}}function checkForNewAlerts() {factoryState.alerts = []; // Clear global alerts, rebuild from deviceslet activeAlertCount = 0;Object.values(factoryDevices).forEach(device => {device.alerts = []; // Clear device alerts firstconst sensorVal = device.sensors.value;let alertLevel = null;let message = '';if (device.status === 'error' || sensorVal >= device.sensors.thresholdError) {alertLevel = 'error';message = `${device.sensors.type}值异常 (${sensorVal.toFixed(1)}),可能导致故障`;} else if (device.status === 'warning' || sensorVal >= device.sensors.thresholdWarning) {alertLevel = 'warning';message = `${device.sensors.type}值偏高 (${sensorVal.toFixed(1)}),请关注`;}if (alertLevel && Math.random() < 0.8) { // Don't generate alert every single timeconst newAlert = {id: `alrt-${device.id}-${Date.now()}`,deviceId: device.id,deviceName: device.name,level: alertLevel,message: message,timestamp: new Date()};device.alerts.push(newAlert);factoryState.alerts.push(newAlert);activeAlertCount++;}});// Add a RUL based alertObject.values(factoryDevices).forEach(device => {if (device.sensors.rul < 100 && device.status !== 'offline' && Math.random() < 0.5) { // RUL warning < 100 hoursconst newAlert = {id: `alrt-${device.id}-rul-${Date.now()}`,deviceId: device.id,deviceName: device.name,level: 'warning',message: `预估剩余寿命低 (${device.sensors.rul.toFixed(0)} 小时),建议安排维护`,timestamp: new Date()};// Avoid duplicate RUL alerts for the same device if one already existsif (!device.alerts.some(a => a.message.includes('剩余寿命'))) {device.alerts.push(newAlert);factoryState.alerts.push(newAlert);activeAlertCount++;}}});factoryState.alerts.sort((a, b) => b.timestamp - a.timestamp); // Sort newest firstpredictiveAlertsCountEl.textContent = activeAlertCount;if (activeAlertCount > 0) {predictiveAlertsCountEl.classList.add('alert');} else {predictiveAlertsCountEl.classList.remove('alert');}// Update maintenance panel if a device is selectedif (selectedDeviceId) {displayMaintenanceInfo(selectedDeviceId);}}// --- Rendering Functions ---function renderDeviceList() {deviceListUl.innerHTML = ''; // Clear listconst filteredDevices = Object.values(factoryDevices).filter(device =>device.name.toLowerCase().includes(searchTerm)|| device.type.toLowerCase().includes(searchTerm)|| device.location.toLowerCase().includes(searchTerm)|| device.id.toLowerCase().includes(searchTerm));if (filteredDevices.length === 0) {deviceListUl.innerHTML = '<li class="placeholder">未找到匹配设备</li>';return;}filteredDevices.sort((a, b) => a.name.localeCompare(b.name)) // Sort alphabetically.forEach(device => {const li = document.createElement('li');li.className = 'device-item';li.dataset.id = device.id;if (device.id === selectedDeviceId) {li.classList.add('selected');}li.innerHTML = `<span class="device-name">${device.name} <small>(${device.location})</small></span><span class="device-status ${device.status}">${device.status.toUpperCase()}</span>`;deviceListUl.appendChild(li);});}function displayGlobalEnergyData() {selectedDeviceEnergyEl.textContent = '全局';currentPowerEl.textContent = factoryState.totalPower.toFixed(1);todayEnergyEl.textContent = factoryState.todayEnergyGlobal.toFixed(1);weekEnergyEl.textContent = factoryState.weekEnergyGlobal.toFixed(1);// Global efficiency metric might be complex, leave blank or use an averageefficiencyMetricEl.textContent = '--';// TODO: Update global charts (placeholders for now)}function displayDeviceEnergyData(deviceId) {const device = factoryDevices[deviceId];if (!device) return;selectedDeviceEnergyEl.textContent = device.name;currentPowerEl.textContent = device.power.toFixed(1);todayEnergyEl.textContent = device.todayEnergy.toFixed(1);weekEnergyEl.textContent = device.weekEnergy.toFixed(1);efficiencyMetricEl.textContent = device.efficiencyMetric ? device.efficiencyMetric.toFixed(2) : '--';// TODO: Update energy charts for the specific device (placeholders)}function displayMaintenanceInfo(deviceId = null) {if (!deviceId) {selectedDeviceMaintenanceEl.textContent = '全局概览'; // Or maybe show all active alerts?selectedSensorTypeEl.textContent = '--';rulEstimateEl.textContent = '--';alertListUl.innerHTML = '<li class="placeholder">选择设备查看警报</li>';// TODO: Clear or show global sensor overview chart (placeholder)return;}const device = factoryDevices[deviceId];if (!device) return;selectedDeviceMaintenanceEl.textContent = device.name;selectedSensorTypeEl.textContent = device.sensors.type;rulEstimateEl.textContent = device.sensors.rul.toFixed(0);// Display alerts for this devicealertListUl.innerHTML = '';const deviceAlerts = factoryState.alerts.filter(a => a.deviceId === deviceId);if (deviceAlerts.length === 0) {alertListUl.innerHTML = '<li class="placeholder">无活跃警报</li>';} else {deviceAlerts.forEach(alert => {const li = document.createElement('li');li.className = 'alert-item';li.innerHTML = `<span class="alert-icon ${alert.level}"></span><span class="alert-message">${alert.message}</span><span class="alert-time">${alert.timestamp.toLocaleTimeString('zh-CN')}</span>`;alertListUl.appendChild(li);});}// TODO: Update sensor trend chart for the device (placeholder)}// --- Initial Call ---initializeIIoTMonitor();
});
相关文章:
19、云端工业物联网生态组件 - 工厂能效与预测维护 - /数据与物联网组件/cloud-iiot-factory-analysis
76个工业组件库示例汇总 云端工业物联网生态组件 - 工厂能效与预测维护 (模拟) 概述 这是一个交互式的 Web 组件,旨在模拟一个云端工业物联网 (IIoT) 平台的核心界面,专注于工厂层面的能效分析和基于传感器数据的预测性维护概念。用户可以监控模拟的设…...
python打卡day25
python的异常处理机制 知识点回顾: 异常处理机制debug过程中的各类报错try-except机制try-except-else-finally机制 在即将进入深度学习专题学习前,我们最后差缺补漏,把一些常见且重要的知识点给他们补上,加深对代码和流程的理解。…...
Jmeter变量传递介绍
文章目录 一、Jmeter变量类型及作用域二、变量传递方式1. 用户定义变量(User Defined Variables)2. CSV 数据文件(CSV Data Set Config)3.正则表达式提取器4.后置处理器(Post Processor)4.1BeanShell/JSR223 后置处理器…...
机器学习 Day16 聚类算法 ,数据降维
聚类算法 1.简介 1.1 聚类概念 无监督学习:聚类是一种无监督学习算法,不需要预先标记的训练数据 相似性分组:根据样本之间的相似性自动将样本归到不同类别 相似度度量:常用欧式距离作为相似度计算方法 1.2 聚类vs分类 聚类&…...
白日梦:一个方便快捷的将故事制作成视频的工具
我有故事,但我想把它制作成视频,有没有什么好用的工具可以使用呢?如果你也被类似的问题困扰,那么今天分享的这个工具将会解决这个问题。从需求来看,我们希望的是纯文本的故事输入,完整的故事视频输出&#…...
ultralytics中tasks.py---parse_model函数解析
一、根据scale获取对应的深度、宽度和最大通道数 具体例如yaml文件内容如下: depth=0.33,那么重复的模块例如C2f原本重复次数是3,6,6,3,那么T对应的模型重复次数就是三分之一即1,1,2,1次。这个在后面定义的: width=0.25,max_channels=1024 原本c2=64,但经过make_div…...
Codeforces Round 1003 (Div. 4)
A. Skibidus and Amog’u 题目大意 给你一个字符串,把末尾的us换成i 解题思路 删掉最后两个加上“i”即可 代码实现 #include <bits/stdc.h>using i64 long long;int main() {std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);int …...
基于RFSOC ZU28DR+DSP 6U VPX处理板
板卡概述 基于RFSOC ZU28DRDSP 6U VPX处理板,是一款基于6U VPX总线架构的高速信号处理平台,数模混合信号处理卡,采用 Xilinx ZYNQ UltraScale RFSoC ZU28DR和TI DSP TMS320C6678组合设计,两者之间通过4x 5G SRIO互联。本板卡可实…...
C# 通过脚本实现接口
以前C#脚本用的委托注入模式,今天在AI提示下,尝试用脚本直接实现接口,然后C#可以动态或指定新类型创建接口实现对象。从代码角度看,稍显复杂,但脚本方面显得更简洁和有条理。 引用包需要Microsoft.CodeAnalysis、Micro…...
代码随想录算法训练营Day58
力扣695.岛屿的最大面积【medium】 力扣827.最大人工岛【hard】 一、力扣695.岛屿的最大面积【medium】 题目链接:力扣695.岛屿的最大面积 视频链接:代码随想录 1、思路 和岛屿数量那道题很像,只是递归这边要多一个怎么计算面积,…...
若依框架页面
1.页面地址 若依管理系统 2.账号和密码 管理员 账号admin 密码admin123 运维 账号yuwei 密码123456 自己搭建的地址方便大家学习,不要攻击哦,谢谢啊...
redis 缓存穿透,缓存击穿,缓存雪崩
一:什么是缓存 (1)计算机:cpu、内存、磁盘,cpu任何需要的数据都要从内容中读入数据放入cpu,从cup内部添加一个缓存 (2)web开发的每个阶段都可以添加缓存 (3)缓存优缺点&a…...
ORACLE查看归档是否打开
一、使用V$DATABASE视图 SELECT log_mode FROM v$database; 结果说明: ARCHIVELOG - 数据库处于归档模式 NOARCHIVELOG - 数据库处于非归档模式 二、 使用v$instance视图 SELECT archiver FROM v$instance; 结果说明: STARTED - 归档进程已启动(归档模…...
Python环境管理工具深度指南:pip、Poetry、uv、Conda
Python环境管理工具深度指南:pip、Poetry、uv、Conda Python开发中,环境管理和依赖管理是不可避开的重要话题。合理地管理项目的Python环境(尤其是虚拟环境)有助于隔离不同项目的依赖,避免版本冲突,并确保…...
高等数学第七章---微分方程(§7.4-§7.5可降阶的高阶微分方程、二阶线性微分方程)
7.4 可降阶的高阶微分方程 某些类型的高阶微分方程可以通过适当的变量代换,将其阶数降低,从而化为阶数较低的方程进行求解。 一、 y ( n ) f ( x ) y^{(n)}f(x) y(n)f(x) 型方程 特征:方程的左端是 y y y 的 n n n 阶导数,右…...
Jmeter对服务端进行压测快速上手
安装 下载 安装jmeter的之前必须先装有JDK 官网下载地址:https://archive.apache.org/dist/jmeter/binaries/ jmeter3.0的对应jdk1.7,jmeter4.0对应jdk1.8以上,否者启用jmeter也会报错 配置 配置环境变量 在系统变量PATH上加上: %JMET…...
【嵌入模型与向量数据库】
目录 一、什么是向量? 二、为什么需要向量数据库? 三、向量数据库的特点 四、常见的向量数据库产品 FAISS 支持的索引类型 vs 相似度 五、常见向量相似度方法对比 六、应该用哪种 七、向量数据库的核心逻辑 🔍 示例任务:…...
鸿蒙OSUniApp 开发实时聊天页面的最佳实践与实现#三方框架 #Uniapp
使用 UniApp 开发实时聊天页面的最佳实践与实现 在移动应用开发领域,实时聊天功能已经成为许多应用不可或缺的组成部分。本文将深入探讨如何使用 UniApp 框架开发一个功能完善的实时聊天页面,从布局设计到核心逻辑实现,带领大家一步步打造专…...
React构建组件
React构建组件 React 组件构建方式详解 React 组件的构建方式随着版本迭代不断演进,目前主要有 函数组件 和 类组件 两种核心模式,并衍生出多种高级组件设计模式。以下是完整的构建方式指南: 文章目录 React构建组件React 组件构建方式详解…...
auto.js面试题及答案
以下是常见的 Auto.js 面试题及参考答案,涵盖基础知识、脚本编写、运行机制、权限、安全等方面,适合开发岗位的技术面试准备: 一、基础类问题 什么是 Auto.js?它的主要用途是什么? 答案: Auto.js 是一个…...
OPC UA + ABP vNext 企业级实战:高可用数据采集框架指南
🚀📊 OPC UA ABP vNext 企业级实战:高可用数据采集框架指南 🚀 📑 目录 🚀📊 OPC UA ABP vNext 企业级实战:高可用数据采集框架指南 🚀一、前言 🎯二、系统…...
【springcloud学习(dalston.sr1)】Ribbon负载均衡(七)
该系列项目整体介绍及源代码请参照前面写的一篇文章【springcloud学习(dalston.sr1)】项目整体介绍(含源代码)(一) (一)Ribbon 负载均衡的理解 ribbon是一种客户端的负载均衡。类似于比如我们在火车站窗口…...
编程题 03-树1 树的同构【PAT】
文章目录 题目输入格式输出格式输入样例1(对应图一)输出样例1输入样例2(对应图二)输出样例2 题解解题思路完整代码 编程练习题目集目录 题目 给定两棵树 T 1 T_1 T1 和 T 2 T_2 T2 。如果 T 1 T_1 T1 可以通过若干次左右…...
团结引擎开源车模 Sample 发布:光照渲染优化 动态交互全面体验升级
光照、材质与交互效果的精细控制,通常意味着复杂的技术挑战,但借助 Shader Graph 14.1.0(已内置在团结引擎官方 1.5.0 版本中),这一切都变得简单易用。通过最新团结引擎官方车模 Sample,开发者能切身感受到全新光照优化与编辑功能…...
Chrome安装最新vue-devtool插件
本vue-devtool版本是官方的 v7.6.8版本,兼容性好、功能齐全且稳定。 操作步骤: 方法一: 打开谷歌浏览器 --> 右上角三个点 --> 扩展程序 --> 管理扩展程序 --> 加载已解压的扩展程序, 然后选择解压后的文件夹即可。…...
鸿蒙OSUniApp打造多功能图表展示组件 #三方框架 #Uniapp
使用UniApp打造多功能图表展示组件 在当前移动应用开发领域,数据可视化已成为不可或缺的一部分。无论是展示销售数据、用户增长趋势还是其他业务指标,一个优秀的图表组件都能有效提升用户体验。UniApp作为一款跨平台开发框架,如何在其中实现…...
海量数据Top k 与查重问题
海量数据求top k 问题: - 求最大的前k个元素、求最小的前k个元素 - 求最大的第k个元素、求最小的第k个元素 解法: - 大根堆、小跟堆 -》 优先级队列(priority_queue) - 快速分割函数 priority_queue<int,vector<int>…...
Beats
Beats是一个开放源代码的数据发送器。我们可以把Beats作为一种代理安装在我 们的服务器上,这样就可以比较方便地将数据发送到Elasticsearch或者Logstash 中。Elastic Stack提供了多种类型的Beats组件。 Beats可以直接将数据发送到Elasticsearch或者发送到Logstash&a…...
微型PCB打样厂家选型指南
智能手机、可穿戴设备、医疗电子等高精尖领域,微型PCB(印制电路板)如同设备的“神经中枢”,承载着信号传输、电源分配、元件互联等核心功能。其设计精度与制造质量直接决定了产品的性能上限与可靠性。而打样环节,则是从…...
ISP有感自发
一、黑电平 由于传感器,即便在无光的情况下,依然会产生微小的暗电流,这些暗电流可能是噪点会影响后期的调试。因此,我们便将这些电流处理为0,成为纯黑的颜色。可以在源头消除这些误差。 如何矫正黑电平: …...
编程技能:字符串函数04,直接使用 strcpy,解决报错
专栏导航 本节文章分别属于《Win32 学习笔记》和《MFC 学习笔记》两个专栏,故划分为两个专栏导航。读者可以自行选择前往哪个专栏。 (一)WIn32 专栏导航 上一篇:编程技能:字符串函数03,strncpy 回到目录…...
网络编程超时检测,unix域套接字,粘包
刷题: # 超时检测核心要点## 1. 基本类型### 阻塞模式- 永久等待数据,无超时机制- 典型函数:recv()阻塞调用### 非阻塞模式- 立即返回结果(成功/错误)- 设置方式:fcntl(fd, F_SETFL, O_NONBLOCK)### 超时检…...
springboot AOP 接口限流(基于IP的接口限流和黑白名单)
使用 Spring Boot 自定义注解和AOP实现基于IP的接口限流和黑白名单 在我们日常开发的项目中为了保证系统的稳定性,很多时候我们需要对系统做限流处理,它可以有效防止恶意请求对系统造成过载。常见的限流方案主要有: 网关限流: NG…...
Python uv包管理器使用指南:从入门到精通
Python uv包管理器使用指南:从入门到精通 作为一名Python开发者,你是否曾经为虚拟环境管理和依赖包安装而头疼?今天我要向大家介绍一个强大的工具——uv包管理器,它将彻底改变你的Python开发体验。 什么是uv包管理器?…...
【计算机网络】TLS中的对称加密和非对称加密的应用,应对第三方抓包的双向https认证
TLS工作流程简化版 证书验证流程 客户端通过CA的公钥验证服务器数字证书的签名,确保服务器身份可信,防止中间人攻击。 预主密钥加密传输 客户端生成预主密钥,用服务器证书中的公钥加密后发送给服务器,只有服务器(持有…...
Stable Diffusion WebUI 插件大全:功能详解与下载地址
Stable Diffusion WebUI 的强大之处在于其丰富的插件生态,这些插件可以大幅提升 AI 绘画的效率和质量。本文将详细介绍 21 个常用插件,包括它们的功能、效果说明以及下载地址,帮助你更好地使用 Stable Diffusion WebUI。 插件的安装方式 直…...
【行为型之策略模式】游戏开发实战——Unity灵活算法架构的核心实现策略
文章目录 🎮 策略模式(Strategy Pattern)深度解析一、模式本质与核心价值二、经典UML结构三、Unity实战代码(动态伤害计算系统)1. 定义策略接口与上下文2. 实现具体策略3. 客户端使用 四、模式进阶技巧1. 策略组合2. 策…...
第二十九节:直方图处理-直方图均衡化
在数字图像处理中,直方图均衡化(Histogram Equalization)是一种经典的对比度增强技术。它通过重新分配图像像素的亮度值,使图像的灰度级分布更加均匀,从而显著提升图像的视觉效果。 一、直方图基础 1.1 什么是直方图? 直方图(Histogram)是图像处理中用于描述图像像素…...
性能比拼: Nginx vs. Envoy
本内容是对知名性能评测博主 Anton Putra Nginx vs. Envoy performance benchmark 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准 Envoy 被设计为服务网格中的高性能代理。 你可以将它部署在虚拟机(VM)中,或作为 sidecar 方式部…...
在 C 语言中,U、UL、ULL、L、LL 等符号使用说明
在 C 语言中,U、UL、ULL、L、LL 等符号是用于明确指定整数字面量类型的后缀,其核心作用是避免数据类型隐式转换导致的溢出或未定义行为。以下是具体分类和使用场景: 一、整数字面量后缀分类 后缀全称适用场景示例说明Uunsigned100U无符号整数…...
一般枚举题目合集
一般枚举题目合集 枚举NOIP 2011 提高组 铺地毯P2327 [SCOI2005] 扫雷蓝桥真题 跑步蓝桥真题 猜年龄 二进制枚举常用的技巧整理子集 - 力扣P10449 费解的开关UVA11464 Even Parity通过Virtual Judge提交代码正解 日期枚举蓝桥真题 跑步NOIP 2016 普及组 回文日期日期统计 写这段…...
MCP(Model Context Protocol,模型上下文协议)
1. 起因, 目的: MCP, 貌似最近很火,简单了解一下, 跟上时代节奏。看似是一个工具,一个新概念,其实是个鸡肋(仅仅代表个人观点)。 2. 先看效果 这里插入图片 3. 过程: 问题1, 什么是 MCP h…...
MQTT 在Spring Boot 中的使用
在 Spring Boot 中使用 MQTT 通常会借助 Spring Integration 项目提供的 MQTT 支持。这使得 MQTT 的集成可以很好地融入 Spring 的消息驱动和企业集成模式。 以下是如何在 Spring Boot 中集成和使用 MQTT 的详细步骤: 前提条件: MQTT Brokerÿ…...
uniapp使用全局组件,
在 Uniapp 中,如果你的组件是应用层组件(例如全局悬浮按钮、全局通知栏等),并且希望它自动出现在所有页面而无需在每个页面模板中手动添加组件标签,可以通过以下两种方案实现: 方案一:通过 app.…...
【三维重建】三维场景生成:综述
标题:《3D Scene Generation: A Survey》 来源:新加坡南洋理工大学 项目:https://github.com/hzxie/Awesome-3D-Scene-Generation 文章目录 摘要一、前言二、准备工作2.1 任务定义2.2 三维场景表示2.3 生成模型 三、方法:分层分类…...
怎样将MM模块常用报表设置为ALV默认格式(MB52、MB5B、ME2M、ME1M等)
【SAP系统研究】 对SAP系统中的报表,最方便的格式就是ALV了,可排序、可导出,非常友好。 但有些常见报表却不是默认ALV界面的,譬如MB52: 是不是有点别扭?但其实是可以后台配置进行调整的。 现将一些常用报表修改为默认ALV的方法进行总结,便于大家使用。 一、MB52、MB5…...
Flutter 开发入门:从一个简单的计数器应用开始
在当今快速发展的移动应用开发领域,Flutter 框架以其高效、跨平台的特点脱颖而出,成为许多开发者的首选。本文将通过一个简单的 Flutter 项目代码,带你深入了解 Flutter 开发的基本概念和流程。这个项目是一个简单的计数器应用,它…...
Python解释器、REPL与脚本的区别
用ChatGPT做软件测试 “初学者写代码,高手理解运行。” 要成为真正理解代码的人,必须透彻理解:Python 是如何运行你的代码的?解释器、REPL 和脚本之间的界限与联系究竟是什么? 一、编程学习常见误区:把“运…...
总共76dp 空出20dp然后放一个控件的写法
<FrameLayout android:id"id/bt_user_agree" android:layout_width"120dp" android:layout_height"76dp" > <ImageView android: 这里里上一个 android:layout_width"wrap_content" android:layout_height"40dp" …...
【PmHub后端篇】PmHub集成 Sentinel+OpenFeign实现网关流量控制与服务降级
在微服务架构中,保障服务的稳定性和高可用性至关重要。本文将详细介绍在 PmHub 中如何利用 Sentinel Gateway 进行网关限流,以及集成 Sentinel OpenFeign 实现自定义的 fallback 服务降级。 1 熔断降级的必要性 在微服务架构中,服务间的调…...