Files
tra-app/src/pages/index/dialog.vue
T
2025-12-05 09:05:42 +08:00

1151 lines
30 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="index-dialog-page">
<!-- <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="top-desc">内容由AI生成</view>
<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/history.png"
alt=""
class="image-icon"
@click="showMenuList = !showMenuList"
></image>
<view :class="['more-list', showMenuList ? 'show' : '']">
<view class="more-item" @click.stop="showHistory">历史</view>
<view class="more-item" @click.stop="toMessage">消息</view>
<view class="more-item" @click.stop="toMePage">我的</view>
</view>
</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>
<image :src="luimgAddr" alt="" class="image-pet" mode="widthFix"></image>
<view class="ai-info-bg-box">
<view class="hello-text">{{ userInfo ? 'Hi,我是' + userInfo?.mascotInfo?.mascotName : 'Hi' }}</view>
<view class="info-text">工作学习我都能帮你</view>
<view class="info-btn">试试他的能力</view>
</view>
</view>
<view class="questions-view">
<scroll-view :scroll-x="true" :show-scrollbar="false">
<view class="question-row">
<view
class="question-item"
v-for="item in Math.ceil(questionList.length / 2)"
@click="sendText(questionList[item - 1].hotContent)"
>
{{ questionList[item - 1].hotContent }}
</view>
</view>
<view class="question-row">
<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>
</view>
</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, index) in talkingList"
:talkingType="item.type"
:talkingInfo="item"
:isLast="index + 1 === talkingList.length"
:isAnswering="!answerIsOver"
:activeVoiceId="activeVoiceTalkingItemId"
@handleEvents="talkItemEvents"
></TalkingItem>
</scroll-view>
</view>
<view class="router-list">
<scroll-view class="" :scroll-x="true" :show-scrollbar="false">
<view class="btns-item" @click="routerTo('AI学')">
<image src="@/static/images/dialog/icons/study.png" alt="" class="image-icon"></image>
{{ 'AI学' }}
</view>
<view class="btns-item" @click="routerTo('AI练')">
<image src="@/static/images/dialog/icons/test.png" alt="" class="image-icon"></image>
{{ 'AI练' }}
</view>
<view class="btns-item" @click="routerTo('AI考')">
<image src="@/static/images/dialog/icons/exam.png" alt="" class="image-icon"></image>
{{ 'AI考' }}
</view>
<view class="btns-item" @click="routerTo('去PK')">
<image src="@/static/images/dialog/icons/PK.png" alt="" class="image-icon"></image>
{{ '去PK' }}
</view>
<view class="btns-item" @click="routerTo('任务')">
<image src="@/static/images/dialog/icons/task.png" alt="" class="image-icon"></image>
{{ '任务' }}
</view>
<view class="btns-item" @click="routerTo('错题')">
<image src="@/static/images/dialog/icons/wrong.png" alt="" class="image-icon"></image>
{{ '错题' }}
</view>
<view class="btns-item" @click="routerTo('分析')">
<image src="@/static/images/dialog/icons/static.png" alt="" class="image-icon"></image>
{{ '分析' }}
</view>
</scroll-view>
</view>
<TouchBtn
class="talk-btns"
@uploadVoice="uploadRecordNow"
@submitAnswer="submitAnswerNow"
@startRecord="startRecordCallback"
:loadingText="sendLoadingText"
:isLoading="!answerIsOver"
:adjustPosition="true"
:isDisabled="isHistory"
/>
<History ref="historyRef" @showDetail="showHistoryDetail"></History>
<PreviewVue ref="previewRef" />
</scroll-view>
</view>
<badge ref="badgeRef"></badge>
<points ref="pointsRef"></points>
<!-- 反馈组件 -->
<Feedback ref="feedbackRef" @feedbackAnswer="feedbackAnswer"></Feedback>
<!-- <file-preview ref="previewFileRef" :file-id="'603058d8-88e0-43d2-8242-3132b85bc91c'" v-model="showPreview" /> -->
<!-- 水印组件 -->
<watermark ref="watermarkRef"></watermark>
</template>
<script setup>
import { ref, unref, onMounted, watch, nextTick, computed, onActivated } from 'vue';
import common from '@/common/common';
import { setupKeyboardHeightListener } from '@/common/common';
import TouchBtn from '@/pages/course/components/touchBtn.vue';
import TalkingItem from './components/talking-item.vue';
import PreviewVue from './components/preview.vue';
import { useSocketStore } from '@/store/socket.js';
import { useStorageStore } from '@/store/storage.js';
import { storeToRefs } from 'pinia';
import { onLoad, onShow, onUnload, onHide, onBackPress } from '@dcloudio/uni-app';
import { get_base_url, goto_login_fun } from '@/api/request';
import { getUserInfo, getPhoneEnvBool } from '@/common/common';
import { commonUploadVoiceFile } from '@/api/common.js';
import {
queryHotQuestionApi,
insertTraAskFeedback,
queryAskHisByBatchIdPaging,
updateLikeStat,
updateDownvoteStat
} from '@/api/dialog.js';
import Feedback from './components/feedback.vue';
import History from './components/history.vue';
import badge from '@/components/points-and-badge/badge';
import points from '@/components/points-and-badge/points';
import usePointsAndBadge from '@/components/points-and-badge/usePointsAndBadge';
const { pointAndBadgesRun, badgeRef, pointsRef } = usePointsAndBadge();
const { statusBarHeight } = uni.getWindowInfo();
const pageTopPadding = computed(() => statusBarHeight + 'px');
const socketStore = useSocketStore();
const { SocketObj } = storeToRefs(socketStore);
const feedbackRef = ref();
const watermarkRef = ref();
const userInfo = ref(getUserInfo());
const luimgAddr = computed(()=> unref(userInfo)?.mascotInfo?.imgAddr || '')
const userParams = '/' + (unref(userInfo)?.loginName??'')
const questionList = ref([
// '对公小程序开户流程?',
// '厅堂服务经理2025年管理办法?',
// '厅堂服务经理2025年考核表单?',
// '吉林银行重要空白凭证调微业务操作规程?',
// '协助有权机关查询冻结扣划业务操作规程?',
// '柜面个人账户操作规程?',
// '久悬未取款账户如何办理销户?',
// '境外来华人员个人账户业务开户如何办理?',
// '营业机构日间管理风险防控要点有哪些?',
// '现金管理平台柜面业务操作?'
]);
const scrollBoxRef = ref();
const scrollTop = ref(99999);
const scrollToBottomNow = (time = 100) => {
nextTick(() => {
setTimeout(() => {
scrollTop.value += 100;
scrollTop.value += 100;
}, time);
});
};
const isHistory = ref(false);
const activeVoiceTalkingItemId = ref('');
// ws 初始化逻辑
const reconnectTimer = null; // 重连timer
const isManualClose = ref(false); // 是否手动关闭
const reqBatch = ref('');
const seqNo = ref('');
const mascotId = computed(() => {
return unref(userInfo)?.mascotInfo?.mascotId || 'Tst00001';
});
const answerText = ref('');
const answerFileList = ref('');
const answerIsOver = ref(true);
const talkingList = ref([]);
const createNewDialog = () => {
if (talkingList.value.length === 0) {
common.msg('已经是最新对话');
}
common.redirectTo(`/pages/index/dialog`);
};
const showModelComfirm = ref(false);
const reconcatNum = ref(1);
const askTime = ref(0)
const initsocketTask = () => {
isHistory.value = false;
socketStore.creatSocket('/traask/asksocket/open?summary=');
// unref(SocketObj).on('open', (res)=>{
// if(!answerIsOver.value){
// sendMessage({
// "commond" : 'ASK-RE-START',
// "body" : {
// reqBatch: reqBatch.value,
// seqNo: seqNo.value,
// answerContent: answerText.value
// }
// })
// }
// })
unref(SocketObj).on('error', () => {
if (watchFlag.value === 1 || showModelComfirm.value) return;
if (reconcatNum.value === 5) {
common.msg('系统网络异常,请稍后再试!');
return;
}
showModelComfirm.value = true;
common
.show('提示信息', '网络环境不稳定,请重试!', false, '', '确认')
.then((res) => {
reconcatNum.value += 1;
common.redirectTo(`/pages/index/dialog`);
})
.finally(() => {
showModelComfirm.value = false;
});
});
unref(SocketObj).on('message', (res) => {
const { rtnCode, body, commond } = JSON.parse(res.data);
let _id = new Date().getTime() + 'id';
if (rtnCode === '0000') {
if (commond === 'ASK-OPEN') {
if (!answerIsOver.value) {
// 问题没完成, 重新尝试回答
sendMessage({
commond: 'ASK-RE-START',
body: {
reqBatch: reqBatch.value,
seqNo: seqNo.value,
answerContent: answerText.value
}
});
} else {
// 新连接
sendMessage({
commond: 'ASK-START',
body: {
mascotId: mascotId.value,
deviceImei: ''
}
});
}
return;
}
if (commond === 'ASK-START') {
// console.log('开启对话!')
reqBatch.value = body.reqBatch;
return;
}
if (commond === 'ASK') {
console.log('发送问题成功!');
if (talkingList.value.length > 0 && talkingList.value[talkingList.value.length - 1].isLoading) {
talkingList.value.pop();
}
seqNo.value = body.seqNo;
touchBtnCallBack.value && touchBtnCallBack.value();
touchBtnCallBack.value = null;
talkingList.value.push({
type: 'question',
talkingText: body.intrctContent,
isLoading: false,
id: _id,
...body,
talkingVoice: askData.value.talkingVoice
});
talkingList.value.push({
type: 'answer',
isLoading: true,
id: _id + 'loading'
});
scrollToBottomNow();
return;
}
if (commond === 'ASK-STOP') {
console.log('停止回答标记!');
stopAnswerCallBack.value && stopAnswerCallBack.value(askData.value);
setTimeout(() => {
stopAnswerCallBack.value = null;
answerIsOver.value = true;
}, 10);
return;
}
if (commond === 'ASK-ANSWER') {
if (body.event === 'start') {
console.log('开始回答!');
if (askTime.value === 0){
pointAndBadgesRun('06')
askTime.value = 1
}
answerIsOver.value = false;
answerText.value = '';
talkingList.value.pop();
talkingList.value.push({
type: 'answer',
talkingText: answerText.value,
isLoading: false,
id: _id,
...body,
askData: {
...askData.value
},
talkingFiles: [],
talkingCrsList: []
});
} else if (body.event === 'token') {
answerIsOver.value = false;
answerText.value += body.data;
} else if (body.event === 'end') {
console.log('完成回答!');
answerIsOver.value = true;
} else if (body.event === 'sourceDocuments') {
console.log('回答返回文件列表!');
console.log('body: ', body);
if (talkingList.value.length === 0) return;
let _data = body.data;
talkingList.value[talkingList.value.length - 1].talkingFiles = _data.knowledgeList || [];
talkingList.value[talkingList.value.length - 1].talkingCrsList = _data.crsList || [];
}
return;
}
if (commond === 'ASK-RE-ANSWER') {
// console.log('开始继续回答!')
if (body.event === 'start') {
answerIsOver.value = false;
answerText.value = '';
} else if (body.event === 'token') {
answerIsOver.value = false;
answerText.value = body.data;
} else if (body.event === 'end') {
answerIsOver.value = true;
}
return;
}
if (commond === 'ASK-ERR') {
console.log('提问失败,系统异常!');
return;
}
} else {
if (['0005', 'QQ0005'].includes(res.rtnCode)) {
goto_login_fun();
}
}
});
watchFlag.value += 1;
};
const sendLoadingText = ref('问题回答中,请在问题回答结束后重试!');
const reconnect = () => {
if (reconnectTimer || isManualClose.value) return;
reconnectTimer = setTimeout(() => {
initsocketTask();
}, 3000);
};
const sendMessage = (data) => {
unref(SocketObj).send(data);
};
watch(
() => answerText.value,
(val) => {
if (val) {
changeText(val);
scrollToBottomNow();
}
}
);
const changeText = () => {
if (talkingList.value.length === 0) return;
talkingList.value[talkingList.value.length - 1].talkingText = answerText.value;
};
const isDownloading = ref(false)
const stopAnswerCallBack = ref(null);
const talkItemEvents = ({ type, data, id, info = {} }) => {
switch (type) {
case 'reAnswer':
console.log('重新提问回答');
// 停止获取
sendMessage({
commond: 'ASK-STOP',
body: {
reqBatch: reqBatch.value,
seqNo: seqNo.value
}
});
sendMessage({
commond: 'ASK',
body: data.askData
});
// // 设置停止回调
// stopAnswerCallBack.value = ($data) => {
// sendMessage({
// "commond": 'ASK',
// "body": $data
// })
// }
break;
case 'stop':
console.log('停止获取数据');
stopAnswerCallBack.value = null;
// ASK-STOP
sendMessage({
commond: 'ASK-STOP',
body: {
reqBatch: reqBatch.value,
seqNo: seqNo.value
}
});
break;
case 'changePlay':
activeVoiceTalkingItemId.value = id;
break;
case 'feedback':
let _feedstatus = data.downvoteStat === 'Y' ? 'N' : 'Y';
let _feedid = data.seqNo || data.askId;
if (_feedstatus === 'N') {
updateDownvoteStat({
askId: _feedid,
stat: _feedstatus
}).then((res) => {
talkingList.value.forEach((t) => {
if (t.seqNo === _feedid || t.askId === _feedid) {
t.downvoteStat = 'N';
}
});
});
} else {
feedbackRef.value.open(data);
}
break;
case 'great':
let _status = data.likeStat === 'Y' ? 'N' : 'Y';
let _id = data.seqNo || data.askId;
updateLikeStat({
askId: _id,
stat: _status
}).then((res) => {
talkingList.value.forEach((t) => {
if (t.seqNo === _id || t.askId === _id) {
t.likeStat = _status;
if (_status === 'Y') {
t.downvoteStat = 'N';
}
}
});
});
break;
case 'preview':
common.navigateTo('/pages/index/preview?fileId=' + info.docId);
// if (getPhoneEnvBool('AND')) {
// common.navigateTo('/pages/index/preview?fileId=' + info.docId);
// } else {
// common.navigateTo('/pages/index/preview?fileId=' + info.docId); return
// if(isDownloading.value) return
// const base_url = get_base_url('/traask/traFilePreview/');
// let fileUrl = base_url + '/traask/traFilePreview/' + info.docId + userParams;
// const localFilePath = '_doc/pdf_view/' + info.docName + '.pdf';
// isDownloading.value = true
// downloadAndSaveAvatar(fileUrl, localFilePath).then((res) => {
// uni.openDocument({
// filePath: res,
// showMenu: true,
// success: function () {
// console.log('打开文档成功');
// }
// })
// }).finally(()=>{
// setTimeout(()=>{
// isDownloading.value = false
// },1000)
// });
// }
break;
case 'toCourse':
console.log(type, data, id);
break;
default:
break;
}
};
const downloadAndSaveAvatar = async (fileUrl, localFilePath) => {
try {
//#ifdef APP-PLUS
return new Promise((resolve, reject) => {
console.log('开始下载:', fileUrl);
const dtask = plus.downloader.createDownload(
fileUrl,
{
filename: localFilePath
},
(d, status) => {
if (status === 200) {
console.log('保存路径:', d.filename);
resolve(d.filename);
} else {
console.error('文件下载失败:', status);
reject(new Error(`下载失败,状态码: ${status}`));
}
}
);
dtask.start();
});
// #endif
//#ifdef H5
return new Promise((resolve, reject) => {
resolve();
});
// #endif
} catch (error) {
console.error('创建目录失败:', error);
throw error;
}
};
const feedbackAnswer = (params) => {
talkingList.value.forEach((t) => {
if (t.seqNo === params.askId) {
t.downvoteStat = 'Y';
t.likeStat = 'N';
}
});
};
const historyRef = ref(null);
const showMenuList = ref(false);
const showHistory = () => {
showMenuList.value = false;
historyRef.value.open();
};
const toMessage = () => {
showMenuList.value = false;
common.navigateTo('/pages/messageNotification/index');
};
const toMePage = () => {
showMenuList.value = false;
common.switchTab('/pages/me/index');
};
const showHistoryDetail = (item) => {
isHistory.value = true;
queryAskHisByBatchIdPaging({
batchId: item.reqBatch,
page: 1,
limit: 100
}).then((res) => {
console.log(res);
talkingList.value = (res.body || []).map((t, index) => {
// let _obj = JSON.parse( t.respContent)
// console.log(_obj,0)
// if(t.chatRole === 'TCH'){
// console.log(JSON.parse(_obj),1)
// }
let _text;
let _talkingCrsList;
let _talkingFiles;
if (t.chatRole === 'TCH') {
_text = t.respContentVo?.messageBuileder || '';
_talkingCrsList = t.respContentVo?.resultMap?.crsList || [];
_talkingFiles = t.respContentVo?.resultMap?.knowledgeList || [];
} else {
_text = t.respContent;
}
return {
type: t.chatRole === 'TCH' ? 'answer' : 'question',
talkingText: _text,
isLoading: false,
askId: t.askId,
seqNo: t.askId,
id: t.askId + index,
talkingVoice: '',
reqBatch: item.reqBatch,
intrctWay: '01', //01-文本;02-语音;03-图片
intrctContent: _text,
bucketKey: '',
downvoteStat: t.downvoteStat,
likeStat: t.likeStat,
talkingCrsList: _talkingCrsList,
talkingFiles: _talkingFiles,
isHistory: true
};
});
historyRef.value.close();
});
};
const routerTo = (type) => {
switch (type) {
case 'AI学':
common.switchTab('/pages/course/index');
break;
case 'AI练':
common.switchTab('/pages/sparring/index');
break;
case 'AI考':
common.navigateTo('/pages/testingHall/index');
break;
case '任务':
common.navigateTo('/pages/learningTasks/index');
break;
case '错题':
common.navigateTo('/pages/wrongQuestionRecord/index');
break;
case '去PK':
common.navigateTo('/pages/competition/index');
break;
case '分析':
common.navigateTo('/pages/analytics/study');
break;
default:
common.msg('页面建设中,敬请期待!');
break;
}
};
const touchBtnCallBack = ref(null);
const askData = ref({});
const sendText = (item) => {
submitAnswerNow(item);
};
// 发送语音
const uploadRecordNow = (voicePath) => {
// /traask/traAskchat/voiceTrans
//#ifndef APP-PLUS
// h5 假数据
// #endif
//#ifdef APP-PLUS
talkingList.value.push({
type: 'question',
talkingText: '',
isLoading: true
});
scrollToBottomNow();
commonUploadVoiceFile(voicePath, '/traask/traAskchat/voiceTrans', {})
.then((_res) => {
if (!!(_res.body.transContent || '').trim()) {
askData.value = {
reqBatch: reqBatch.value,
intrctWay: '02', //01-文本;02-语音;03-图片
intrctContent: _res.body.transContent,
bucketKey: _res.body.fileId,
ossFileAddr: _res.body.ossFileAddr,
talkingVoice: voicePath
};
sendMessage({
commond: 'ASK',
body: askData.value
});
} else {
talkingList.value.pop();
uni.showToast({
title: '未识别到文字',
icon: 'none',
duration: 1000
});
}
})
.catch((err) => {
talkingList.value.pop();
uni.showToast({
title: '系统异常,请联系管理员',
icon: 'none',
duration: 1000
});
});
// #endif
};
// 发送文本
const submitAnswerNow = (val, cb = null) => {
if (!answerIsOver.value) {
// 问题回答中
return;
}
touchBtnCallBack.value = cb;
askData.value = {
reqBatch: reqBatch.value,
intrctWay: '01', //01-文本;02-语音;03-图片
intrctContent: val,
bucketKey: ''
};
sendMessage({
commond: 'ASK',
body: askData.value
});
setHeight({height: 0})
};
const startRecordCallback = () => {
// 开始录音回调
};
const watchFlag = ref(1);
const scrolltolower = () => {
console.log('scrolltolower');
const pages = getCurrentPages();
const pageCount = pages?.length || 0;
// 处理页面数量不足的情况,此为调试时候异常情况
if (pageCount <= 1) {
common.switchTab('/pages/index/index');
return;
}
const prevPage = pages[pageCount - 2]; // 获取上一页实例并验证
// 根据上一页路由决定跳转方式
if (prevPage.route === 'pages/login/login') {
// 登录页特殊处理,如果刚好等于2说明书刚启动,里面只有登录页和当前页,这样直接返回老首页
pageCount === 2 ? common.switchTab('/pages/index/index') : common.navigateBack(2);
} else {
// 普通页面返回上一页
common.navigateBack();
}
};
onBackPress((options) => {
const from = options.from;
if (from === 'backbutton') {
// 判断上一级是否是登录,是登录就返回两层跳过登录页
const pages = getCurrentPages();
if (pages && pages.length > 1) {
const page = pages[pages.length - 2];
if (page.route === 'pages/login/login') {
if (pages.length == 2) {
common.switchTab('/pages/index/index');
} else {
common.navigateBack(2);
}
return true;
}
}
}
return false;
});
const getQuestionList = () => {
queryHotQuestionApi().then((res) => {
console.log(res);
questionList.value = res.body
.map((t) => {
return {
...t,
hotContent: t.refineContent
};
})
.filter((t) => t.refineContent);
});
};
const loadData = async () => {
userInfo.value = getUserInfo();
getQuestionList();
initsocketTask();
};
onLoad(() => {
//#ifdef APP-PLUS
plus.screen.lockOrientation('portrait-primary')
// #endif
changeAppHeightBottom();
if (!common.isLogin()) {
common.navigateTo('/pages/login/login');
return;
}
// 判断下如果没有设置吉祥物就跳转到吉祥物页面
if (userInfo.value?.mascotInfo.mascotId === null) {
//说明这人在上次选吉祥物的时候退出了,没有选到吉祥物
common.redirectTo('/pages/mascot/mascot_select_list');
return;
}
loadData();
});
const previewRef = ref();
const previewFileRef = ref();
const showPreview = ref(false);
onMounted(() => {
// previewFileRef.value.open({
// fileId: '0006e7f7-a332-4c81-9802-ac4e2d971c71'
// })
});
const refreshData = () => {
loadData();
};
const keyboardHeight = ref('0px');
const setHeight = (res) => {
keyboardHeight.value = (res.height || 0) + 'px';
};
const keyBoardIsHide = computed(() => {
return parseInt(keyboardHeight.value) == 0;
});
const bottomHeight = ref('0px');
const totalBotHeight = computed(() => {
return keyBoardIsHide.value ? 0 + 'px' : parseInt(keyboardHeight.value) - parseInt(bottomHeight.value) + 'px';
});
const changeAppHeightBottom = (height) => {
//#ifdef APP-PLUS
// 获取系统信息
const systemInfo = uni.getSystemInfoSync();
// 计算安全区域底部高度
bottomHeight.value = systemInfo.screenHeight - systemInfo.safeArea.bottom + 'px';
// #endif
};
const deleteFolder = () => {
//#ifdef APP-PLUS
plus.io.resolveLocalFileSystemURL('_doc/pdf_view', function (entry) {
console.log('entry', entry);
entry.removeRecursively(function (res) {
console.log('删除成功');
});
});
// #endif
};
//#ifdef APP-PLUS
onHide(() => {
uni.offKeyboardHeightChange(setHeight);
});
onShow(() => {
userInfo.value = getUserInfo();
uni.onKeyboardHeightChange(setHeight);
nextTick(() => {
watermarkRef.value?.updateWatermarkText();
});
});
// #endif
onUnload(() => {
watchFlag.value = 1;
deleteFolder();
socketStore?.closeSocket();
// setupKeyboardHeightListener(changeAppHeightBottom)
});
defineExpose({
refreshData
});
</script>
<style scoped lang="scss">
.index-dialog-page {
position: relative;
display: flex;
flex-direction: column;
height: 100vh;
overflow: hidden;
}
.top-bg {
background: linear-gradient(0deg, rgba(234, 246, 255, 0) 0%, #e6eafd 100%);
height: 480rpx;
width: 100%;
}
.bot-bg {
// background-color: #F6F8FF;
background: linear-gradient(136deg, rgba(234, 246, 255, 0) 0%, #fff 100%);
width: 100%;
flex: 1;
}
.index-dialog-body {
position: absolute;
overflow: hidden;
height: calc(100% - v-bind(totalBotHeight));
width: 100%;
padding: 0;
bottom: 0;
left: 0;
box-sizing: border-box;
padding-top: v-bind(pageTopPadding);
// padding-bottom: v-bind(bottomHeight);
// display: flex;
// flex-direction: column;
.body-title {
height: 90rpx;
text-align: center;
font-size: 33rpx;
padding-top: 20rpx;
line-height: 46rpx;
box-sizing: border-box;
font-weight: 500;
color: #000;
position: relative;
.top-desc{
position: absolute;
bottom: -10rpx;
font-size: 18rpx;
color: #999;
left: 50%;
transform: translateX(-50%);
}
// margin-bottom: 23rpx;
.arrow-icon {
position: absolute;
left: 36rpx;
top: 30rpx;
color: #000;
}
}
.seek-setting {
position: absolute;
z-index: 13;
right: 45rpx;
top: 8rpx;
font-size: 26rpx;
width: 140rpx;
height: 52rpx;
padding: 10rpx 0;
// overflow: hidden;
line-height: 32rpx;
text-align: right;
padding-right: 48rpx;
.more-list {
position: absolute;
top: 100%;
right: 0;
width: 100rpx;
text-align: center;
background-color: #fff;
border-radius: 12rpx;
padding: 16rpx 0;
display: none;
z-index: 21;
&.show {
display: block;
}
.more-item {
line-height: 60rpx;
font-size: 29rpx;
color: #333;
position: relative;
z-index: 22;
}
}
.image-icon {
width: 30rpx;
height: 32rpx;
position: absolute;
right: 0;
top: 10rpx;
}
.image-icon-new {
right: 50rpx;
width: 30rpx;
height: 32rpx;
position: absolute;
top: 10rpx;
}
}
.ai-info {
padding: 0 24rpx;
height: 250rpx;
overflow: hidden;
padding-top: 72rpx;
margin-bottom: 24rpx;
position: relative;
box-sizing: border-box;
.image-pet {
width: 230rpx;
// height: 235rpx;
position: absolute;
right: 24rpx;
top: -20rpx;
z-index: 2;
}
.image-pet-bg {
position: absolute;
padding: 0 24rpx;
box-sizing: border-box;
width: 100%;
height: 230rpx;
left: 0;
bottom: 0;
z-index: 2;
}
.ai-info-bg-box {
position: absolute;
z-index: 3;
left: 0;
top: 68rpx;
width: 100%;
// background-color: #ccc;
padding: 0 64rpx;
height: 178rpx;
.hello-text {
height: 54rpx;
line-height: 44rpx;
font-size: 28rpx;
color: #666;
}
.info-text {
height: 44rpx;
line-height: 44rpx;
font-size: 32rpx;
color: #000;
font-weight: 600;
}
.info-btn {
width: 220rpx;
font-size: 29rpx;
height: 54rpx;
color: #fff;
background: linear-gradient(104deg, #5547f3 0%, #4e86f4 100%);
line-height: 54rpx;
text-align: center;
border-radius: 15rpx 15rpx 0 0;
position: absolute;
left: 68rpx;
bottom: 0;
}
}
}
.questions-view {
padding-left: 24rpx;
padding-right: 24rpx;
height: 184rpx;
box-sizing: border-box;
.question-row {
white-space: nowrap;
margin-bottom: 16rpx;
}
.question-item {
white-space: nowrap;
height: 66rpx;
line-height: 66rpx;
background-color: #fff;
border: 2rpx solid #e0dede;
padding: 0 16rpx;
border-radius: 11rpx;
margin-right: 16rpx;
display: inline-block;
font-size: 26rpx;
&:last-child {
margin-right: 0;
}
}
}
.router-list {
height: 84rpx;
padding: 20rpx 30rpx 0;
background-color: #fff;
border-radius: 15rpx 15rpx 0 0;
white-space: nowrap;
box-sizing: border-box;
.btns-item {
display: inline-block;
box-sizing: border-box;
height: 62rpx;
border: 2rpx solid #e0dede;
border-radius: 15rpx;
margin-right: 16rpx;
padding: 0 20rpx 0 64rpx;
line-height: 58rpx;
font-size: 29rpx;
position: relative;
.image-icon {
position: absolute;
width: 31rpx;
height: 31rpx;
top: 50%;
transform: translateY(-50%);
left: 24rpx;
}
&:last-child {
margin-right: 0;
}
}
}
.talking-list {
height: calc(100% - 772rpx);
min-height: 300rpx;
padding: 12rpx 24rpx;
box-sizing: border-box;
min-height: 300rpx;
.talking-scroll-list {
height: 100%;
}
}
}
// .talking-list {
// height: calc(100% - 832rpx);
// padding: 12rpx 24rpx;
// box-sizing: border-box;
// .talking-scroll-list {
// height: 100%;
// }
// }
</style>