fix(v2.2): StoryPlayer 推进竞态加固(双审查 SHOULD-FIX)
- speak 兜底定时器先于 speak 注册 + try/catch:speak 抛异常不再导致 剧情永久卡死(估时/forceNext 未注册的失败模式) - speak onEnd 与估时闭包加行号守卫(lineIndex===i && !ended):迟到的 上一句 onEnd 不再提前放行当前句 - SceneTheater 估时封顶 20s(与 MAX_LINE_MS 对齐),注释同步 v2.2 语义 - plan Task 10 更新为实际实现(SetServerRoot + /static 挂载) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1392,9 +1392,10 @@ git commit -m "feat: 全自动演出——开场自动进入/回复自动继续/
|
||||
> 用户走查反馈:① 必须点跳过才出选项(speak onEnd 部分环境不回调,逐句推进靠 20s forceNext 兜底,体验像卡死);② 剧情不需要文字展示区,直接语音播放;③ 前端应与后端共用 :8080。规格:spec「v2.2 修订」章节。
|
||||
|
||||
**Files:**
|
||||
- Modify: `ui-src/src/components/StoryPlayer.vue`(纯语音 + 估时兜底)
|
||||
- Modify: `ui-src/src/components/StoryPlayer.vue`(纯语音 + 估时兜底 + 审查加固)
|
||||
- Modify: `ui-src/src/components/SceneTheater.vue`(估时兜底 + 20s 封顶)
|
||||
- Modify: `ui-src/src/pages/play/play.vue`(移除 :show-pinyin 传参)
|
||||
- Modify: `main.go`(AddStaticPath 托管前端产物)
|
||||
- Modify: `main.go`(SetServerRoot 托管前端产物 + /static 素材挂载)
|
||||
|
||||
- [ ] **Step 1: StoryPlayer 改纯语音演绎**
|
||||
|
||||
@@ -1522,12 +1523,15 @@ export default {
|
||||
|
||||
- [ ] **Step 3: main.go 托管前端产物(8080 单端口)**
|
||||
|
||||
`main.go` 在 `controller.Register(s)` 后加:
|
||||
`main.go` 在 `controller.Register(s)` 后加(**须用 SetServerRoot**——走查发现 GoFrame v2.10.2 `AddStaticPath("/", ...)` 因前缀防误匹配守卫 `uri[len(prefix)] != '/'` 只服务根路径,`/assets/*` 子路径全部 404;素材目录 `ui-src/static` 以 `/static` 前缀单独挂载,与后端 `scene.image` 返回的 `/static/generated/...` URL 对应):
|
||||
|
||||
```go
|
||||
// 生产形态:前端产物 ui-src/dist 由后端 :8080 统一托管(前后端同端口)
|
||||
if _, err := os.Stat("ui-src/dist"); err == nil {
|
||||
s.AddStaticPath("/", "ui-src/dist")
|
||||
s.SetServerRoot("ui-src/dist")
|
||||
}
|
||||
if _, err := os.Stat("ui-src/static"); err == nil {
|
||||
s.AddStaticPath("/static", "ui-src/static")
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -79,8 +79,8 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.speaking = true
|
||||
// v2.1:朗读结束自动进入决策幕——最短展示 1.2s,之后 speak onEnd 即进入;
|
||||
// 无 TTS/onEnd 缺失最迟 15s 兜底(「跳过」仍可手动跳过)
|
||||
// v2.1:朗读结束自动进入决策幕——最短展示 1.2s,之后 speak onEnd 即进入
|
||||
// v2.2:估时兜底——onEnd 缺失时按文本长度估时自动进入(最长 20s,不卡死;「跳过」仍可手动跳过)
|
||||
this.speechDone = false
|
||||
this.ready = false
|
||||
let done = false
|
||||
@@ -91,8 +91,8 @@ export default {
|
||||
this.$emit('done')
|
||||
}
|
||||
this.minTimer = setTimeout(() => { this.ready = true; if (this.speechDone) finishAuto() }, 1200)
|
||||
// 兜底按文本长度估时(onEnd 缺失时按朗读预期时长自动进入,不卡 15s)
|
||||
this.autoTimer = setTimeout(finishAuto, Math.max(4000, this.content.length * 320 + 2000))
|
||||
// 兜底按文本长度估时(onEnd 缺失时按朗读预期时长自动进入),封顶 20s 与 StoryPlayer MAX_LINE_MS 对齐
|
||||
this.autoTimer = setTimeout(finishAuto, Math.max(4000, Math.min(this.content.length * 320 + 2000, 20000)))
|
||||
const onSpeechEnd = () => {
|
||||
this.speechDone = true
|
||||
if (this.ready) finishAuto()
|
||||
|
||||
@@ -61,22 +61,30 @@ export default {
|
||||
}
|
||||
this.lineIndex = i
|
||||
this.ended = false
|
||||
this.lineDone = { sp: false, fb: false }
|
||||
this.lineDone = { sp: false }
|
||||
this.moodTick = true
|
||||
this.after(350, () => { this.moodTick = false })
|
||||
const total = Array.from(line.text).length
|
||||
speak(line.text, '', () => {
|
||||
this.lineDone.sp = true
|
||||
this.tryNext(i)
|
||||
})
|
||||
// 估时兜底:onEnd 缺失(浏览器静音策略/无语音)时按文本长度估时放行,不卡死
|
||||
// 估时/forceNext 兜底定时器先于 speak 注册:speak 抛异常(stub 环境/无 TTS)也不会卡死
|
||||
this.after(Math.max(2500, total * 320 + 1200), () => {
|
||||
if (!this.lineDone.sp) {
|
||||
if (this.lineIndex === i && !this.ended && !this.lineDone.sp) {
|
||||
this.lineDone.sp = true
|
||||
this.tryNext(i)
|
||||
}
|
||||
})
|
||||
this.after(MAX_LINE_MS, () => this.forceNext(i))
|
||||
try {
|
||||
speak(line.text, '', () => {
|
||||
// 行号守卫:迟到的第 i 句 onEnd 不得提前放行当前句
|
||||
if (this.lineIndex === i && !this.ended) {
|
||||
this.lineDone.sp = true
|
||||
this.tryNext(i)
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
this.lineDone.sp = true
|
||||
this.tryNext(i)
|
||||
}
|
||||
},
|
||||
tryNext(i) {
|
||||
if (this.ended || this.lineIndex !== i || !this.lineDone.sp) return
|
||||
|
||||
Reference in New Issue
Block a user