This commit is contained in:
Felix
2025-12-06 17:47:09 +08:00
parent f860f4782d
commit 156e6eca6f
5 changed files with 141 additions and 62 deletions

View File

@@ -121,6 +121,7 @@ interface IPageData {
overlayVisible: boolean,
highlightWords: string[],
highlightShow: boolean,
analizing: boolean,
highlightZoom: boolean,
focusWordIndex: number,
focusTransform: string,
@@ -258,6 +259,7 @@ Page<IPageData, IPageInstance>({
overlayVisible: false,
highlightWords: [],
highlightShow: false,
analizing: false,
highlightZoom: false,
focusWordIndex: 0,
focusTransform: '',
@@ -269,10 +271,12 @@ Page<IPageData, IPageInstance>({
},
onMicHighlight() {
const pre = this.data.cachedHighlightWords || []
const cachedIdx = typeof this.data.cachedSentenceIndex === 'number' ? this.data.cachedSentenceIndex : -1
const currentIdx = typeof this.data.selectedSentenceIndex === 'number' ? this.data.selectedSentenceIndex : -1
const needRecompute = (!pre || pre.length === 0 || cachedIdx !== currentIdx)
// const pre = this.data.cachedHighlightWords || []
// const cachedIdx = typeof this.data.cachedSentenceIndex === 'number' ? this.data.cachedSentenceIndex : -1
// const currentIdx = typeof this.data.selectedSentenceIndex === 'number' ? this.data.selectedSentenceIndex : -1
// const needRecompute = (!pre || pre.length === 0 || cachedIdx !== currentIdx)
this.computeHighlightLayout()
const startAnim = () => {
const words = this.data.cachedHighlightWords || []
@@ -308,21 +312,19 @@ Page<IPageData, IPageInstance>({
}, 50)
}
if (needRecompute) {
try {
wx.nextTick(() => {
this.computeHighlightLayout()
setTimeout(() => startAnim(), 80)
})
} catch (e) {
setTimeout(() => {
this.computeHighlightLayout()
setTimeout(() => startAnim(), 80)
}, 0)
}
} else {
startAnim()
// if (needRecompute) {
try {
wx.nextTick(() => {
setTimeout(() => startAnim(), 80)
})
} catch (e) {
setTimeout(() => {
setTimeout(() => startAnim(), 80)
}, 0)
}
// } else {
// startAnim()
// }
},
// 切换评分区域展开状态
toggleScoreSection() {
@@ -548,11 +550,11 @@ Page<IPageData, IPageInstance>({
console.log('---lisa-handleRecordEnd')
this.stopRecording()
// 淡出高亮层
this.setData({ overlayVisible: false })
const timer = setTimeout(() => {
this.setData({ highlightShow: false, highlightZoom: false, focusTransform: '', highlightWords: [] })
clearTimeout(timer)
}, 320)
// this.setData({ overlayVisible: false })
// const timer = setTimeout(() => {
// this.setData({ highlightShow: false, highlightZoom: false, focusTransform: '', highlightWords: [] })
// clearTimeout(timer)
// }, 320)
},
// 点击图片预览
@@ -790,17 +792,20 @@ Page<IPageData, IPageInstance>({
// 如果还没有音频上下文,则创建并绑定事件
if (!this.audioContext) {
this.audioContext = wx.createInnerAudioContext()
this.audioContext.onCanplay(() => {
setTimeout(() => {
const duration = this.audioContext!.duration
if (duration && duration > 0) {
this.setData({
audioDuration: duration,
currentTime: this.audioContext!.currentTime
})
}
}, 100)
})
try { (this.audioContext as any).obeyMuteSwitch = false } catch (e) {}
try { (this.audioContext as any).autoplay = false } catch (e) {}
try { (this.audioContext as any).obeyMuteSwitch = false } catch (e) {}
// this.audioContext.onCanplay(() => {
// setTimeout(() => {
// const duration = this.audioContext!.duration
// if (duration && duration > 0) {
// this.setData({
// audioDuration: duration,
// currentTime: this.audioContext!.currentTime
// })
// }
// }, 100)
// })
this.audioContext.onPlay(() => {
const duration = this.audioContext!.duration
// 停止可能存在的动画计时器
@@ -1085,13 +1090,13 @@ Page<IPageData, IPageInstance>({
this.getStandardVoice(currentSentence.id)
}
try {
wx.nextTick(() => {
this.computeHighlightLayout()
})
} catch (e) {
setTimeout(() => this.computeHighlightLayout(), 0)
}
// try {
// wx.nextTick(() => {
// this.computeHighlightLayout()
// })
// } catch (e) {
// setTimeout(() => this.computeHighlightLayout(), 0)
// }
},
onLoad(options: Record<string, string>) {
@@ -1117,7 +1122,7 @@ Page<IPageData, IPageInstance>({
})
.finally(() => {
this.setData({ loadingMaskVisible: false })
try { wx.nextTick(() => { this.computeHighlightLayout() }) } catch (e) { setTimeout(() => this.computeHighlightLayout(), 0) }
// try { wx.nextTick(() => { this.computeHighlightLayout() }) } catch (e) { setTimeout(() => this.computeHighlightLayout(), 0) }
})
}
// 更新例句和评分信息
@@ -1167,13 +1172,13 @@ Page<IPageData, IPageInstance>({
if (currentSentence.id) {
this.getStandardVoice(currentSentence.id)
}
try {
wx.nextTick(() => {
this.computeHighlightLayout()
})
} catch (e) {
setTimeout(() => this.computeHighlightLayout(), 0)
}
// try {
// wx.nextTick(() => {
// this.computeHighlightLayout()
// })
// } catch (e) {
// setTimeout(() => this.computeHighlightLayout(), 0)
// }
if (!res.image_file_id) {
this.setData({ loadingMaskVisible: false })
}
@@ -1188,7 +1193,7 @@ Page<IPageData, IPageInstance>({
icon: 'none'
})
this.setData({ loadingMaskVisible: false })
try { wx.nextTick(() => { this.computeHighlightLayout() }) } catch (e) { setTimeout(() => this.computeHighlightLayout(), 0) }
// try { wx.nextTick(() => { this.computeHighlightLayout() }) } catch (e) { setTimeout(() => this.computeHighlightLayout(), 0) }
})
.finally(() => {
wx.hideLoading()
@@ -1208,8 +1213,9 @@ Page<IPageData, IPageInstance>({
content: '录音完成,是否确认提交?',
success: (result) => {
if (result.confirm) {
wx.showLoading({ title: '正在解析...' })
// wx.showLoading({ title: '正在解析...' })
console.log('录音文件路径:', res.tempFilePath)
this.setData({ analizing: true })
apiManager.uploadFile(res.tempFilePath).then((fileId) => {
apiManager.getAssessmentResult(fileId, this.data.currentSentence.id).then((result) => {
const assessmentResult = result.assessment_result.assessment.result
@@ -1224,6 +1230,7 @@ Page<IPageData, IPageInstance>({
sentences[currentIndex].details = {
assessment: { result: assessmentResult }
}
sentences[currentIndex].file_id = fileId
const wordScores = assessmentResult.Words?.map((word: any) => ({
word: word.Word,
@@ -1239,31 +1246,72 @@ Page<IPageData, IPageInstance>({
this.setData({
sentences,
isScoreModalOpen: true,
currentSentence: sentences[currentIndex],
hasScoreInfo: !allNegative && !!assessmentResult,
totalScore: suggestedScore >= 0 ? Number(suggestedScore.toFixed(2)) : 0,
accuracyScore: pronAccuracy >= 0 ? Number(pronAccuracy.toFixed(2)) : 0,
completenessScore: pronCompletion >= 0 ? Number(pronCompletion.toFixed(2)) : 0,
fluencyScore: pronFluency >= 0 ? Number(pronFluency.toFixed(2)) : 0,
wordScores
wordScores,
overlayVisible: false,
highlightShow: false,
highlightZoom: false,
focusTransform: '',
highlightWords: [],
analizing: false
})
this.onScoreTap()
// this.updateCircleProgress()
wx.hideLoading()
// wx.hideLoading()
}).catch(err => {
console.error('获取评估结果失败:', err)
this.setData({
overlayVisible: false,
highlightShow: false,
highlightZoom: false,
focusTransform: '',
highlightWords: [],
analizing: false
})
wx.showToast({ title: '评估失败', icon: 'none' })
wx.hideLoading()
})
}).catch(err => {
console.error('上传录音失败:', err)
this.setData({
overlayVisible: false,
highlightShow: false,
highlightZoom: false,
focusTransform: '',
highlightWords: [],
analizing: false
})
wx.showToast({ title: '上传失败', icon: 'none' })
wx.hideLoading()
})
}
},
fail: () => {
this.setData({
overlayVisible: false,
highlightShow: false,
highlightZoom: false,
focusTransform: '',
highlightWords: [],
analizing: false
})
}
})
} else {
this.setData({
overlayVisible: false,
highlightShow: false,
highlightZoom: false,
focusTransform: '',
highlightWords: [],
analizing: false
})
wx.showToast({
title: '说话时间太短',
icon: 'none'
@@ -1563,10 +1611,10 @@ Page<IPageData, IPageInstance>({
})
}
try { if ((this as any)._layoutDebounceTimer) clearTimeout((this as any)._layoutDebounceTimer) } catch (e) {}
;(this as any)._layoutDebounceTimer = setTimeout(() => {
this.computeHighlightLayout()
}, 100)
// try { if ((this as any)._layoutDebounceTimer) clearTimeout((this as any)._layoutDebounceTimer) } catch (e) {}
// ;(this as any)._layoutDebounceTimer = setTimeout(() => {
// this.computeHighlightLayout()
// }, 100)
},
// 处理句子数据,分割单词和音标

View File

@@ -29,11 +29,11 @@
</view>
</view>
</view>
<view class="highlight-area {{overlayVisible ? 'show' : ''}}">
<view class="highlight-area {{overlayVisible ? 'show' : ''}}" catchtouchstart="noop" catchtouchmove="noop" catchtouchend="noop">
<view wx:for="{{highlightWords}}" wx:key="index"
class="overlay-word {{highlightShow ? 'show' : ''}} {{highlightZoom ? 'zoom' : ''}}"
style="left: {{item.left}}px; top: {{item.top}}px; width: {{item.width}}px; height: {{item.height}}px; {{item.transform ? ('transform: ' + item.transform) : ''}}">
<text class="overlay-text">{{item.text}}</text>
<view class="overlay-text {{analizing ? 'loading-shimmer' : ''}}" style="animation-delay: {{index * 90}}ms;">{{item.text}}</view>
</view>
</view>
<view wx:if="{{isRecording}}" class="recording-mask" catchtouchstart="noop" catchtouchmove="noop" catchtouchend="noop"></view>

View File

@@ -1503,3 +1503,32 @@
from { rotate: 0deg; }
to { rotate: 360deg; }
}
.loading-shimmer {
/* transition: all 0.3s ease; */
/* animation: loading-shimmer 2.6s ease infinite; */
}
@keyframes loading-shimmer {
0% {
transform: translate3D(0, 0, 0) scale(1);
color: #868F97;
text-shadow: 0 0 0 rgba(134, 143, 151, 0);
}
13% {
transform: translate3D(1px, -1px, 0) scale(1.2);
color: white;
}
16% {
text-shadow: 0 0 2px #d8dbde;
}
26% {
transform: translate3D(0, 0, 0) scale(1);
color: #a1a8af;
opacity: 1;
}
100% {
transform: scale(1);
opacity: 0.8;
}
}

View File

@@ -113,7 +113,8 @@ Page({
onShow() {
this.setData({ isProcessing: false })
if (this.data.shouldResetOnReturn) {
this.resetPageState()
// this.resetPageState()
this.loadTodaySummary()
this.setData({ shouldResetOnReturn: false })
}
},
@@ -816,6 +817,7 @@ Page({
const result = await apiManager.uploadImage(imagePath)
if (result.image_id) {
this.setData({ shouldResetOnReturn: true })
this.resetPageState()
wx.navigateTo({
url: `/pages/assessment/assessment?imageId=${result.image_id}`
})

View File

@@ -35,7 +35,7 @@
<!-- <view class="date">{{ current_date }}</view> -->
<!-- <view class="hello">{{DayTypeMap[day_type]}}</view> -->
<!-- <view class="begin-text">用一个新单词, 开启美好的一天</view> -->
<view class="camera-wrawpper {{todaySummary.length == 0 && groupedHistory.length == 0 && !takePhoto ? 'default' : ''}} {{takePhoto ? 'action' : ''}}">
<view class="camera-wrawpper {{!isLoading && todaySummary.length == 0 && groupedHistory.length == 0 && !takePhoto ? 'default' : ''}} {{takePhoto ? 'action' : ''}}">
<view class="camera" bindtap="handleImageSelect">
<view class="strip"></view>
<view class="lens">