diff --git a/internal/web/ui.go b/internal/web/ui.go index 02547cf..910ae0d 100644 --- a/internal/web/ui.go +++ b/internal/web/ui.go @@ -837,6 +837,7 @@ func (u *UI) Routes() (chi.Router, error) { r.Post("/devices/batch-config", u.actionDeviceBatchConfig) r.Post("/discovery/search", u.actionDiscoverySearch) r.Get("/devices/{id}", u.pageDevice) + r.Post("/devices/{id}/overlays", u.actionDeviceOverlaysSave) r.Post("/devices/{id}/alias", u.actionDeviceAliasSave) r.Get("/devices/{id}/config-versions", u.pageDeviceConfigVersions) r.Get("/devices/{id}/config-versions/{versionID}", u.apiDeviceConfigVersion) @@ -1204,30 +1205,6 @@ func (u *UI) pageConsole(w http.ResponseWriter, r *http.Request) { } // Build console device data - var allOverlays []ConsoleOverlay - if u.preview != nil { - if overlays, err := u.preview.ListOverlayAssets(); err == nil { - for _, o := range overlays { - allOverlays = append(allOverlays, ConsoleOverlay{Name: o.Name, Description: o.Description}) - } - } - } - // Pre-load device overlay selections - deviceOverlaySelections := map[string]map[string]bool{} - if u.preview != nil { - for _, dev := range devices { - if dev == nil { - continue - } - if names, err := u.preview.GetDeviceOverlays(dev.DeviceID); err == nil { - m := map[string]bool{} - for _, n := range names { - m[n] = true - } - deviceOverlaySelections[dev.DeviceID] = m - } - } - } var consoleDevices []ConsoleDeviceData for _, dev := range devices { if dev == nil { @@ -1293,14 +1270,6 @@ func (u *UI) pageConsole(w http.ResponseWriter, r *http.Request) { diskUsage = m.Disk temp = m.Temperature } - // Mark which overlays are enabled for this device - deviceOverlays := make([]ConsoleOverlay, len(allOverlays)) - copy(deviceOverlays, allOverlays) - if sel, ok := deviceOverlaySelections[dev.DeviceID]; ok { - for i := range deviceOverlays { - deviceOverlays[i].Enabled = sel[deviceOverlays[i].Name] - } - } consoleDevices = append(consoleDevices, ConsoleDeviceData{ Device: dev, CPUUsage: cpuUsage, @@ -1311,7 +1280,6 @@ func (u *UI) pageConsole(w http.ResponseWriter, r *http.Request) { MaxUnits: maxUnits, Channels: channels, Features: features, - Overlays: deviceOverlays, Cameras: cameras, }) } @@ -1406,7 +1374,6 @@ func (u *UI) actionConsoleSave(w http.ResponseWriter, r *http.Request) { DeviceID: dev.DeviceID, Features: features, SourceNames: sources, - Overlays: cleanFormList(r.Form["device_"+dev.DeviceID+"_overlay"]), }) } @@ -1418,7 +1385,6 @@ func (u *UI) actionConsoleSave(w http.ResponseWriter, r *http.Request) { // Step 3: save features to DB BEFORE creating tasks (avoids SQLITE_BUSY race). for _, req := range requests { _ = u.preview.SaveDeviceFeatures(req.DeviceID, req.Features) - _ = u.preview.SaveDeviceOverlays(req.DeviceID, req.Overlays) } // Step 4: run pipeline (creates tasks asynchronously). @@ -1964,12 +1930,37 @@ func (u *UI) pageDevice(w http.ResponseWriter, r *http.Request) { http.NotFound(w, r) return } - u.render(w, r, "device", u.deviceDetailPageData(dev)) + data := u.deviceDetailPageData(dev) + data.Message = strings.TrimSpace(r.URL.Query().Get("msg")) + data.Error = strings.TrimSpace(r.URL.Query().Get("error")) + u.render(w, r, "device", data) +} + +func (u *UI) actionDeviceOverlaysSave(w http.ResponseWriter, r *http.Request) { + id := chi.URLParam(r, "id") + if err := r.ParseForm(); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + overlays := cleanFormList(r.Form["overlay"]) + if u.preview != nil { + _ = u.preview.SaveDeviceOverlays(id, overlays) + } + http.Redirect(w, r, "/devices/"+url.PathEscape(id)+"?msg="+url.QueryEscape("覆盖参数已保存"), http.StatusFound) } func (u *UI) deviceDetailPageData(dev *models.Device) PageData { data := u.deviceControlPageData(dev) data.Title = "设备详情" + // Load overlays for device-specific override selection + if u.preview != nil { + if overlays, err := u.preview.ListOverlayAssets(); err == nil { + data.AssetOverlays = overlays + if selected, err := u.preview.GetDeviceOverlays(dev.DeviceID); err == nil { + data.SelectedOverlays = selected + } + } + } if data.ConfigStatus == nil && u.stateRepo != nil && dev != nil { if state, err := u.stateRepo.Get(dev.DeviceID); err == nil && state != nil { data.PersistedConfig = state @@ -6377,18 +6368,11 @@ type ConsoleDeviceData struct { MaxUnits int Channels []ConsoleChannel Features []ConsoleFeature - Overlays []ConsoleOverlay Cameras []string Busy bool BusyMsg string } -type ConsoleOverlay struct { - Name string - Description string - Enabled bool -} - type ConsoleChannel struct { Name string Display string diff --git a/internal/web/ui/templates/console.html b/internal/web/ui/templates/console.html index 4281b3a..1fc9cbd 100644 --- a/internal/web/ui/templates/console.html +++ b/internal/web/ui/templates/console.html @@ -68,19 +68,7 @@ {{end}} - {{if $cd.Overlays}} -
| - | {{$o.Name}} | -