Merge branch 'develop' of http://25.13.9.101:9000/K17_AITS/tra-app into develop

This commit is contained in:
田岩
2025-07-11 11:10:49 +08:00
5 changed files with 111 additions and 17 deletions
@@ -0,0 +1,85 @@
<template>
<view>
<rich-text :nodes="contentHtml"></rich-text>
</view>
</template>
<script>
// import {Marked} from 'marked';
import MarkdownIt from 'markdown-it';
export default {
name:"markdown-preview",
props: {
mdString: {
default:`## 我是二级标题
### 我是三级标题
| 我是表头 | 表头 2 |
| :----------- | :----------- |
|1|2|
在客服交流中使用标准术语是提高专业形象和服务质量的重要手段。以下是一些常见的客服标准用语及其适用场景:
1. **问候与介绍:**
- “您好,欢迎来到[公司名称],我是您的客服代表[姓名],很高兴为您服务。”
- “早上好/下午好/晚上好,[公司名称]客服中心,请问有什么可以帮到您的吗?”
2. **确认信息:**
- “为了更好地为您提供服务,能否麻烦您提供一下[具体需要的信息,如订单号、会员账号等]?”
- “我来确认一下,您的问题是关于[问题的具体描述],对吗?”
3. **表达理解与同情:**
- “非常理解您的感受,遇到这种情况确实会让人感到不便/烦恼。”
- “感谢您的耐心等待,我们正在积极处理您的问题。”
4. **解决问题:**
- “针对您提到的问题,我们可以采取[解决方案]的方式解决,您看这样可以吗?”
- “我已经记录了您的反馈,并将尽快转交给相关部门处理,预计[解决时间]内会有结果。”
5. **结束对话:**
- “如果您没有其他问题的话,那我们就先这样吧,祝您生活愉快!”
- “再次感谢您的来电,期待下次为您服务。再见!”
6. **特殊情况处理:**
- “很抱歉给您带来了不愉快的体验,这并不是我们希望发生的事情。我们会立即调查此事,并确保类似情况不再发生。”
- “对于您所反映的情况,我们深感歉意,但根据我们的规定,[解释原因]。不过,我可以尝试帮您寻找其他的解决方案。”
以上是客服交流中常用的标准化语言,实际应用时可根据具体情况适当调整,以保持沟通的真实性和亲和力。`,
type: String
}
},
data() {
return {
contentHtml:'',
mdObj:null
};
},
watch:{
mdString: {
handler(val){
this.contentHtml = this.parseContent(val)
},
deep: true,
immediate: true
}
},
methods:{
parseContent(text){
if(this.mdObj){
return this.mdObj.render(text)
}else{
setTimeout(()=>{
return this.parseContent(text)
},500)
}
}
},
mounted(){
this.mdObj = new MarkdownIt()
this.contentHtml = this.parseContent(this.mdString)
console.log(this.contentHtml)
}
}
</script>
<style>
</style>
+17 -6
View File
@@ -1,6 +1,6 @@
<!-- type: 0纯文本信息不翻译 1语音回答 2 文本回答 3, 段落信息 4 问题信息 5 统计信息 6: 发送loading状态 7: 教师反馈文本不翻译 -->
<template>
<view class="ai-answer" v-if="[3,4,5].indexOf(type) >= 0">
<view :class="['ai-answer', props.class]" :id="props.id" v-if="[3,4,5].indexOf(type) >= 0">
<view class="user-info">
<view class="avatar-box">
<ImagePreview class="img-box" :imgId="dataInfo?.userInfo?.imgAddr"></ImagePreview>
@@ -80,7 +80,7 @@
重新学
<image class="icon icon-iamge" src="@/static/images/course/refresh-white.png" ></image>
</view>
<view class="next-btn" @click.stop="goOnGetQues" v-if="showNextBtn && [3, 6].indexOf(type) >= 0 && isLast && !isPlaying">继续
<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">
@@ -90,7 +90,7 @@
</view>
</view>
</view>
<view class="ai-answer" v-if="[7].indexOf(type) >= 0">
<view :class="['ai-answer', props.class]" :id="props.id" v-if="[7].indexOf(type) >= 0">
<view class="user-info">
<view class="avatar-box">
<ImagePreview class="img-box" :imgId="dataInfo?.userInfo?.imgAddr"></ImagePreview>
@@ -108,7 +108,7 @@
</view>
</view>
</view>
<view class="user-answer" v-else-if="[1, 2].indexOf(type) >= 0">
<view :class="['user-answer', props.class]" :id="props.id" v-else-if="[1, 2].indexOf(type) >= 0">
<view class="user-info">
<view class="avatar-box">
<image v-if="userInfo.imagePath" class="img-box" :src="userInfo.imagePath" style="width: 100%; height: 100%;"></image>
@@ -157,7 +157,7 @@
</view>
</view>
</view>
<view class="user-answer" v-else-if="[0, 6].indexOf(type) >= 0">
<view :class="['user-answer', props.class]" :id="props.id" v-else-if="[0, 6].indexOf(type) >= 0">
<view class="user-info">
<view class="avatar-box">
<image v-if="userInfo.imagePath" class="img-box" :src="userInfo.imagePath" style="width: 100%; height: 100%;"></image>
@@ -228,6 +228,14 @@ const audioCacheObj = computed(() => storageStore.audioObj)
default: () => ({}),
type: Object
},
class: {
default:'',
type: String
},
id: {
default:'',
type: String
}
})
const { type, dataInfo, activeVoiceId, isPlaying, isLast, lastQuestionInfo} = toRefs(props)
@@ -327,7 +335,7 @@ const audioCacheObj = computed(() => storageStore.audioObj)
}
// readType 阅读内容类型pgrh段落/qns问题
emit('changePlay', unref(dataInfo)?.id)
if(talkVoiceObj.value.src === itemVoice.value) {
if(talkVoiceObj.value.src && talkVoiceObj.value.src === itemVoice.value) {
talkVoiceObj.value.play()
return
}
@@ -402,6 +410,9 @@ const audioCacheObj = computed(() => storageStore.audioObj)
})
}
const showNextBtn = ref(true)
const showGoonBtn = computed(()=>{
return showNextBtn.value && [3, 6].indexOf(props.type) >= 0 && isLast.value && !isPlaying.value
})
const goOnGetQues = () => {
if(props.type === 5){
emit('nextQuestion', unref(dataInfo))
+3 -8
View File
@@ -167,16 +167,11 @@ import { onMounted, ref, computed } from 'vue'
}
// 点击生产线分类
const changePrdLine = (item)=>{
activePrdlineType.value = item.value
activePrdlineType.value = item.value === activePrdlineType.value ? '' : item.value
}
// 点击课程分类
const changeCourseType = (item)=>{
activeCourseType.value = item.value
setTimeout(()=>{
console.log(courseListTreeShow.value)
})
activeCourseType.value = item.value === activeCourseType.value ? '' : item.value
}
const showTypeName = computed(()=>{
return (activeTab.value === '全部' && activeCourseType.value === '') || (activeTab.value === '生产线' && activePrdlineType.value === '')
@@ -241,7 +236,7 @@ import { onMounted, ref, computed } from 'vue'
const changeTab = (item) => {
if(!item) return
activeTab.value = item.name
activeTag.value = ''
// activeTag.value = ''
activeCourseType.value = ''
activePrdlineType.value = ''
switch (item.name){
+5 -2
View File
@@ -1,8 +1,11 @@
<template>
<view>AI问答</view>
<view>
<MarkdownPreview/>
</view>
</template>
<script>
<script setup>
import MarkdownPreview from '@/components/markdown-preview/markdown-preview.vue';
</script>
<style>
+1 -1
View File
@@ -84,7 +84,7 @@
<image class="icon" src="@/static/images/index/navigation_course.png"></image>
<view class="title">课程中心</view>
</view>
<view class="item">
<view class="item" @click="common.navigateTo('/pages/index/dialog')">
<image class="icon" src="@/static/images/index/navigation_question_answering.png"></image>
<view class="title">AI问答</view>
</view>