Files
teaching-feedback-assistant/pages/feedback/index.wxml
2026-07-22 17:26:55 +08:00

126 lines
5.7 KiB
Plaintext

<view class="page-shell feedback-page">
<text class="eyebrow">课堂反馈</text>
<view class="page-heading">
<text class="page-title">反馈生成</text>
</view>
<text class="page-subtitle">填写课堂表现并保存到教学反馈记录。</text>
<view wx:if="{{errorMessage}}" class="status-banner">
<view class="status-copy">
<text>{{errorMessage}}</text>
<view wx:if="{{errorRequestId}}" class="status-request-id">
<text>请求编号:{{errorRequestId}}</text>
<text class="status-action" bindtap="copyRequestId">复制</text>
</view>
</view>
<text class="status-action" bindtap="retryLoad">重试</text>
</view>
<view class="feedback-form surface">
<picker class="feedback-field" mode="selector" range="{{profileOptions}}" value="{{selectedProfileIndex}}" disabled="{{loading || recording || voiceBusy}}" bindchange="onProfileChange">
<text class="form-label">学生档案</text>
<text class="form-value">{{loading ? '正在加载...' : profileOptions[selectedProfileIndex]}}</text>
</picker>
<picker class="feedback-field" mode="date" value="{{draft.feedbackDate}}" disabled="{{recording || voiceBusy}}" bindchange="onDateChange">
<text class="form-label">反馈日期</text>
<text class="form-value">{{draft.feedbackDate}}</text>
</picker>
<view class="content-field">
<view class="content-label-row">
<text class="form-label">反馈内容</text>
<view class="content-actions">
<text class="content-count">{{contentLength}} / 2000</text>
<button
wx:if="{{contentLength > 0}}"
class="content-clear-button"
disabled="{{recording || voiceBusy}}"
bindtap="clearFeedbackContent"
>清空</button>
</view>
</view>
<textarea
class="feedback-textarea"
value="{{draft.content}}"
maxlength="2000"
disabled="{{recording || voiceBusy}}"
placeholder="记录课堂完成情况、进步与后续建议"
bindinput="onContentInput"
/>
<view class="voice-input-row">
<button
class="voice-button {{recording ? 'voice-button-recording' : ''}}"
disabled="{{saving || voiceBusy}}"
bindtap="toggleRecording"
aria-label="{{recording ? '结束录音' : '开始录音'}}"
>
<text class="voice-button-icon">{{recording ? '■' : '●'}}</text>
<text>{{recording ? '结束录音' : '语音录入'}}</text>
</button>
<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>
<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">
<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>
</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}}"
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>
</view>
<view wx:if="{{!loading && profiles.length === 0}}" class="profiles-hint">
<text>当前没有学生档案,反馈仍可不关联学生直接保存。</text>
<text class="status-action" bindtap="goStudents">新建档案</text>
</view>
</view>