You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
559 lines
12 KiB
559 lines
12 KiB
<template> |
|
<view class="detail"> |
|
<scroll-view scroll-y="true" :scroll-top="scrollTop" |
|
:style="{height: isExpanded ? 'calc(100% - 332rpx)' : 'calc(100% - 210rpx)'}" class="chatlist" |
|
ref="scrollView" @click="clickContent"> |
|
<view v-if="!msgList.length" class="helloContent"> |
|
<image :src="$.imgSrc + '/left_user.png'" class="imgLeft" /> |
|
<view class="titleBox"> |
|
<view class="titleOne"> |
|
您好,我是海信通途大模型 |
|
</view> |
|
<view class="titleTwo"> |
|
作为你的智能伙伴,我可以为你提供交通领域知识的答疑解惑。 |
|
</view> |
|
<view class=""> |
|
你这样试着问我: |
|
</view> |
|
<view class="tipQuestions"> |
|
<view class="" v-for="(item,index) in tipQuestions" :key=index> |
|
<view class="tipItem" @click="handleBtn(item.text)"> |
|
<view class="title"> |
|
{{item.title}} |
|
</view> |
|
<view class=""> |
|
{{item.text}} |
|
</view> |
|
</view> |
|
</view> |
|
</view> |
|
</view> |
|
</view> |
|
<view :class="['bar', item.answerId == '0' ? 'currAnswer' : '']" v-for="(item,index) in msgList" |
|
:key="item.id"> |
|
<image :src="item.answerId == '0' ? $.imgSrc + '/self.png' : $.imgSrc + '/left_user.png'" class="img" /> |
|
<view class="content"> |
|
<zeroMarkdownView :markdown="item.data" /> |
|
<!-- <ua-markdown :source="mdvalue" /> --> |
|
</view> |
|
</view> |
|
<view class="loading-animation" v-if="loading"> |
|
<view class="bounce-dot"></view> |
|
<view class="bounce-dot"></view> |
|
<view class="bounce-dot"></view> |
|
</view> |
|
</scroll-view> |
|
<view class="input-wrapper" :class="{ 'input-wrapper-expanded': isExpanded }"> |
|
<view class="topContent"> |
|
<input class="uni-input" placeholder="请输入内容" :value="inputValue" @confirm="handleSend" |
|
@input="onKeyInput" /> |
|
|
|
<uni-icons class="uni-icon" type="plus" size="30" @click="handlePlus"></uni-icons> |
|
</view> |
|
<view v-if="isExpanded" class="expanded"> |
|
<view @click="chooseImage" class="expandedItem"> |
|
<uni-icons class="camera-icon" type="image" size="28"></uni-icons> |
|
<view>照片</view> |
|
</view> |
|
<view class="expandedItem" style="margin-top: 6px;"> |
|
<image src="../../static/video.png" class="video"></image> |
|
<view>视频</view> |
|
</view> |
|
|
|
</view> |
|
</view> |
|
</view> |
|
</template> |
|
|
|
<script> |
|
|
|
import zeroMarkdownView from '../../components/zeroMarkdownView/zeroMarkdownView.vue' |
|
let baseUrl = '' |
|
export default { |
|
components: { zeroMarkdownView }, |
|
data() { |
|
return { |
|
$: this.$, |
|
active: 0, |
|
inputValue: '', |
|
es: null, |
|
msgList: [], |
|
loading: false, |
|
streamLoading: true, |
|
scrollTop: 0, |
|
title: '', |
|
isExpanded: false, |
|
sessionId: '', |
|
id: '', |
|
tipQuestions: [{ |
|
title: '标准法规', |
|
text: '一级公路停车视距标准是什么?', |
|
}, |
|
{ |
|
title: '工作指南', |
|
text: '如何开展道路安全隐患排查工作?', |
|
}, |
|
{ |
|
title: '参考案例', |
|
text: '请给我一个典型的视距不良路口案例。', |
|
} |
|
] |
|
} |
|
}, |
|
onLoad() { |
|
let params = uni.getStorageSync('itemMessage') |
|
// params = JSON.parse(decodeURIComponent(this.$route.query.params)) |
|
// this.sessionId = params.sessionId |
|
// this.id = '37020017407' |
|
this.sessionId = '37020000000' |
|
this.id = '37020017407' |
|
// console.log(params.roadName,"5555"); |
|
let str = ''; |
|
if (params.roadName) { |
|
str += '路段名:' + params.roadName; |
|
this.title = params.roadName + '智能排查'; |
|
} |
|
if (params.id) { |
|
str += ',id:' + params.id; |
|
} |
|
// this.queryChat("开始隐患排查," + str, ); |
|
}, |
|
onUnload() { |
|
if (this.es) { |
|
this.es.close(); |
|
this.es = null; |
|
} |
|
}, |
|
methods: {async queryChat(voiceText) { |
|
// console.log(voiceText,"voiceText"); |
|
this.loading = true; |
|
const [err, res] = await uni.request({ |
|
// url: 'http://10.16.3.159:8777/api/local_doc_qa/local_doc_chat', |
|
url: this.$.chatUrl+'/chat', |
|
dataType: 'json', |
|
method: 'POST', |
|
// responseType: 'arraybuffer', |
|
headers: { |
|
// 'Accept': 'text/event-stream', |
|
'content-type': 'application/json' |
|
}, |
|
data: { |
|
voiceText, |
|
"sceneFlag": "", |
|
"sessionId": this.sessionId, |
|
"id": this.id, |
|
"multiType": "", |
|
"userId": "admin1", |
|
"deptId": "3702000000", |
|
"type": 0 |
|
// "user_id": "zzp", |
|
// "kb_ids": ["KBa80ea15e786241eca70a20f136f4e34c"], |
|
// "question": "隐患排查流程是什么", |
|
// "streaming": true, |
|
// "history": [] |
|
} |
|
}); |
|
console.log(res) |
|
if (res && res.data && res.data.code == 200) { |
|
// console.log('request success', res.data) |
|
const { |
|
result = {} |
|
} = res.data; |
|
const { |
|
data = {} |
|
} = result; |
|
if (data.tabkey - 1 != this.active) { |
|
this.active = data.tabkey - 1 > 0 ? data.tabkey - 1 : 0; |
|
} |
|
if (data.content) { |
|
this.changeMsgList(data.answerId || '1', data.content); |
|
} |
|
this.loading = false; |
|
} else { |
|
if (err) { |
|
console.log('request fail', err.errMsg); |
|
} |
|
uni.showToast({ |
|
title: "查询失败", |
|
icon: "error", |
|
duration: 2000 |
|
}) |
|
} |
|
}, |
|
// 快捷回复 |
|
handleBtn(text) { |
|
|
|
this.handleSend(text) |
|
}, |
|
// 输入框 |
|
onKeyInput(event) { |
|
this.inputValue = event.detail.value |
|
}, |
|
// 发送 |
|
handleSend(text) { |
|
if (!this.inputValue & !text) { |
|
uni.showToast({ |
|
title: "请输入内容", |
|
icon: "closeempty", |
|
duration: 2000 |
|
}) |
|
} |
|
this.changeMsgList('0', this.inputValue || text); |
|
this.queryChat(this.inputValue || text,); |
|
this.inputValue = ''; |
|
}, |
|
// 更新列表信息 |
|
changeMsgList(answerId, data) { |
|
|
|
let id = 1; |
|
if (this.msgList.length > 0) { |
|
id = this.msgList[this.msgList.length - 1].id + 1; |
|
} |
|
if (answerId == '1') { // 后台返回来的消息 |
|
let newdata = ''; |
|
let index = 0; |
|
const timer = setInterval(() => { |
|
console.log(this.msgList); |
|
newdata = newdata += data[index] |
|
if (this.msgList?.filter(item => (item.id == id)).length == 0) { |
|
this.msgList = [...this.msgList, { |
|
id, |
|
answerId, |
|
data: newdata, |
|
}]; |
|
} else { |
|
this.msgList[this.msgList.length - 1].data = newdata; |
|
} |
|
index += 1; |
|
this.$nextTick(() => { |
|
const height = this.$refs.scrollView && this.$refs.scrollView.$refs && this |
|
.$refs.scrollView.$refs.content ? this.$refs.scrollView.$refs.content |
|
.scrollHeight : 0; |
|
this.scrollTop = height; |
|
}) |
|
if (newdata == data) { |
|
clearInterval(timer); |
|
} |
|
}, 50) |
|
} else { |
|
this.msgList = [...this.msgList, { |
|
id, |
|
answerId, |
|
data, |
|
}]; |
|
this.$nextTick(() => { |
|
const height = this.$refs.scrollView && this.$refs.scrollView.$refs && this.$refs |
|
.scrollView.$refs.content ? this.$refs.scrollView.$refs.content.scrollHeight : 0; |
|
this.scrollTop = height; |
|
}) |
|
} |
|
}, |
|
handlePlus() { |
|
this.isExpanded = !this.isExpanded; |
|
}, |
|
clickContent() { |
|
if (this.isExpanded) { |
|
this.isExpanded = !this.isExpanded; |
|
} |
|
}, |
|
goToKnowledge() { |
|
uni.navigateTo({ |
|
url: `/pages/home/detail?params=${encodeURIComponent(JSON.stringify(item))}` |
|
}) |
|
}, |
|
// 选择图片 |
|
chooseImage() { |
|
uni.chooseImage({ |
|
count: 6, //默认9 |
|
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有 |
|
sourceType: ['album'], //从相册选择 |
|
success: (res) => { |
|
if (res.tempFilePaths && res.tempFilePaths.length) { |
|
let str = ''; |
|
for (let i = 0; i < res.tempFilePaths.length; i++) { |
|
str += ``; |
|
} |
|
this.changeMsgList('0', str); |
|
this.queryChat(res.tempFilePaths); |
|
} |
|
} |
|
}); |
|
} |
|
} |
|
} |
|
</script> |
|
|
|
<style scoped lang="scss"> |
|
.detail { |
|
width: 100%; |
|
margin: auto; |
|
height: 100vh; |
|
overflow: hidden; |
|
|
|
.knowledge { |
|
width: 40rpx; |
|
height: 40rpx; |
|
} |
|
|
|
.helloContent { |
|
display: flex; |
|
|
|
.imgLeft { |
|
width: 80rpx; |
|
height: 80rpx; |
|
margin-top: 15rpx; |
|
} |
|
|
|
.titleBox { |
|
display: inline-block; |
|
max-width: 80%; |
|
border: 1px solid #ddd; |
|
border-radius: 5px; |
|
padding: 0; |
|
margin: 15rpx 0rpx 0 20rpx; |
|
// flex: 1; |
|
overflow: hidden; |
|
background-color: #ffffff; |
|
padding: 15rpx; |
|
|
|
.titleOne { |
|
font-weight: 700; |
|
font-size: 30rpx |
|
} |
|
|
|
.titleTwo { |
|
margin: 15rpx 0; |
|
} |
|
.tipItem{ |
|
background-color: #e1f8f8; |
|
margin:15rpx; |
|
padding:15rpx; |
|
.title{ |
|
font-size: 30rpx; |
|
font-weight: 700; |
|
} |
|
} |
|
} |
|
} |
|
|
|
.stepBox { |
|
width: 100%; |
|
height: 150rpx; |
|
display: flex; |
|
justify-content: center; |
|
align-items: center; |
|
background-color: #ffffff; |
|
|
|
.step { |
|
display: flex; |
|
|
|
.stepItem { |
|
display: flex; |
|
flex-direction: column; |
|
align-items: center; |
|
} |
|
|
|
.circles { |
|
display: flex; |
|
// justify-content: space-between; |
|
padding: 22px 0; |
|
|
|
.circle { |
|
width: 4rpx; |
|
height: 4rpx; |
|
border-radius: 50%; |
|
background-color: #e9edf5; |
|
margin: 0 1px; |
|
} |
|
|
|
.circleActive { |
|
width: 4rpx; |
|
height: 4rpx; |
|
border-radius: 50%; |
|
background-color: #ccc; |
|
margin: 0 1px; |
|
} |
|
} |
|
|
|
.stepCircle { |
|
width: 60rpx; |
|
height: 60rpx; |
|
line-height: 60rpx; |
|
border-radius: 50%; |
|
background-color: #e9edf5; |
|
color: #a0abbd; |
|
text-align: center; |
|
margin-bottom: 10rpx; |
|
} |
|
|
|
.stepCircleActive { |
|
width: 50rpx; |
|
height: 50rpx; |
|
line-height: 50rpx; |
|
border-radius: 50%; |
|
background-color: #295cbc; |
|
color: #ffffff; |
|
text-align: center; |
|
margin-bottom: 4rpx; |
|
border: 5px solid #c6d8fc; |
|
} |
|
|
|
.stepText { |
|
font-size: 16px; |
|
color: #bcc3cd; |
|
} |
|
} |
|
|
|
} |
|
|
|
.chatlist { |
|
width: 96%; |
|
margin: auto; |
|
height: calc(100% - 210rpx); |
|
background-color: #f0f2f7; |
|
|
|
.bar { |
|
width: 100%; |
|
display: flex; |
|
margin-bottom: 40rpx; |
|
overflow: hidden; |
|
|
|
.img { |
|
width: 80rpx; |
|
height: 80rpx; |
|
margin-top: 15rpx; |
|
} |
|
|
|
.content { |
|
display: inline-block; |
|
max-width: 80%; |
|
border: 1px solid #ddd; |
|
border-radius: 5px; |
|
padding: 0; |
|
margin: 15rpx 20rpx 0 20rpx; |
|
// flex: 1; |
|
overflow: hidden; |
|
background-color: #ffffff; |
|
|
|
._img { |
|
max-width: 80% |
|
} |
|
} |
|
|
|
|
|
&.currAnswer { |
|
flex-direction: row-reverse; |
|
|
|
.content { |
|
background-color: #cce0ff; |
|
} |
|
} |
|
|
|
} |
|
} |
|
|
|
.input-wrapper { |
|
display: flex; |
|
width: 100%; |
|
margin: 20rpx auto 0 auto; |
|
height: 80rpx; |
|
flex-direction: column; |
|
background-color: #FFFFFF; |
|
box-sizing: border-box; |
|
border-top: 1px solid #e2e4e9; |
|
bottom: 1px solid #e2e4e9; |
|
padding: 20rpx 20rpx 0 20rpx; |
|
|
|
.topContent { |
|
display: flex; |
|
width: 100%; |
|
} |
|
|
|
.expanded { |
|
background-color: #f5f7fa; |
|
display: flex; |
|
|
|
.expandedItem { |
|
width: 106rpx; |
|
height: 106rpx; |
|
display: flex; |
|
flex-direction: column; |
|
align-items: center; |
|
justify-content: space-between; |
|
|
|
.camera-icon { |
|
margin-top: 5px |
|
} |
|
} |
|
|
|
.video { |
|
width: 60rpx; |
|
height: 60rpx; |
|
|
|
} |
|
} |
|
} |
|
|
|
.input-wrapper-expanded { |
|
|
|
height: 200rpx; |
|
} |
|
|
|
.uni-input { |
|
height: 56rpx; |
|
line-height: 56rpx; |
|
font-size: 30rpx; |
|
padding: 0rpx 10rpx; |
|
flex: 1; |
|
background-color: #fff; |
|
} |
|
|
|
.uni-icon { |
|
font-family: uniicons; |
|
font-size: 48rpx; |
|
font-weight: normal; |
|
font-style: normal; |
|
width: 48rpx; |
|
height: 48rpx; |
|
line-height: 48rpx; |
|
color: #999999; |
|
margin: 0 10rpx; |
|
} |
|
|
|
.loading-animation { |
|
display: flex; |
|
justify-content: center; |
|
margin-top: 0; |
|
|
|
.bounce-dot { |
|
width: 20rpx; |
|
height: 20rpx; |
|
margin: 10rpx; |
|
background-color: #666; |
|
border-radius: 50%; |
|
animation: bounce 1.4s infinite both; |
|
|
|
&:nth-child(2) { |
|
animation-delay: 0.2s; |
|
} |
|
|
|
&:nth-child(3) { |
|
animation-delay: 0.4s; |
|
} |
|
} |
|
} |
|
} |
|
|
|
@keyframes bounce { |
|
|
|
0%, |
|
80%, |
|
100% { |
|
transform: scale(0); |
|
} |
|
|
|
40% { |
|
transform: scale(1); |
|
} |
|
} |
|
</style>
|
|
|