Files
miniprogram-1/miniprogram/pages/qa_exercise/qa_exercise.wxml
2026-01-03 15:47:49 +08:00

200 lines
9.9 KiB
Plaintext

<view class="qa-exercise-container">
<view wx:if="{{!contentReady}}" class="page-loading-mask">
<view class="loading-center">
<view class="scanner scanner-visible">
<view class="star star1"></view>
<view class="star star2"></view>
<view class="star star3"></view>
</view>
<view class="status-text">{{statusText}}</view>
</view>
</view>
<view class="container {{contentVisible ? 'fade-in' : 'fade-out'}}" wx:if="{{contentReady}}">
<view class="process-container" wx:if="{{qaList && qaList.length > 0}}">
<block wx:for="{{qaList}}" wx:key="index">
<view class="process-dot {{processDotClasses[index]}} {{index === currentIndex ? 'current' : ''}}"></view>
</block>
</view>
<view class="image-card">
<image wx:if="{{imageLocalUrl}}" class="image" src="{{imageLocalUrl}}" mode="aspectFill" bindtap="previewImage" bindload="onImageLoad" binderror="onImageError"></image>
<view class="view-full" wx:if="{{imageLocalUrl}}" bindtap="previewImage">
<t-icon name="zoom-in" size="32rpx" />
<!-- <text>View Full</text> -->
</view>
</view>
<view class="question-title">
<text wx:for="{{questionWords}}" wx:key="index" class="word-item" data-word="{{item}}" bindtap="handleWordClick">{{item}}</text>
</view>
<!-- <view class="progress-text">{{progressText}}</view> -->
<scroll-view class="question-scroll" scroll-y="true">
<view class="question-content {{modeAnim}}" wx:if="{{questionMode === 'choice'}}">
<view class="choice-title">Select the correct answer ({{selectedCount}}/{{choiceRequiredCount}})</view>
<view class="option-list">
<view wx:for="{{choiceOptions}}" wx:key="index" class="option-item {{evalClasses[index]}} {{(!choiceSubmitted && !selectedFlags[index] && selectedCount >= choiceRequiredCount) ? 'disabled' : ''}}" data-index="{{index}}" data-word="{{item.content}}" bindtap="selectOption" bindlongpress="onOptionLongPress">
<view class="option-radio">
<view class="radio-dot {{selectedFlags[index] ? 'on' : ''}} {{(evalClasses[index] === 'opt-incorrect' && selectedFlags[index]) ? 'red' : ''}}"></view>
</view>
<text class="option-text">{{item.content}}</text>
</view>
</view>
</view>
<view class="question-content {{modeAnim}}" wx:if="{{questionMode === 'cloze'}}">
<view class="choice-title">Select the correct word to complete the sentence:</view>
<view class="cloze-sentence">
<text class="cloze-text">{{clozeParts[0]}}</text>
<text class="cloze-fill">_____</text>
<text class="cloze-text">{{clozeParts[1]}}</text>
</view>
<view class="option-list">
<view wx:for="{{clozeOptions}}" wx:key="index" class="option-item {{evalClasses[index]}}" data-index="{{index}}" data-word="{{item}}" bindtap="selectClozeOption" bindlongpress="onOptionLongPress">
<view class="option-radio">
<view class="radio-dot {{selectedClozeIndex === index ? 'on' : ''}} {{(evalClasses[index] === 'opt-incorrect' && selectedClozeIndex === index) ? 'red' : ''}}"></view>
</view>
<text class="option-text">{{item}}</text>
</view>
</view>
</view>
<view class="question-content {{modeAnim}}" wx:if="{{questionMode === 'free_text'}}">
<view class="tip-row">
<t-icon name="info-circle" size="32rpx" />
<text class="tip-text">Tip: Be specific about the object type.</text>
</view>
<view class="answer-row">
<text class="answer-label">Your Answer</text>
<text class="answer-hint" bindtap="onHintTap">Need a hint?</text>
</view>
<view class="input-card">
<textarea class="answer-input" placeholder="Type your answer here..." maxlength="200" bindinput="inputChange" value="{{freeTextInput}}" />
<text class="input-type">English input</text>
</view>
</view>
<view class="submit-row">
<button class="submit-btn" bindtap="onSubmitTap" disabled="{{submitDisabled}}" wx:if="{{retryDisabled}}">提交</button>
<button class="submit-btn" bindtap="onRetryTap" disabled="{{retryDisabled}}" wx:else>重试</button>
</view>
</scroll-view>
</view>
<view class="bottom-bar {{contentVisible ? 'show' : ''}}">
<t-icon name="chevron-left" class="bottom-btn {{currentIndex <= 0 ? 'disabled' : ''}}" size="48rpx" bind:tap="onPrevTap" />
<t-icon name="{{isPlaying ? 'pause' : 'play'}}" class="bottom-btn" size="48rpx" bind:tap="playStandardVoice" />
<t-icon name="swap" class="bottom-btn" size="48rpx" bind:tap="toggleMode" />
<t-icon name="fact-check" class="bottom-btn {{resultDisplayed ? '' : 'disabled'}}" size="48rpx" bind:tap="onScoreTap" />
<t-icon name="chevron-right" class="bottom-btn {{(qaList && (currentIndex >= qaList.length - 1)) ? 'disabled' : ''}}" size="48rpx" bind:tap="onNextTap" />
</view>
<word-dictionary
id="wordDict"
visible="{{showDictPopup}}"
expanded="{{showDictExtended}}"
loading="{{dictLoading}}"
wordDict="{{wordDict}}"
showBackIcon="{{showBackIcon}}"
prototypeWord="{{prototypeWord}}"
forceHidePrototype="{{forceHidePrototype}}"
isWordEmptyResult="{{isWordEmptyResult}}"
dictDefaultTabValue="{{dictDefaultTabValue}}"
activeWordAudioType="{{activeWordAudioType}}"
wordAudioPlaying="{{wordAudioPlaying}}"
wordAudioIconName="{{wordAudioIconName}}"
bind:close="handleDictClose"
bind:more="handleDictMore"
bind:tabsChange="onTabsChange"
bind:tabsClick="onTabsClick"
bind:back="handleBackToPreviousWord"
bind:wordTap="handleWordClick"
/>
<view class="word-popup-mask" wx:if="{{showDictPopup}}" bindtap="handleDictClose"></view>
<view class="qa-detail-overlay" wx:if="{{qaDetailVisible}}" bindtap="onCloseDetailModal"></view>
<view class="qa-detail-modal {{qaDetailVisible ? 'show' : ''}}" wx:if="{{qaDetailVisible}}">
<view class="modal-header">
<text class="modal-title">题目解析</text>
<t-icon name="close" class="modal-close" size="40rpx" bind:tap="onCloseDetailModal" />
</view>
<scroll-view class="detail-body" scroll-y="true">
<view class="section">
<text class="question-text">{{qaDetailQuestionText}}</text>
</view>
<view class="section">
<view class="overview-card {{qaDetailResultStatus}}">
<view class="overview-icon">
<t-icon name="{{qaDetailIconName}}" size="40rpx" color="#fff" />
</view>
<view class="overview-content">
<text class="overview-label">评估详情 (EVALUATION DETAIL)</text>
<text class="overview-text">{{qaDetailOverviewText}}</text>
</view>
</view>
</view>
<block wx:for="{{qaDetailBlocks}}" wx:key="index">
<view class="section" wx:if="{{item.items && item.items.length}}">
<!-- <text class="section-title">{{item.title}}</text> -->
<view wx:if="{{item.variant === 'incorrect'}}" class="detail-row incorrect">
<view class="detail-icon">
<t-icon name="{{item.iconName || 'data-error' }}" size="40rpx" color="#fff" />
</view>
<view class="detail-content">
<text class="detail-label">错误选项</text>
<view class="detail-items incorrect-list">
<view class="incorrect-item" wx:for="{{item.items}}" wx:key="index">
<view class="incorrect-head">
<view class="chip incorrect">{{item.content}}</view>
<text class="error-type">{{item.error_type}}</text>
</view>
<text class="error-reason">{{item.error_reason}}</text>
</view>
</view>
</view>
</view>
<view wx:if="{{item.variant === 'info'}}" class="detail-row your-choice {{qaDetailResultStatus}}">
<view class="detail-icon">
<t-icon name="{{item.iconName || 'info-circle' }}" size="40rpx" color="#fff" />
</view>
<view class="detail-content">
<text class="detail-label">{{item.title}}</text>
<view class="detail-items">
<text class="detail-item" wx:for="{{item.items}}" wx:key="index">{{item}}</text>
</view>
</view>
</view>
<view wx:if="{{item.variant !== 'incorrect' && item.variant !== 'info'}}" class="detail-row {{item.variant}}">
<view class="detail-icon">
<t-icon name="{{item.iconName || 'info-circle' }}" size="40rpx" color="#fff" />
</view>
<view class="detail-content">
<text class="detail-label">{{item.title}}</text>
<view class="detail-items">
<text class="detail-item" wx:for="{{item.items}}" wx:key="index">{{item}}</text>
</view>
</view>
</view>
</view>
</block>
</scroll-view>
</view>
<view class="completion-popup-mask" wx:if="{{showCompletionPopup}}">
<view class="completion-card">
<view class="completion-close" bindtap="handleCompletionPopupClose">
<t-icon name="close" size="48rpx" color="#ccc" />
</view>
<view class="completion-trophy">
<view class="trophy-circle">
<t-icon name="thumb-up-2" size="80rpx" color="#001858" />
</view>
<view class="confetti c1"></view>
<view class="confetti c2"></view>
<view class="confetti c3"></view>
</view>
<view class="completion-title">Excellent Job!</view>
<!-- <view class="completion-subtitle">You've mastered the vocabulary for this photo scene.</view> -->
<button class="completion-share-btn" open-type="share" data-type="achievement">
<t-icon name="share" size="36rpx" color="#fff" style="margin-right: 12rpx;" />
Share Achievement
</button>
</view>
</view>
</view>