fix: 修复背景聊天消失和修复返回
This commit is contained in:
parent
258eb17281
commit
70625f6ea1
14
.vscode/launch.json
vendored
Normal file
14
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Debug h5",
|
||||||
|
"type": "chrome",
|
||||||
|
"runtimeArgs": ["--remote-debugging-port=9222"],
|
||||||
|
"request": "launch",
|
||||||
|
"url": "http://localhost:5173",
|
||||||
|
"webRoot": "${workspaceFolder}",
|
||||||
|
"preLaunchTask": "uni:h5"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
16
.vscode/tasks.json
vendored
Normal file
16
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "uni:h5",
|
||||||
|
"type": "npm",
|
||||||
|
"script": "dev --devtools",
|
||||||
|
"isBackground": true,
|
||||||
|
"problemMatcher": "$vite",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -9,6 +9,8 @@ import 'element-plus/dist/index.css'
|
|||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import { prototypeInterceptor, requestInterceptor, routeInterceptor } from './interceptors'
|
import { prototypeInterceptor, requestInterceptor, routeInterceptor } from './interceptors'
|
||||||
import store from './store'
|
import store from './store'
|
||||||
|
// import VConsole from 'vconsole'
|
||||||
|
// new VConsole()
|
||||||
|
|
||||||
export function createApp() {
|
export function createApp() {
|
||||||
const app = createSSRApp(App)
|
const app = createSSRApp(App)
|
||||||
|
@ -10,18 +10,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col h-screen bg-gray-50">
|
<div class="flex flex-col h-screen bg-gray-50">
|
||||||
<!-- Navigation Bar -->
|
<!-- Navigation Bar -->
|
||||||
<div class="flex-none flex items-center justify-between px-5 py-3 bg-white shadow-md h-10">
|
<div
|
||||||
|
class="flex-none flex items-center justify-between px-5 py-3 bg-white shadow-md h-10 pt-10 z-999"
|
||||||
|
>
|
||||||
<image src="/static/aichat/back.png" class="w-2 h-4" @click="goBack" />
|
<image src="/static/aichat/back.png" class="w-2 h-4" @click="goBack" />
|
||||||
<div class="text-lg font-medium">小墨</div>
|
<div class="text-lg font-medium ml-12">小墨</div>
|
||||||
<div class="flex items-center space-x-3">
|
<div class="flex items-center space-x-3">
|
||||||
<!-- v-if="rawList.length > 0" -->
|
<!-- v-if="rawList.length > 0" -->
|
||||||
<image src="/static/aichat/time.png" class="w-5 h-5" @click="openPopup" />
|
<image src="/static/aichat/time.png" class="w-5 h-5 mr-4" @click="openPopup" />
|
||||||
<image src="/static/aichat/new.png" class="w-5 h-5" @click="newChat" />
|
<image src="/static/aichat/new.png" class="w-5 h-5" @click="newChat" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 消息区 -->
|
<!-- 消息区 -->
|
||||||
<div :class="['flex relative', showActions ? 'h-105' : 'h-130']">
|
<div
|
||||||
|
:class="[
|
||||||
|
'flex relative p-b-10',
|
||||||
|
showActions ? (uploadList.length ? 'h-118' : 'h-137') : 'h-157',
|
||||||
|
]"
|
||||||
|
>
|
||||||
<!-- 背景层 -->
|
<!-- 背景层 -->
|
||||||
<div
|
<div
|
||||||
v-if="!messages.length"
|
v-if="!messages.length"
|
||||||
@ -171,7 +177,7 @@
|
|||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<!-- 上传列表 -->
|
<!-- 上传列表 -->
|
||||||
<div v-if="uploadList.length" class="flex px-4 py-2 overflow-x-auto space-x-3 bg-#f9fafb">
|
<div v-if="uploadList.length" class="flex px-4 py-2 overflow-x-auto space-x-3 bg-transparent">
|
||||||
<div
|
<div
|
||||||
v-for="item in uploadList"
|
v-for="item in uploadList"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
@ -233,7 +239,15 @@
|
|||||||
placeholder="想对我说点什么~"
|
placeholder="想对我说点什么~"
|
||||||
class="flex-1 h-10 px-3 border border-gray-100 bg-[#f9f9f9] rounded-full focus:outline-none"
|
class="flex-1 h-10 px-3 border border-gray-100 bg-[#f9f9f9] rounded-full focus:outline-none"
|
||||||
/>
|
/>
|
||||||
<image src="/static/aichat/add-circle.png" class="w-7 h-7 mx-3" @click="toggleActions" />
|
<image
|
||||||
|
src="/static/aichat/add-circle.png"
|
||||||
|
class="w-7 h-7 mx-3"
|
||||||
|
@click="toggleActions"
|
||||||
|
:style="{
|
||||||
|
transform: `rotate(${rotation}deg)`,
|
||||||
|
transition: 'transform 0.3s ease',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
<image
|
<image
|
||||||
src="/static/aichat/enter.png"
|
src="/static/aichat/enter.png"
|
||||||
class="w-7 h-7"
|
class="w-7 h-7"
|
||||||
@ -336,11 +350,10 @@ interface IMessage {
|
|||||||
content: string | any[]
|
content: string | any[]
|
||||||
timestamp: Date
|
timestamp: Date
|
||||||
}
|
}
|
||||||
const assistantAvatar =
|
const userAvatar = ref('')
|
||||||
'https://dci-file-new.bj.bcebos.com/fonchain-main/test/runtime/image/avatar/40/b8ed6fea-6662-416d-8bb3-1fd8a8197061.jpg'
|
|
||||||
const userAvatar = assistantAvatar
|
|
||||||
const baseUrl = getEnvBaseUrl()
|
const baseUrl = getEnvBaseUrl()
|
||||||
const token = useUserStore().userInfo.token || import.meta.env.VITE_DEV_TOKEN || ''
|
// const token = useUserStore().userInfo.token || import.meta.env.VITE_DEV_TOKEN || ''
|
||||||
const messages = reactive<IMessage[]>([])
|
const messages = reactive<IMessage[]>([])
|
||||||
//获取用户上下文
|
//获取用户上下文
|
||||||
const historyUserMsgs = reactive<any[]>([])
|
const historyUserMsgs = reactive<any[]>([])
|
||||||
@ -365,7 +378,8 @@ const MAX_CONCURRENT_UPLOADS = 6
|
|||||||
const showPopup = ref(false)
|
const showPopup = ref(false)
|
||||||
const fullscreen = ref(false)
|
const fullscreen = ref(false)
|
||||||
|
|
||||||
function openPopup() {
|
async function openPopup() {
|
||||||
|
await fetchHistoryList()
|
||||||
showPopup.value = true
|
showPopup.value = true
|
||||||
}
|
}
|
||||||
function closePopup() {
|
function closePopup() {
|
||||||
@ -407,33 +421,120 @@ const groups = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 点击历史记录条目,跳转聊天页面
|
// 点击历史记录条目,跳转聊天页面
|
||||||
function goChat(listUuid: string) {
|
async function goChat(listUuid: string) {
|
||||||
uni.navigateTo({ url: `/pages/chat/index?listUuid=${listUuid}` })
|
await fetchHistoryDiets(listUuid)
|
||||||
|
showPopup.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------
|
/** 1. 创建聊天会话 */
|
||||||
// 拉取历史记录接口(替换为你自己的 API)
|
const listUuid = ref('')
|
||||||
// ------------------
|
|
||||||
onMounted(async () => {
|
|
||||||
const body = {
|
|
||||||
page: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
async function createChatSession() {
|
||||||
try {
|
try {
|
||||||
const resp: any = await uni.request({
|
const createResp: any = await uni.request({
|
||||||
url: `${baseUrl}/chat/list`,
|
url: `${baseUrl}/chat/create`,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: body,
|
data: {
|
||||||
|
gptModel: 'gpt-3.5-turbo',
|
||||||
|
},
|
||||||
header: {
|
header: {
|
||||||
Authorization: token,
|
Authorization: token,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
// 如果后台返回新的会话信息,可以在这里处理,比如拿到 listUuid 等
|
||||||
|
console.log('createChatSession →', createResp)
|
||||||
|
listUuid.value = createResp.data.data.listUuid
|
||||||
|
} catch (err) {
|
||||||
|
console.error('createChatSession error:', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ------------------
|
||||||
|
// 拉取历史记录接口(替换为你自己的 API)
|
||||||
|
// ------------------
|
||||||
|
|
||||||
if (resp.data.data) {
|
/** 2. 拉取历史记录列表 */
|
||||||
rawList.value = resp.data.data
|
async function fetchHistoryList() {
|
||||||
|
try {
|
||||||
|
const resp: any = await uni.request({
|
||||||
|
url: `${baseUrl}/chat/list`,
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
page: 1,
|
||||||
|
pageSize: 30,
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
Authorization: token,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if (resp.data && resp.data.data) {
|
||||||
|
rawList.value = resp.data.data.data
|
||||||
|
console.log('fetchHistoryList →', rawList.value)
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (err) {
|
||||||
|
console.error('fetchHistoryList error:', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** 3. 拉取历史记录详情 */
|
||||||
|
|
||||||
|
async function fetchHistoryDiets(value) {
|
||||||
|
try {
|
||||||
|
const resp: any = await uni.request({
|
||||||
|
url: `${baseUrl}/chat/detail`,
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
listUuid: value,
|
||||||
|
gptModel: 'gpt-3.5-turbo',
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
Authorization: token,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if (resp.data) {
|
||||||
|
rawList.value = resp.data
|
||||||
|
console.log('fetchHistoryLisssst →', rawList.value)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('fetchHistoryList error:', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const token = ref<string>('')
|
||||||
|
const userInfo = ref<any>({})
|
||||||
|
const refreshToken = ref<string>('')
|
||||||
|
const statusBarHeight = ref<number>(0)
|
||||||
|
const mask = ref('')
|
||||||
|
// ---- 页面初始化 ----
|
||||||
|
onMounted(() => {
|
||||||
|
// 1. 定义一个 init 函数,拿 Extras 并依次调用接口
|
||||||
|
const init = async () => {
|
||||||
|
// plusready 后才能用 plus.webview
|
||||||
|
const wv = plus.webview.currentWebview()
|
||||||
|
token.value = wv.token || uni.getStorageSync('token')
|
||||||
|
userInfo.value = JSON.parse(wv.userInfo) || {}
|
||||||
|
refreshToken.value = wv.refreshToken || uni.getStorageSync('refreshToken')
|
||||||
|
statusBarHeight.value = wv.statusBarHeight || uni.getSystemInfoSync().statusBarHeight
|
||||||
|
userAvatar.value = userInfo.value.Avatar
|
||||||
|
mask.value = userInfo.value.ID
|
||||||
|
await createChatSession()
|
||||||
|
await fetchHistoryList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 如果在 Plus 环境里,等 plusready
|
||||||
|
if (window.plus && plus.webview) {
|
||||||
|
document.addEventListener('plusready', init, false)
|
||||||
|
// plusready 可能已经触发过,直接再调用一次以防万一
|
||||||
|
if (plus.webview.currentWebview()) {
|
||||||
|
init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 3. 普通 H5 调试,直接从 storage/SystemInfo 拿
|
||||||
|
else {
|
||||||
|
token.value = uni.getStorageSync('token')
|
||||||
|
userInfo.value = uni.getStorageSync('userInfo')
|
||||||
|
refreshToken.value = uni.getStorageSync('refreshToken')
|
||||||
|
statusBarHeight.value = uni.getSystemInfoSync().statusBarHeight
|
||||||
|
|
||||||
|
createChatSession().then(fetchHistoryList)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
function scrollToBottom() {
|
function scrollToBottom() {
|
||||||
@ -479,18 +580,21 @@ const formatDayGroup = (d: Date) => dayjs(d).format('YYYY/MM/DD HH:mm')
|
|||||||
const formatTimeShort = (d: Date) => dayjs(d).format('MM/DD HH:mm')
|
const formatTimeShort = (d: Date) => dayjs(d).format('MM/DD HH:mm')
|
||||||
|
|
||||||
function goBack() {
|
function goBack() {
|
||||||
window.history.back()
|
const wv = plus.webview.currentWebview()
|
||||||
|
wv.close('slide-out-right', 300) // 或者直接 wv.close()
|
||||||
}
|
}
|
||||||
function viewHistory() {
|
function viewHistory() {
|
||||||
uni.navigateTo({ url: '/pages/history/history' })
|
uni.navigateTo({ url: '/pages/history/history' })
|
||||||
}
|
}
|
||||||
function newChat() {
|
async function newChat() {
|
||||||
messages.splice(0)
|
messages.splice(0)
|
||||||
|
await createChatSession()
|
||||||
inputText.value = ''
|
inputText.value = ''
|
||||||
}
|
}
|
||||||
|
const rotation = ref(0)
|
||||||
function toggleActions() {
|
function toggleActions() {
|
||||||
showActions.value = !showActions.value
|
showActions.value = !showActions.value
|
||||||
|
rotation.value += 45
|
||||||
scrollToBottom()
|
scrollToBottom()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,7 +610,7 @@ const uploadConfig = reactive({
|
|||||||
url: 'http://114.218.158.24:9020/upload/img',
|
url: 'http://114.218.158.24:9020/upload/img',
|
||||||
formData: {
|
formData: {
|
||||||
source: 'chat',
|
source: 'chat',
|
||||||
mask: '2076',
|
mask: mask.value,
|
||||||
type: uploadFileTypeEm.image,
|
type: uploadFileTypeEm.image,
|
||||||
},
|
},
|
||||||
image: {
|
image: {
|
||||||
@ -827,6 +931,7 @@ async function sendText(msg) {
|
|||||||
model: 'gpt-4-vision-preview',
|
model: 'gpt-4-vision-preview',
|
||||||
max_tokens: 1000,
|
max_tokens: 1000,
|
||||||
temperature: 1,
|
temperature: 1,
|
||||||
|
listUuid: listUuid.value,
|
||||||
top_p: 1,
|
top_p: 1,
|
||||||
presence_penalty: 0,
|
presence_penalty: 0,
|
||||||
frequency_penalty: 0,
|
frequency_penalty: 0,
|
||||||
@ -835,6 +940,8 @@ async function sendText(msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
aiMsg.content = ''
|
||||||
|
|
||||||
const resp = await fetch(baseUrl + '/chat/completion', {
|
const resp = await fetch(baseUrl + '/chat/completion', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json', Authorization: token },
|
headers: { 'Content-Type': 'application/json', Authorization: token },
|
||||||
@ -854,7 +961,7 @@ async function sendText(msg) {
|
|||||||
buffer = parts.pop()!
|
buffer = parts.pop()!
|
||||||
for (const part of parts) {
|
for (const part of parts) {
|
||||||
scrollToBottom()
|
scrollToBottom()
|
||||||
console.log('1')
|
console.log('1', aiMsg.content)
|
||||||
const chunk = part.trim()
|
const chunk = part.trim()
|
||||||
if (chunk === '[DONE]') {
|
if (chunk === '[DONE]') {
|
||||||
done = true
|
done = true
|
||||||
@ -889,8 +996,16 @@ async function sendText(msg) {
|
|||||||
|
|
||||||
function copyText(msg: IMessage) {
|
function copyText(msg: IMessage) {
|
||||||
if (typeof msg.content === 'string') {
|
if (typeof msg.content === 'string') {
|
||||||
navigator.clipboard.writeText(msg.content)
|
uni.setClipboardData({
|
||||||
alert('已复制')
|
data: msg.content,
|
||||||
|
success() {
|
||||||
|
uni.showToast({ title: '已复制', icon: 'success' })
|
||||||
|
},
|
||||||
|
fail(err) {
|
||||||
|
console.error('复制失败', err)
|
||||||
|
uni.showToast({ title: '复制失败', icon: 'error' })
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ export interface IGptRequestBody {
|
|||||||
max_tokens: number
|
max_tokens: number
|
||||||
temperature: number
|
temperature: number
|
||||||
top_p: number
|
top_p: number
|
||||||
|
listUuid: string
|
||||||
presence_penalty: number
|
presence_penalty: number
|
||||||
frequency_penalty: number
|
frequency_penalty: number
|
||||||
messages: IMessage[]
|
messages: IMessage[]
|
||||||
|
Loading…
Reference in New Issue
Block a user