fix: 关闭 AI 跟练震动并修复结束重复记录等问题

- 去掉倒计时、计数、评分和调整目标次数时的震动
- 手动结束训练不再重入 finish,避免同一次训练记两条历史
- 领练模式倒计时中暂停后恢复,直接重新倒计时,不再卡在站位
- 摄像头识别随时失败都切到领练模式,不再只在就绪后 1.5 秒检查一次
This commit is contained in:
2026-10-31 10:34:48 +08:00
parent 4932ed7651
commit c695217afe
2 changed files with 17 additions and 13 deletions
@@ -104,10 +104,7 @@ const minutes = computed(() => {
function change(dir: 1 | -1) {
const [lo, hi] = props.exercise.repRange
const next = Math.min(hi, Math.max(lo, props.target + dir * props.exercise.repStep))
if (next !== props.target) {
emit('update:target', next)
uni.vibrateShort({ type: 'light' } as any)
}
if (next !== props.target) emit('update:target', next)
}
</script>
+16 -9
View File
@@ -479,12 +479,19 @@ function startStage(m: 'vision' | 'sim' | 'guided') {
function onCameraReady() {
if (mode.value !== 'vision') return
camera.start()
setTimeout(() => {
const s = camera.status.value
if (s === 'unsupported' || s === 'error') fallbackToGuided('当前手机暂不支持动作识别,已切换为领练模式')
}, 1500)
}
// VisionKit 启动、取帧失败是异步回调,可能晚于任何固定等待时间;随时失败随时切到领练,不会卡在站位。
// 同步触发:再来一次时状态会在同一轮里 unsupported → starting → unsupported,默认异步合并后看不到变化
watch(
() => camera.status.value,
(s) => {
if (stage.value !== 'camera' || mode.value !== 'vision') return
if (s === 'unsupported' || s === 'error') fallbackToGuided('当前手机暂不支持动作识别,已切换为领练模式')
},
{ flush: 'sync' },
)
function onCameraError() {
camera.onCameraError(null)
fallbackToGuided('摄像头不可用,已切换为领练模式')
@@ -541,18 +548,15 @@ function onEvent(e: SessionEvent) {
break
case 'countdown':
voice.speak(String(e.n), 'high')
uni.vibrateShort({ type: 'light' } as any)
break
case 'rep': {
if (mode.value === 'guided') {
// 领练模式不评分:只报数和轻震动
uni.vibrateShort({ type: 'light' } as any)
// 领练模式不评分:只报数
if (shouldSpeakCount(e.count)) voice.speak(String(e.count), 'count')
break
}
const text = e.grade === 'perfect' ? '完美' : e.grade === 'good' ? '不错' : '加油'
Object.assign(pop, { key: pop.key + 1, text, score: e.score, grade: e.grade })
uni.vibrateShort({ type: e.grade === 'perfect' ? 'medium' : 'light' } as any)
if (e.tip) {
showTip(e.tip, e.joints ?? [])
voice.speak(e.tip, 'high')
@@ -648,11 +652,14 @@ function onPause() {
function onResume() {
if (!session) return
handle(session.resume(Date.now()))
// 倒计时中暂停,恢复后会回到站位;领练模式没有识别、站位永远过不去,直接重新倒计时
if (mode.value === 'guided' && session.phase === 'framing') startGuided()
}
function finish() {
if (!session || stage.value !== 'camera') return
handle(session.finish())
// 只改状态、不派发 done 事件:done 的处理就是调用 finish,派发会重入,同一次训练记两条历史
session.finish()
const s = summarize(session, ex.value.netMet)
if (mode.value === 'guided') {
Object.assign(s, {