修改消息列表
This commit is contained in:
+7
-1
@@ -16,11 +16,17 @@ ENV = 'development'
|
|||||||
|
|
||||||
# VITE_APP_BASE_API_Url = 'http://25.18.122.65:7001'
|
# VITE_APP_BASE_API_Url = 'http://25.18.122.65:7001'
|
||||||
# VITE_APP_BASE_API_Url = 'http://25.16.122.91:9786'
|
# VITE_APP_BASE_API_Url = 'http://25.16.122.91:9786'
|
||||||
VITE_APP_BASE_API_Url = 'http://25.18.122.66:9786'
|
#VITE_APP_BASE_API_Url = 'http://25.18.122.66:9786'
|
||||||
|
|
||||||
# h5专用地址x2
|
# h5专用地址x2
|
||||||
|
|
||||||
#sit
|
#sit
|
||||||
# VITE_APP_BASE_H5_API_Url = 'http://25.18.122.91:9786'
|
# VITE_APP_BASE_H5_API_Url = 'http://25.18.122.91:9786'
|
||||||
|
|
||||||
|
|
||||||
|
# VITE_APP_BASE_H5_API_Url = 'http://25.18.122.65:7001'
|
||||||
|
#VITE_APP_BASE_H5_API_Url = 'http://25.18.122.91:9786'
|
||||||
|
|
||||||
# VITE_APP_BASE_H5_API_Url = 'http://25.18.122.78:9786'
|
# VITE_APP_BASE_H5_API_Url = 'http://25.18.122.78:9786'
|
||||||
|
|
||||||
# VITE_APP_BASE_H5_API_Url_TRAASK = 'http://25.64.16.144:9605'
|
# VITE_APP_BASE_H5_API_Url_TRAASK = 'http://25.64.16.144:9605'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<image :src="imgUrlShow" :mode="mode" @click="showDetail" style="width: 100%; height: 100%"></image>
|
<image :src="imgUrlShow" :mode="mode" @click="showDetail" style="width: 100%; height: 100%"></image>
|
||||||
<uni-popup ref="PopupRef" class="popup" mask-background-color="rgba(0,0,0,.2)">
|
<uni-popup ref="PopupRef" class="popup" mask-background-color="rgba(0,0,0,.2)" @change="changeShow">
|
||||||
<view class="overlay-box" @click="closePopup">
|
<view class="overlay-box" @click="closePopup">
|
||||||
<image class="detail-img" :src="imgUrlShow" :mode="mode"></image>
|
<image class="detail-img" :src="imgUrlShow" :mode="mode"></image>
|
||||||
</view>
|
</view>
|
||||||
@@ -88,18 +88,28 @@
|
|||||||
},
|
},
|
||||||
immediate: true,
|
immediate: true,
|
||||||
deep: true
|
deep: true
|
||||||
|
},
|
||||||
|
showModel(val){
|
||||||
|
if(!val){
|
||||||
|
this.storageStore.setTouchBtnZIndex(12);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
changeShow(data){
|
||||||
|
if(!data.show){
|
||||||
|
this.storageStore.setTouchBtnZIndex(12);
|
||||||
|
}else{
|
||||||
|
this.storageStore.setTouchBtnZIndex(-1);
|
||||||
|
}
|
||||||
|
},
|
||||||
closePopup() {
|
closePopup() {
|
||||||
this.showModel = false;
|
this.showModel = false;
|
||||||
this.storageStore.setTouchBtnZIndex(9);
|
|
||||||
this.$refs.PopupRef.close();
|
this.$refs.PopupRef.close();
|
||||||
},
|
},
|
||||||
showDetail() {
|
showDetail() {
|
||||||
if (!!this.previewDetail) {
|
if (!!this.previewDetail) {
|
||||||
this.showModel = true;
|
this.showModel = true;
|
||||||
this.storageStore.setTouchBtnZIndex(-1);
|
|
||||||
this.$refs.PopupRef.open();
|
this.$refs.PopupRef.open();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
></image>
|
></image>
|
||||||
</view>
|
</view>
|
||||||
<!-- <uv-overlay :show="showModel" opacity=".6" @click.stop="showModel = false"> -->
|
<!-- <uv-overlay :show="showModel" opacity=".6" @click.stop="showModel = false"> -->
|
||||||
<uni-popup ref="PopupRef" class="popup" mask-background-color="rgba(0,0,0,.2)">
|
<uni-popup ref="PopupRef" class="popup" mask-background-color="rgba(0,0,0,.2)" @change="changeShow">
|
||||||
<view class="overlay-box" @click="playEnded">
|
<view class="overlay-box" @click="playEnded">
|
||||||
<video class="video-cont-center"
|
<video class="video-cont-center"
|
||||||
:id="`video`+ fileId"
|
:id="`video`+ fileId"
|
||||||
@@ -91,11 +91,17 @@
|
|||||||
},
|
},
|
||||||
immediate: true,
|
immediate: true,
|
||||||
deep: true,
|
deep: true,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
changeShow(data){
|
||||||
|
if(!data.show){
|
||||||
|
this.storageStore.setTouchBtnZIndex(12);
|
||||||
|
}else{
|
||||||
|
this.storageStore.setTouchBtnZIndex(-1);
|
||||||
|
}
|
||||||
|
},
|
||||||
showModelNow(){
|
showModelNow(){
|
||||||
this.storageStore.setTouchBtnZIndex(-1)
|
|
||||||
this.$refs.PopupRef.open()
|
this.$refs.PopupRef.open()
|
||||||
this.showModel = true
|
this.showModel = true
|
||||||
},
|
},
|
||||||
@@ -103,7 +109,6 @@
|
|||||||
console.log('err:',info)
|
console.log('err:',info)
|
||||||
},
|
},
|
||||||
playEnded(){
|
playEnded(){
|
||||||
this.storageStore.setTouchBtnZIndex(9)
|
|
||||||
this.$refs.PopupRef.close()
|
this.$refs.PopupRef.close()
|
||||||
this.showModel = false
|
this.showModel = false
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -355,6 +355,16 @@
|
|||||||
"titleNView": false
|
"titleNView": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/example/dialog",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "AI问答演示",
|
||||||
|
"app-plus": {
|
||||||
|
"titleNView": false,
|
||||||
|
"animationType": "fade-in"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tabBar": {
|
"tabBar": {
|
||||||
|
|||||||
@@ -121,7 +121,7 @@
|
|||||||
const showTalkingModel = ref(false);
|
const showTalkingModel = ref(false);
|
||||||
const keyboardIsShow = ref(false);
|
const keyboardIsShow = ref(false);
|
||||||
const talkModelRef = ref();
|
const talkModelRef = ref();
|
||||||
storageStore.setTouchBtnZIndex(9);
|
storageStore.setTouchBtnZIndex(12);
|
||||||
const btnZindex = computed(() => storageStore.getTouchBtnZIndex);
|
const btnZindex = computed(() => storageStore.getTouchBtnZIndex);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|||||||
@@ -766,7 +766,7 @@ const closeStudy = () => {
|
|||||||
}
|
}
|
||||||
onHide(() => {
|
onHide(() => {
|
||||||
changePlayItemId('')
|
changePlayItemId('')
|
||||||
if (isPreview.value === 'S') {
|
if (!isPreview.value) {
|
||||||
closeStudy()
|
closeStudy()
|
||||||
}
|
}
|
||||||
// socketStore.closeSocket()
|
// socketStore.closeSocket()
|
||||||
@@ -785,7 +785,7 @@ onShow(() => {
|
|||||||
if (watchFlag.value === 1) return
|
if (watchFlag.value === 1) return
|
||||||
// getData('2');
|
// getData('2');
|
||||||
// initsocketTask()
|
// initsocketTask()
|
||||||
if (isPreview.value === 'S') {
|
if (!isPreview.value) {
|
||||||
studyStartApi({
|
studyStartApi({
|
||||||
crsId: crsId.value,
|
crsId: crsId.value,
|
||||||
teacherNo: choiceTeacher.value,
|
teacherNo: choiceTeacher.value,
|
||||||
@@ -806,7 +806,7 @@ onShow(() => {
|
|||||||
const watchFlag = ref(1)
|
const watchFlag = ref(1)
|
||||||
onUnload(() => {
|
onUnload(() => {
|
||||||
console.log('onUnload')
|
console.log('onUnload')
|
||||||
if (isPreview.value === 'S') {
|
if (!isPreview.value) {
|
||||||
closeStudy()
|
closeStudy()
|
||||||
}
|
}
|
||||||
// socketStore.closeSocket()
|
// socketStore.closeSocket()
|
||||||
|
|||||||
@@ -0,0 +1,408 @@
|
|||||||
|
<template>
|
||||||
|
<view class="answer-content" v-if="props.isLoading">
|
||||||
|
<view class="talking-cont">
|
||||||
|
<CommonLoading color="#06f" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="answer-content" v-else>
|
||||||
|
<view :class="['talking-gif', !voiceLoading&&(props.activeVoiceId === dataInfo.id) ? 'is-play' : '']">
|
||||||
|
</view>
|
||||||
|
<view class="talking-cont">
|
||||||
|
<MarkdownPreview :mdString="mdText" />
|
||||||
|
</view>
|
||||||
|
<view class="talking-link">
|
||||||
|
<view :class="['link-cont', activeNames.indexOf(1) >= 0 ? 'is-active' : '']" v-if="fileList.length > 0">
|
||||||
|
<view class="link-info" @click="changeActive(1)">
|
||||||
|
<view class="info-text"> 引用知识库{{ fileList.length }}篇相关资料 </view>
|
||||||
|
</view>
|
||||||
|
<view class="link-items">
|
||||||
|
<view class="link-item" v-for="(item, index) in fileList" @click.stop="previewFile(item)">{{ index + 1 }}. {{ item.docName }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view v-else-if="!props.isAnswering" class="link-cont-desc">本次回答参考资料来源于网络</view>
|
||||||
|
<view :class="['link-cont', activeNames.indexOf(2) >= 0 ? 'is-active' : '']" v-if="crsList.length > 0">
|
||||||
|
<view class="link-info" @click="changeActive(2)">
|
||||||
|
<view class="info-text"> 发现{{ crsList.length }}个关联课程 </view>
|
||||||
|
</view>
|
||||||
|
<view class="link-items">
|
||||||
|
<view class="link-item" v-for="(item, index) in crsList" @click.stop="previewCrs(item)">{{ index + 1 }}. {{ item.crsName }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="btns-cont">
|
||||||
|
<view class="replay-btn" >
|
||||||
|
<image class="icon" src="@/static/images/course/play.png" style="width: 100%; height: 100%"
|
||||||
|
v-show="!(!voiceLoading&&(props.activeVoiceId === dataInfo.id))"
|
||||||
|
@click.stop="playVoice()" ></image>
|
||||||
|
<image class="icon"src="@/static/images/course/pause.png"
|
||||||
|
style="width: 100%; height: 100%" @click.stop="pauseVoice"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, computed, ref, watch, toRefs } from 'vue'
|
||||||
|
import { onUnload } from '@dcloudio/uni-app';
|
||||||
|
import MarkdownPreview from '@/components/markdown-preview/markdown-preview.vue'
|
||||||
|
import common from '@/common/common'
|
||||||
|
import {
|
||||||
|
downloadVoiceFile,
|
||||||
|
} from '@/api/common.js';
|
||||||
|
|
||||||
|
const emit = defineEmits(['handleEvents'])
|
||||||
|
const props = defineProps({
|
||||||
|
dataInfo: {
|
||||||
|
default: () => ({}),
|
||||||
|
type: Object
|
||||||
|
},
|
||||||
|
isLoading: {
|
||||||
|
default: false,
|
||||||
|
type: Boolean
|
||||||
|
},
|
||||||
|
isAnswering: {
|
||||||
|
default: false,
|
||||||
|
type: Boolean
|
||||||
|
},
|
||||||
|
activeVoiceId:{
|
||||||
|
default:'',
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
isLast: {
|
||||||
|
default: false,
|
||||||
|
type: Boolean
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const { activeVoiceId, dataInfo } = toRefs(props)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.dataInfo,
|
||||||
|
() => {},
|
||||||
|
{
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
watch(
|
||||||
|
() => props.isLoading,
|
||||||
|
() => {},
|
||||||
|
{
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
const mdText = computed(() => {
|
||||||
|
let _text = (props.dataInfo?.talkingText|| '').replace(/\\n/g, `\n`);
|
||||||
|
return _text
|
||||||
|
})
|
||||||
|
const fileList = computed(() => props.dataInfo?.talkingFiles || [])
|
||||||
|
const crsList = computed(() => props.dataInfo?.talkingCrsList || [])
|
||||||
|
const activeNames = ref([1, 2])
|
||||||
|
const isPlaying = ref(false)
|
||||||
|
|
||||||
|
const talkVoiceObj = ref(null)
|
||||||
|
const voiceLoading = ref(false)
|
||||||
|
|
||||||
|
const voiceTime = ref('')
|
||||||
|
const itemVoice = ref('')
|
||||||
|
const initVoice = () => {
|
||||||
|
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(()=>{
|
||||||
|
// setVoiceTime(0)
|
||||||
|
// },100)
|
||||||
|
}
|
||||||
|
const setVoiceTime = (sum) => {
|
||||||
|
sum += 1
|
||||||
|
if(Math.ceil(talkVoiceObj.value.duration)>0){
|
||||||
|
voiceTime.value = (Math.ceil(talkVoiceObj.value.duration) || 1 ) + 's'
|
||||||
|
}else{
|
||||||
|
if(sum === 20) {
|
||||||
|
voiceTime.value = 0 + 's'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setTimeout(()=>{
|
||||||
|
setVoiceTime(sum)
|
||||||
|
},200)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const playVoice = (readType = 'pgth') => {
|
||||||
|
let _content = mdText.value;
|
||||||
|
if (!_content) {
|
||||||
|
common.msg('没有可以播放的文字信息!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isPlaying.value = true
|
||||||
|
voiceLoading.value = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
let _params = {}
|
||||||
|
let _url =
|
||||||
|
'/trastudy/traStdyInfo/readContent?' +
|
||||||
|
Object.keys(_params)
|
||||||
|
.map((t) => {
|
||||||
|
return encodeURIComponent(t) + '=' + encodeURIComponent(_params[t]);
|
||||||
|
})
|
||||||
|
.join('&');
|
||||||
|
|
||||||
|
downloadVoiceFile(_url)
|
||||||
|
.then((res) => {
|
||||||
|
if (res?.data) {
|
||||||
|
common.msg(res.data.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
voiceLoading.value = false;
|
||||||
|
itemVoice.value = res.tempFilePath;
|
||||||
|
talkVoiceObj.value.src = res.tempFilePath;
|
||||||
|
talkVoiceObj.value.play();
|
||||||
|
storageStore.setStorage('audio', _url + _params.teachNo, itemVoice.value);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
voiceLoading.value = false;
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
const pauseVoice = () => {
|
||||||
|
if(!talkVoiceObj.value) return
|
||||||
|
talkVoiceObj.value.pause()
|
||||||
|
isPlaying.value = false
|
||||||
|
emit('changePlay', '')
|
||||||
|
}
|
||||||
|
onMounted(()=>{
|
||||||
|
initVoice()
|
||||||
|
})
|
||||||
|
onUnload(()=>{
|
||||||
|
pauseVoice()
|
||||||
|
})
|
||||||
|
watch(() => props.dataInfo.talkingVoice,(val)=>{
|
||||||
|
if(val){
|
||||||
|
initVoice()
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
})
|
||||||
|
const changeActive = val => {
|
||||||
|
if (activeNames.value.indexOf(val) >= 0) {
|
||||||
|
activeNames.value = activeNames.value.filter(t => t !== val)
|
||||||
|
} else {
|
||||||
|
activeNames.value.push(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const reAnswer = () => {
|
||||||
|
emit('handleEvents', 'reAnswer')
|
||||||
|
}
|
||||||
|
const stopAnswer = () => {
|
||||||
|
emit('handleEvents', 'stop')
|
||||||
|
}
|
||||||
|
const zanAnswer = () => {
|
||||||
|
emit('handleEvents', 'great')
|
||||||
|
}
|
||||||
|
const feedbackAnswer = () => {
|
||||||
|
emit('handleEvents', 'feedback')
|
||||||
|
}
|
||||||
|
const previewFile = item => {
|
||||||
|
emit('handleEvents', 'preview', item)
|
||||||
|
}
|
||||||
|
const previewCrs = item => {
|
||||||
|
common.navigateTo('/pages/courseDetail/index?crsId=' + item.crsId)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.answer-content {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
padding: 20rpx;
|
||||||
|
border-radius: 15rpx;
|
||||||
|
padding-bottom: 10rpx;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
float: left;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 80rpx;
|
||||||
|
|
||||||
|
.talking-gif{
|
||||||
|
width: 200rpx;
|
||||||
|
height: 38rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
background: url(@/static/images/course/voice-gray.png) no-repeat;
|
||||||
|
background-size: contain;
|
||||||
|
padding-left: 168rpx;
|
||||||
|
&.is-play{
|
||||||
|
background: url(@/static/images/course/voice-gif.gif) no-repeat;
|
||||||
|
background-size: contain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.talking-cont {
|
||||||
|
padding-bottom: 20rpx;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.btns-cont {
|
||||||
|
overflow: hidden;
|
||||||
|
border-top: 3rpx solid #eee;
|
||||||
|
padding-bottom: 10rpx;
|
||||||
|
|
||||||
|
.replay-btn {
|
||||||
|
float: left;
|
||||||
|
width: 46rpx;
|
||||||
|
height: 46rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.play-btn {
|
||||||
|
float: left;
|
||||||
|
width: 46rpx;
|
||||||
|
height: 46rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.next-learn-btn {
|
||||||
|
float: left;
|
||||||
|
padding: 0 60rpx 0 20rpx;
|
||||||
|
height: 62rpx;
|
||||||
|
line-height: 62rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
background-color: #06f;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
margin-top: 16rpx;
|
||||||
|
margin-right: 16rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&.replay-study-btn {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.restart {
|
||||||
|
background-color: #eaf2ff;
|
||||||
|
color: #06f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-iamge {
|
||||||
|
width: 25rpx;
|
||||||
|
height: 25rpx;
|
||||||
|
position: absolute;
|
||||||
|
right: 20rpx;
|
||||||
|
top: 50%;
|
||||||
|
margin-top: -12rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.replay-learn-btn {
|
||||||
|
float: left;
|
||||||
|
padding: 0 60rpx 0 20rpx;
|
||||||
|
height: 62rpx;
|
||||||
|
line-height: 62rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #06f;
|
||||||
|
background-color: #eaf2ff;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
margin-top: 16rpx;
|
||||||
|
margin-right: 16rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.icon-iamge {
|
||||||
|
width: 25rpx;
|
||||||
|
height: 25rpx;
|
||||||
|
position: absolute;
|
||||||
|
right: 20rpx;
|
||||||
|
top: 50%;
|
||||||
|
margin-top: -12rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.next-btn {
|
||||||
|
float: right;
|
||||||
|
padding: 0 60rpx 0 20rpx;
|
||||||
|
height: 62rpx;
|
||||||
|
line-height: 62rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
background-color: #06f;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
margin-top: 16rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.icon-iamge {
|
||||||
|
width: 25rpx;
|
||||||
|
height: 25rpx;
|
||||||
|
position: absolute;
|
||||||
|
right: 20rpx;
|
||||||
|
top: 50%;
|
||||||
|
margin-top: -12rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.link-cont-desc {
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.link-cont {
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
.link-info {
|
||||||
|
height: 50rpx;
|
||||||
|
line-height: 50rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
|
||||||
|
.info-text {
|
||||||
|
float: left;
|
||||||
|
padding-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
float: left;
|
||||||
|
position: relative;
|
||||||
|
top: 12rpx;
|
||||||
|
width: 12rpx;
|
||||||
|
height: 12rpx;
|
||||||
|
border-right: 4rpx solid #333;
|
||||||
|
border-bottom: 4rpx solid #333;
|
||||||
|
transform: rotate(135deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
.link-info {
|
||||||
|
&::after {
|
||||||
|
top: 18rpx;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-items {
|
||||||
|
max-height: 600rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-items {
|
||||||
|
max-height: 0rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
|
||||||
|
.link-item {
|
||||||
|
line-height: 48rpx;
|
||||||
|
color: #06f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,266 @@
|
|||||||
|
<template>
|
||||||
|
<view class="talking-info" v-if="dataInfo.intrctWay === '02'">
|
||||||
|
<view :class="['talking-gif', !voiceLoading&&(props.activeVoiceId === dataInfo.id) ? 'is-play' : '']">
|
||||||
|
<CommonLoading color="#fff" v-show="voiceLoading"/>
|
||||||
|
</view>
|
||||||
|
<view class="right-time">{{voiceTime}}</view>
|
||||||
|
<view class="talking-cont">
|
||||||
|
<text :class="['talking-text translate-text loading']" v-show="!translateLoading">
|
||||||
|
{{ showContent }}
|
||||||
|
</text>
|
||||||
|
<view class="talking-text translate-text" v-if="translateLoading">
|
||||||
|
<CommonLoading color="#fff"/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="btns-cont">
|
||||||
|
<view class="play-btn">
|
||||||
|
<image class="icon"
|
||||||
|
v-show="!(!voiceLoading&&(props.activeVoiceId === dataInfo.id))"
|
||||||
|
@click="playVoice"
|
||||||
|
src="@/static/images/course/play-blue.png"
|
||||||
|
style="width: 100%;height: 100%;"
|
||||||
|
></image>
|
||||||
|
<image class="icon"
|
||||||
|
v-show="!voiceLoading&&(props.activeVoiceId === dataInfo.id)"
|
||||||
|
@click.stop="pauseVoice"
|
||||||
|
src="@/static/images/course/stop-blue.png"
|
||||||
|
style="width: 100%;height: 100%;"
|
||||||
|
></image>
|
||||||
|
<!-- <view class="icon text-btn" v-if="type === 1" @click.stop="translateVoice(dataInfo)">文</view> -->
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="talking-info talking-info-text" v-else-if="dataInfo.intrctWay === '01'">
|
||||||
|
<view class="talking-cont">
|
||||||
|
<text :class="['talking-text translate-text loading']">
|
||||||
|
{{ showContent }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="talking-info talking-info-loading" v-else>
|
||||||
|
<view :class="['talking-gif']">
|
||||||
|
<CommonLoading color="#fff"/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed, unref, ref, toRefs, watch, onMounted } from "vue"
|
||||||
|
import { onUnload } from '@dcloudio/uni-app';
|
||||||
|
const props = defineProps({
|
||||||
|
dataInfo: {
|
||||||
|
default: () => ({}),
|
||||||
|
type: Object
|
||||||
|
},
|
||||||
|
activeVoiceId:{
|
||||||
|
default:'',
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const { activeVoiceId, dataInfo } = toRefs(props)
|
||||||
|
const emit = defineEmits(['changePlay'])
|
||||||
|
watch(() => props.dataInfo, () => {},{deep: true,immediate: true})
|
||||||
|
// 声音播放初始化
|
||||||
|
const talkVoiceObj = ref(null)
|
||||||
|
|
||||||
|
const isPlaying = ref(false)
|
||||||
|
const voiceLoading = ref(false)
|
||||||
|
const translateLoading = ref(false)
|
||||||
|
|
||||||
|
const voiceTime = ref('')
|
||||||
|
const itemVoice = ref('')
|
||||||
|
const showContent = computed(()=>{
|
||||||
|
return dataInfo.value.talkingText || ''
|
||||||
|
})
|
||||||
|
onMounted(()=>{
|
||||||
|
initVoice()
|
||||||
|
})
|
||||||
|
onUnload(()=>{
|
||||||
|
pauseVoice()
|
||||||
|
})
|
||||||
|
watch(() => props.dataInfo.talkingVoice,(val)=>{
|
||||||
|
if(val){
|
||||||
|
initVoice()
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
})
|
||||||
|
const pauseVoice = () => {
|
||||||
|
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.play()
|
||||||
|
return
|
||||||
|
}else{
|
||||||
|
talkVoiceObj.value.src = ''
|
||||||
|
if(unref(dataInfo).talkingVoice){
|
||||||
|
setTimeout(()=>{
|
||||||
|
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'){
|
||||||
|
itemVoice.value = unref(dataInfo).talkingVoice
|
||||||
|
talkVoiceObj.value.src = itemVoice.value
|
||||||
|
setTimeout(()=>{
|
||||||
|
setVoiceTime(0)
|
||||||
|
},100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const setVoiceTime = (sum) => {
|
||||||
|
sum += 1
|
||||||
|
if(Math.ceil(talkVoiceObj.value.duration)>0){
|
||||||
|
voiceTime.value = (Math.ceil(talkVoiceObj.value.duration) || 1 ) + 's'
|
||||||
|
}else{
|
||||||
|
if(sum === 20) {
|
||||||
|
voiceTime.value = 0 + 's'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setTimeout(()=>{
|
||||||
|
setVoiceTime(sum)
|
||||||
|
},200)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.talking-info{
|
||||||
|
padding: 20rpx;
|
||||||
|
border-radius: 15rpx;
|
||||||
|
background-color: #06f;
|
||||||
|
padding-bottom: 30rpx;
|
||||||
|
position: relative;
|
||||||
|
color: #fff;
|
||||||
|
width: 100%;
|
||||||
|
float: right;
|
||||||
|
.talking-gif{
|
||||||
|
width: 200rpx;
|
||||||
|
height: 38rpx;
|
||||||
|
background: url(@/static/images/course/voice-gray.png) no-repeat;
|
||||||
|
background-size: contain;
|
||||||
|
padding-left: 168rpx;
|
||||||
|
&.is-play{
|
||||||
|
background: url(@/static/images/course/voice-white.gif) no-repeat;
|
||||||
|
background-size: contain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.right-time{
|
||||||
|
position: absolute;
|
||||||
|
right: 20rpx;
|
||||||
|
top: 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
height: 38rpx;
|
||||||
|
line-height: 38rpx;
|
||||||
|
}
|
||||||
|
&.talking-info-loading{
|
||||||
|
padding-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
&.talking-info-text{
|
||||||
|
padding-bottom: 20rpx;
|
||||||
|
width: auto;
|
||||||
|
float: right;
|
||||||
|
.talking-cont{
|
||||||
|
margin-top: 0rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.talking-cont{
|
||||||
|
margin-top: 16rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
.talking-text{
|
||||||
|
font-size: 28rpx;
|
||||||
|
line-height: 48rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
word-break: break-all;
|
||||||
|
white-space: pre-line;
|
||||||
|
overflow: hidden;
|
||||||
|
&.translate-text{
|
||||||
|
min-height: 48rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.btns-cont{
|
||||||
|
overflow: hidden;
|
||||||
|
border-top: 3rpx solid #eee;
|
||||||
|
.replay-btn{
|
||||||
|
float: left;
|
||||||
|
width: 46rpx;
|
||||||
|
height: 46rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-right: 16rpx;
|
||||||
|
margin-top: 25rpx;
|
||||||
|
}
|
||||||
|
.play-btn{
|
||||||
|
float: left;
|
||||||
|
width: 46rpx;
|
||||||
|
height: 46rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-right: 16rpx;
|
||||||
|
margin-top: 25rpx;
|
||||||
|
}
|
||||||
|
.text-btn{
|
||||||
|
float: left;
|
||||||
|
width: 46rpx;
|
||||||
|
height: 46rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
line-height: 46rpx;
|
||||||
|
text-align: center;
|
||||||
|
color: #fff;
|
||||||
|
margin-right: 16rpx;
|
||||||
|
margin-top: 25rpx;
|
||||||
|
background-color: #67A4ff;
|
||||||
|
font-size: 24rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
}
|
||||||
|
.text-right-btn{
|
||||||
|
float: right;
|
||||||
|
padding: 0 10rpx;
|
||||||
|
height: 46rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
line-height: 46rpx;
|
||||||
|
text-align: center;
|
||||||
|
margin-left: 16rpx;
|
||||||
|
margin-top: 25rpx;
|
||||||
|
}
|
||||||
|
.next-btn{
|
||||||
|
float: right;
|
||||||
|
padding: 0 60rpx 0 20rpx;
|
||||||
|
height: 62rpx;
|
||||||
|
line-height: 62rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
background-color: #06f;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
margin-top: 16rpx;
|
||||||
|
position: relative;
|
||||||
|
.icon-iamge{
|
||||||
|
width: 25rpx;
|
||||||
|
height: 25rpx;
|
||||||
|
position: absolute;
|
||||||
|
right: 20rpx;
|
||||||
|
top: 50%;
|
||||||
|
margin-top: -12rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
<template>
|
||||||
|
<view class="talking-item">
|
||||||
|
<questionVue v-if="talkingType === 'question'" @changePlay="changePlay" :dataInfo="talkingInfo" :isLast="isLast"
|
||||||
|
:activeVoiceId="activeVoiceId"></questionVue>
|
||||||
|
<answerVue v-else-if="talkingType === 'answer'" :dataInfo="props.talkingInfo" :isLast="isLast"
|
||||||
|
:isLoading="!!props.talkingInfo.isLoading" :isAnswering="props.isAnswering" @handleEvents="handleEvents">
|
||||||
|
</answerVue>
|
||||||
|
<view v-else></view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
toRefs,
|
||||||
|
watch
|
||||||
|
} from 'vue'
|
||||||
|
import questionVue from './question.vue';
|
||||||
|
import answerVue from './answer.vue';
|
||||||
|
|
||||||
|
const emit = defineEmits(['handleEvents'])
|
||||||
|
const props = defineProps({
|
||||||
|
talkingType: {
|
||||||
|
default: 'question',
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
talkingInfo: {
|
||||||
|
default: () => ({}),
|
||||||
|
type: Object
|
||||||
|
},
|
||||||
|
activeVoiceId: {
|
||||||
|
default: '',
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
isAnswering: {
|
||||||
|
default: false,
|
||||||
|
type: Boolean
|
||||||
|
},
|
||||||
|
isLast: {
|
||||||
|
default: false,
|
||||||
|
type: Boolean
|
||||||
|
},
|
||||||
|
})
|
||||||
|
watch(() => props.activeVoiceId, () => {}, {
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
})
|
||||||
|
watch(() => props.talkingInfo, () => {}, {
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
})
|
||||||
|
const {
|
||||||
|
talkingType
|
||||||
|
} = toRefs(props)
|
||||||
|
const handleEvents = (type, info = {}) => {
|
||||||
|
emit('handleEvents', {
|
||||||
|
type,
|
||||||
|
data: props.talkingInfo,
|
||||||
|
id: "",
|
||||||
|
info
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const changePlay = (id) => {
|
||||||
|
emit('handleEvents', {
|
||||||
|
type: 'changePlay',
|
||||||
|
data: props.talkingInfo,
|
||||||
|
id,
|
||||||
|
info: {}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.talking-item {
|
||||||
|
overflow: hidden;
|
||||||
|
margin-top: 0rpx;
|
||||||
|
|
||||||
|
&+.talking-item {
|
||||||
|
margin-top: 30rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -115,6 +115,7 @@
|
|||||||
:border="false"
|
:border="false"
|
||||||
@click="common.navigateTo('/pages/preview/index')"
|
@click="common.navigateTo('/pages/preview/index')"
|
||||||
></uv-cell>
|
></uv-cell>
|
||||||
|
<!-- <uv-cell title="问答演示" :isLink="true" @click="common.navigateTo('/pages/example/dialog')"></uv-cell> -->
|
||||||
</uv-cell-group>
|
</uv-cell-group>
|
||||||
</view>
|
</view>
|
||||||
<view class="cell_div">
|
<view class="cell_div">
|
||||||
|
|||||||
+11
-1
@@ -43,6 +43,16 @@
|
|||||||
"titleNView": false
|
"titleNView": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/example/dialog",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "AI问答演示",
|
||||||
|
"app-plus": {
|
||||||
|
"titleNView": false,
|
||||||
|
"animationType": "fade-in"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,7 @@ export const useStorageStore = defineStore('storageStore',{
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions:{
|
actions:{
|
||||||
setTouchBtnZIndex(index = 1){
|
setTouchBtnZIndex(index = 12){
|
||||||
this.touchBtnZIndex = index
|
this.touchBtnZIndex = index
|
||||||
},
|
},
|
||||||
setStorage(type, id, url) {
|
setStorage(type, id, url) {
|
||||||
|
|||||||
Reference in New Issue
Block a user