Commit Graph

33 Commits

Author SHA1 Message Date
caoqianming 42cdbbc0cc fix(web): fetch all unit runtimes on page load
Root cause: state.runtimes was empty after refresh because the engine
only pushes UnitRuntimeChanged on state transitions — if the engine
is mid-wait-phase, no push occurs and badges show OFFLINE.

Fix: add GET /api/unit/runtimes batch endpoint (returns all known
runtimes as { unit_id: UnitRuntime }) and call it in parallel with
the unit list fetch inside loadUnits(), so runtime badges are correct
immediately after page load.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 09:11:47 +08:00
caoqianming 4ce91adf60 refactor(web): remove dead code and translate plan docs to Chinese
- ops.js: remove unused `formatValue` import
- logs.js: remove `export` from internal-only `appendLog`
- state.js: fix stale comment ({ valueEl, qualityEl } → { dotEl })
- docs: rewrite both plan docs in Chinese; update dual-view-web plan to
  reflect actual implementation (sigDotClass dots, loadAllEquipmentCards,
  syncEquipmentButtonsForUnit, batch auto buttons in startOps)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 08:57:29 +08:00
caoqianming 8c1b7b636d refactor(engine): replace 500ms ticker with per-unit event-driven tasks
- Engine now spawns one async task per enabled unit (supervised every 10s)
- wait_phase uses sleep_until + select! for precise timing; 500ms fault-tick
  runs inside each phase so fault/comm is still checked promptly
- WS UnitRuntimeChanged pushed only on state transitions, not every tick
- ControlRuntimeStore gains notify_unit/get_or_create_notify for instant
  wake-up when handlers change auto_enabled or fault_locked
- UnitRuntime: remove last_tick_at, current_run/stop/distributor_elapsed_sec;
  add display_acc_sec (snapshot at transition, avoids mid-cycle jitter)
- accumulated_run_sec now increments by exact run_time_sec*1000 per cycle
- unit.state_changed events no longer written to DB (too frequent)
- Frontend: show display_acc_sec instead of accumulated_run_sec
- styles: event-card flex-shrink:0 fixes text overlap under flex column

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 08:33:00 +08:00
caoqianming da03441c11 refactor(events): display each event on a single line
Flatten two-row card (meta + message) into one flex row:
badge | time | event_type | message (ellipsis overflow)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 16:40:43 +08:00
caoqianming a8d36578fa feat: ws backoff, signal dots, dom cap, unwrap fix, batch size limit
- logs.js: WS reconnect exponential backoff 1s→2s→4s…30s
- ops.js: replace badge+text signal display with red/green/yellow dots
  (sig-on=green, sig-fault=red, sig-warn=yellow, gray=off)
- events.js: cap live-prepended event cards at 100 DOM nodes
- source.rs: fix attach_children unwrap() → Option<TreeNode>/filter_map
- point.rs: add max=500 validation to all batch Vec<Uuid> fields

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 16:37:14 +08:00
caoqianming 13c4b515d7 fix(docs): widen API drawer and fix TOC scroll hijacking window
- Add .api-drawer (1100px) so content area is ~880px instead of ~540px
- Replace scrollIntoView with apiDocContent.scrollBy to avoid scrolling
  the window and collapsing the drawer layout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 14:41:17 +08:00
caoqianming bc6e6e889f feat(events): infinite scroll with page_size=10, replace full re-render
Replace bulk load+re-render with scroll-based pagination: load 10 items
on init, append next page when scrolling near the bottom. prependEvent
now inserts directly into DOM instead of rebuilding from state.events.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 13:23:18 +08:00
caoqianming 2a247dd70b fix(toast): remove shake class before hiding to ensure animationend fires
When dismiss() was called on a persistent+shaking toast, the .shake CSS
rule (declared after .hiding) overrode toast-out animation. If shake had
already finished, no animationend fired and the element was never removed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 13:16:50 +08:00
caoqianming b7d55fed81 refactor(web): unify toast — remove duplicate, reuse api.js showToast
- Deleted redundant toast.js (was duplicating api.js's toast with conflicting CSS)
- Extended api.js showToast: returns {dismiss}, supports shake option, guards
  against double-dismiss
- Removed duplicate #toastContainer CSS block from styles.css; added shake
  animation to existing toast CSS
- logs.js: import showToast from api.js; WS disconnect shows persistent error
  toast with shake, reconnect shows success toast

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 13:11:23 +08:00
caoqianming 69ae0b05b7 feat(web): add toast notifications + WS disconnect alert
- New toast.js module: showToast(message, type, duration)
  - types: error / warning / success / info
  - duration=0 → persistent until dismissed or manually closed
  - click to dismiss early
  - shake animation on appear
- WS disconnect: persistent red error toast "后端连接断开,正在重连…"
- WS reconnect: dismisses disconnect toast, shows green "连接已恢复" for 3s

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 13:08:14 +08:00
caoqianming 757d6f9a3a feat(control): batch start/stop auto control for all enabled units
Backend:
- POST /api/control/unit/batch-start-auto — starts auto on all enabled
  units that are not fault/comm locked and not already running auto
- POST /api/control/unit/batch-stop-auto — stops auto on all units

Frontend (ops view):
- Add "全部启动" / "全部停止" buttons in the unit sidebar header

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 13:05:23 +08:00
caoqianming b28ac23520 feat(web): show WS connection status indicator in topbar
Green dot + "已连接" when socket is open; red dot + "连接断开,重连中…"
on close/error. Reconnect timer (2s) already in place.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 12:41:50 +08:00
caoqianming b832d98196 fix(control): block manual commands during auto, fix engine stop_time=0 bug, add sim feedback
- validator: reject equipment start/stop when unit auto_enabled
- engine: fix stop_time_sec==0 causing infinite Stopped state (never starts)
- engine: call simulate_run_feedback after auto commands when SIMULATE_PLC=true
- command: extract simulate_run_feedback to shared module (was private in handler)
- web: disable Start/Stop buttons when unit auto is active; sync on WS runtime update

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 12:37:43 +08:00
caoqianming 36cfe9ecfc feat(web): add runtime badge and auto/ack buttons to ops unit list
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 10:47:09 +08:00
caoqianming 4076f6575e feat(web): dual-view UI — 运维/配置 tab, ops equipment cards with live signal values
- Add 运维/配置 tab switch; grid-ops / grid-config layout classes
- New ops-panel: unit sidebar + equipment card grid (REM/RUN/FLT signals)
- All equipment cards shown by default; unit click acts as filter
- Signal cells seed from point_monitor cache on render, then update via WS PointNewValue
- New log-stream-panel: SSE realtime log stream, active only in config view
- Backend: get_unit_detail now includes point_monitor (current value) in each point

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 10:25:20 +08:00
caoqianming dae5bdcb9e fix(web): fix node count showing 2x by counting only details elements
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 08:27:06 +08:00
caoqianming 3e277cdb52 refactor(web): event card layout to 2-line (meta row + message row)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 16:46:32 +08:00
caoqianming a405623ec1 refactor(web): remove realtime log stream, compact event list to single line
- Remove SSE log stream (EventSource /api/logs/stream) and logView panel
- System events panel now occupies the full bottom-middle panel
- Each event renders as a single flex row: level badge, type, message, timestamp
- Remove logSource from state, logView from dom, startLogs from app bootstrap

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 16:39:01 +08:00
caoqianming d88d8375fd fix(frontend): pre-select active unit when opening new equipment modal
When a unit is selected in the sidebar, the create-equipment modal now
pre-fills the unit dropdown with that unit. Previously it always reset
to empty, so newly created equipment got unit_id=null and was hidden by
the unit filter after save.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 16:35:33 +08:00
caoqianming d1131c4e2d fix(frontend): show fault/comm locked state in runtime badge
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 15:04:17 +08:00
caoqianming 0c2ce48d23 feat(frontend): handle UnitRuntimeChanged WebSocket message 2026-03-24 14:58:29 +08:00
caoqianming 21f6008cba feat(frontend): add start/stop control buttons to equipment cards 2026-03-24 14:58:16 +08:00
caoqianming 89023e867b feat(frontend): show runtime state and auto/ack buttons on unit cards 2026-03-24 14:58:07 +08:00
caoqianming 31ccf49b75 feat(frontend): add runtimes map to state 2026-03-24 14:57:41 +08:00
caoqianming 49a4afa4a4 feat(web): auto-toast on API errors with dismissible notifications
Add showToast() utility in api.js and a matching toast stylesheet.
apiFetch now automatically shows a toast for any 400+ response before
re-throwing, so callers can still .catch() for additional handling.

Toasts stack at the bottom-right, auto-dismiss after 4s, and support
error/warning/success/info levels via a left-border colour accent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 13:43:57 +08:00
caoqianming a38204511a refactor(control): align point roles and equipment kind 2026-03-24 13:17:53 +08:00
caoqianming c50127b9d0 feat(event): stream created events over websocket 2026-03-24 12:28:12 +08:00
caoqianming 1f29eb3871 feat(web): add unit and event management views 2026-03-24 10:56:57 +08:00
caoqianming 4d53ee0337 refactor(web): split index html into flat fragments 2026-03-23 14:14:19 +08:00
caoqianming 6cdc51a249 refactor(point): fold binding into edit action 2026-03-23 13:20:03 +08:00
caoqianming e55c1d5efb fix(chart): restore realtime updates and axes 2026-03-23 12:55:12 +08:00
caoqianming fec7b60d6b feat(web): reorganize equipment layout and point flows 2026-03-23 12:49:26 +08:00
caoqianming 06ace5e67d refactor(app): split services and web modules 2026-03-23 11:31:38 +08:00