feat(practice): streamline pilot content operations

This commit is contained in:
2026-07-25 12:51:39 +08:00
parent 35b37b07f7
commit fa9d6da975
9 changed files with 380 additions and 24 deletions
+15 -5
View File
@@ -74,7 +74,7 @@
<text class="scene-picker-note">复杂场景的正式前置解锁规则仍待业务确认;系统不会以估算分数硬性拦截已发布训练。</text>
</view>
<view v-if="loggedIn && practiceView === 'prep' && availableScenarios.length" class="panel scenario-card employee-card">
<view v-if="loggedIn && practiceView === 'prep' && availableScenarios.length" class="panel scenario-card practice-scenario-card employee-card">
<view class="scenario-headline">
<text class="scenario-title">{{ activeScenarioName }}</text>
<text class="scenario-desc">{{ selectedScenarioDescription }}</text>
@@ -110,7 +110,14 @@
>
{{ status === 'finished' ? '再练一次' : '我已准备好,开始练习' }}
</button>
<view v-if="(status === 'idle' || status === 'finished') && realtimePersonaOptions.length" class="realtime-persona-picker">
</view>
<view v-if="loggedIn && practiceView === 'prep'" class="panel scenario-card realtime-entry-card employee-card">
<view class="scenario-headline">
<text class="scenario-title">实时陪练 Beta</text>
<text class="scenario-desc">直接与数字师傅或模拟业主对话,不依赖场景审核发布。</text>
</view>
<view v-if="realtimePersonaOptions.length" class="realtime-persona-picker">
<view class="realtime-persona-heading">
<text class="realtime-persona-title">实时陪练人设</text>
</view>
@@ -134,10 +141,10 @@
<button
v-if="status === 'idle' || status === 'finished'"
class="secondary-button realtime-start-button"
:disabled="!canStartPractice || busy"
:disabled="!canStartRealtime || busy"
@click="startRealtime"
>
实时陪练 Beta
开始实时陪练
</button>
<text class="realtime-beta-note">自然打断、边听边说;本次体验不计入训练成绩。</text>
</view>
@@ -593,6 +600,9 @@ const canStartPractice = computed(() =>
&& (status.value === 'idle' || status.value === 'finished')
&& Boolean(selectedScenario.value?.id)
);
const canStartRealtime = computed(() =>
status.value === 'idle' || status.value === 'finished'
);
const hasTraineeReply = computed(() => turns.value.some((item) => item.role === 'trainee'));
const canFinishPractice = computed(() => hasTraineeReply.value && !redFlagActive.value);
const hasCoachState = computed(() => emotionScore.value > 0 || trustScore.value > 0 || redFlagActive.value);
@@ -1005,7 +1015,7 @@ const stopRealtime = () => {
};
const startRealtime = async () => {
if (!canStartPractice.value || !requireLogin()) return;
if (!canStartRealtime.value || !requireLogin()) return;
speechPlayback.stop();
cancelRecording();
turnVoiceGeneration += 1;