2026-07-22 16:01:28 +08:00
|
|
|
|
package ui
|
|
|
|
|
|
|
2026-07-22 21:24:10 +08:00
|
|
|
|
import (
|
|
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
|
|
|
|
"silverpose/v2/internal/fall"
|
|
|
|
|
|
"silverpose/v2/internal/source"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2026-07-22 16:01:28 +08:00
|
|
|
|
// WindowSpec locks the visual baseline tested by the Windows UI Spike. The
|
|
|
|
|
|
// production V2 app will consume the same semantic colours and medium desktop
|
|
|
|
|
|
// layout after the decoding/inference pipeline is complete.
|
|
|
|
|
|
type WindowSpec struct {
|
|
|
|
|
|
Title string
|
|
|
|
|
|
Width int
|
|
|
|
|
|
Height int
|
|
|
|
|
|
BackgroundHex string
|
2026-07-22 21:24:10 +08:00
|
|
|
|
SurfaceHex string
|
|
|
|
|
|
AccentHex string
|
2026-07-22 16:01:28 +08:00
|
|
|
|
AlertHex string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func MonitorWindowSpec() WindowSpec {
|
|
|
|
|
|
return WindowSpec{
|
2026-07-22 21:24:10 +08:00
|
|
|
|
Title: "Silver Pose V2",
|
2026-07-22 16:01:28 +08:00
|
|
|
|
Width: 1120,
|
|
|
|
|
|
Height: 720,
|
2026-07-22 21:24:10 +08:00
|
|
|
|
BackgroundHex: "#EAF1F8",
|
|
|
|
|
|
SurfaceHex: "#FFFFFF",
|
|
|
|
|
|
AccentHex: "#2563EB",
|
2026-07-22 16:01:28 +08:00
|
|
|
|
AlertHex: "#C62828",
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-07-22 21:24:10 +08:00
|
|
|
|
|
|
|
|
|
|
// ViewModel is a UI-thread-neutral snapshot. It deliberately stores only a
|
|
|
|
|
|
// source environment variable name and status, never a resolved RTSP URL.
|
|
|
|
|
|
type ViewModel struct {
|
|
|
|
|
|
ConnectionText string
|
|
|
|
|
|
StateText string
|
|
|
|
|
|
EventText string
|
|
|
|
|
|
SettingsSummary string
|
|
|
|
|
|
Critical bool
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func NewViewModel() ViewModel {
|
|
|
|
|
|
return ViewModel{
|
|
|
|
|
|
ConnectionText: "等待启动监控",
|
|
|
|
|
|
StateText: "检测状态:正常",
|
|
|
|
|
|
EventText: "事件:暂无",
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (model *ViewModel) Apply(state fall.State, status source.Status) {
|
|
|
|
|
|
model.Critical = state == fall.Confirmed
|
|
|
|
|
|
switch state {
|
|
|
|
|
|
case fall.Confirmed:
|
|
|
|
|
|
model.StateText = "检测状态:确认摔倒"
|
|
|
|
|
|
model.EventText = "事件:已确认,已保存证据"
|
|
|
|
|
|
case fall.Suspect:
|
|
|
|
|
|
model.StateText = "检测状态:疑似倒地"
|
|
|
|
|
|
model.EventText = "事件:正在持续确认"
|
|
|
|
|
|
case fall.Recovering:
|
|
|
|
|
|
model.StateText = "检测状态:恢复观察中"
|
|
|
|
|
|
model.EventText = "事件:等待恢复稳定"
|
|
|
|
|
|
default:
|
|
|
|
|
|
model.StateText = "检测状态:正常"
|
|
|
|
|
|
model.EventText = "事件:暂无"
|
|
|
|
|
|
}
|
|
|
|
|
|
switch status {
|
|
|
|
|
|
case source.Connected:
|
|
|
|
|
|
model.ConnectionText = "视频流:在线"
|
|
|
|
|
|
case source.Retrying:
|
|
|
|
|
|
model.ConnectionText = "视频流:正在重连,不触发摔倒报警"
|
|
|
|
|
|
case source.Stopped:
|
|
|
|
|
|
model.ConnectionText = "视频流:已停止"
|
|
|
|
|
|
default:
|
|
|
|
|
|
model.ConnectionText = "视频流:正在连接"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (model *ViewModel) SetSourceReady(environmentName string, ready bool) {
|
|
|
|
|
|
state := "未就绪"
|
|
|
|
|
|
if ready {
|
|
|
|
|
|
state = "已就绪"
|
|
|
|
|
|
}
|
|
|
|
|
|
model.SettingsSummary = fmt.Sprintf("来源环境变量 %s:%s", environmentName, state)
|
|
|
|
|
|
}
|