ux(setup): voice.resource_id 留空时自动用 settings.default_resource_id
问题: step 2 有 "默认资源 ID" 字段,但 step 3 的每个 voice 行 也有 "资源 ID" 字段,要求用户填 2 次。用户经常只在 step 2 填, 留空 step 3 的 resource_id,导致 voice 行拿到 form placeholder "volc.megatts.icl" 或空串。结果 settings 和 voice 不一致, 运行时火山 500(mismatch / not granted)。 修法 (后端兜底,无需前端改动): 1. 装时校验放宽: resource_id 留空是允许的(原来是必填) 2. 装时遍历 voices, 如果 voice.resource_id == "" 就用 settings.default_resource_id 兜底, 并记 log 用户收益: step 3 voice 行的 resource_id 字段可以不动, step 2 填一次就行,始终保持一致。 可选前端优化 (待前端做): step 2 的 "默认资源 ID" 改变时, 自动同步所有 voice 行的 resource_id (placeholder 提示已自动填充)。 e2e 验证 (本机): - 提交 install body 中 voice[0].resource_id="" - 启动 log: '[setup] voice "chun" resource_id 留空,自动用 default_resource_id="seed-icl-2.0"' - dumpdb 看 voice chun.resource_id = seed-icl-2.0 (从 settings 兜底) ✓ 二进制: ~18MB → ~18MB (代码量几乎不变) 未 push (待用户确认)
This commit is contained in:
+14
-4
@@ -190,11 +190,21 @@ func SetupSubmitHandler(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("[setup] 检测到 %d 条已存在 voices,本次将跳过清空(name 冲突由 ErrDuplicate 处理)", len(existing))
|
||||
}
|
||||
inserted := 0
|
||||
// 【UX 改进】voice 行的 resource_id 留空时,自动用 settings.default_resource_id 兜底。
|
||||
// 用户在 step 2 填了 default_resource_id 后,step 3 的 voice 行 resource_id
|
||||
// 可以不填 — 保持一致。否则会出现 "settings 里 seed-icl-2.0,voice 里 volc.megatts.icl"
|
||||
// 这种 mismatch,运行时 500。
|
||||
defaultResourceID := settingsKV["default_resource_id"]
|
||||
for _, v := range body.Voices {
|
||||
voiceResourceID := v.ResourceID
|
||||
if voiceResourceID == "" {
|
||||
voiceResourceID = defaultResourceID
|
||||
log.Printf("[setup] voice %q resource_id 留空,自动用 default_resource_id=%q", v.Name, defaultResourceID)
|
||||
}
|
||||
_, err := s.VoiceInsert(store.Voice{
|
||||
Name: v.Name,
|
||||
Speaker: v.Speaker,
|
||||
ResourceID: v.ResourceID,
|
||||
ResourceID: voiceResourceID,
|
||||
Model: v.Model,
|
||||
Language: v.Language,
|
||||
Enabled: true,
|
||||
@@ -267,9 +277,9 @@ func validateSetupVoices(vs []SetupVoice) error {
|
||||
if strings.TrimSpace(v.Speaker) == "" {
|
||||
return fmt.Errorf("voices[%d] (%s): speaker is required", i, v.Name)
|
||||
}
|
||||
if strings.TrimSpace(v.ResourceID) == "" {
|
||||
return fmt.Errorf("voices[%d] (%s): resource_id is required", i, v.Name)
|
||||
}
|
||||
// 【UX 改进】resource_id 留空是允许的 — 装时(下面那个循环)会自动用
|
||||
// settings.default_resource_id 兜底。用户只填 step 2 一处即可。
|
||||
_ = v.ResourceID // (保留以便以后加更细的校验)
|
||||
if _, dup := names[v.Name]; dup {
|
||||
return fmt.Errorf("voices[%d]: duplicate name %q", i, v.Name)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user