Browse Source

feat: integrate STT into diet/exercise check-in pages

Xiaogang Liao 4 tuần trước cách đây
mục cha
commit
d47fa4e526

+ 15 - 2
cfc-frontend/pages/growth/diet-checkin.vue

@@ -99,6 +99,7 @@
 <script>
 import config from '../../config'
 import { parseDate } from '../../utils/format.js'
+import { sttTranscribe } from '../../utils/api.js'
 
 export default {
   data() {
@@ -121,7 +122,9 @@ export default {
         foodItems: '',
         remark: '',
         photos: [],
-        voicePath: ''
+        voicePath: '',
+        voiceText: '',
+        voiceDuration: 0
       }
     }
   },
@@ -150,6 +153,15 @@ export default {
       if (this.recordTimer) { clearInterval(this.recordTimer); this.recordTimer = null }
       this.form.voicePath = res.tempFilePath
       this.form.voiceDuration = res.duration
+      var self = this
+      uni.showLoading({ title: '语音识别中...', mask: true })
+      sttTranscribe(res.tempFilePath).then(function(text) {
+        self.form.voiceText = text
+        uni.hideLoading()
+      }).catch(function(err) {
+        uni.hideLoading()
+        console.warn('STT 转写失败:', err)
+      })
     })
     this.recorderManager.onError((err) => {
       this.isRecording = false
@@ -278,7 +290,8 @@ export default {
             foodItems: self.form.foodItems || '',
             remark: self.form.remark || '',
             photoUrls: photoUrls.join(','),
-            voiceUrl: voiceUrl
+            voiceUrl: voiceUrl,
+            voiceText: self.form.voiceText || ''
           },
           header: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token },
           success: function(res) {

+ 15 - 3
cfc-frontend/pages/growth/exercise-checkin.vue

@@ -111,6 +111,7 @@
 <script>
 import config from '../../config'
 import { parseDate } from '../../utils/format.js'
+import { sttTranscribe } from '../../utils/api.js'
 
 export default {
   data() {
@@ -143,7 +144,9 @@ export default {
         caloriesBurned: '',
         remark: '',
         photos: [],
-        voicePath: ''
+        voicePath: '',
+        voiceText: '',
+        voiceDuration: 0
       }
     }
   },
@@ -169,6 +172,15 @@ export default {
       if (this.recordTimer) { clearInterval(this.recordTimer); this.recordTimer = null }
       this.form.voicePath = res.tempFilePath
       this.form.voiceDuration = res.duration
+      var self = this
+      uni.showLoading({ title: '语音识别中...', mask: true })
+      sttTranscribe(res.tempFilePath).then(function(text) {
+        self.form.voiceText = text
+        uni.hideLoading()
+      }).catch(function(err) {
+        uni.hideLoading()
+        console.warn('STT 转写失败:', err)
+      })
     })
     this.recorderManager.onError(() => {
       this.isRecording = false
@@ -292,11 +304,11 @@ export default {
             caloriesBurned: self.form.caloriesBurned ? parseInt(self.form.caloriesBurned) : null,
             remark: self.form.remark || '',
             photoUrls: photoUrls.join(','),
-            voiceUrl: voiceUrl
+            voiceUrl: voiceUrl,
+            voiceText: self.form.voiceText || ''
           },
           header: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token },
           success: function(res) {
-            self.submitting = false
             if (res.data && res.data.code === 200) {
               uni.showToast({ title: '打卡成功', icon: 'success' })
               self.form.exerciseType = ''