feat: device detail page shows real model/resource status with SHA256 comparison; filter unavailable features on console

This commit is contained in:
tian 2026-07-20 16:34:31 +08:00
parent 0a9a1bd005
commit 29db6be66d
12 changed files with 50 additions and 1 deletions

View File

@ -119,6 +119,8 @@ type PageData struct {
ConsoleUnassignedUnits []service.RecognitionUnitAsset
FaceGalleryPersons []storage.PersonRecord
FaceGalleryQuality map[string]string
DeviceModelStatuses []service.InstalledModelStatus
DeviceResourceStatuses []service.InstalledResourceStatus
Templates []service.Template
Template *service.Template
AssetTab string
@ -1721,6 +1723,28 @@ func (u *UI) deviceDetailPageData(dev *models.Device) PageData {
data.SelectedProfile = assignment.ProfileName
}
}
// Load device model and resource status vs management standards.
if dev.Online && u.agent != nil {
if items, err := service.FetchInstalledModelStatuses(u.agent, dev); err == nil {
data.DeviceModelStatuses = items
}
if items, err := service.FetchInstalledResourceStatuses(u.agent, dev); err == nil {
data.DeviceResourceStatuses = items
}
}
if strings.TrimSpace(u.dbPath) != "" {
if store, err := storage.OpenSQLite(u.dbPath); err == nil {
modelsRepo := storage.NewModelsRepo(store.DB())
if items, err := modelsRepo.List(); err == nil {
data.StandardModels = items
}
resourcesRepo := storage.NewResourcesRepo(store.DB())
if items, err := resourcesRepo.List(); err == nil {
data.StandardResources = items
}
store.Close()
}
}
return data
}

View File

@ -166,12 +166,37 @@
<div>
<h3 class="title-with-icon">{{icon "assets"}}<span>模型与资源</span></h3>
</div>
<a class="btn secondary" href="/models">进入模型管理</a>
<a class="btn secondary" href="/models">模型管理</a>
</div>
{{if .StandardModels}}
<div class="info-list compact-list" style="margin-bottom:0">
{{range $m := .StandardModels}}
{{$status := "missing"}}
{{range $d := $.DeviceModelStatuses}}{{if eq $d.Name $m.Name}}{{if eq $d.SHA256 $m.SHA256}}{{$status = "ok"}}{{else}}{{$status = "mismatch"}}{{end}}{{end}}{{end}}
<div style="display:flex;justify-content:space-between;align-items:center"><span class="mono" title="{{$m.Name}}" style="margin-bottom:0">{{$m.Name}}</span>
<strong style="flex-shrink:0">{{if eq $status "ok"}}<span class="pill ok">一致</span>{{else if eq $status "mismatch"}}<span class="pill warn">不一致</span>{{else}}<span class="pill bad">缺失</span>{{end}}</strong></div>
{{end}}
</div>
{{end}}
{{if .StandardResources}}
<div class="info-list compact-list">
{{range $r := .StandardResources}}
{{$status := "missing"}}
{{range $d := $.DeviceResourceStatuses}}{{if eq $d.Name $r.Name}}{{if eq $d.SHA256 $r.SHA256}}{{$status = "ok"}}{{else}}{{$status = "mismatch"}}{{end}}{{end}}{{end}}
<div style="display:flex;justify-content:space-between;align-items:center"><span class="mono" title="{{$r.Name}}" style="margin-bottom:0">{{$r.Name}} <span class="muted small">({{resourceTypeLabel $r.ResourceType}})</span></span>
<strong style="flex-shrink:0">{{if eq $status "ok"}}<span class="pill ok">一致</span>{{else if eq $status "mismatch"}}<span class="pill warn">不一致</span>{{else}}<span class="pill bad">缺失</span>{{end}}</strong></div>
{{end}}
</div>
{{end}}
{{if not (or .StandardModels .StandardResources)}}
<div class="info-list compact-list">
<div><span>模型入口</span><strong>通过模型管理页上传到设备</strong></div>
<div><span>人脸库</span><strong>通过资源管理与基础配置维护</strong></div>
</div>
{{end}}
<div class="actions">
<form method="post" action="/devices/{{.Device.DeviceID}}/face-gallery/reload">
<button type="submit" class="secondary">重载人脸库</button>