fix scroll view

This commit is contained in:
Felix
2026-01-27 10:21:55 +08:00
parent 96b0a20fa0
commit dc65893293
3 changed files with 81 additions and 63 deletions

View File

@@ -83,6 +83,7 @@ interface IData {
fixedMode?: QuestionMode, fixedMode?: QuestionMode,
canvasWidth?: number, canvasWidth?: number,
canvasHeight?: number, canvasHeight?: number,
showConfetti?: boolean
confetti?: any confetti?: any
nextButtonIcon?: string nextButtonIcon?: string
isAutoSwitching?: boolean isAutoSwitching?: boolean
@@ -300,6 +301,7 @@ Page<IData, IPageInstance>({
fixedMode: undefined, fixedMode: undefined,
canvasWidth: 0, canvasWidth: 0,
canvasHeight: 0, canvasHeight: 0,
showConfetti: false,
confetti: null, confetti: null,
nextButtonIcon: 'chevron-right', nextButtonIcon: 'chevron-right',
isAutoSwitching: false, isAutoSwitching: false,
@@ -439,7 +441,7 @@ Page<IData, IPageInstance>({
if (depth <= 0) return 'dot-0' if (depth <= 0) return 'dot-0'
if (depth === 1) return 'dot-1' if (depth === 1) return 'dot-1'
if (depth === 2) return 'dot-2' if (depth === 2) return 'dot-2'
return 'dot-3' return 'dot-1'
}) })
this.setData({ processDotClasses: items }) this.setData({ processDotClasses: items })
}, },
@@ -597,19 +599,26 @@ Page<IData, IPageInstance>({
}, },
fireConfetti() { fireConfetti() {
// 触发五彩纸屑效果 - 注意这是异步方法返回Promise // 触发五彩纸屑效果 - 注意这是异步方法返回Promise
this.setData({ showConfetti: true });
(this as any).confetti.fire({ (this as any).confetti.fire({
particleCount: 100, particleCount: 100,
spread: 70, spread: 70,
origin: { x: 0.5, y: 0.5 } origin: { x: 0.5, y: 0.5 }
}).then(() => { }).then(() => {
logger.log('五彩纸屑效果已启动'); logger.log('五彩纸屑效果已启动');
// 动画大概持续几秒,这里设置延迟关闭
setTimeout(() => {
this.setData({ showConfetti: false });
}, 5000);
}).catch((err: any) => { }).catch((err: any) => {
logger.error('启动失败', err); logger.error('启动失败', err);
this.setData({ showConfetti: false });
}); });
}, },
resetConfetti() { resetConfetti() {
// 重置画布,清除五彩纸屑 // 重置画布,清除五彩纸屑
this.setData({ showConfetti: false });
(this as any).confetti?.reset?.(); (this as any).confetti?.reset?.();
}, },
@@ -2248,8 +2257,8 @@ Page<IData, IPageInstance>({
let sceneList: any[] = [] let sceneList: any[] = []
let eventList: any[] = [] let eventList: any[] = []
let userRole = {} let userRole: any = null
let assistantRole = {} let assistantRole: any = null
let style = {} let style = {}
const hasScene = scenesSelected.length > 0 const hasScene = scenesSelected.length > 0
@@ -2367,6 +2376,13 @@ Page<IData, IPageInstance>({
assistantRole = { en: String(pair.role1_en), zh: String(pair.role1_zh || pair.role1_en) } assistantRole = { en: String(pair.role1_en), zh: String(pair.role1_zh || pair.role1_en) }
} }
} }
} else if (rolesList.length > 0) {
// 如果没有选择角色,随机选择一个并默认分配 role1 给 user
const pair = rolesList[Math.floor(Math.random() * rolesList.length)]
if (pair) {
userRole = { en: String(pair.role1_en), zh: String(pair.role1_zh || pair.role1_en) }
assistantRole = { en: String(pair.role2_en), zh: String(pair.role2_zh || pair.role2_en) }
}
} }
} }

View File

@@ -276,11 +276,10 @@
<view class="bottom-bar {{contentVisible ? 'show' : ''}}" wx:if="{{questionMode !== 'conversation'}}"> <view class="bottom-bar {{contentVisible ? 'show' : ''}}" wx:if="{{questionMode !== 'conversation'}}">
<t-icon name="chevron-left" class="bottom-btn {{currentIndex <= 0 ? 'disabled' : ''}}" size="48rpx" bind:tap="onPrevTap" /> <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="{{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="fact-check" class="bottom-btn {{resultDisplayed ? '' : 'disabled'}}" size="48rpx" bind:tap="onScoreTap" />
<t-icon name="{{nextButtonIcon || 'chevron-right'}}" class="bottom-btn {{(qaList && (currentIndex >= qaList.length - 1)) ? 'disabled' : ''}}" size="48rpx" bind:tap="onNextTap" /> <t-icon name="{{nextButtonIcon || 'chevron-right'}}" class="bottom-btn {{(qaList && (currentIndex >= qaList.length - 1)) ? 'disabled' : ''}}" size="48rpx" bind:tap="onNextTap" />
</view> </view>
<t-drawer visible="{{historyVisible}}" placement="left" bind:visible-change="onHistoryDrawerClose" close-btn="{{true}}"> <t-drawer visible="{{historyVisible}}" placement="left" bind:visible-change="onHistoryDrawerClose" close-btn="{{true}}">
<scroll-view scroll-y class="history-drawer-scroll" bindscrolltolower="onHistoryScrollBottom"> <scroll-view scroll-y class="history-drawer-scroll" bindscrolltolower="onHistoryScrollBottom">
<view class="history-list"> <view class="history-list">
<t-cell <t-cell
@@ -384,66 +383,66 @@
<text class="modal-title">题目解析</text> <text class="modal-title">题目解析</text>
<t-icon name="close" class="modal-close" size="40rpx" bind:tap="onCloseDetailModal" /> <t-icon name="close" class="modal-close" size="40rpx" bind:tap="onCloseDetailModal" />
</view> </view>
<scroll-view class="detail-body" scroll-y="{{true}}"> <scroll-view class="detail-body" scroll-y="{{true}}">
<view class="section"> <view class="section">
<text class="question-text">{{qaDetailQuestionText}}</text> <text class="question-text">{{qaDetailQuestionText}}</text>
</view> </view>
<view class="section"> <view class="section">
<view class="overview-card {{qaDetailResultStatus}}"> <view class="overview-card {{qaDetailResultStatus}}">
<view class="overview-icon"> <view class="overview-icon">
<t-icon name="{{qaDetailIconName}}" size="40rpx" color="#fff" /> <t-icon name="{{qaDetailIconName}}" size="40rpx" color="#fff" />
</view> </view>
<view class="overview-content"> <view class="overview-content">
<text class="overview-label">评估详情 (EVALUATION DETAIL)</text> <text class="overview-label">评估详情 (EVALUATION DETAIL)</text>
<text class="overview-text">{{qaDetailOverviewText}}</text> <text class="overview-text">{{qaDetailOverviewText}}</text>
</view>
</view> </view>
</view> </view>
</view> <block wx:for="{{qaDetailBlocks}}" wx:key="index">
<block wx:for="{{qaDetailBlocks}}" wx:key="index"> <view class="section" wx:if="{{item.items && item.items.length}}">
<view class="section" wx:if="{{item.items && item.items.length}}"> <!-- <text class="section-title">{{item.title}}</text> -->
<!-- <text class="section-title">{{item.title}}</text> --> <view wx:if="{{item.variant === 'incorrect'}}" class="detail-row incorrect">
<view wx:if="{{item.variant === 'incorrect'}}" class="detail-row incorrect"> <view class="detail-icon">
<view class="detail-icon"> <t-icon name="{{item.iconName || 'data-error' }}" size="40rpx" color="#fff" />
<t-icon name="{{item.iconName || 'data-error' }}" size="40rpx" color="#fff" /> </view>
</view> <view class="detail-content">
<view class="detail-content"> <text class="detail-label">错误选项</text>
<text class="detail-label">错误选项</text> <view class="detail-items incorrect-list">
<view class="detail-items incorrect-list"> <view class="incorrect-item" wx:for="{{item.items}}" wx:key="index">
<view class="incorrect-item" wx:for="{{item.items}}" wx:key="index"> <view class="incorrect-head">
<view class="incorrect-head"> <view class="chip incorrect">{{item.content}}</view>
<view class="chip incorrect">{{item.content}}</view> <text class="error-type">{{item.error_type}}</text>
<text class="error-type">{{item.error_type}}</text> </view>
<text class="error-reason">{{item.error_reason}}</text>
</view> </view>
<text class="error-reason">{{item.error_reason}}</text> </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>
</view> </view>
</view> </view>
<view wx:if="{{item.variant === 'info'}}" class="detail-row your-choice {{qaDetailResultStatus}}"> </block>
<view class="detail-icon"> </scroll-view>
<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>
<view class="completion-popup-mask" wx:if="{{showCompletionPopup}}"> <view class="completion-popup-mask" wx:if="{{showCompletionPopup}}">
@@ -467,5 +466,5 @@
</button> </button>
</view> </view>
</view> </view>
<vx-confetti id="confetti" class="confetti-canvas" width="{{canvasWidth}}" height="{{canvasHeight}}"></vx-confetti> <vx-confetti id="confetti" class="confetti-canvas {{showConfetti ? 'show' : ''}}" width="{{canvasWidth}}" height="{{canvasHeight}}"></vx-confetti>
</view> </view>

View File

@@ -30,7 +30,6 @@
position: relative; position: relative;
overflow: hidden; overflow: hidden;
/* padding-bottom: calc(110rpx + env(safe-area-inset-bottom)); */ /* padding-bottom: calc(110rpx + env(safe-area-inset-bottom)); */
/* transition: padding-bottom 0.3s ease; */
transition: margin-bottom 0.3s ease; transition: margin-bottom 0.3s ease;
} }
.inner-scroll { .inner-scroll {
@@ -38,8 +37,7 @@
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
/* height: 100%; */ height: 100%;
height: 500rpx;
} }
.chat-mode-scroll { .chat-mode-scroll {
/* padding-bottom: calc(110rpx + env(safe-area-inset-bottom)); */ /* padding-bottom: calc(110rpx + env(safe-area-inset-bottom)); */
@@ -681,6 +679,7 @@
} }
.confetti-canvas { .confetti-canvas {
display: none;
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
@@ -690,6 +689,10 @@
pointer-events: none; /* 确保canvas不会阻挡点击事件 */ pointer-events: none; /* 确保canvas不会阻挡点击事件 */
} }
.confetti-canvas.show {
display: block;
}
.type-container { .type-container {
display: flex; display: flex;
justify-content: center; justify-content: center;
@@ -701,7 +704,7 @@
position: relative; position: relative;
left: 50%; left: 50%;
transform: translateX(-50%); transform: translateX(-50%);
z-index: 100; z-index: 99;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05); box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
} }