新增pdf预览

This commit is contained in:
杨航
2025-08-22 17:44:53 +08:00
parent 839f4c1075
commit c723d89bbc
398 changed files with 78873 additions and 101 deletions
+1
View File
@@ -28,3 +28,4 @@ VITE_APP_BASE_H5_API_Url = 'http://25.18.122.65:7001'
#VITE_APP_BASE_H5_API_Url_TRAAPP = 'http://25.64.16.130:9601'
VITE_APP_BASE_H5_API_Url_TRASTUDY = 'http://25.64.16.130:9602'
#VITE_APP_BASE_H5_API_Url_TRAASK = 'http://25.64.16.144:9605'
@@ -0,0 +1,108 @@
<template>
<view class="popup-view" v-if="modelValue">
<view class="close-preview" @click="emit('update:modelValue', false)" >X</view>
<view class="popup-view-preview" v-if="showView">
<web-view :src="showUrl" :fullscreen="true" class="web-view-class" :webview-styles="{
width: '100%',
height: '100%'
}"></web-view>
</view>
</view>
<view v-else></view>
</template>
<script setup>
import {
ref,
onMounted,
computed,
defineProps,
watch
} from 'vue'
import {
getToken
} from "@/common/common.js"
import {
downloadFile
} from "@/api/common.js"
import {
get_base_url
} from '@/api/request.js'
const emit = defineEmits(['update:modelValue'])
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
fileId: {
default: '',
type: String
},
fileName: {
default: '',
type: String
}
})
watch(()=>props.modelValue,(val)=>{
if(val){
openPdfFn()
}else{
showView.value = false
}
})
const base_url = get_base_url('/traask/traFilePreview/')
const showUrl = ref('')
const viewerUrl = ref('/static/pdf-view/web/viewer.html')
const showView = ref(false)
const openPdfFn = (data) => {
const token = getToken();
const header = {};
let _id = data?.fileId || props.fileId
let fileUrl = base_url + '/traask/traFilePreview/' + _id
if (token)
header['summary'] = token
uni.downloadFile({
//需要预览的文件地址
url: fileUrl,
header: header,
success: (res) => {
//下载成功,得到文件临时地址
console.log('下载成功', res.tempFilePath);
//条件编译,若为h5端则直接赋值文件地址
// #ifdef H5
let newUrl = res.tempFilePath
// #endif
//条件编译,若为App端,则需要将本地文件系统URL转换为平台绝对路径
// #ifdef APP-PLUS
let newUrl = plus.io.convertLocalFileSystemURL(res.tempFilePath)
// #endif
showUrl.value = viewerUrl.value + '?file=' + newUrl
showView.value = true
}
})
}
</script>
<style lang="scss">
.popup-view{
width: 100vw;
height: 100vh;
}
.popup-view-preview{
height: 100vh;
width: 100%;
z-index: 100;
position: relative;
}
.close-preview{
position: fixed;
right: 20rpx;
top: calc(var(--status-bar-height) + 20rpx);
color: #000;
z-index: 1000;
font-size: 30rpx;
}
</style>
+1
View File
@@ -10,6 +10,7 @@
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"renderer": "auto",
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : false,
+9
View File
@@ -270,6 +270,15 @@
"titleNView": false
}
}
},
{
"path": "pages/index/preview",
"style": {
"navigationBarTitleText": "",
"app-plus": {
"titleNView": false
}
}
}
],
"tabBar": {
+1 -1
View File
@@ -18,7 +18,7 @@
<image class="total-score-icon" src="@/static/images/course/score.png" alt=""></image>
</view>
<view v-for="(item,index) in dataList" :class="['score-item', 'score-item'+(index+1)]">
<view class="score-item-name">{{ item.gradeDimensName }}</view>
<view class="score-item-name">{{ item.gradeDimens || item.gradeDimensName }}</view>
<view class="score-item-score">{{ item.anlyGrade }}</view>
</view>
</view>
+36 -13
View File
@@ -8,9 +8,10 @@
6 发送loading状态
7 教师反馈文本不翻译
8 问题反馈信息
9 已学完当前知识点反馈信息
-->
<template>
<view :class="['ai-answer', props.class]" :id="props.id" v-if="[3,4,5,8].indexOf(type) >= 0">
<view :class="['ai-answer', props.class]" :id="props.id" v-if="[3,4,5,8,9].indexOf(type) >= 0">
<!-- 头像信息 -->
<view class="user-info">
<view class="avatar-box">
@@ -24,14 +25,14 @@
<!-- 对话信息 -->
<view :class="['talking-info', [4].indexOf(type) >= 0 ? 'talking-info-less':''] ">
<!-- 语音加载状态 -->
<view :class="['talking-gif', !voiceLoading && (activeVoiceId === dataInfo.id)?'is-play':'']" v-if="!([5, 8].indexOf(type) >= 0)">
<view :class="['talking-gif', !voiceLoading && (activeVoiceId === dataInfo.id)?'is-play':'']" v-if="!([5, 8, 9].indexOf(type) >= 0)">
<CommonLoading color="#06f" v-show="voiceLoading"/>
</view>
<view class="talking-cont">
<!-- 加载状态 -->
<CommonLoading color="#06f" v-show="dataInfo.isLoading"/>
<!-- 题干/段落内容 -->
<text class="talking-text" v-if="[3, 5, 6].indexOf(type) >= 0 && !dataInfo.isLoading">
<text class="talking-text" v-if="[3, 5, 6, 9].indexOf(type) >= 0 && !dataInfo.isLoading">
{{ showContent }}
</text>
<text class="talking-text" v-if="[4].indexOf(type) >= 0 && dataInfo.qnsTyp === 'ES'">
@@ -58,18 +59,22 @@
<ChartThree v-if="dataInfo.evalDimens.length === 3" :dataList="dataInfo.evalDimens" :score="dataInfo.intrctGrade"/>
<ChartFive v-if="dataInfo.evalDimens.length === 5" :dataList="dataInfo.evalDimens" :score="dataInfo.intrctGrade"/>
</view>
<!-- 参考答案 -->
<view class="talking-text" v-if="type === 5 && !dataInfo.isLoading" style="overflow: hidden;">
参考答案{{ dataInfo.itemAnswer }}
</view>
<!-- 举例预览 -->
<view class="talking-text" v-if="type === 3 && dataInfo.knoExampie " style="overflow: hidden;">
举例{{ dataInfo.knoExampie }}
</view>
</view>
<view class="btns-cont" v-show="!dataInfo.isLoading">
<!-- 重新回答 -->
<view class="replay-btn" @click.stop="restartPlay" v-if="!([5, 8].indexOf(type) >= 0)">
<!-- 重新播放 -->
<view class="replay-btn" @click.stop="restartPlay" v-if="!([5, 8, 9].indexOf(type) >= 0)">
<image class="icon" src="@/static/images/course/replay.png" style="width: 100%;height: 100%;"></image>
</view>
<!-- 止回答 -->
<view class="play-btn" v-if="!([5,8].indexOf(type) >= 0)">
<!-- 播放/ -->
<view class="play-btn" v-if="!([5, 8, 9].indexOf(type) >= 0)">
<image
class="icon"
src="@/static/images/course/play.png"
@@ -86,7 +91,7 @@
></image>
</view>
<view class="next-learn-btn"
v-if="showNextBtn && [5,8].indexOf(type) >= 0 && isLast"
v-if="showNextBtn && [5,8,9].indexOf(type) >= 0 && isLast"
@click.stop="goOnRestartPrgh"
>
重新学
@@ -102,7 +107,7 @@
</view>
<view
class="replay-study-btn next-learn-btn"
v-if="showNextBtn && [5,8].indexOf(type) >= 0 && isLast && (dataInfo.passStat === 'PS' || !!dataInfo.traQnsInfoVo?.judgeResult)"
v-if="showGoOnStudyBtn"
@click.stop="goOnGetQues"
>
继续学
@@ -111,7 +116,7 @@
<view class="next-btn" @click.stop="goOnGetQues" v-if="showGoonBtn">继续
<image class="icon icon-iamge" src="@/static/images/course/goon.png" ></image></view>
</view>
<!-- 解析信息 -->
<!-- 简答鼓励信息 -->
<view class="talking-cont last-cont" v-if=" [5].indexOf(type) >= 0 && !dataInfo.isLoading">
<view class="talking-text">
{{ changeBr(dataInfo.suggestContent || '--') }}
@@ -335,7 +340,21 @@ const audioCacheObj = computed(() => storageStore.audioObj)
deep: true,
immediate: true
})
const showGoOnStudyBtn = computed(()=> {
if(!(showNextBtn.value && isLast.value)){
return false
}
if(type.value === 5){
return true
}
if(type.value === 8){
return !!dataInfo.value.traQnsInfoVo?.judgeResult
}
if(type.value === 9){
return dataInfo.value.stdyStat === 'Y'
}
return false
})
const transformContent = ref('')
const showContentBase = computed(() => {
if(props.isTransform){
@@ -345,7 +364,8 @@ const audioCacheObj = computed(() => storageStore.audioObj)
else if(props.type === 2) return unref(dataInfo)?.chatContent || unref(dataInfo)?.talkingContent
else if(props.type === 3) return unref(dataInfo)?.chatContent || unref(dataInfo)?.pgrphContent
else if(props.type === 4) return unref(dataInfo)?.chatContent || unref(dataInfo)?.qnsContent
else if(props.type === 5) return unref(dataInfo)?.chatContent || unref(dataInfo)?.evalContent
else if(props.type === 5) return unref(dataInfo)?.chatContent || unref(dataInfo)?.analyContent
else if(props.type === 9) return unref(dataInfo)?.chatContent || unref(dataInfo)?.analyContent
else if(props.type === 0) return unref(dataInfo)?.chatContent || unref(dataInfo)?.talkingContent
else return unref(dataInfo)?.chatContent || unref(dataInfo)?.talkingContent
}
@@ -527,9 +547,12 @@ const audioCacheObj = computed(() => storageStore.audioObj)
if([5,8].indexOf(props.type) >= 0){
// 完成问题
emit('nextQuestion', unref(dataInfo))
}else if(props.type === 3){
}else if([3].indexOf(props.type) >= 0){
// 完成段落
emit('nextQuestion', unref(dataInfo), 'overGraph')
}else if([9].indexOf(props.type) >= 0){
// 下一段落
emit('nextQuestion', unref(dataInfo), 'nextGraph')
}
}
const clickNow = () => {
+51 -33
View File
@@ -446,23 +446,8 @@
.then(res => {
let _id = new Date().getTime() + 'id'
let _body = res.body || {}
if (Number(_body.bodyTyp) === 7) {
common.show('恭喜你已学完全部知识点', '有什么心得跟我们分享吗?', true, '取消', '去评论').then((res) => {
if (res) {
// 去评论
common.redirectTo(
`/pages/courseDetail/submit?crsId=${crsId.value}&crsNum=${crsNum.value}&from=study&imgId=${imageId.value}`
)
} else {
// 取消
common.redirectTo(
`/pages/courseDetail/index?crsId=${crsId.value}&crsNum=${crsNum.value}&from=study`)
}
}).finally(() => {})
return
}
if (_body.chatBody && _body.chatBody?.stdyStat !== 'N') {
let _id = new Date().getTime() + 'id'
console.log(_body)
if (_body.bodyTyp === '4') {
lastTalkingInfo.value = {
crsId: crsId.value,
stdyId: unref(stdyId),
@@ -470,9 +455,6 @@
logId: unref(logId),
pgrphId,
chatContent: _body.chatContent || '',
userInfo: {
...choiceTeacherInfo.value
},
...(_body.chatBody || {}),
type: 4,
userInfo: {
@@ -487,7 +469,22 @@
qstLogId.value = _body.chatBody?.qstLogId
scrollToBottomNow(800)
} else {
getGraphInfoUnStudy()
// getGraphInfoUnStudy()
lastTalkingInfo.value = {
crsId: crsId.value,
stdyId: unref(stdyId),
stdyBatch: unref(stdyBatch),
logId: unref(logId),
chatContent: _body.chatContent || '',
stdyStat: _body.chatBody.stdyStat,
type: 9,
pgrphId,
userInfo: {
...choiceTeacherInfo.value
},
id: _id,
}
talkingList.value.push(JSON.parse(JSON.stringify(lastTalkingInfo.value)))
}
})
}
@@ -524,6 +521,16 @@
scrollToBottomNow()
getQuestionInfoUnStudy(info.pgrphId)
})
} else if (type === 'nextGraph') {
talkingList.value.push({
crsId: info.crsId,
pgrphId: info.pgrphId,
talkingContent: '继续学',
type: 0,
id: _id
})
// 下个段落
getGraphInfoUnStudy()
} else if (type === 'reStart') {
talkingList.value.push({
crsId: info.crsId,
@@ -569,10 +576,11 @@
type: 0,
id: _id
})
console.log(unref(logId))
textChartApi({
processType: 'NEW-KNOW',
requestBody: JSON.stringify({
logId: info.logId,
logId: unref(logId),
pgrphId: info.pgrphId
})
}).then(res => {
@@ -732,6 +740,7 @@
crsId: crsId.value, // 课程ID 必输项:true 类型:String
stdyBatch: stdyBatch.value, // 学习批次 必输项:true 类型:String
ansterContent: '', // 回答文本内容 必输项:false 类型:String
asrStartTm: unref(lastTalkingInfo).asrStartTm
}
let _id = new Date().getTime() + 'id'
//#ifndef APP-PLUS
@@ -829,7 +838,8 @@
qstLogId: unref(qstLogId), // 段落ID 必输项:true 类型:String
crsId: crsId.value, // 课程ID 必输项:true 类型:String
stdyBatch: stdyBatch.value, // 学习批次 必输项:true 类型:String
ansterContent: val // 回答文本内容 必输项:false 类型:String
ansterContent: val, // 回答文本内容 必输项:false 类型:String
asrStartTm: unref(lastTalkingInfo).asrStartTm
}
textChartApi({
processType: 'ANSER-TEXT',
@@ -876,14 +886,15 @@
talkingList.value = talkingList.value.filter(t => t.recordId !== data.recordId)
})
}
const loadingQstLogId = ref('')
const loadingExecLogId = ref('')
const answerQuestionNow = (data) => {
let _data = {
qnsId: data.qnsId, // 问题ID 必输项:true 类型:String
pgrphId: data.pgrphId, // 段落ID 必输项:true 类型:String
crsId: crsId.value, // 课程ID 必输项:true 类型:String
stdyBatch: stdyBatch.value, // 学习批次 必输项:true 类型:String
ansterContent: data.answer.join(',') // 回答文本内容 必输项:false 类型:String
ansterContent: data.answer.join(','), // 回答文本内容 必输项:false 类型:String
asrStartTm: data.asrStartTm
}
// 发出答案
let _answer = data.answerItems.map(t => t.itemNo).join('')
@@ -931,13 +942,14 @@
processType: 'ANSER-OVER',
requestBody: JSON.stringify({
qnsId: data.qnsId,
stdyPgrphId: data.stdyPgrphId
stdyPgrphId: data.stdyPgrphId,
asrStartTm: data.asrStartTm
})
})
.then(res => {
// common.msg('完成成功,开始获取评分维度数据!')
let _state = res.body.chatBody.processStat
if (_state === 'ER') {
let _state = res.body.chatBody.isWait
if (_state !== 'Y') {
common.msg('提交答案失败!')
return
}
@@ -950,8 +962,8 @@
},
type: 0
})
loadingQstLogId.value = res.body.chatBody.qstLogId
qstLogId.value = loadingQstLogId.value
loadingExecLogId.value = res.body.chatBody.execLogId
qstLogId.value = loadingExecLogId.value
let _id = new Date().getTime() + 'id'
lastTalkingInfo.value = {
isLoading: true,
@@ -964,15 +976,17 @@
talkingList.value.push(JSON.parse(JSON.stringify(lastTalkingInfo.value)))
scrollToBottomNow(0)
getQuestionEvalateRequest(_id, data, 1)
}).catch(err=> {
console.log(err)
})
}
// 查询问题回答评分
const getQuestionEvalateRequest = (id, data, num) => {
if (loadingQstLogId.value) {
if (loadingExecLogId.value) {
textChartApi({
processType: 'ANSER-RESULT',
requestBody: JSON.stringify({
qstLogId: loadingQstLogId.value
execLogId: loadingExecLogId.value
})
})
.then(res => {
@@ -986,11 +1000,15 @@
lastTalkingInfo.value = {
..._body.chatBody,
pgrphId: data.pgrphId,
qstLogId: loadingQstLogId.value,
qstLogId: loadingExecLogId.value,
id,
userInfo: {
...choiceTeacherInfo.value
},
evalDimens: (_body.chatBody.essayEvalVo||[]).map(t=>({
...t,
gradeDimensName: t.gradeDimens
})),
type: 5
}
return lastTalkingInfo.value
+8 -4
View File
@@ -7,14 +7,14 @@
</view>
<view class="answer-content" v-else>
<view class="talking-link">
<view :class="['link-cont', activeNames.indexOf(1) >= 0 ? 'is-active' : '']" @click="changeActive(1)">
<view class="link-info">
<view :class="['link-cont', activeNames.indexOf(1) >= 0 ? 'is-active' : '']">
<view class="link-info" @click="changeActive(1)">
<view class="info-text">
引用知识库{{3}}篇相关资料
引用知识库{{fileList.length}}篇相关资料
</view>
</view>
<view class="link-items">
<view class="link-item" v-for="(item, index) in 3">{{index+1}}. {{item}}</view>
<view class="link-item" v-for="(item, index) in fileList" @click.stop="previewFile(item)">{{index+1}}. {{item.docName}}</view>
</view>
</view>
<view :class="['link-cont', activeNames.indexOf(2) >= 0 ? 'is-active' : '']">
@@ -84,6 +84,7 @@
immediate: true
})
const mdText = computed(() => props.dataInfo?.talkingText)
const fileList = computed(() => props.dataInfo?.talkingFiles || [])
const activeNames = ref([1, 2])
const changeActive = (val) => {
@@ -105,6 +106,9 @@
const feedbackAnswer = ()=>{
emit('handleEvents', 'feedback')
}
const previewFile = (item) => {
emit('handleEvents', 'preview', item)
}
</script>
<style scoped lang="scss">
+43 -28
View File
@@ -1,39 +1,34 @@
<template>
<view class="talking-item">
<questionVue
v-if="talkingType === 'question'"
@changePlay="changePlay"
:dataInfo="talkingInfo"
:activeVoiceId="activeVoiceId"
></questionVue>
<answerVue
v-else-if="talkingType === 'answer'"
:dataInfo="props.talkingInfo"
:isLoading="!!props.talkingInfo.isLoading"
:isAnswering="props.isAnswering"
@handleEvents="handleEvents"
></answerVue>
<questionVue v-if="talkingType === 'question'" @changePlay="changePlay" :dataInfo="talkingInfo"
:activeVoiceId="activeVoiceId"></questionVue>
<answerVue v-else-if="talkingType === 'answer'" :dataInfo="props.talkingInfo"
:isLoading="!!props.talkingInfo.isLoading" :isAnswering="props.isAnswering" @handleEvents="handleEvents">
</answerVue>
<view v-else></view>
</view>
</template>
<script setup>
import { toRefs, watch } from 'vue'
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',
talkingType: {
default: 'question',
type: String
},
talkingInfo:{
talkingInfo: {
default: () => ({}),
type: Object
},
activeVoiceId:{
default:'',
activeVoiceId: {
default: '',
type: String
},
isAnswering: {
@@ -41,22 +36,42 @@
type: Boolean
}
})
watch(() => props.activeVoiceId, () => {},{deep: true,immediate: true})
watch(() => props.talkingInfo, () => {},{deep: true,immediate: true})
const { talkingType } = toRefs(props)
const handleEvents = (type) => {
emit('handleEvents',{ type, data: props.talkingInfo, id:""})
watch(() => props.activeVoiceId, () => {}, {
deep: true,
immediate: true
})
watch(() => props.talkingInfo, () => {}, {
deep: true,
immediate: true
})
const {
talkingType
} = toRefs(props)
const handleEvents = (type, info) => {
console.log(info)
emit('handleEvents', {
type,
data: props.talkingInfo,
id: "",
info
})
}
const changePlay = (id) => {
emit('handleEvents', {type: 'changePlay', data: props.talkingInfo, id})
emit('handleEvents', {
type: 'changePlay',
data: props.talkingInfo,
id,
info: {}
})
}
</script>
<style scoped lang="scss">
.talking-item{
.talking-item {
overflow: hidden;
margin-top: 0rpx;
&+.talking-item{
&+.talking-item {
margin-top: 30rpx;
}
}
+44 -20
View File
@@ -1,20 +1,20 @@
<template>
<view class="index-dialog-page">
<view class="index-dialog-page" v-show="!showPreview">
<!-- <MarkdownPreview/> -->
<view class="top-bg"></view>
<view class="bot-bg"></view>
<scroll-view class="index-dialog-body" :scroll-y="true" upper-threshold="0" refresher-enabled="true"
refresher-default-style="none" @refresherrefresh="scrolltolower">
<view class="body-title">
<!-- <uv-icon class="arrow-icon" name="arrow-left" @click="common.navigateBack()"/> -->
AI问答
<view class="seek-setting">
<image src="@/static/images/dialog/new-dialog.png" alt="" class="image-icon-new" @click="createNewDialog"></image>
<image src="@/static/images/dialog/new-dialog.png" alt="" class="image-icon-new" @click="createNewDialog">
</image>
<image src="@/static/images/dialog/history.png" alt="" class="image-icon" @click="showHistory"></image>
</view>
</view>
<view class="ai-info">
<!-- <image src="@/static/images/dialog/pet-3.png" alt="" class="image-pet-bg"></image> -->
<image src="@/static/images/dialog/pet-bg-base.png" alt="" class="image-pet-bg"></image>
@@ -33,8 +33,7 @@
</view>
</view>
<view class="question-row">
<view class="question-item"
v-for="item in questionList.length - Math.ceil(questionList.length/2)"
<view class="question-item" v-for="item in questionList.length - Math.ceil(questionList.length/2)"
@click="sendText(questionList[item + Math.ceil(questionList.length/2)-1].hotContent)">
{{questionList[item + Math.ceil(questionList.length/2)-1].hotContent}}
</view>
@@ -42,10 +41,10 @@
</scroll-view>
</view>
<view class="talking-list">
<scroll-view class="talking-scroll-list" :scroll-y="true" :scroll-top="scrollTop"
:show-scrollbar="false" :scroll-with-animation="false">
<TalkingItem v-for="item in talkingList" :talkingType="item.type" :talkingInfo="item" :isAnswering="!answerIsOver"
:activeVoiceId="activeVoiceTalkingItemId" @handleEvents="talkItemEvents">
<scroll-view class="talking-scroll-list" :scroll-y="true" :scroll-top="scrollTop" :show-scrollbar="false"
:scroll-with-animation="false">
<TalkingItem v-for="item in talkingList" :talkingType="item.type" :talkingInfo="item"
:isAnswering="!answerIsOver" :activeVoiceId="activeVoiceTalkingItemId" @handleEvents="talkItemEvents">
</TalkingItem>
</scroll-view>
</view>
@@ -87,9 +86,10 @@
<!-- 反馈组件 -->
<Feedback ref="feedbackRef"></Feedback>
<History ref="historyRef"></History>
<PreviewVue ref="previewRef"/>
<PreviewVue ref="previewRef" />
</scroll-view>
</view>
<file-preview ref="previewFileRef" :file-id="'603058d8-88e0-43d2-8242-3132b85bc91c'" v-model="showPreview" />
</template>
<script setup>
@@ -138,7 +138,7 @@
} from "@/api/dialog.js"
import Feedback from './components/feedback.vue'
import History from './components/history.vue'
const {
statusBarHeight
} = uni.getWindowInfo()
@@ -149,7 +149,7 @@
const {
SocketObj
} = storeToRefs(socketStore)
const feedbackRef = ref()
const userInfo = ref(getUserInfo())
const questionList = ref([
@@ -184,6 +184,7 @@
return unref(userInfo)?.mascotInfo?.mascotId || 'Tst00001'
})
const answerText = ref('')
const answerFileList = ref('')
const answerIsOver = ref(true)
const talkingList = ref([])
@@ -267,7 +268,6 @@
seqNo.value = body.seqNo
touchBtnCallBack.value && touchBtnCallBack.value()
touchBtnCallBack.value = null
console.log('嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻', body);
talkingList.value.push({
type: 'question',
talkingText: body.intrctContent,
@@ -304,7 +304,10 @@
isLoading: false,
id: _id,
...body,
askData: {...askData.value}
askData: {
...askData.value
},
talkingFiles: []
})
} else if (body.event === 'token') {
answerIsOver.value = false
@@ -312,6 +315,10 @@
} else if (body.event === 'end') {
console.log('完成回答!')
answerIsOver.value = true
} else if (body.event === 'sourceDocuments') {
console.log('回答返回文件列表!')
if (talkingList.value.length === 0) return
talkingList.value[talkingList.value.length - 1].talkingFiles = JSON.parse(body.data) || []
}
return
}
@@ -364,7 +371,12 @@
}
const stopAnswerCallBack = ref(null)
const talkItemEvents = ({type, data, id}) => {
const talkItemEvents = ({
type,
data,
id,
info = {}
}) => {
switch (type) {
case 'reAnswer':
console.log('重新提问回答')
@@ -407,6 +419,14 @@
case 'feedback':
feedbackRef.value.open(data)
break;
case 'preview':
console.log(type, data, id)
// showPreview.value = true
common.navigateTo('/pages/index/preview?fileId=' + info.docId)
break;
case 'toCourse':
console.log(type, data, id)
break;
default:
break;
}
@@ -558,24 +578,28 @@
return
}
// 判断下如果没有设置吉祥物就跳转到吉祥物页面
if(userInfo.value?.mascotInfo.mascotId === null) { //说明这人在上次选吉祥物的时候退出了,没有选到吉祥物
if (userInfo.value?.mascotInfo.mascotId === null) { //说明这人在上次选吉祥物的时候退出了,没有选到吉祥物
common.redirectTo('/pages/mascot/mascot_select_list');
return
}
})
const previewRef = ref()
const previewFileRef = ref()
const showPreview = ref(false)
onMounted(() => {
loadData()
// previewRef.value.open()
// previewFileRef.value.open({
// fileId: '0006e7f7-a332-4c81-9802-ac4e2d971c71'
// })
})
const refreshData = () => {
loadData();
};
const keyboardHeight = ref('0px')
const setHeight = (res) => {
keyboardHeight.value = res.height +'px'
keyboardHeight.value = res.height + 'px'
}
//#ifdef APP-PLUS
onHide(() => {
+127
View File
@@ -0,0 +1,127 @@
<template>
<view class="popup-view">
<view class="body-title">
<uv-icon class="arrow-icon" name="arrow-left" @click="backRouter()" />
文件预览
</view>
<view class="popup-view-preview" v-if="showView">
<web-view :src="showUrl" :fullscreen="true" :webview-styles="{
width: '100%',
height: '100%'
}"></web-view>
</view>
</view>
</template>
<script >
import {
getToken
} from "@/common/common.js"
import common from '@/common/common';
import {
downloadFile
} from "@/api/common.js"
import {
get_base_url
} from '@/api/request.js'
var wv
export default{
data(){
return {
fileId:'',
showUrl:'',
viewerUrl: '/static/pdf-view/web/viewer.html',
showView: false,
wv: null
}
},
onLoad(params){
this.fileId = params.fileId || '';
},
onShow(){
this.openPdfFn({
fileId: this.fileId
})
},
onReady(){
//#ifdef APP-PLUS
var currentWebview = this.$scope.$getAppWebview()
setTimeout(()=>{
wv = currentWebview.children()[0]
wv.setStyle({
top: 80
})
uni.onKeyboardHeightChange(setHeight)
},1000)
// #endif
},
methods:{
// setHeight(res){
// wv.setStyle({
// top: res.height + 20
// })
// },
backRouter(){
common.navigateBack()
},
openPdfFn(data){
const base_url = get_base_url('/traask/traFilePreview/')
const token = getToken();
const header = {};
let _id = data?.fileId
let fileUrl = base_url + '/traask/traFilePreview/' + _id
if (token)
header['summary'] = token
uni.downloadFile({
//需要预览的文件地址
url: fileUrl,
header: header,
success: (res) => {
//下载成功,得到文件临时地址
//条件编译,若为h5端则直接赋值文件地址
// #ifdef H5
let newUrl = res.tempFilePath
// #endif
//条件编译,若为App端,则需要将本地文件系统URL转换为平台绝对路径
// #ifdef APP-PLUS
let newUrl = plus.io.convertLocalFileSystemURL(res.tempFilePath)
// #endif
this.showUrl = this.viewerUrl + '?file=' + newUrl
this.showView = true
}
})
}
}
}
</script>
<style lang="scss" scoped>
.popup-view{
width: 100vw;
height: 100vh;
}
.body-title {
height: 90rpx;
text-align: center;
font-size: 33rpx;
padding-top: 10rpx;
line-height: 46rpx;
box-sizing: border-box;
font-weight: 500;
color: #000;
position: fixed;
top: var(--status-bar-height);
left: 0;
width: 100vw;
z-index: 10000;
// margin-bottom: 23rpx;
.arrow-icon {
position: absolute;
left: 21rpx;
top: 5rpx;
color: #000;
padding: 15rpx;
// background-color: red;
}
}
</style>
+10 -2
View File
@@ -1,6 +1,5 @@
{
"pages": [
{
"pages": [{
"path": "pages/course/index",
"style": {
"navigationBarTitleText": "课程中心",
@@ -27,5 +26,14 @@
}
}
},
{
"path": "pages/index/preview",
"style": {
"navigationBarTitleText": "",
"app-plus": {
"titleNView": false
}
}
}
]
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,3 @@
àRCopyright 1990-2009 Adobe Systems Incorporated.
All rights reserved.
See ./LICENSEáCNS2-H
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,3 @@
àRCopyright 1990-2009 Adobe Systems Incorporated.
All rights reserved.
See ./LICENSEá ETen-B5-H` ^
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+4
View File
@@ -0,0 +1,4 @@
àRCopyright 1990-2009 Adobe Systems Incorporated.
All rights reserved.
See ./LICENSE!!º]aX!!]`21> p z$]"Rd-Uƒ7*„␍4„%+ „Z „{/%…<9K…b1]†." ‰`]‡,"]ˆ
"]ˆh"]‰F"]Š$"]"]`"]Œ>"]"]z"]ŽX"]6"]"]r"]P"]."]“ "]“j"]”H"]•&"]"]b"]—@"]˜"]˜|"]™Z"]š8"]"]t"]œR"]0"]ž"]žl"]ŸJ"] ("]¡"]¡d"]¢B"]£ "X£~']¤W"]¥5"]¦"]¦q"]§O"]¨-"]© "]©i"]ªG"]«%"]¬"]¬a"]­?"]®"]®{"]¯Y"]°7"]±"]±s"]²Q"]³/"]´␍"]´k"]µI"]¶'"]·"]·c"]¸A"]¹"]¹}"]º["]»9
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More