1. 新增SSE看板广播机制,业务操作后主动推送刷新事件 2. 新增产线工序横道图与工位状态展示面板 3. 移除dashboard无用的three.js依赖 4. 重构WMS客户端布局与WMS前端资源哈希 5. 新增工位终端时钟图标与大屏自适应布局 6. 新增系统截图脚本与说明书生成工具 7. 修复多处代码细节与空值处理逻辑
82 lines
1.5 KiB
Go
82 lines
1.5 KiB
Go
package sse
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"sync"
|
|
)
|
|
|
|
// SseMsg SSE 事件消息
|
|
type SseMsg struct {
|
|
Type string // 事件名,如表单名 dashboard.*
|
|
Data string // JSON 字符串
|
|
}
|
|
|
|
// Hub SSE 推送中心(支持看板局部刷新)
|
|
type Hub struct {
|
|
mu sync.Mutex
|
|
clients map[chan SseMsg]struct{}
|
|
closed map[chan SseMsg]bool
|
|
}
|
|
|
|
func NewHub() *Hub {
|
|
return &Hub{clients: make(map[chan SseMsg]struct{})}
|
|
}
|
|
|
|
// Add 新增客户端
|
|
func (h *Hub) Add() chan SseMsg {
|
|
ch := make(chan SseMsg, 16)
|
|
h.mu.Lock()
|
|
h.clients[ch] = struct{}{}
|
|
h.mu.Unlock()
|
|
return ch
|
|
}
|
|
|
|
func (h *Hub) Remove(ch chan SseMsg) {
|
|
h.mu.Lock()
|
|
if _, ok := h.clients[ch]; ok {
|
|
delete(h.clients, ch)
|
|
close(ch)
|
|
}
|
|
h.mu.Unlock()
|
|
}
|
|
|
|
// Publish 广播事件
|
|
func (h *Hub) Publish(typ string, data string) {
|
|
h.mu.Lock()
|
|
defer h.mu.Unlock()
|
|
for ch := range h.clients {
|
|
select {
|
|
case ch <- SseMsg{Type: typ, Data: data}:
|
|
default:
|
|
}
|
|
}
|
|
}
|
|
|
|
// Handler SSE 长连接端点
|
|
func (h *Hub) Handler(w http.ResponseWriter, r *http.Request) {
|
|
fl, ok := w.(http.Flusher)
|
|
if !ok {
|
|
http.Error(w, "streaming unsupported", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "text/event-stream")
|
|
w.Header().Set("Cache-Control", "no-cache")
|
|
w.Header().Set("Connection", "keep-alive")
|
|
ch := h.Add()
|
|
defer h.Remove(ch)
|
|
|
|
h.Publish("dashboard.hello", "{}")
|
|
for {
|
|
select {
|
|
case m := <-ch:
|
|
if _, err := fmt.Fprintf(w, "event: %s\ndata: %s\n\n", m.Type, m.Data); err != nil {
|
|
return
|
|
}
|
|
fl.Flush()
|
|
case <-r.Context().Done():
|
|
return
|
|
}
|
|
}
|
|
}
|