feat: 装配线看板修正、统一密钥Hardman_2026、操作日志追溯、日志按天存储

Dashboard 移除 CNC/清洗机等不存在设备,改为纯装配线看板(扫码枪+拧紧枪+人工);JWT/内部token统一为 Hardman_2026 写入各 etc/*.yaml,MES 建表 DSN 改读 yaml;event_log 增加 workOrderNo/operator,BOM/备料/PLC下发/拧紧/扫码报工/半成品/AGV 全链路埋点,日志页支持工单号/操作人筛选;MES/WMS 日志按天存储(dailyWriter),WMS SetWriter 用 logx.NewWriter 适配
This commit is contained in:
SunYF
2026-08-28 09:22:19 +08:00
parent a2afd2f6dc
commit 450a094f0e
39 changed files with 516 additions and 2111 deletions
+48 -82
View File
@@ -1,31 +1,23 @@
import { useEffect, useRef, useState } from 'react';
import { useEffect } from 'react';
import { useStore } from './store/useStore';
import { color } from './theme/tokens';
import KPICards from './components/KPICards';
import EquipmentGrid from './components/EquipmentGrid';
import ProductionChart from './components/ProductionChart';
import CncStatusChart from './components/CncStatusChart';
import AlarmTable from './components/AlarmTable';
import TrendChart from './components/TrendChart';
import YieldRateChart from './components/YieldRateChart';
import SamplingTrendChart from './components/SamplingTrendChart';
import InspectionTrendChart from './components/InspectionTrendChart';
import MachineMonitor from './components/MachineMonitor';
import { AppHeader } from './components/AppHeader';
import { Panel } from './components/ui/Panel';
type Page = 'overview' | 'monitor';
export default function App() {
const [page, setPage] = useState<Page>('overview');
const fetchAll = useStore((s) => s.fetchAll);
const refresh = useStore((s) => s.refresh);
const intervalRef = useRef<ReturnType<typeof setInterval>>();
useEffect(() => {
fetchAll();
intervalRef.current = setInterval(refresh, 10000);
return () => clearInterval(intervalRef.current);
const t = setInterval(refresh, 10000);
return () => clearInterval(t);
}, [fetchAll, refresh]);
// 订阅 MES SSE:看板相关事件(dashboard_update)实时触发刷新
@@ -37,15 +29,7 @@ export default function App() {
return () => es.close();
}, [refresh]);
// 产线概览 / 设备监控 每 30s 自动轮播切换
// 依赖 page:用户手动切页后计时从 0 重新开始,避免刚切完立刻被自动切走
useEffect(() => {
const t = setInterval(() => {
setPage((p) => (p === 'overview' ? 'monitor' : 'overview'));
}, 30000);
return () => clearInterval(t);
}, [page]);
// 装配线看板:仅产线概览(扫码枪+拧紧枪工位,无 CNC/清洗机)
return (
<div style={{
width: '100vw', height: '100vh',
@@ -54,72 +38,54 @@ export default function App() {
gap: 10, overflow: 'hidden',
color: color.text.primary,
}}>
<AppHeader page={page} onChangePage={setPage} />
<AppHeader />
{page === 'overview' ? (
<main style={{
flex: 1, minHeight: 0, display: 'flex',
flexDirection: 'column', gap: 10,
animation: 'fade-in-up 300ms ease',
<main style={{
flex: 1, minHeight: 0, display: 'flex',
flexDirection: 'column', gap: 10,
animation: 'fade-in-up 300ms ease',
}}>
{/* KPI Row */}
<div style={{ flexShrink: 0 }}>
<KPICards />
</div>
{/* Middle Row: Equipment | Production | Alarms */}
<div style={{
flex: 3, display: 'grid',
gridTemplateColumns: '1fr 1.4fr 1fr',
gap: 10, minHeight: 0,
}}>
{/* KPI Row */}
<div style={{ flexShrink: 0 }}>
<KPICards />
</div>
<Panel title="工位状态" subtitle="STATION STATUS" padding={8}>
<EquipmentGrid />
</Panel>
<Panel title="生产进度" subtitle="WORK ORDERS" padding={4}>
<ProductionChart />
</Panel>
<Panel
title="活跃报警"
subtitle="LIVE ALARMS"
accent={color.status.danger}
padding={8}
>
<AlarmTable />
</Panel>
</div>
{/* Middle Row: Equipment | Production | CNC Status | Alarms */}
<div style={{
flex: 3, display: 'grid',
gridTemplateColumns: '1fr 1fr 1fr 1fr',
gap: 10, minHeight: 0,
}}>
<Panel title="设备槽位" subtitle="SLOT USAGE" padding={8}>
<EquipmentGrid />
</Panel>
<Panel title="CNC 状态" subtitle="CNC STATUS" padding={8}>
<CncStatusChart />
</Panel>
<Panel title="生产进度" subtitle="WORK ORDERS" padding={4}>
<ProductionChart />
</Panel>
<Panel
title="活跃报警"
subtitle="LIVE ALARMS"
accent={color.status.danger}
padding={8}
>
<AlarmTable />
</Panel>
</div>
{/* Bottom Row */}
<div style={{
flex: 2, display: 'grid',
gridTemplateColumns: '1fr 1fr 1fr 1fr',
gap: 10, minHeight: 0,
}}>
<Panel title="近10日产量趋势" subtitle="10-DAY OUTPUT" padding={4}>
<TrendChart />
</Panel>
<Panel title="近10日合格率统计" subtitle="10-DAY YIELD" padding={4}>
<YieldRateChart />
</Panel>
<Panel title="近10日抽检趋势" subtitle="10-DAY SAMPLING" padding={4}>
<SamplingTrendChart />
</Panel>
<Panel title="近10日内窥镜趋势" subtitle="10-DAY INSPECTION" padding={4}>
<InspectionTrendChart />
</Panel>
</div>
</main>
) : (
<main style={{
flex: 1, minHeight: 0,
animation: 'fade-in-up 300ms ease',
{/* Bottom Row */}
<div style={{
flex: 2, display: 'grid',
gridTemplateColumns: '1.4fr 1fr',
gap: 10, minHeight: 0,
}}>
<MachineMonitor />
</main>
)}
<Panel title="近10日产量趋势" subtitle="10-DAY OUTPUT" padding={4}>
<TrendChart />
</Panel>
<Panel title="近10日合格率统计" subtitle="10-DAY YIELD" padding={4}>
<YieldRateChart />
</Panel>
</div>
</main>
</div>
);
}