|
@ -1,87 +1,105 @@ |
|
|
<script setup> |
|
|
<script setup> |
|
|
import { ref, nextTick, watch, onMounted } from 'vue' |
|
|
import { ref, nextTick, watch, onMounted } from 'vue' |
|
|
import { useUserInfo } from '../store/userPermissionCode' |
|
|
import { useUserInfo } from '../store/userPermissionCode' |
|
|
import axios from 'axios' |
|
|
|
|
|
import { ElMessage } from 'element-plus'; |
|
|
|
|
|
import { Loading, Position } from '@element-plus/icons-vue'; // 引入图标组件 |
|
|
|
|
|
import { marked } from 'marked'; // 引入marked库 |
|
|
import { marked } from 'marked'; // 引入marked库 |
|
|
import katex from 'katex'; // 引入 KaTeX 库 |
|
|
import katex from 'katex'; // 引入 KaTeX 库 |
|
|
import 'katex/dist/katex.min.css'; // 引入 KaTeX 样式 |
|
|
import 'katex/dist/katex.min.css'; // 引入 KaTeX 样式 |
|
|
|
|
|
|
|
|
const { getQueryVariable,getSessionId,fetchUserInfo,loading,isReady } = useUserInfo() |
|
|
|
|
|
|
|
|
import { newSessionAPI, codeAPI,dataListAPI } from '../api/sword' |
|
|
|
|
|
const { getQueryVariable, getSessionId, fetchUserInfo, isReady, |
|
|
|
|
|
brainPermission, // 从 brainPerssion 修正 |
|
|
|
|
|
swordPermission, |
|
|
|
|
|
pricePermission, |
|
|
|
|
|
timePermission, |
|
|
|
|
|
aibullPermission, |
|
|
|
|
|
aiGnbullPermission, |
|
|
|
|
|
airadarPermission, |
|
|
|
|
|
aiGoldMarketList, } = useUserInfo() |
|
|
|
|
|
|
|
|
|
|
|
// 错误信息 |
|
|
const errorMsg = ref('') |
|
|
const errorMsg = ref('') |
|
|
|
|
|
|
|
|
|
|
|
// token校验 |
|
|
const isTokenValid = ref(false) |
|
|
const isTokenValid = ref(false) |
|
|
|
|
|
// 创建对话校验 |
|
|
|
|
|
const isSessionValid = ref(false) |
|
|
|
|
|
// 获取token |
|
|
const fnGetToken = () => { |
|
|
const fnGetToken = () => { |
|
|
localStorage.setItem('localToken', decodeURIComponent(String(getQueryVariable('token')))) |
|
|
localStorage.setItem('localToken', decodeURIComponent(String(getQueryVariable('token')))) |
|
|
// console.log(localStorage.getItem('localToken')); |
|
|
// console.log(localStorage.getItem('localToken')); |
|
|
} |
|
|
} |
|
|
|
|
|
// 定时调用 |
|
|
setTimeout(() => { |
|
|
setTimeout(() => { |
|
|
fnGetToken() |
|
|
fnGetToken() |
|
|
}, 800) |
|
|
}, 800) |
|
|
|
|
|
|
|
|
// 验证 token |
|
|
// 验证 token |
|
|
const validateToken = async () => { |
|
|
const validateToken = async () => { |
|
|
const token = localStorage.getItem('localToken') |
|
|
const token = localStorage.getItem('localToken') |
|
|
// console.log('token', token); |
|
|
|
|
|
|
|
|
// 判断token是否存在 |
|
|
if (!token) { |
|
|
if (!token) { |
|
|
console.error('未找到 token,请重新登录') |
|
|
console.error('未找到 token,请重新登录') |
|
|
errorMsg.value = '用户未登录' |
|
|
errorMsg.value = '用户未登录' |
|
|
return false |
|
|
return false |
|
|
} |
|
|
} |
|
|
// 如果token验证通过,获取权限 |
|
|
|
|
|
|
|
|
// 如果token存在,获取权限 |
|
|
await fetchUserInfo(); |
|
|
await fetchUserInfo(); |
|
|
console.log('loading', loading.value); |
|
|
|
|
|
if(!isReady.value){ |
|
|
|
|
|
|
|
|
if (!isReady.value) { |
|
|
|
|
|
console.log('token校验失败,请重新登录') |
|
|
errorMsg.value = 'token 验证失败' |
|
|
errorMsg.value = 'token 验证失败' |
|
|
return false |
|
|
|
|
|
|
|
|
return false |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return true |
|
|
return true |
|
|
} |
|
|
} |
|
|
// 创建新对话 |
|
|
// 创建新对话 |
|
|
const sessionId = ref(localStorage.getItem('sessionId') || {}); |
|
|
|
|
|
|
|
|
// 客服对话sessionId |
|
|
|
|
|
const sessionSessionId = ref(localStorage.getItem('sessionSessionId') || {}); |
|
|
|
|
|
// 获取用户问题中股票代码的对话的sessionId |
|
|
|
|
|
const codeSessionId = ref(localStorage.getItem('codeSessionId') || {}); |
|
|
|
|
|
|
|
|
const add = async () => { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const createNewSessionSession = async () => { |
|
|
try { |
|
|
try { |
|
|
const result = await axios.post( |
|
|
|
|
|
"http://whi3s4.natappfree.cc/api/v1/chats/8b37cd9cf0c811efa4210242ac120003/completions", |
|
|
|
|
|
{}, |
|
|
|
|
|
{ |
|
|
|
|
|
headers: { |
|
|
|
|
|
'Content-Type': 'application/json', |
|
|
|
|
|
Authorization: 'Bearer ragflow-hkNjEwYjcwZjBlMDExZWZiYjYzMDI0Mm' |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
); |
|
|
|
|
|
const data = result.data; |
|
|
|
|
|
console.log(data); |
|
|
|
|
|
console.log(data, 'data11111111'); |
|
|
|
|
|
// 判断 data 是否为空 |
|
|
|
|
|
if (Object.keys(data).length === 0) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
// 假设 getSessionId 函数已经正确定义 |
|
|
|
|
|
const sss = String(getSessionId("session_id", data)); |
|
|
|
|
|
sessionId.value = sss; |
|
|
|
|
|
localStorage.setItem('sessionId', sss); |
|
|
|
|
|
console.log('sss', sss); |
|
|
|
|
|
|
|
|
// 调用创建新对话的API |
|
|
|
|
|
const sessionResult = await newSessionAPI({ token: localStorage.getItem('localToken') }); |
|
|
|
|
|
// 处理返回的数据,获取session_id |
|
|
|
|
|
const sessionData = sessionResult.data; |
|
|
|
|
|
console.log(sessionData, 'sessionData'); |
|
|
|
|
|
// 假设 getSessionId 函数已经正确定义,获取session_id |
|
|
|
|
|
sessionSessionId.value = String(sessionData.sessionId); |
|
|
|
|
|
codeSessionId.value = String(sessionData.codeSessionId); |
|
|
|
|
|
// 将session_id存储到localStorage中 |
|
|
|
|
|
localStorage.setItem('sessionSessionId', sessionSessionId.value); |
|
|
|
|
|
localStorage.setItem('codeSessionId', codeSessionId.value); |
|
|
|
|
|
// 打印session_id |
|
|
|
|
|
console.log('session_session_id:', sessionSessionId.value); |
|
|
|
|
|
console.log('code_session_id:', codeSessionId.value); |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
console.log("请求失败", error); |
|
|
console.log("请求失败", error); |
|
|
ElMessage.error("添加失败,请检查输入内容是否正确"); |
|
|
|
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|
// 页面加载时验证 token |
|
|
|
|
|
validateToken().then((isValid) => { |
|
|
|
|
|
isTokenValid.value = isValid |
|
|
|
|
|
if (isValid) { |
|
|
|
|
|
console.log('Token 验证成功') |
|
|
|
|
|
if (!localStorage.getItem('sessionId')) { |
|
|
|
|
|
console.log('没有sessionId,创建新对话') |
|
|
|
|
|
add() |
|
|
|
|
|
|
|
|
// 页面加载时如果token验证通过,创建新对话 |
|
|
|
|
|
const createNewSession = async () => { |
|
|
|
|
|
try { |
|
|
|
|
|
if (isTokenValid.value) { |
|
|
|
|
|
console.log('Token 验证成功') |
|
|
|
|
|
if (!localStorage.getItem('sessionSessionId')) { |
|
|
|
|
|
console.log('没有sessionSessionId,创建新对话') |
|
|
|
|
|
await createNewSessionSession() |
|
|
|
|
|
} |
|
|
|
|
|
if (!localStorage.getItem('codeSessionId')) { |
|
|
|
|
|
console.log('没有codeSessionId,创建新对话') |
|
|
|
|
|
} |
|
|
|
|
|
if (localStorage.getItem('sessionSessionId') && localStorage.getItem('codeSessionId')) { |
|
|
|
|
|
isSessionValid.value = true |
|
|
|
|
|
console.log('sessionSessionId和codeSessionId都存在,对话创建成功') |
|
|
|
|
|
} else { |
|
|
|
|
|
errorMsg.value = '对话创建失败' |
|
|
|
|
|
console.log('sessionSessionId或codeSessionId不存在,对话创建失败') |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
console.error(error); |
|
|
} |
|
|
} |
|
|
}) |
|
|
|
|
|
|
|
|
} |
|
|
// 定义Props(可配置参数) |
|
|
// 定义Props(可配置参数) |
|
|
const props = defineProps({ |
|
|
const props = defineProps({ |
|
|
apiUrl: { |
|
|
apiUrl: { |
|
@ -119,7 +137,7 @@ const sendMessage = async () => { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
if (isLoading.value) return; |
|
|
if (isLoading.value) return; |
|
|
const content = inputMessage.value.trim(); |
|
|
|
|
|
|
|
|
let content = inputMessage.value.trim(); |
|
|
if (!content) return; |
|
|
if (!content) return; |
|
|
// 添加用户消息 |
|
|
// 添加用户消息 |
|
|
messages.value.push({ |
|
|
messages.value.push({ |
|
@ -142,16 +160,96 @@ const sendMessage = async () => { |
|
|
scrollToBottom(); |
|
|
scrollToBottom(); |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
// 调用API获取回复 |
|
|
|
|
|
const response = await fetch("http://whi3s4.natappfree.cc/api/v1/chats/8b37cd9cf0c811efa4210242ac120003/completions", { |
|
|
|
|
|
|
|
|
// 调用API判断问题类型并提取股票代码 |
|
|
|
|
|
const judgeCode = await fetch("http://192.168.1.162/api/v1/chats/d107d300f38211ef93e60242ac120003/completions", { |
|
|
method: 'POST', |
|
|
method: 'POST', |
|
|
headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ragflow-hkNjEwYjcwZjBlMDExZWZiYjYzMDI0Mm' }, |
|
|
headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ragflow-hkNjEwYjcwZjBlMDExZWZiYjYzMDI0Mm' }, |
|
|
body: JSON.stringify({ question: content, stream: true, session_id: sessionId.value }) // 设置 stream 为 true |
|
|
|
|
|
|
|
|
body: JSON.stringify({ question: content, stream: true, session_id: codeSessionId.value }) // 设置 stream 为 true |
|
|
}); |
|
|
}); |
|
|
if (!response.ok) { |
|
|
|
|
|
throw new Error(`HTTP error! status: ${response.status}`); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 处理API返回的数据 |
|
|
|
|
|
const judgeCodeData = judgeCode.body.getReader(); |
|
|
|
|
|
const judegeDecoer = new TextDecoder('utf-8'); |
|
|
|
|
|
let judgepartialData = ''; |
|
|
|
|
|
let prevJudgeData = null; // 倒数第二条数据 |
|
|
|
|
|
let lastJudgeData = null; // 最后一条数据 |
|
|
|
|
|
|
|
|
|
|
|
while (true) { |
|
|
|
|
|
const { done, value } = await judgeCodeData.read(); |
|
|
|
|
|
if (done) { |
|
|
|
|
|
if (judgepartialData) { |
|
|
|
|
|
const lines = judgepartialData.split('\n'); |
|
|
|
|
|
for (const line of lines) { |
|
|
|
|
|
if (line.startsWith('data:')) { |
|
|
|
|
|
prevJudgeData = lastJudgeData; // 更新倒数第二条 |
|
|
|
|
|
lastJudgeData = JSON.parse(line.slice(5)); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
judgepartialData += judegeDecoer.decode(value); |
|
|
|
|
|
|
|
|
|
|
|
const lines = judgepartialData.split('\n'); |
|
|
|
|
|
judgepartialData = lines.pop(); |
|
|
|
|
|
|
|
|
|
|
|
for (const line of lines) { |
|
|
|
|
|
if (line.startsWith('data:')) { |
|
|
|
|
|
try { |
|
|
|
|
|
prevJudgeData = lastJudgeData; // 将当前最后一条设为倒数第二条 |
|
|
|
|
|
lastJudgeData = JSON.parse(line.slice(5)); |
|
|
|
|
|
console.log('倒数第二条:', prevJudgeData); |
|
|
|
|
|
console.log('最新数据:', lastJudgeData); |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
console.error('JSON解析错误:', e); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
console.log('最后接收的数据:', prevJudgeData.data.answer); // 输出最终数据 |
|
|
|
|
|
|
|
|
|
|
|
const params = ref({}); |
|
|
|
|
|
const codeRegex = /<think>([\s\S]*?)<\/think>([\s\S]*)/; |
|
|
|
|
|
const codeMatch = prevJudgeData.data.answer.match(codeRegex); |
|
|
|
|
|
let answer = prevJudgeData.data.answer; |
|
|
|
|
|
if (codeMatch) { |
|
|
|
|
|
answer = codeMatch[2].trim(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const codes = answer.split(','); |
|
|
|
|
|
if (codes[0] === 'true') { |
|
|
|
|
|
params.value.market = codes[1]; |
|
|
|
|
|
params.value.code = codes[2]; |
|
|
|
|
|
params.value.token = localStorage.getItem('localToken'); |
|
|
|
|
|
params.value.brainPrivilegeState = brainPermission; // 从 brainPerssion 修正 |
|
|
|
|
|
params.value.swordPrivilegeState = swordPermission; |
|
|
|
|
|
params.value.stockForecastPrivilegeState = pricePermission; |
|
|
|
|
|
params.value.spaceForecastPrivilegeState = timePermission; |
|
|
|
|
|
params.value.aibullPrivilegeState = aibullPermission; |
|
|
|
|
|
params.value.aigoldBullPrivilegeState = aiGnbullPermission; |
|
|
|
|
|
params.value.airadarPrivilegeState = airadarPermission; |
|
|
|
|
|
params.value.marketList = aiGoldMarketList; |
|
|
|
|
|
|
|
|
|
|
|
// 调用API获取夺宝奇兵数据 |
|
|
|
|
|
|
|
|
|
|
|
const dataList=await dataListAPI(params.value); |
|
|
|
|
|
|
|
|
|
|
|
const dataListData = JSON.stringify(dataList.data); |
|
|
|
|
|
console.log(dataListData,'dataListData'); |
|
|
|
|
|
|
|
|
|
|
|
content=content+'请结合下方夺宝奇兵的数据,成体系,有表格的回答'+dataListData; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 调用API获取回复 |
|
|
|
|
|
const response = await fetch("http://192.168.1.162/api/v1/chats/8b37cd9cf0c811efa4210242ac120003/completions", { |
|
|
|
|
|
method: 'POST', |
|
|
|
|
|
headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ragflow-hkNjEwYjcwZjBlMDExZWZiYjYzMDI0Mm' }, |
|
|
|
|
|
body: JSON.stringify({ question: content, stream: true, session_id: sessionSessionId.value }) // 设置 stream 为 true |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
// 移除加载消息 |
|
|
// 移除加载消息 |
|
|
messages.value = messages.value.filter(msg => !msg.isLoading); |
|
|
messages.value = messages.value.filter(msg => !msg.isLoading); |
|
|
|
|
|
|
|
@ -257,8 +355,11 @@ onMounted(async () => { |
|
|
// 先获取 token |
|
|
// 先获取 token |
|
|
fnGetToken() |
|
|
fnGetToken() |
|
|
// 再验证 token |
|
|
// 再验证 token |
|
|
const isValid = await validateToken() |
|
|
|
|
|
isTokenValid.value = isValid |
|
|
|
|
|
|
|
|
isTokenValid.value = await validateToken() |
|
|
|
|
|
// 存储codeSessionId |
|
|
|
|
|
localStorage.setItem('codeSessionId', codeSessionId.value); |
|
|
|
|
|
await createNewSession() |
|
|
|
|
|
|
|
|
}) |
|
|
}) |
|
|
</script> |
|
|
</script> |
|
|
<template> |
|
|
<template> |
|
@ -310,8 +411,8 @@ onMounted(async () => { |
|
|
</el-tooltip> |
|
|
</el-tooltip> |
|
|
</div> |
|
|
</div> |
|
|
<!-- 未登录覆盖层 --> |
|
|
<!-- 未登录覆盖层 --> |
|
|
<div v-if="!isTokenValid" class="overlay"> |
|
|
|
|
|
<div class="overlay-content">{{errorMsg}}</div> |
|
|
|
|
|
|
|
|
<div v-if="!isTokenValid || !isSessionValid" class="overlay"> |
|
|
|
|
|
<div class="overlay-content">{{ errorMsg }}</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</template> |
|
|
</template> |
|
|