feat(voice): add async selectable summaries
This commit is contained in:
@@ -62,60 +62,103 @@
|
||||
<view class="voice-state {{voiceActionable ? 'voice-state-actionable' : ''}}" bindtap="toggleVoiceDetails">
|
||||
<text class="voice-status">{{voiceStatus}}</text>
|
||||
<text wx:if="{{recording}}" class="recording-time">{{recordingTime}}</text>
|
||||
<text wx:elif="{{voiceActionable}}" class="voice-state-arrow">{{voiceDetailsExpanded ? '⌃' : '⌄'}}</text>
|
||||
<view wx:elif="{{voiceActionable}}" class="voice-state-arrow {{voiceDetailsExpanded ? 'voice-state-arrow-expanded' : ''}}"></view>
|
||||
</view>
|
||||
<view wx:if="{{voiceDetailsExpanded}}" class="voice-record-list">
|
||||
<view class="voice-record-list-heading">
|
||||
<text>语音记录</text>
|
||||
<text>{{voiceLessonViews.length}}节</text>
|
||||
</view>
|
||||
<view
|
||||
wx:for="{{voiceLessonViews}}"
|
||||
wx:key="id"
|
||||
wx:for-item="lesson"
|
||||
class="voice-record-item"
|
||||
>
|
||||
<view class="voice-record-header">
|
||||
<view>
|
||||
<text class="voice-record-title">第{{lesson.sequence}}节</text>
|
||||
<text class="voice-record-duration">{{lesson.durationText}} · {{lesson.transcriptLength}}字</text>
|
||||
</view>
|
||||
<text class="voice-record-status">{{lesson.statusText}}</text>
|
||||
</view>
|
||||
<text
|
||||
wx:if="{{lesson.transcript}}"
|
||||
selectable
|
||||
class="voice-record-transcript {{expandedVoiceLessonId === lesson.id ? 'voice-record-transcript-expanded' : ''}}"
|
||||
>{{lesson.transcript}}</text>
|
||||
<text wx:else class="voice-record-empty">{{lesson.emptyText}}</text>
|
||||
<view wx:if="{{lesson.transcript}}" class="voice-record-actions">
|
||||
<view class="voice-summary-selection-heading">
|
||||
<text>已选 {{selectedSummaryLessonCount}} / {{eligibleSummaryLessonCount}}</text>
|
||||
<button
|
||||
wx:if="{{lesson.transcriptExpandable}}"
|
||||
wx:if="{{eligibleSummaryLessonCount > 0}}"
|
||||
class="voice-record-text-button"
|
||||
data-lesson-id="{{lesson.id}}"
|
||||
bindtap="toggleVoiceLessonTranscript"
|
||||
>{{expandedVoiceLessonId === lesson.id ? '收起' : '展开'}}</button>
|
||||
<button
|
||||
class="voice-record-add-button"
|
||||
data-lesson-id="{{lesson.id}}"
|
||||
disabled="{{!lesson.canAdd || voiceBusy}}"
|
||||
bindtap="addVoiceLessonToDraft"
|
||||
>{{lesson.addActionText}}</button>
|
||||
disabled="{{recording || voiceBusy || summaryBusy || (summaryRun && (summaryRun.status === 'queued' || summaryRun.status === 'processing'))}}"
|
||||
bindtap="toggleAllSummaryLessons"
|
||||
>{{allSummaryLessonsSelected ? '取消全选' : '全选'}}</button>
|
||||
</view>
|
||||
</view>
|
||||
<checkbox-group bindchange="onSummarySelectionChange">
|
||||
<view
|
||||
wx:for="{{voiceLessonViews}}"
|
||||
wx:key="id"
|
||||
wx:for-item="lesson"
|
||||
class="voice-record-item"
|
||||
>
|
||||
<view class="voice-record-header">
|
||||
<view class="voice-record-title-row">
|
||||
<checkbox
|
||||
wx:if="{{lesson.summaryEligible}}"
|
||||
class="voice-summary-checkbox"
|
||||
value="{{lesson.id}}"
|
||||
checked="{{lesson.summarySelected}}"
|
||||
disabled="{{recording || voiceBusy || summaryBusy || (summaryRun && (summaryRun.status === 'queued' || summaryRun.status === 'processing'))}}"
|
||||
color="#007aff"
|
||||
/>
|
||||
<view>
|
||||
<text class="voice-record-title">第{{lesson.sequence}}节</text>
|
||||
<text class="voice-record-duration">{{lesson.durationText}} · {{lesson.transcriptLength}}字</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="voice-record-status">{{lesson.statusText}}</text>
|
||||
</view>
|
||||
<text
|
||||
wx:if="{{lesson.transcript}}"
|
||||
selectable
|
||||
class="voice-record-transcript {{expandedVoiceLessonId === lesson.id ? 'voice-record-transcript-expanded' : ''}}"
|
||||
>{{lesson.transcript}}</text>
|
||||
<text wx:else class="voice-record-empty">{{lesson.emptyText}}</text>
|
||||
<view wx:if="{{lesson.transcript}}" class="voice-record-actions">
|
||||
<button
|
||||
wx:if="{{lesson.transcriptExpandable}}"
|
||||
class="voice-record-text-button"
|
||||
data-lesson-id="{{lesson.id}}"
|
||||
bindtap="toggleVoiceLessonTranscript"
|
||||
>{{expandedVoiceLessonId === lesson.id ? '收起' : '展开'}}</button>
|
||||
<button
|
||||
class="voice-record-add-button"
|
||||
data-lesson-id="{{lesson.id}}"
|
||||
disabled="{{!lesson.canAdd || voiceBusy}}"
|
||||
bindtap="addVoiceLessonToDraft"
|
||||
>{{lesson.addActionText}}</button>
|
||||
</view>
|
||||
</view>
|
||||
</checkbox-group>
|
||||
<view wx:if="{{eligibleSummaryLessonCount > 0}}" class="voice-summary-controls">
|
||||
<button
|
||||
class="voice-summary-button"
|
||||
loading="{{summaryBusy}}"
|
||||
disabled="{{recording || voiceBusy || summaryBusy || selectedSummaryLessonCount === 0 || (summaryRun && (summaryRun.status === 'queued' || summaryRun.status === 'processing'))}}"
|
||||
bindtap="generateFeedbackSummary"
|
||||
>{{summaryActionText}}({{selectedSummaryLessonCount}}节)</button>
|
||||
</view>
|
||||
<view wx:if="{{summaryRun}}" class="voice-summary-preview {{summaryRun.status === 'failed' ? 'voice-summary-preview-failed' : ''}}">
|
||||
<view class="voice-summary-preview-heading">
|
||||
<text>总结预览</text>
|
||||
<text>{{summaryStatusText}}</text>
|
||||
</view>
|
||||
<text wx:if="{{summaryRun.content}}" selectable class="voice-summary-preview-content">{{summaryRun.content}}</text>
|
||||
<text wx:elif="{{summaryRun.status === 'queued' || summaryRun.status === 'processing'}}" class="voice-summary-preview-note">已选择 {{summaryRun.lessonIds.length}} 节录音</text>
|
||||
<button
|
||||
wx:if="{{summaryRun.status === 'ready'}}"
|
||||
class="voice-summary-apply-button"
|
||||
loading="{{summaryBusy}}"
|
||||
disabled="{{summaryBusy}}"
|
||||
bindtap="applyGeneratedSummary"
|
||||
>替换输入框</button>
|
||||
</view>
|
||||
</view>
|
||||
<view wx:if="{{session && session.failedSegmentCount > 0}}" class="voice-failure-recovery">
|
||||
<text class="voice-failure-hint">{{voiceFailureHint}}</text>
|
||||
<button
|
||||
class="voice-discard-button"
|
||||
disabled="{{saving || generating || recording || voiceBusy}}"
|
||||
disabled="{{saving || summaryBusy || recording || voiceBusy}}"
|
||||
bindtap="discardFailedSegments"
|
||||
>放弃失败录音</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<button class="save-feedback primary-button" loading="{{saving || generating}}" disabled="{{saving || generating || recording || voiceBusy || (session && session.processingSegmentCount > 0 && session.failedSegmentCount === 0)}}" bindtap="saveFeedback">{{primaryActionText}}</button>
|
||||
<button class="save-feedback primary-button" loading="{{saving}}" disabled="{{saving || summaryBusy || recording || voiceBusy || (summaryRun && (summaryRun.status === 'queued' || summaryRun.status === 'processing')) || (session && session.processingSegmentCount > 0 && session.failedSegmentCount === 0)}}" bindtap="saveFeedback">{{primaryActionText}}</button>
|
||||
</view>
|
||||
|
||||
<view wx:if="{{!loading && profiles.length === 0}}" class="profiles-hint">
|
||||
|
||||
Reference in New Issue
Block a user