1543 lines
46 KiB
HTML
1543 lines
46 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>产线通讯信号可视化监控看板</title>
|
||
<style>
|
||
:root {
|
||
--bg: #07111d;
|
||
--bg-soft: rgba(10, 22, 38, 0.84);
|
||
--panel: rgba(10, 24, 42, 0.76);
|
||
--panel-strong: rgba(8, 18, 32, 0.9);
|
||
--line: rgba(114, 206, 255, 0.22);
|
||
--cyan: #6fd4ff;
|
||
--cyan-strong: #4bb5ff;
|
||
--green: #27d980;
|
||
--blue: #31a6ff;
|
||
--yellow: #f3c64e;
|
||
--red: #ff5d6c;
|
||
--text: #e8f3ff;
|
||
--text-soft: #8ca8c8;
|
||
--shadow: 0 16px 48px rgba(0, 0, 0, 0.35);
|
||
}
|
||
|
||
* {
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
html,
|
||
body {
|
||
margin: 0;
|
||
min-height: 100%;
|
||
background:
|
||
radial-gradient(circle at top left, rgba(39, 117, 203, 0.18), transparent 28%),
|
||
radial-gradient(circle at top right, rgba(0, 195, 255, 0.1), transparent 24%),
|
||
linear-gradient(180deg, #06101a 0%, #07111d 45%, #081523 100%);
|
||
color: var(--text);
|
||
font-family: "Microsoft YaHei", "PingFang SC", "Segoe UI", sans-serif;
|
||
}
|
||
|
||
body {
|
||
padding: 14px;
|
||
}
|
||
|
||
.dashboard {
|
||
min-height: calc(100vh - 28px);
|
||
display: grid;
|
||
grid-template-rows: 86px minmax(0, 1fr) 272px;
|
||
gap: 14px;
|
||
}
|
||
|
||
.panel {
|
||
border: 1px solid var(--line);
|
||
background: var(--panel);
|
||
box-shadow: var(--shadow);
|
||
backdrop-filter: blur(10px);
|
||
border-radius: 8px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.topbar {
|
||
display: grid;
|
||
grid-template-columns: 360px 1fr 560px;
|
||
align-items: stretch;
|
||
gap: 14px;
|
||
}
|
||
|
||
.title-block {
|
||
padding: 16px 20px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
background:
|
||
linear-gradient(90deg, rgba(38, 102, 173, 0.28), rgba(10, 24, 42, 0.2)),
|
||
var(--panel-strong);
|
||
}
|
||
|
||
.eyebrow {
|
||
color: var(--cyan);
|
||
font-size: 12px;
|
||
letter-spacing: 1px;
|
||
text-transform: uppercase;
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
h1 {
|
||
margin: 0;
|
||
font-size: 28px;
|
||
line-height: 1.1;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.subtitle {
|
||
margin-top: 8px;
|
||
color: var(--text-soft);
|
||
font-size: 13px;
|
||
}
|
||
|
||
.top-center {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||
gap: 12px;
|
||
padding: 12px;
|
||
}
|
||
|
||
.kpi {
|
||
padding: 14px 16px;
|
||
border: 1px solid rgba(114, 206, 255, 0.16);
|
||
background: linear-gradient(180deg, rgba(14, 30, 50, 0.92), rgba(8, 20, 34, 0.8));
|
||
border-radius: 8px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
gap: 6px;
|
||
}
|
||
|
||
.kpi-label {
|
||
color: var(--text-soft);
|
||
font-size: 12px;
|
||
}
|
||
|
||
.kpi-value {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: 8px;
|
||
font-size: 30px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.kpi-meta {
|
||
color: var(--text-soft);
|
||
font-size: 12px;
|
||
}
|
||
|
||
.status-board {
|
||
padding: 12px;
|
||
display: grid;
|
||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||
gap: 10px;
|
||
align-content: center;
|
||
}
|
||
|
||
.mini-stat {
|
||
border-radius: 8px;
|
||
padding: 12px 14px;
|
||
background: linear-gradient(180deg, rgba(12, 28, 48, 0.94), rgba(8, 18, 32, 0.84));
|
||
border: 1px solid rgba(114, 206, 255, 0.15);
|
||
}
|
||
|
||
.mini-stat .label {
|
||
font-size: 12px;
|
||
color: var(--text-soft);
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
.mini-stat .value {
|
||
font-size: 22px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.main {
|
||
display: grid;
|
||
grid-template-columns: 360px minmax(0, 1fr) 380px;
|
||
gap: 14px;
|
||
min-height: 0;
|
||
}
|
||
|
||
.column {
|
||
min-height: 0;
|
||
display: grid;
|
||
gap: 14px;
|
||
}
|
||
|
||
.column.left {
|
||
grid-template-rows: 268px 1fr 230px;
|
||
}
|
||
|
||
.column.right {
|
||
grid-template-rows: 360px 1fr;
|
||
}
|
||
|
||
.section {
|
||
display: flex;
|
||
flex-direction: column;
|
||
min-height: 0;
|
||
}
|
||
|
||
.section-header {
|
||
height: 44px;
|
||
padding: 0 16px;
|
||
border-bottom: 1px solid rgba(114, 206, 255, 0.12);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
background: rgba(8, 18, 32, 0.44);
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 15px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.section-note {
|
||
color: var(--text-soft);
|
||
font-size: 12px;
|
||
}
|
||
|
||
.section-body {
|
||
flex: 1;
|
||
min-height: 0;
|
||
padding: 14px;
|
||
}
|
||
|
||
.unit-list {
|
||
display: grid;
|
||
gap: 10px;
|
||
}
|
||
|
||
.unit-card {
|
||
border: 1px solid rgba(114, 206, 255, 0.14);
|
||
border-radius: 8px;
|
||
padding: 12px;
|
||
background: rgba(8, 18, 32, 0.58);
|
||
}
|
||
|
||
.unit-top {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.unit-name {
|
||
font-size: 15px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.unit-status {
|
||
font-size: 12px;
|
||
padding: 4px 8px;
|
||
border-radius: 999px;
|
||
background: rgba(39, 217, 128, 0.18);
|
||
color: #8effc2;
|
||
}
|
||
|
||
.unit-status.warn {
|
||
background: rgba(243, 198, 78, 0.18);
|
||
color: #ffe08b;
|
||
}
|
||
|
||
.unit-status.alarm {
|
||
background: rgba(255, 93, 108, 0.18);
|
||
color: #ff98a3;
|
||
}
|
||
|
||
.signal-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||
gap: 10px;
|
||
}
|
||
|
||
.signal {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
color: var(--text-soft);
|
||
font-size: 12px;
|
||
}
|
||
|
||
.dot {
|
||
width: 10px;
|
||
height: 10px;
|
||
border-radius: 50%;
|
||
box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.04);
|
||
flex: 0 0 auto;
|
||
}
|
||
|
||
.dot.green { background: var(--green); }
|
||
.dot.blue { background: var(--blue); }
|
||
.dot.yellow { background: var(--yellow); }
|
||
.dot.red { background: var(--red); }
|
||
.dot.gray { background: #54667d; }
|
||
|
||
.task-grid {
|
||
display: grid;
|
||
gap: 12px;
|
||
}
|
||
|
||
.task-card {
|
||
padding: 14px;
|
||
border-radius: 8px;
|
||
border: 1px solid rgba(114, 206, 255, 0.14);
|
||
background: linear-gradient(180deg, rgba(11, 24, 42, 0.9), rgba(8, 18, 32, 0.75));
|
||
}
|
||
|
||
.task-head,
|
||
.task-foot,
|
||
.flow-head {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
gap: 8px;
|
||
align-items: center;
|
||
}
|
||
|
||
.task-id {
|
||
font-size: 18px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.badge {
|
||
padding: 4px 8px;
|
||
border-radius: 999px;
|
||
font-size: 12px;
|
||
background: rgba(49, 166, 255, 0.18);
|
||
color: #8cccff;
|
||
}
|
||
|
||
.task-route {
|
||
margin: 14px 0 10px;
|
||
padding: 12px;
|
||
border-radius: 8px;
|
||
background: rgba(7, 18, 31, 0.72);
|
||
border: 1px solid rgba(114, 206, 255, 0.12);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 10px;
|
||
}
|
||
|
||
.route-node {
|
||
flex: 1;
|
||
text-align: center;
|
||
}
|
||
|
||
.route-label {
|
||
font-size: 11px;
|
||
color: var(--text-soft);
|
||
margin-bottom: 4px;
|
||
}
|
||
|
||
.route-value {
|
||
font-size: 22px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.route-arrow {
|
||
color: var(--cyan);
|
||
font-size: 26px;
|
||
flex: 0 0 auto;
|
||
}
|
||
|
||
.task-meta {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||
gap: 10px;
|
||
margin-top: 10px;
|
||
}
|
||
|
||
.meta-card {
|
||
padding: 10px;
|
||
border-radius: 8px;
|
||
background: rgba(255, 255, 255, 0.03);
|
||
}
|
||
|
||
.meta-label {
|
||
font-size: 11px;
|
||
color: var(--text-soft);
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
.meta-value {
|
||
font-size: 14px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.flow-grid {
|
||
display: grid;
|
||
gap: 12px;
|
||
}
|
||
|
||
.flow-card {
|
||
padding: 12px;
|
||
border-radius: 8px;
|
||
border: 1px solid rgba(114, 206, 255, 0.14);
|
||
background: rgba(8, 18, 32, 0.65);
|
||
}
|
||
|
||
.flow-title {
|
||
font-weight: 700;
|
||
}
|
||
|
||
.steps {
|
||
margin-top: 12px;
|
||
display: grid;
|
||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||
gap: 8px;
|
||
align-items: center;
|
||
}
|
||
|
||
.step {
|
||
position: relative;
|
||
text-align: center;
|
||
padding-top: 22px;
|
||
color: var(--text-soft);
|
||
font-size: 11px;
|
||
}
|
||
|
||
.step::before {
|
||
content: "";
|
||
position: absolute;
|
||
top: 0;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
width: 12px;
|
||
height: 12px;
|
||
border-radius: 50%;
|
||
background: #54667d;
|
||
box-shadow: 0 0 0 4px rgba(255,255,255,0.03);
|
||
}
|
||
|
||
.step.active::before {
|
||
background: var(--blue);
|
||
box-shadow: 0 0 12px rgba(49, 166, 255, 0.55);
|
||
}
|
||
|
||
.step.done::before {
|
||
background: var(--green);
|
||
box-shadow: 0 0 12px rgba(39, 217, 128, 0.45);
|
||
}
|
||
|
||
.step.error::before {
|
||
background: var(--red);
|
||
box-shadow: 0 0 12px rgba(255, 93, 108, 0.45);
|
||
}
|
||
|
||
.model-panel {
|
||
position: relative;
|
||
min-height: 0;
|
||
overflow: hidden;
|
||
background:
|
||
linear-gradient(180deg, rgba(6, 14, 25, 0.12), rgba(6, 14, 25, 0.28)),
|
||
rgba(8, 18, 32, 0.7);
|
||
}
|
||
|
||
.model-stage {
|
||
position: absolute;
|
||
inset: 0;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.model-frame {
|
||
position: absolute;
|
||
inset: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
border: 0;
|
||
opacity: 0.92;
|
||
filter: saturate(0.75) contrast(1.05) brightness(0.8);
|
||
}
|
||
|
||
.model-overlay {
|
||
position: absolute;
|
||
inset: 0;
|
||
background:
|
||
radial-gradient(circle at center, rgba(17, 110, 180, 0.12), transparent 44%),
|
||
linear-gradient(180deg, rgba(4, 12, 22, 0.1), rgba(5, 10, 18, 0.4));
|
||
pointer-events: none;
|
||
}
|
||
|
||
.model-grid {
|
||
position: absolute;
|
||
inset: 0;
|
||
background-image:
|
||
linear-gradient(rgba(111, 212, 255, 0.08) 1px, transparent 1px),
|
||
linear-gradient(90deg, rgba(111, 212, 255, 0.08) 1px, transparent 1px);
|
||
background-size: 72px 72px;
|
||
mask-image: linear-gradient(180deg, transparent 0%, rgba(0,0,0,0.75) 18%, rgba(0,0,0,0.75) 82%, transparent 100%);
|
||
opacity: 0.32;
|
||
}
|
||
|
||
.hud-top {
|
||
position: absolute;
|
||
top: 18px;
|
||
left: 18px;
|
||
right: 18px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
gap: 16px;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.hud-card {
|
||
min-width: 220px;
|
||
max-width: 32%;
|
||
border-radius: 8px;
|
||
border: 1px solid rgba(114, 206, 255, 0.22);
|
||
background: rgba(8, 18, 32, 0.42);
|
||
padding: 12px 14px;
|
||
backdrop-filter: blur(6px);
|
||
}
|
||
|
||
.hud-card h3 {
|
||
margin: 0 0 10px;
|
||
font-size: 13px;
|
||
color: var(--cyan);
|
||
}
|
||
|
||
.hud-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
gap: 12px;
|
||
font-size: 12px;
|
||
color: var(--text-soft);
|
||
margin-top: 6px;
|
||
}
|
||
|
||
.hud-row strong {
|
||
color: var(--text);
|
||
font-size: 14px;
|
||
}
|
||
|
||
.device-tag {
|
||
position: absolute;
|
||
padding: 8px 10px;
|
||
border-radius: 8px;
|
||
border: 1px solid rgba(114, 206, 255, 0.18);
|
||
background: rgba(8, 18, 32, 0.42);
|
||
backdrop-filter: blur(6px);
|
||
min-width: 116px;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.device-tag.alert {
|
||
border-color: rgba(255, 93, 108, 0.52);
|
||
box-shadow: 0 0 18px rgba(255, 93, 108, 0.16);
|
||
}
|
||
|
||
.device-name {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
font-size: 12px;
|
||
font-weight: 700;
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
.device-meta {
|
||
font-size: 11px;
|
||
color: var(--text-soft);
|
||
line-height: 1.45;
|
||
}
|
||
|
||
.path-line {
|
||
position: absolute;
|
||
left: 14%;
|
||
right: 16%;
|
||
bottom: 24%;
|
||
height: 2px;
|
||
background: linear-gradient(90deg, rgba(111, 212, 255, 0), rgba(111, 212, 255, 0.85), rgba(111, 212, 255, 0));
|
||
box-shadow: 0 0 14px rgba(111, 212, 255, 0.3);
|
||
}
|
||
|
||
.path-line::before,
|
||
.path-line::after {
|
||
content: "";
|
||
position: absolute;
|
||
top: 50%;
|
||
width: 12px;
|
||
height: 12px;
|
||
margin-top: -6px;
|
||
border-radius: 50%;
|
||
background: var(--cyan);
|
||
box-shadow: 0 0 18px rgba(111, 212, 255, 0.55);
|
||
}
|
||
|
||
.path-line::before { left: 0; }
|
||
.path-line::after { right: 0; }
|
||
|
||
.path-flow {
|
||
position: absolute;
|
||
top: -4px;
|
||
left: 22%;
|
||
width: 10px;
|
||
height: 10px;
|
||
border-radius: 50%;
|
||
background: #89ddff;
|
||
box-shadow: 0 0 18px rgba(111, 212, 255, 0.85);
|
||
animation: travel 3.8s linear infinite;
|
||
}
|
||
|
||
@keyframes travel {
|
||
from { left: 0; }
|
||
to { left: calc(100% - 10px); }
|
||
}
|
||
|
||
.stage-caption {
|
||
position: absolute;
|
||
left: 18px;
|
||
bottom: 18px;
|
||
padding: 12px 14px;
|
||
border-radius: 8px;
|
||
background: rgba(8, 18, 32, 0.48);
|
||
border: 1px solid rgba(114, 206, 255, 0.18);
|
||
backdrop-filter: blur(6px);
|
||
max-width: 360px;
|
||
}
|
||
|
||
.stage-caption strong {
|
||
display: block;
|
||
margin-bottom: 6px;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.stage-caption p {
|
||
margin: 0;
|
||
color: var(--text-soft);
|
||
font-size: 12px;
|
||
line-height: 1.55;
|
||
}
|
||
|
||
.equipment-table,
|
||
.assist-grid,
|
||
.bottom-grid {
|
||
display: grid;
|
||
gap: 10px;
|
||
}
|
||
|
||
.equipment-row {
|
||
display: grid;
|
||
grid-template-columns: 116px 88px 88px 1fr 62px;
|
||
gap: 10px;
|
||
align-items: center;
|
||
border: 1px solid rgba(114, 206, 255, 0.12);
|
||
border-radius: 8px;
|
||
padding: 10px 12px;
|
||
background: rgba(8, 18, 32, 0.58);
|
||
font-size: 12px;
|
||
}
|
||
|
||
.equipment-row.alarm {
|
||
border-color: rgba(255, 93, 108, 0.35);
|
||
background: rgba(52, 10, 18, 0.5);
|
||
}
|
||
|
||
.equip-name {
|
||
font-weight: 700;
|
||
font-size: 13px;
|
||
}
|
||
|
||
.equip-col .label {
|
||
color: var(--text-soft);
|
||
font-size: 11px;
|
||
margin-bottom: 4px;
|
||
}
|
||
|
||
.equip-col .value {
|
||
font-weight: 700;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.status-strip {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 6px;
|
||
}
|
||
|
||
.status-pill {
|
||
padding: 4px 8px;
|
||
border-radius: 999px;
|
||
font-size: 11px;
|
||
background: rgba(255,255,255,0.05);
|
||
color: var(--text-soft);
|
||
}
|
||
|
||
.status-pill.on {
|
||
color: #9be7ff;
|
||
background: rgba(49, 166, 255, 0.18);
|
||
}
|
||
|
||
.status-pill.ok {
|
||
color: #8effc2;
|
||
background: rgba(39, 217, 128, 0.18);
|
||
}
|
||
|
||
.status-pill.warn {
|
||
color: #ffe08b;
|
||
background: rgba(243, 198, 78, 0.18);
|
||
}
|
||
|
||
.status-pill.alarm {
|
||
color: #ff98a3;
|
||
background: rgba(255, 93, 108, 0.18);
|
||
}
|
||
|
||
.assist-grid {
|
||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||
}
|
||
|
||
.assist-card {
|
||
padding: 12px;
|
||
border-radius: 8px;
|
||
border: 1px solid rgba(114, 206, 255, 0.12);
|
||
background: rgba(8, 18, 32, 0.58);
|
||
}
|
||
|
||
.assist-title {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
gap: 8px;
|
||
align-items: center;
|
||
font-weight: 700;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.mini-flow {
|
||
display: flex;
|
||
gap: 6px;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.bottom {
|
||
display: grid;
|
||
grid-template-columns: 1.2fr 1fr 1fr;
|
||
gap: 14px;
|
||
min-height: 0;
|
||
}
|
||
|
||
.storage-groups {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||
gap: 12px;
|
||
}
|
||
|
||
.storage-card {
|
||
border-radius: 8px;
|
||
border: 1px solid rgba(114, 206, 255, 0.12);
|
||
background: rgba(8, 18, 32, 0.58);
|
||
padding: 12px;
|
||
}
|
||
|
||
.storage-head {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
gap: 8px;
|
||
align-items: center;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.storage-head strong {
|
||
font-size: 14px;
|
||
}
|
||
|
||
.storage-head span {
|
||
color: var(--text-soft);
|
||
font-size: 12px;
|
||
}
|
||
|
||
.slots {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||
gap: 8px;
|
||
}
|
||
|
||
.slot {
|
||
aspect-ratio: 1;
|
||
border-radius: 6px;
|
||
border: 1px solid rgba(114, 206, 255, 0.14);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 12px;
|
||
color: var(--text-soft);
|
||
background: rgba(255, 255, 255, 0.03);
|
||
}
|
||
|
||
.slot.filled {
|
||
color: #d8f5ff;
|
||
background: linear-gradient(180deg, rgba(49, 166, 255, 0.26), rgba(39, 217, 128, 0.2));
|
||
box-shadow: inset 0 0 0 1px rgba(126, 233, 255, 0.2);
|
||
}
|
||
|
||
.table-list {
|
||
display: grid;
|
||
gap: 8px;
|
||
max-height: 100%;
|
||
overflow: auto;
|
||
padding-right: 2px;
|
||
}
|
||
|
||
.event-row,
|
||
.log-row {
|
||
display: grid;
|
||
gap: 10px;
|
||
border-radius: 8px;
|
||
padding: 10px 12px;
|
||
border: 1px solid rgba(114, 206, 255, 0.12);
|
||
background: rgba(8, 18, 32, 0.58);
|
||
font-size: 12px;
|
||
}
|
||
|
||
.event-row {
|
||
grid-template-columns: 66px 76px 82px 62px 1fr;
|
||
align-items: center;
|
||
}
|
||
|
||
.event-level {
|
||
font-size: 11px;
|
||
padding: 4px 8px;
|
||
border-radius: 999px;
|
||
text-align: center;
|
||
}
|
||
|
||
.event-level.critical {
|
||
color: #ff98a3;
|
||
background: rgba(255, 93, 108, 0.18);
|
||
}
|
||
|
||
.event-level.warn {
|
||
color: #ffe08b;
|
||
background: rgba(243, 198, 78, 0.18);
|
||
}
|
||
|
||
.log-row {
|
||
grid-template-columns: 66px 1fr;
|
||
align-items: start;
|
||
}
|
||
|
||
.muted {
|
||
color: var(--text-soft);
|
||
}
|
||
|
||
.scroll {
|
||
overflow: auto;
|
||
}
|
||
|
||
@media (max-width: 1600px) {
|
||
.main {
|
||
grid-template-columns: 320px minmax(0, 1fr) 340px;
|
||
}
|
||
|
||
.topbar {
|
||
grid-template-columns: 320px 1fr 500px;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="dashboard">
|
||
<div class="topbar">
|
||
<section class="panel title-block">
|
||
<div class="eyebrow">Industrial signal board</div>
|
||
<h1>产线通讯信号可视化监控看板</h1>
|
||
<div class="subtitle">长地轨 / 短地轨 / 关节机器人 / 加工设备 / 物料库联动监控</div>
|
||
</section>
|
||
|
||
<section class="panel top-center">
|
||
<div class="kpi">
|
||
<div class="kpi-label">在线单元</div>
|
||
<div class="kpi-value">3 <span class="muted">/ 3</span></div>
|
||
<div class="kpi-meta">PCS 运行信号全部在线</div>
|
||
</div>
|
||
<div class="kpi">
|
||
<div class="kpi-label">自动模式</div>
|
||
<div class="kpi-value">2 <span class="muted">单元</span></div>
|
||
<div class="kpi-meta">关节单元等待人工复位</div>
|
||
</div>
|
||
<div class="kpi">
|
||
<div class="kpi-label">允许接收任务</div>
|
||
<div class="kpi-value">3 <span class="muted">单元</span></div>
|
||
<div class="kpi-meta">当前可派发搬运任务</div>
|
||
</div>
|
||
<div class="kpi">
|
||
<div class="kpi-label">执行中任务</div>
|
||
<div class="kpi-value">2 <span class="muted">条</span></div>
|
||
<div class="kpi-meta">短地轨与关节单元忙碌</div>
|
||
</div>
|
||
<div class="kpi">
|
||
<div class="kpi-label">当前报警</div>
|
||
<div class="kpi-value">3 <span class="muted">条</span></div>
|
||
<div class="kpi-meta">含设备报警和测量错误</div>
|
||
</div>
|
||
<div class="kpi">
|
||
<div class="kpi-label">库位占用率</div>
|
||
<div class="kpi-value">67% <span class="muted">16 / 24</span></div>
|
||
<div class="kpi-meta">可用于节拍与供料判断</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="panel status-board">
|
||
<div class="mini-stat">
|
||
<div class="label">通讯状态</div>
|
||
<div class="value">稳定</div>
|
||
</div>
|
||
<div class="mini-stat">
|
||
<div class="label">最近刷新</div>
|
||
<div class="value" id="clock">2026-06-24 10:31:25</div>
|
||
</div>
|
||
<div class="mini-stat">
|
||
<div class="label">任务节拍</div>
|
||
<div class="value">92s</div>
|
||
</div>
|
||
<div class="mini-stat">
|
||
<div class="label">程序一致性</div>
|
||
<div class="value">5 / 6</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
|
||
<div class="main">
|
||
<div class="column left">
|
||
<section class="panel section">
|
||
<div class="section-header">
|
||
<div class="section-title">线体状态总览</div>
|
||
<div class="section-note">PCS / AUTO / ALLOW / EMG</div>
|
||
</div>
|
||
<div class="section-body scroll">
|
||
<div class="unit-list">
|
||
<div class="unit-card">
|
||
<div class="unit-top">
|
||
<div class="unit-name">长地轨</div>
|
||
<div class="unit-status">可派发任务</div>
|
||
</div>
|
||
<div class="signal-grid">
|
||
<div class="signal"><span class="dot green"></span>PCS 运行</div>
|
||
<div class="signal"><span class="dot green"></span>允许接收任务</div>
|
||
<div class="signal"><span class="dot green"></span>自动模式</div>
|
||
<div class="signal"><span class="dot gray"></span>急停未触发</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="unit-card">
|
||
<div class="unit-top">
|
||
<div class="unit-name">短地轨</div>
|
||
<div class="unit-status">可派发任务</div>
|
||
</div>
|
||
<div class="signal-grid">
|
||
<div class="signal"><span class="dot green"></span>PCS 运行</div>
|
||
<div class="signal"><span class="dot green"></span>允许接收任务</div>
|
||
<div class="signal"><span class="dot green"></span>自动模式</div>
|
||
<div class="signal"><span class="dot gray"></span>急停未触发</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="unit-card">
|
||
<div class="unit-top">
|
||
<div class="unit-name">关节</div>
|
||
<div class="unit-status warn">人工确认中</div>
|
||
</div>
|
||
<div class="signal-grid">
|
||
<div class="signal"><span class="dot green"></span>PCS 运行</div>
|
||
<div class="signal"><span class="dot green"></span>允许接收任务</div>
|
||
<div class="signal"><span class="dot yellow"></span>自动待恢复</div>
|
||
<div class="signal"><span class="dot gray"></span>急停未触发</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="panel section">
|
||
<div class="section-header">
|
||
<div class="section-title">机器人任务监控</div>
|
||
<div class="section-note">TASK / START / END / RECIPE</div>
|
||
</div>
|
||
<div class="section-body scroll">
|
||
<div class="task-grid">
|
||
<div class="task-card">
|
||
<div class="task-head">
|
||
<div>
|
||
<div class="muted">长地轨</div>
|
||
<div class="task-id">#1024</div>
|
||
</div>
|
||
<div class="badge">执行中</div>
|
||
</div>
|
||
<div class="task-route">
|
||
<div class="route-node">
|
||
<div class="route-label">起始位置</div>
|
||
<div class="route-value">01</div>
|
||
</div>
|
||
<div class="route-arrow">→</div>
|
||
<div class="route-node">
|
||
<div class="route-label">结束位置</div>
|
||
<div class="route-value">06</div>
|
||
</div>
|
||
</div>
|
||
<div class="task-meta">
|
||
<div class="meta-card">
|
||
<div class="meta-label">配方号</div>
|
||
<div class="meta-value">RCP-01</div>
|
||
</div>
|
||
<div class="meta-card">
|
||
<div class="meta-label">托盘类型</div>
|
||
<div class="meta-value">Pallet-A</div>
|
||
</div>
|
||
<div class="meta-card">
|
||
<div class="meta-label">零件类型</div>
|
||
<div class="meta-value">-</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="task-card">
|
||
<div class="task-head">
|
||
<div>
|
||
<div class="muted">短地轨</div>
|
||
<div class="task-id">#2048</div>
|
||
</div>
|
||
<div class="badge">准备就绪</div>
|
||
</div>
|
||
<div class="task-route">
|
||
<div class="route-node">
|
||
<div class="route-label">起始位置</div>
|
||
<div class="route-value">03</div>
|
||
</div>
|
||
<div class="route-arrow">→</div>
|
||
<div class="route-node">
|
||
<div class="route-label">结束位置</div>
|
||
<div class="route-value">09</div>
|
||
</div>
|
||
</div>
|
||
<div class="task-meta">
|
||
<div class="meta-card">
|
||
<div class="meta-label">配方号</div>
|
||
<div class="meta-value">RCP-09</div>
|
||
</div>
|
||
<div class="meta-card">
|
||
<div class="meta-label">托盘类型</div>
|
||
<div class="meta-value">Pallet-C</div>
|
||
</div>
|
||
<div class="meta-card">
|
||
<div class="meta-label">零件类型</div>
|
||
<div class="meta-value">短轴</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="task-card">
|
||
<div class="task-head">
|
||
<div>
|
||
<div class="muted">关节</div>
|
||
<div class="task-id">#3086</div>
|
||
</div>
|
||
<div class="badge" style="background: rgba(255, 93, 108, 0.18); color: #ff98a3;">异常中断</div>
|
||
</div>
|
||
<div class="task-route">
|
||
<div class="route-node">
|
||
<div class="route-label">起始位置</div>
|
||
<div class="route-value">02</div>
|
||
</div>
|
||
<div class="route-arrow">→</div>
|
||
<div class="route-node">
|
||
<div class="route-label">结束位置</div>
|
||
<div class="route-value">04</div>
|
||
</div>
|
||
</div>
|
||
<div class="task-meta">
|
||
<div class="meta-card">
|
||
<div class="meta-label">配方号</div>
|
||
<div class="meta-value">RCP-11</div>
|
||
</div>
|
||
<div class="meta-card">
|
||
<div class="meta-label">托盘类型</div>
|
||
<div class="meta-value">Pallet-B</div>
|
||
</div>
|
||
<div class="meta-card">
|
||
<div class="meta-label">零件类型</div>
|
||
<div class="meta-value">长轴</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="panel section">
|
||
<div class="section-header">
|
||
<div class="section-title">机器人反馈流程</div>
|
||
<div class="section-note">FLAG → READY → BUSY → COMPLETE</div>
|
||
</div>
|
||
<div class="section-body scroll">
|
||
<div class="flow-grid">
|
||
<div class="flow-card">
|
||
<div class="flow-head">
|
||
<div class="flow-title">长地轨</div>
|
||
<div class="badge">BUSY</div>
|
||
</div>
|
||
<div class="steps">
|
||
<div class="step done">FLAG</div>
|
||
<div class="step done">READY</div>
|
||
<div class="step active">BUSY</div>
|
||
<div class="step">COMPLETE</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flow-card">
|
||
<div class="flow-head">
|
||
<div class="flow-title">短地轨</div>
|
||
<div class="badge">READY</div>
|
||
</div>
|
||
<div class="steps">
|
||
<div class="step done">FLAG</div>
|
||
<div class="step active">READY</div>
|
||
<div class="step">BUSY</div>
|
||
<div class="step">COMPLETE</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flow-card">
|
||
<div class="flow-head">
|
||
<div class="flow-title">关节</div>
|
||
<div class="badge" style="background: rgba(255, 93, 108, 0.18); color: #ff98a3;">ERROR</div>
|
||
</div>
|
||
<div class="steps">
|
||
<div class="step done">FLAG</div>
|
||
<div class="step done">READY</div>
|
||
<div class="step error">BUSY</div>
|
||
<div class="step">COMPLETE</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
|
||
<section class="panel model-panel">
|
||
<div class="model-stage">
|
||
<iframe class="model-frame" src="https://www.baidu.com" title="三维模型占位"></iframe>
|
||
<div class="model-overlay"></div>
|
||
<div class="model-grid"></div>
|
||
|
||
<div class="hud-top">
|
||
<div class="hud-card">
|
||
<h3>搬运路径</h3>
|
||
<div class="hud-row"><span>当前任务</span><strong>#1024</strong></div>
|
||
<div class="hud-row"><span>路径</span><strong>长地轨 01 → 06</strong></div>
|
||
<div class="hud-row"><span>状态</span><strong>执行中</strong></div>
|
||
</div>
|
||
<div class="hud-card">
|
||
<h3>模型叠加说明</h3>
|
||
<div class="hud-row"><span>iframe</span><strong>百度占位</strong></div>
|
||
<div class="hud-row"><span>图表层</span><strong>半透明 HUD</strong></div>
|
||
<div class="hud-row"><span>交互</span><strong>可替换真实三维模型</strong></div>
|
||
</div>
|
||
<div class="hud-card">
|
||
<h3>模型区域联动</h3>
|
||
<div class="hud-row"><span>高亮单元</span><strong>关节 / 短地轨</strong></div>
|
||
<div class="hud-row"><span>报警设备</span><strong>MAZAK / 测量仪</strong></div>
|
||
<div class="hud-row"><span>库位同步</span><strong>长地轨 S4 / S7</strong></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="device-tag" style="left: 8%; top: 26%;">
|
||
<div class="device-name"><span class="dot green"></span>长地轨</div>
|
||
<div class="device-meta">PCS 运行<br>任务 #1024</div>
|
||
</div>
|
||
|
||
<div class="device-tag" style="left: 28%; top: 18%;">
|
||
<div class="device-name"><span class="dot blue"></span>F500</div>
|
||
<div class="device-meta">程序 1202 / 1202<br>自动运行中</div>
|
||
</div>
|
||
|
||
<div class="device-tag" style="left: 44%; top: 23%;">
|
||
<div class="device-name"><span class="dot green"></span>L2000LSY</div>
|
||
<div class="device-meta">上料完成<br>下料完成</div>
|
||
</div>
|
||
|
||
<div class="device-tag" style="left: 62%; top: 19%;">
|
||
<div class="device-name"><span class="dot yellow"></span>L2100SY</div>
|
||
<div class="device-meta">程序待同步<br>D:3301 A:3298</div>
|
||
</div>
|
||
|
||
<div class="device-tag" style="left: 18%; top: 58%;">
|
||
<div class="device-name"><span class="dot green"></span>短地轨</div>
|
||
<div class="device-meta">允许接收任务<br>任务 #2048</div>
|
||
</div>
|
||
|
||
<div class="device-tag alert" style="left: 52%; top: 54%;">
|
||
<div class="device-name"><span class="dot red"></span>MAZAK</div>
|
||
<div class="device-meta">自动运行中<br>报警触发</div>
|
||
</div>
|
||
|
||
<div class="device-tag" style="left: 72%; top: 62%;">
|
||
<div class="device-name"><span class="dot blue"></span>YKD5132H</div>
|
||
<div class="device-meta">上料就绪<br>下料就绪</div>
|
||
</div>
|
||
|
||
<div class="device-tag alert" style="left: 78%; top: 34%;">
|
||
<div class="device-name"><span class="dot red"></span>测量仪</div>
|
||
<div class="device-meta">运行异常<br>等待复测</div>
|
||
</div>
|
||
|
||
<div class="path-line">
|
||
<div class="path-flow"></div>
|
||
</div>
|
||
|
||
<div class="stage-caption">
|
||
<strong>中央三维模型区</strong>
|
||
<p>当前使用百度页面作为 iframe 占位。后续替换真实三维模型地址后,可保留上方透明状态层,继续叠加设备标签、任务路径和报警定位。</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<div class="column right">
|
||
<section class="panel section">
|
||
<div class="section-header">
|
||
<div class="section-title">加工设备状态</div>
|
||
<div class="section-note">程序号 / 上下料 / 运行 / 报警</div>
|
||
</div>
|
||
<div class="section-body scroll">
|
||
<div class="equipment-table">
|
||
<div class="equipment-row">
|
||
<div class="equip-name">F500</div>
|
||
<div class="equip-col">
|
||
<div class="label">目标</div>
|
||
<div class="value">1202</div>
|
||
</div>
|
||
<div class="equip-col">
|
||
<div class="label">实际</div>
|
||
<div class="value">1202</div>
|
||
</div>
|
||
<div class="status-strip">
|
||
<span class="status-pill ok">上料完成</span>
|
||
<span class="status-pill ok">下料完成</span>
|
||
<span class="status-pill on">运行中</span>
|
||
</div>
|
||
<div class="status-pill ok">正常</div>
|
||
</div>
|
||
|
||
<div class="equipment-row">
|
||
<div class="equip-name">L2000LSY</div>
|
||
<div class="equip-col">
|
||
<div class="label">目标</div>
|
||
<div class="value">2206</div>
|
||
</div>
|
||
<div class="equip-col">
|
||
<div class="label">实际</div>
|
||
<div class="value">2206</div>
|
||
</div>
|
||
<div class="status-strip">
|
||
<span class="status-pill ok">上料完成</span>
|
||
<span class="status-pill ok">下料完成</span>
|
||
<span class="status-pill">待命</span>
|
||
</div>
|
||
<div class="status-pill ok">正常</div>
|
||
</div>
|
||
|
||
<div class="equipment-row">
|
||
<div class="equip-name">L2100SY</div>
|
||
<div class="equip-col">
|
||
<div class="label">目标</div>
|
||
<div class="value">3301</div>
|
||
</div>
|
||
<div class="equip-col">
|
||
<div class="label">实际</div>
|
||
<div class="value">3298</div>
|
||
</div>
|
||
<div class="status-strip">
|
||
<span class="status-pill warn">程序待同步</span>
|
||
<span class="status-pill on">运行中</span>
|
||
</div>
|
||
<div class="status-pill warn">预警</div>
|
||
</div>
|
||
|
||
<div class="equipment-row">
|
||
<div class="equip-name">新日</div>
|
||
<div class="equip-col">
|
||
<div class="label">目标</div>
|
||
<div class="value">4108</div>
|
||
</div>
|
||
<div class="equip-col">
|
||
<div class="label">实际</div>
|
||
<div class="value">4108</div>
|
||
</div>
|
||
<div class="status-strip">
|
||
<span class="status-pill ok">上料就绪</span>
|
||
<span class="status-pill">下料等待</span>
|
||
<span class="status-pill on">运行中</span>
|
||
</div>
|
||
<div class="status-pill ok">正常</div>
|
||
</div>
|
||
|
||
<div class="equipment-row alarm">
|
||
<div class="equip-name">MAZAK</div>
|
||
<div class="equip-col">
|
||
<div class="label">目标</div>
|
||
<div class="value">-</div>
|
||
</div>
|
||
<div class="equip-col">
|
||
<div class="label">实际</div>
|
||
<div class="value">-</div>
|
||
</div>
|
||
<div class="status-strip">
|
||
<span class="status-pill ok">上料就绪</span>
|
||
<span class="status-pill on">运行中</span>
|
||
<span class="status-pill alarm">报警</span>
|
||
</div>
|
||
<div class="status-pill alarm">异常</div>
|
||
</div>
|
||
|
||
<div class="equipment-row">
|
||
<div class="equip-name">YKD5132H</div>
|
||
<div class="equip-col">
|
||
<div class="label">目标</div>
|
||
<div class="value">5104</div>
|
||
</div>
|
||
<div class="equip-col">
|
||
<div class="label">实际</div>
|
||
<div class="value">5104</div>
|
||
</div>
|
||
<div class="status-strip">
|
||
<span class="status-pill ok">上料就绪</span>
|
||
<span class="status-pill ok">下料就绪</span>
|
||
<span class="status-pill">待命</span>
|
||
</div>
|
||
<div class="status-pill ok">正常</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="panel section">
|
||
<div class="section-header">
|
||
<div class="section-title">辅助设备状态</div>
|
||
<div class="section-note">打标机 / 清洗机 / 测量仪</div>
|
||
</div>
|
||
<div class="section-body scroll">
|
||
<div class="assist-grid">
|
||
<div class="assist-card">
|
||
<div class="assist-title">
|
||
<span>长地轨打标机</span>
|
||
<span class="status-pill ok">待机中</span>
|
||
</div>
|
||
<div class="mini-flow">
|
||
<span class="status-pill ok">开机中</span>
|
||
<span class="status-pill">未触发 START</span>
|
||
<span class="status-pill">BUSY=0</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="assist-card">
|
||
<div class="assist-title">
|
||
<span>短地轨打标机</span>
|
||
<span class="status-pill on">打标完成保持</span>
|
||
</div>
|
||
<div class="mini-flow">
|
||
<span class="status-pill ok">开机中</span>
|
||
<span class="status-pill warn">脉冲 START 已触发</span>
|
||
<span class="status-pill on">BUSY 保持 1</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="assist-card">
|
||
<div class="assist-title">
|
||
<span>关节打标机</span>
|
||
<span class="status-pill">待命</span>
|
||
</div>
|
||
<div class="mini-flow">
|
||
<span class="status-pill ok">开机中</span>
|
||
<span class="status-pill">等待任务</span>
|
||
<span class="status-pill">IDLE=1</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="assist-card">
|
||
<div class="assist-title">
|
||
<span>清洗机</span>
|
||
<span class="status-pill on">运行中</span>
|
||
</div>
|
||
<div class="mini-flow">
|
||
<span class="status-pill ok">上料就绪</span>
|
||
<span class="status-pill on">BUSY=1</span>
|
||
<span class="status-pill">等待下料</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="assist-card">
|
||
<div class="assist-title">
|
||
<span>测量仪</span>
|
||
<span class="status-pill alarm">错误</span>
|
||
</div>
|
||
<div class="mini-flow">
|
||
<span class="status-pill warn">复测等待</span>
|
||
<span class="status-pill alarm">ERROR=1</span>
|
||
<span class="status-pill">下料未就绪</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="bottom">
|
||
<section class="panel section">
|
||
<div class="section-header">
|
||
<div class="section-title">物料库位矩阵</div>
|
||
<div class="section-note">总库位 24 / 当前有件 16</div>
|
||
</div>
|
||
<div class="section-body">
|
||
<div class="storage-groups">
|
||
<div class="storage-card">
|
||
<div class="storage-head">
|
||
<strong>长地轨</strong>
|
||
<span>6 / 9</span>
|
||
</div>
|
||
<div class="slots">
|
||
<div class="slot filled">S1</div>
|
||
<div class="slot filled">S2</div>
|
||
<div class="slot">S3</div>
|
||
<div class="slot filled">S4</div>
|
||
<div class="slot">S5</div>
|
||
<div class="slot filled">S6</div>
|
||
<div class="slot filled">S7</div>
|
||
<div class="slot">S8</div>
|
||
<div class="slot filled">S9</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="storage-card">
|
||
<div class="storage-head">
|
||
<strong>短地轨</strong>
|
||
<span>6 / 9</span>
|
||
</div>
|
||
<div class="slots">
|
||
<div class="slot filled">S1</div>
|
||
<div class="slot">S2</div>
|
||
<div class="slot filled">S3</div>
|
||
<div class="slot filled">S4</div>
|
||
<div class="slot">S5</div>
|
||
<div class="slot filled">S6</div>
|
||
<div class="slot">S7</div>
|
||
<div class="slot filled">S8</div>
|
||
<div class="slot filled">S9</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="storage-card">
|
||
<div class="storage-head">
|
||
<strong>关节</strong>
|
||
<span>4 / 6</span>
|
||
</div>
|
||
<div class="slots">
|
||
<div class="slot filled">S1</div>
|
||
<div class="slot">S2</div>
|
||
<div class="slot filled">S3</div>
|
||
<div class="slot">S4</div>
|
||
<div class="slot filled">S5</div>
|
||
<div class="slot filled">S6</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="panel section">
|
||
<div class="section-header">
|
||
<div class="section-title">报警与异常事件</div>
|
||
<div class="section-note">EMG / ERROR / ALARM / 程序不一致</div>
|
||
</div>
|
||
<div class="section-body">
|
||
<div class="table-list">
|
||
<div class="event-row">
|
||
<div>10:31:04</div>
|
||
<div>短地轨</div>
|
||
<div>MAZAK</div>
|
||
<div class="event-level critical">严重</div>
|
||
<div>设备报警触发,ALARM=1,建议定位机床侧运行条件。</div>
|
||
</div>
|
||
<div class="event-row">
|
||
<div>10:30:57</div>
|
||
<div>关节</div>
|
||
<div>测量仪</div>
|
||
<div class="event-level critical">严重</div>
|
||
<div>测量仪 ERROR=1,任务 #3086 中断,等待复测确认。</div>
|
||
</div>
|
||
<div class="event-row">
|
||
<div>10:30:32</div>
|
||
<div>长地轨</div>
|
||
<div>L2100SY</div>
|
||
<div class="event-level warn">警告</div>
|
||
<div>目标程序号 3301 与实际程序号 3298 不一致。</div>
|
||
</div>
|
||
<div class="event-row">
|
||
<div>10:29:48</div>
|
||
<div>关节</div>
|
||
<div>自动模式</div>
|
||
<div class="event-level warn">警告</div>
|
||
<div>AUTO_ACTIVE 从 1 变为 0,当前处于人工确认中。</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="panel section">
|
||
<div class="section-header">
|
||
<div class="section-title">任务日志</div>
|
||
<div class="section-note">创建 / 启动 / 执行 / 完成 / 异常</div>
|
||
</div>
|
||
<div class="section-body">
|
||
<div class="table-list">
|
||
<div class="log-row">
|
||
<div>10:31:08</div>
|
||
<div>长地轨 任务 #1024 起点 01 → 终点 06,配方 RCP-01,机器人保持 BUSY。</div>
|
||
</div>
|
||
<div class="log-row">
|
||
<div>10:30:54</div>
|
||
<div>短地轨 任务 #2048 已下发,READY=1,等待进入 BUSY。</div>
|
||
</div>
|
||
<div class="log-row">
|
||
<div>10:30:35</div>
|
||
<div>关节 任务 #3086 在测量仪工位异常中断,ERROR=1。</div>
|
||
</div>
|
||
<div class="log-row">
|
||
<div>10:29:40</div>
|
||
<div>长地轨 F500 上料完成,L2000LSY 下料完成,任务链路可继续派发。</div>
|
||
</div>
|
||
<div class="log-row">
|
||
<div>10:28:52</div>
|
||
<div>短地轨打标机 START 脉冲触发,BUSY 保持,等待后续清零。</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
function updateClock() {
|
||
const now = new Date();
|
||
const pad = (value) => String(value).padStart(2, "0");
|
||
const text = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
|
||
const clock = document.getElementById("clock");
|
||
if (clock) {
|
||
clock.textContent = text;
|
||
}
|
||
}
|
||
|
||
updateClock();
|
||
setInterval(updateClock, 1000);
|
||
</script>
|
||
</body>
|
||
</html>
|