diff --git a/internal/service/tuning.go b/internal/service/tuning.go index d02884b..913d4f5 100644 --- a/internal/service/tuning.go +++ b/internal/service/tuning.go @@ -21,20 +21,24 @@ type TuningItem struct { Value float64 `json:"value"` } -// GetTuningItems reads the tuning section from a template and resolves current -// values from the template's actual node parameters. +// GetTuningItems looks up hardcoded tuning definitions for the template and +// resolves current values from the template's actual node parameters. func (s *ConfigPreviewService) GetTuningItems(templateName string) ([]TuningItem, error) { + stdName := "std_" + templateName + defs := tuningDefinitions[stdName] + if len(defs) == 0 { + return nil, nil + } + raw, _, err := s.readAssetJSON("templates", templateName) if err != nil { return nil, err } - items, err := parseTuningItems(raw) - if err != nil { - return nil, err - } + // Deep copy defs and resolve current values from template. + items := make([]TuningItem, len(defs)) + copy(items, defs) - // Resolve current values from the template's actual node config. templateBody, _ := raw["template"].(map[string]any) nodes, _ := templateBody["nodes"].([]any) nodeMap := make(map[string]map[string]any, len(nodes)) @@ -60,17 +64,20 @@ func (s *ConfigPreviewService) GetTuningItems(templateName string) ([]TuningItem // SaveTuningItems writes tuning values directly into the template's node // parameters and saves the template. Returns affected device IDs. func (s *ConfigPreviewService) SaveTuningItems(templateName string, values map[string]float64) ([]string, error) { + stdName := "std_" + templateName + defs := tuningDefinitions[stdName] + if len(defs) == 0 { + return nil, fmt.Errorf("该模板没有可调参数") + } + raw, _, err := s.readAssetJSON("templates", templateName) if err != nil { return nil, err } - items, err := parseTuningItems(raw) - if err != nil { - return nil, err - } - - // Apply values. + // Resolve current values from defs, overriding with form values. + items := make([]TuningItem, len(defs)) + copy(items, defs) for i := range items { if v, ok := values[items[i].Path]; ok { items[i].Value = v @@ -167,37 +174,33 @@ func (s *ConfigPreviewService) RedeployDevices(deviceIDs []string) ([]string, er // --- path parsing helpers --- -func parseTuningItems(raw map[string]any) ([]TuningItem, error) { - tuningRaw, _ := raw["tuning"].([]any) - if len(tuningRaw) == 0 { - return nil, nil - } - - items := make([]TuningItem, 0, len(tuningRaw)) - for _, item := range tuningRaw { - im, _ := item.(map[string]any) - if im == nil { - continue - } - ti := TuningItem{ - Path: strings.TrimSpace(stringValue(im["path"])), - Label: strings.TrimSpace(stringValue(im["label"])), - Type: strings.TrimSpace(stringValue(im["type"])), - Min: floatValue(im, "min", 0), - Max: floatValue(im, "max", 100), - Step: floatValue(im, "step", 1), - Unit: strings.TrimSpace(stringValue(im["unit"])), - Group: strings.TrimSpace(stringValue(im["group"])), - } - if ti.Type == "" { - ti.Type = "slider" - } - if ti.Path == "" || ti.Label == "" { - continue - } - items = append(items, ti) - } - return items, nil +// tuningDefinitions maps standard template names to their adjustable parameters. +// To expose a new parameter: add a TuningItem entry below. +var tuningDefinitions = map[string][]TuningItem{ + "std_workshop_face_recognition_shoe_alarm": { + // ── 告警 ── + {Path: "alarm_violation.rules[0].cooldown_ms", Label: "劳保鞋告警冷却", Type: "slider", Min: 5000, Max: 300000, Step: 1000, Unit: "ms", Group: "告警"}, + {Path: "alarm_violation.rules[0].min_duration_ms", Label: "违规最小持续时间", Type: "slider", Min: 200, Max: 10000, Step: 100, Unit: "ms", Group: "告警"}, + {Path: "alarm_violation.rules[0].min_hits", Label: "违规最小命中帧数", Type: "slider", Min: 1, Max: 10, Step: 1, Unit: "帧", Group: "告警"}, + {Path: "alarm_violation.rules[0].min_score", Label: "违规最低置信度", Type: "slider", Min: 0.1, Max: 0.9, Step: 0.05, Group: "告警"}, + // ── 人脸 ── + {Path: "alarm_violation.face_rules[0].cooldown_ms", Label: "陌生人脸冷却", Type: "slider", Min: 2000, Max: 120000, Step: 1000, Unit: "ms", Group: "人脸"}, + {Path: "alarm_violation.face_rules[0].min_hits", Label: "陌生人脸命中帧数", Type: "slider", Min: 1, Max: 10, Step: 1, Unit: "帧", Group: "人脸"}, + {Path: "alarm_violation.face_rules[0].max_known_sim", Label: "陌生人脸相似度上限", Type: "slider", Min: 0.1, Max: 0.8, Step: 0.05, Group: "人脸"}, + {Path: "alarm_violation.face_rules[0].hit_window_ms", Label: "陌生人脸命中窗口", Type: "slider", Min: 500, Max: 10000, Step: 500, Unit: "ms", Group: "人脸"}, + {Path: "alarm_violation.face_rules[1].cooldown_ms", Label: "已知人员冷却", Type: "slider", Min: 2000, Max: 120000, Step: 1000, Unit: "ms", Group: "人脸"}, + {Path: "alarm_violation.face_rules[1].min_sim", Label: "已知人员相似度阈值", Type: "slider", Min: 0.3, Max: 0.95, Step: 0.05, Group: "人脸"}, + {Path: "alarm_violation.face_rules[1].min_hits", Label: "已知人员命中帧数", Type: "slider", Min: 1, Max: 10, Step: 1, Unit: "帧", Group: "人脸"}, + {Path: "alarm_violation.face_rules[1].hit_window_ms", Label: "已知人员命中窗口", Type: "slider", Min: 500, Max: 10000, Step: 500, Unit: "ms", Group: "人脸"}, + {Path: "recognize_face.threshold.accept", Label: "人脸识别接受阈值", Type: "slider", Min: 0.3, Max: 0.9, Step: 0.05, Group: "人脸"}, + // ── 工鞋 ── + {Path: "detect_shoe.conf", Label: "工鞋检测置信度", Type: "slider", Min: 0.1, Max: 0.8, Step: 0.05, Group: "工鞋"}, + {Path: "rule_shoe_association.person_shoe_check.min_shoe_score", Label: "工鞋最低分数", Type: "slider", Min: 0.1, Max: 0.6, Step: 0.02, Group: "工鞋"}, + {Path: "rule_shoe_association.person_shoe_check.min_person_score", Label: "人员最低分数", Type: "slider", Min: 0.1, Max: 0.8, Step: 0.05, Group: "工鞋"}, + // ── 检测 ── + {Path: "detect_person.conf", Label: "人体检测置信度", Type: "slider", Min: 0.1, Max: 0.8, Step: 0.05, Group: "检测"}, + {Path: "detect_face.conf_thresh", Label: "人脸检测置信度", Type: "slider", Min: 0.2, Max: 0.9, Step: 0.05, Group: "检测"}, + }, } func splitTuningPath(fullPath string) (nodeID string, rest string) { diff --git a/internal/web/ui/templates/asset_template.html b/internal/web/ui/templates/asset_template.html index f60687c..8ff67bc 100644 --- a/internal/web/ui/templates/asset_template.html +++ b/internal/web/ui/templates/asset_template.html @@ -6,10 +6,7 @@