diff --git a/src/api/common.js b/src/api/common.js index 7b3a4a92..845c484b 100644 --- a/src/api/common.js +++ b/src/api/common.js @@ -72,6 +72,7 @@ export const commonUploadVoiceFile = (file, url, data = {}, fileKey='voice') => }; if (token) header['summary'] = token + console.log(`${base_url}${url}`) return new Promise((resolve, reject) => { uni.uploadFile({ url: `${base_url}${url}`, diff --git a/src/api/login.js b/src/api/login.js index 893c4dba..52b2b984 100644 --- a/src/api/login.js +++ b/src/api/login.js @@ -1,5 +1,9 @@ import request from '@/api/request' import common from "@/common/common"; +import { + queryCurrentValidMascotInfo +} from "@/api/mascot.js" + import { setToken, setUserInfo, @@ -21,7 +25,36 @@ export const useAccountLoginApp = (data) => request({ if (rtnCode === '0000') { setToken(body) + // 获取科技鹿 + queryCurrentValidMascotInfo().then((res) => { + const userInfo = getUserInfo() + setUserInfo({ + ...userInfo, + 'mascotInfo': res + }) + console.log('科技', res); + if (res.imgAddr) { + setTimeout(() => { + const img = new Image(); // 创建Image对象 + // 图片加载成功(缓存完成) + img.onload = () => { + console.log(`图片缓存成功: ${url}`); + resolve(img); // 返回加载完成的Image对象 + }; + + // 图片加载失败 + img.onerror = () => { + console.error(`图片缓存失败: ${url}`); + reject(new Error(`Failed to load image: ${url}`)); + }; + + // 开始加载图片(设置src触发请求,浏览器会自动缓存) + img.src = url; + }) + } + }) const user_data = await queryCurrentUser() + return user_data } @@ -76,46 +109,48 @@ export const queryCurrentUser = (data) => request({ // 预加载头像 // #ifdef APP-PLUS const updateUserAvatar = (imagePath) => { - const userInfo = getUserInfo() - setUserInfo({ - ...userInfo, - 'imagePath': imagePath - }) + const userInfo = getUserInfo() + setUserInfo({ + ...userInfo, + 'imagePath': imagePath + }) } - + try { - const pathName = res.body.imageAddr - const url = base_url + pathName - // 生成唯一文件名,避免冲突 - const filename = pathName.split('/').pop() - const localFilePath = '_downloads/' + filename - - // 先检查是否存在 - uni.getFileInfo({ - filePath: localFilePath, - success: () => { - console.log('头像已存在,无需下载'); - updateUserAvatar(localFilePath) - }, - fail: () => { - console.log('开始下载头像:', url); - const dtask = plus.downloader.createDownload( - url, { - method: 'GET', - filename: '_downloads/' + filename - }, - (download, status) => { - if (status === 200) { - console.log('头像下载成功:', download.filename); - updateUserAvatar(download.filename) - } - } - ) - dtask.start(); - } - }) + const pathName = res.body.imageAddr + const url = base_url + pathName + // 生成唯一文件名,避免冲突 + const filename = pathName.split('/').pop() + const localFilePath = '_downloads/' + filename + + // 先检查是否存在 + uni.getFileInfo({ + filePath: localFilePath, + success: () => { + console.log('头像已存在,无需下载'); + updateUserAvatar(localFilePath) + }, + fail: () => { + console.log('开始下载头像:', url); + const dtask = plus.downloader.createDownload( + url, { + method: 'GET', + filename: '_downloads/' + filename + }, + (download, status) => { + if (status === 200) { + console.log('头像下载成功:', download.filename); + updateUserAvatar(download.filename) + } + } + ) + dtask.start(); + } + }) + + } catch (error) { - console.error('头像预加载过程发生错误:', error); + console.error('头像预加载过程发生错误:', error); } // #endif return res.body diff --git a/src/api/mascot.js b/src/api/mascot.js new file mode 100644 index 00000000..e6ffc827 --- /dev/null +++ b/src/api/mascot.js @@ -0,0 +1,61 @@ +import request from '@/api/request' + +const base_url = '/traapp' + + +/** + * 查询吉祥物列表 + * 出参: + mascotId 吉祥物ID String + mascotName 吉祥物名称 String + mascotNameEn 吉祥物英文名称 String + mascotDesc 吉祥物简介 String + mascotNo 吉祥物编号 String + imgAddr 吉祥物图片 String + imgThumbAddr 吉祥物缩略图 String + showOrder 显示顺序 int + */ +export const queryValidTraMascotInfo = (data) => { + return request({ + url: base_url + '/traMascotInfo/queryValidTraMascotInfo', + method: 'post', + toastErrors: true, + data + }); +}; + +/** + * 设置吉祥物 + * 入参: + mascotId 必输项:true 类型:String + */ +export const setTraMascotInfo = (data) => { + return request({ + url: base_url + '/traMascotInfo/setTraMascotInfo', + method: 'post', + toastErrors: true, + data + }); +}; + +// 查询当前已经选择的吉祥物 +/** + * 查询当前已经选择的吉祥物 + * 出参: + mascotId 吉祥物ID String + mascotName 吉祥物名称 String + mascotNameEn 吉祥物英文名称 String + mascotDesc 吉祥物简介 String + mascotNo 吉祥物编号 String + imgAddr 吉祥物图片 String + imgThumbAddr 吉祥物缩略图 String + showOrder 显示顺序 int + */ +export const queryCurrentValidMascotInfo = (data) => { + return request({ + url: base_url + '/traMascotInfo/queryCurrentValidMascotInfo', + method: 'post', + toastErrors: true, + data + }); +}; \ No newline at end of file diff --git a/src/api/request.js b/src/api/request.js index 51116660..b0c4ae38 100644 --- a/src/api/request.js +++ b/src/api/request.js @@ -6,7 +6,9 @@ import common from '@/common/common.js' const ENV = import.meta.env export const get_base_url = url => { + if (ENV.MODE === 'development') { // 开发环境 + return ENV.VITE_APP_BASE_API_Url // H5必须用非https,手机端必须用https // #ifdef H5 const baseUrl = ENV.VITE_APP_BASE_API_Url diff --git a/src/enum.js b/src/enum.js index 33eb71b4..cb791e77 100644 --- a/src/enum.js +++ b/src/enum.js @@ -8,9 +8,5 @@ export const GENDER = [{ { value: "f", label: "女性", - }, - { - value: "o", - label: "其他", } ] // 性别 \ No newline at end of file diff --git a/src/pages/course/components/talkingItem.vue b/src/pages/course/components/talkingItem.vue index 76700155..15629ef3 100644 --- a/src/pages/course/components/talkingItem.vue +++ b/src/pages/course/components/talkingItem.vue @@ -152,7 +152,7 @@ 撤回 @@ -254,7 +254,7 @@ const audioCacheObj = computed(() => storageStore.audioObj) const itemVoice = ref('') const showWithdraw = computed(()=>{ - let _isMe = unref(lastQuestionInfo).qnsLogId === unref(dataInfo).qnsLogId + let _isMe = unref(lastQuestionInfo).qstLogId === unref(dataInfo).qstLogId let _isQuestion = unref(lastQuestionInfo).isQuestion return _isMe && _isQuestion }) @@ -367,13 +367,17 @@ const audioCacheObj = computed(() => storageStore.audioObj) },100) }else{ voiceLoading.value = true + let _type = props.type == 2 ? 'ans' : props.type == 3 ? 'pgrh' : props.type == 4 ? 'qns' : '' + let _readId = props.type == 2 ? unref(dataInfo)?.intrctId : props.type == 3 ? unref(dataInfo)?.pgrphId : props.type == 4 ? unref(dataInfo)?.qnsId : '' + console.log(unref(dataInfo)) let _params = { crsId: unref(dataInfo)?.crsId || '', pgrphId: unref(dataInfo)?.pgrphId || '', qnsId: unref(dataInfo)?.qnsId || '', - readType: readType, + readType: _type,// 2 文本回答 3, 段落信息 4 问题信息 teachNo: unref(teacherInfo)?.teacherNo, // 必填 - content: _content + readId: _readId + // content: _content } @@ -388,19 +392,6 @@ const audioCacheObj = computed(() => storageStore.audioObj) talkVoiceObj.value.src = url talkVoiceObj.value.play() }else{ - // getAudioByText(_params).then(res=>{ - // // uni.env.USER_DATA_PATH || - // let filePath = `${'/'}/${dataInfo.value.id}.mp3` - // saveFile(res, filePath, () => { - // voiceLoading.value = false - // itemVoice.value = filePath - // talkVoiceObj.value.src = filePath - // talkVoiceObj.value.play() - // storageStore.setStorage('audio', _url + _params.teachNo, itemVoice.value) - // }) - // }).catch(err=>{ - // console.log(err) - // }) downloadVoiceFile(_url).then(res=>{ if(res?.data){ common.msg(res.data.message) diff --git a/src/pages/course/study.vue b/src/pages/course/study.vue index 6c78dcf6..e28d2642 100644 --- a/src/pages/course/study.vue +++ b/src/pages/course/study.vue @@ -446,7 +446,7 @@ const getQuestionInfoUnStudy = (pgrphId) => { id: _id, isQuestion: true } - talkingList.value.push(lastTalkingInfo.value) + talkingList.value.push(JSON.parse(JSON.stringify(lastTalkingInfo.value))) qstLogId.value = _body.chatBody?.qstLogId scrollToBottomNow() }else{ @@ -786,6 +786,7 @@ const submitAnswerNow = (val, cb) => { talkingVoice: '', type: 2, userInfo: {...choiceTeacherInfo.value}, + qstLogId: qstLogId.value, id: _id }) scrollToBottomNow() diff --git a/src/pages/courseDetail/components/introduce.vue b/src/pages/courseDetail/components/introduce.vue index 64df2485..ecf11866 100644 --- a/src/pages/courseDetail/components/introduce.vue +++ b/src/pages/courseDetail/components/introduce.vue @@ -12,7 +12,7 @@ 更新日期 - {{ common.formatDate2(modelValue.mtTime, 'yyyy-MM-dd HH:mm') }} + {{ (modelValue.mtTime || '').substr(0,16) }} @@ -104,6 +104,7 @@ font-size: 22rpx; margin-right: 14rpx; background-color: #f1f3f8; + margin-top: 6rpx; } } .bottom-right { diff --git a/src/pages/courseDetail/index.vue b/src/pages/courseDetail/index.vue index 34b7c40c..711ea9b2 100644 --- a/src/pages/courseDetail/index.vue +++ b/src/pages/courseDetail/index.vue @@ -130,11 +130,11 @@ onMounted(() => { uni.$on('refresh_comment_data', () => { commentRef.value?.getData(); + tabAct.value = 2 }) }) onLoad((params) => { crsNum.value = params.crsNum; - }); onShow(()=>{ getData(); diff --git a/src/pages/index/components/question.vue b/src/pages/index/components/question.vue index 900169d6..0d0b4d79 100644 --- a/src/pages/index/components/question.vue +++ b/src/pages/index/components/question.vue @@ -15,13 +15,13 @@ { if(!talkVoiceObj.value) return talkVoiceObj.value.pause() + isPlaying.value = false emit('changePlay', '') } const playVoice = () =>{ emit('changePlay', unref(dataInfo)?.id) - if(talkVoiceObj.value && talkVoiceObj.value.src && talkVoiceObj.value.src === itemVoice.value) { + if(talkVoiceObj.value && talkVoiceObj.value.src) { talkVoiceObj.value.play() return }else{ - initVoice() talkVoiceObj.value.src = '' - if(itemVoice.value){ + if(unref(dataInfo).talkingVoice){ setTimeout(()=>{ - talkVoiceObj.value.src = itemVoice.value + talkVoiceObj.value.src = unref(dataInfo).talkingVoice talkVoiceObj.value.play() + isPlaying.value = true },100) } } } const initVoice = () => { + talkVoiceObj.value = uni.createInnerAudioContext() + talkVoiceObj.value.onEnded(()=>{ + emit('changePlay', '') + talkVoiceObj.value.src = '' + }) + talkVoiceObj.value.onError(()=>{ + talkVoiceObj.value.src = '' + }) if(unref(dataInfo).intrctWay === '02'){ - talkVoiceObj.value = uni.createInnerAudioContext() - talkVoiceObj.value.onEnded(()=>{ - emit('changePlay', '') - talkVoiceObj.value.src = '' - }) - talkVoiceObj.value.onError(()=>{ - talkVoiceObj.value.src = '' - }) itemVoice.value = unref(dataInfo).talkingVoice talkVoiceObj.value.src = itemVoice.value setTimeout(()=>{ diff --git a/src/pages/index/components/talking-item.vue b/src/pages/index/components/talking-item.vue index 310c256b..9b13471c 100644 --- a/src/pages/index/components/talking-item.vue +++ b/src/pages/index/components/talking-item.vue @@ -4,6 +4,7 @@ v-if="talkingType === 'question'" @changePlay="changePlay" :dataInfo="talkingInfo" + :activeVoiceId="activeVoiceId" > ({}), type: Object + }, + activeVoiceId:{ + default:'', + type: String } }) + watch(() => props.activeVoiceId, () => {},{deep: true,immediate: true}) watch(() => props.talkingInfo, () => {},{deep: true,immediate: true}) const { talkingType } = toRefs(props) const handleEvents = (type) => { diff --git a/src/pages/index/dialog.vue b/src/pages/index/dialog.vue index bbd12434..89bc4911 100644 --- a/src/pages/index/dialog.vue +++ b/src/pages/index/dialog.vue @@ -13,9 +13,11 @@ AI问答 - - - Hi,我是{{'李想'}} + + + + + Hi,我是{{ userInfo.mascotInfo?.mascotName || ''}} 工作学习,我都能帮你! 试试他的能力 @@ -50,6 +52,7 @@ v-for="item in talkingList" :talkingType="item.type" :talkingInfo="item" + :activeVoiceId="activeVoiceTalkingItemId" @handleEvents="talkItemEvents" > @@ -101,7 +104,7 @@ \ No newline at end of file diff --git a/src/pages/setting/index.vue b/src/pages/setting/index.vue index bc3c5b83..88a92335 100644 --- a/src/pages/setting/index.vue +++ b/src/pages/setting/index.vue @@ -8,7 +8,6 @@ 设置 - - + { + + common.navigateTo('/pages/mascot/mascot_select_list') + + // common.loading() + // queryValidTraMascotInfo().then(({body}) => { + // console.log(body); + // common.setPageCache('mascotList', body) + // body.map(({imgAddr}) => { + // const url = imgAddr + // if (imgAddr){ + // const img = new Image(); + // img.onload = () => { + // console.log(`图片缓存成功: ${url}`); + // // resolve(img); + // }; + + // img.onerror = () => { + // console.error(`图片缓存失败: ${url}`); + // // reject(new Error(`Failed to load image: ${url}`)); + // }; + + // img.src = base_url + url; + // } + // }) + // common.hideLoading() + // common.navigateTo('/pages/mascot/mascot_select_list') + + // }) + } + const showGenderText = computed(() => { const item = sexOptions.find((item) => item.value == userInfo.value.gender) if (item) { diff --git a/src/static/images/dialog/pet-bg-base.png b/src/static/images/dialog/pet-bg-base.png new file mode 100644 index 00000000..3512f925 Binary files /dev/null and b/src/static/images/dialog/pet-bg-base.png differ diff --git a/src/static/images/dialog/pet-bg.png b/src/static/images/dialog/pet-bg.png new file mode 100644 index 00000000..40725dfd Binary files /dev/null and b/src/static/images/dialog/pet-bg.png differ diff --git a/src/static/images/mascot/bg_1.png b/src/static/images/mascot/bg_1.png index b76aa9bf..cd84f107 100644 Binary files a/src/static/images/mascot/bg_1.png and b/src/static/images/mascot/bg_1.png differ diff --git a/src/static/images/mascot/btn_1.png b/src/static/images/mascot/btn_1.png index e71f5d7a..f69f6866 100644 Binary files a/src/static/images/mascot/btn_1.png and b/src/static/images/mascot/btn_1.png differ diff --git a/src/static/images/mascot/btn_2.png b/src/static/images/mascot/btn_2.png index 0b3bb5ed..4ff2f464 100644 Binary files a/src/static/images/mascot/btn_2.png and b/src/static/images/mascot/btn_2.png differ