代码提交

master
wujingling0908 5 days ago
parent 6ae5fb58ca
commit f718a18c95
  1. 23
      src/components/chat-new.vue
  2. 10
      src/main.js
  3. 66
      src/store/app.js
  4. 4
      src/tests/store-smoke.test.js
  5. 4
      src/utils/common.js

@ -1,5 +1,7 @@
<script setup>
import { ref, computed, inject, watch, nextTick, onMounted, onActivated, onDeactivated } from 'vue'
import { ref, computed, watch, nextTick, onMounted, onActivated, onDeactivated } from 'vue'
import { storeToRefs } from 'pinia'
import { useAppStore } from '@/store/app.js'
import { onBeforeRouteLeave } from 'vue-router'
import { showToast, showLoadingToast, closeToast, showImagePreview } from 'vant'
import _ from 'lodash'
@ -38,18 +40,9 @@ const { isWX, tokenExist, lostChatInfoNum } = defineProps({
default: 0,
},
})
const store = inject('appStore', null)
// 直接从 pinia store 取响应式字段,避免 inject('chatArr') 在打包后拿到空默认 ref
const chatArr = computed({
get: () => store?.chatArr || [],
set: (val) => {
if (store) store.chatArr = val
},
})
const isChatLoading = computed(() => !!store?.isChatLoading)
const sessionId = computed(() => store?.sessionId || '')
const userId = computed(() => store?.userId || '')
const isLostMessage = computed(() => store?.isLostMessage ?? null)
// 与其他组件一致:直接从 Pinia 取响应式字段,避免 inject 默认空 ref 导致打包后列表不更新
const store = useAppStore()
const { chatArr, isChatLoading, sessionId, userId, isLostMessage } = storeToRefs(store)
const mainContainerRef = ref(null)
const webSocketChannel = '95460000' // 投诉直连渠道号
// mescroll 实例(非响应式)
@ -220,8 +213,8 @@ async function previewImage(item) {
const showTyping = computed(
() =>
isChatLoading.value &&
store.chatArr.length > 0 &&
store.chatArr[store.chatArr.length - 1].type === 'user',
chatArr.value.length > 0 &&
chatArr.value[chatArr.value.length - 1].type === 'user',
)
function sendText(text) {

@ -24,9 +24,9 @@ const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/
const currentHostname = window.location.hostname
const shouldShowVConsole = enableVConsoleDomains.includes(currentHostname)
// if (shouldShowVConsole || (shouldEnableVConsole && isMobile)) {
import('vconsole').then(({ default: VConsole }) => {
new VConsole()
})
import('vconsole').then(({ default: VConsole }) => {
new VConsole()
})
// }
// 根据rem单位适配
@ -41,13 +41,13 @@ function getRem(pwidth, prem) {
var oWidth = document.body.clientWidth || document.documentElement.clientWidth
// 设置最大宽度限制(例如 375px,与聊天框最大宽度保持一致)
var maxWidth = 430
var maxWidth = import.meta.env.VITE_USER_NODE_ENV === 'development' ? 375 : 430
if (oWidth > maxWidth) {
oWidth = maxWidth
}
// 可选:设置最小宽度限制
var minWidth = 320
var minWidth = import.meta.env.VITE_USER_NODE_ENV === 'development' ? 375 : 320
if (oWidth < minWidth) {
oWidth = minWidth
}

@ -362,7 +362,7 @@ export const useAppStore = defineStore('app', () => {
],
}
chatArr.value.push(message)
appendChatArr(message)
isChatLoading.value = messageType === 'user'
return message
}
@ -535,19 +535,27 @@ export const useAppStore = defineStore('app', () => {
})
}
function appendChatArr(messages) {
const list = (Array.isArray(messages) ? messages : [messages]).filter(Boolean)
if (!list.length) return
// 始终换新数组引用,避免打包后视图不刷新
chatArr.value = chatArr.value.concat(list)
}
function pushConversationMessage(payload, fallbackType = 'bot') {
const payloadList = Array.isArray(payload) ? payload : [payload]
const appended = []
let lastMessage = null
payloadList.forEach((item) => {
const message = formatConversationMessage(item, fallbackType)
if (!message) return
chatArr.value.push(message)
appended.push(message)
isChatLoading.value = message.type === 'user'
lastMessage = message
})
appendChatArr(appended)
if (fallbackType === 'bot') isChatLoading.value = false
return lastMessage
}
@ -588,7 +596,7 @@ export const useAppStore = defineStore('app', () => {
],
}
chatArr.value.push(message)
appendChatArr(message)
// 与 addSendMessageList 保持一致:记录当前发送的消息并展示上传 loading
timestamp.value = messageTimestamp
sendLoading.value = true
@ -751,17 +759,18 @@ export const useAppStore = defineStore('app', () => {
// 兼容接口偶发包一层 data
const rawItem =
typeof entry === 'object' && entry.data && !entry.msgText && !entry.answer
typeof entry === 'object' &&
entry.data &&
typeof entry.data === 'object' &&
!entry.msgText &&
!entry.answer &&
entry.fromFlag === undefined
? entry.data
: entry
const normalizedItem =
typeof rawItem === 'object'
? utils.normalizeMessage({ ...rawItem })
: { msgText: String(rawItem), fromFlag: '2', reqAndResType: '01', msgType: '01' }
// 兜底:保证 bot 文本消息有可渲染字段,避免 format 后被丢弃
if (typeof normalizedItem === 'object') {
let normalizedItem
if (typeof rawItem === 'object') {
normalizedItem = utils.normalizeMessage({ ...rawItem })
if (!normalizedItem.msgText) {
normalizedItem.msgText =
normalizedItem.answer ||
@ -770,24 +779,40 @@ export const useAppStore = defineStore('app', () => {
normalizedItem.text ||
''
}
if (normalizedItem.fromFlag === undefined || normalizedItem.fromFlag === null || normalizedItem.fromFlag === '') {
if (
normalizedItem.fromFlag === undefined ||
normalizedItem.fromFlag === null ||
normalizedItem.fromFlag === ''
) {
normalizedItem.fromFlag = '2'
}
if (!normalizedItem.reqAndResType) normalizedItem.reqAndResType = '01'
if (!normalizedItem.msgType) normalizedItem.msgType = '01'
if (!normalizedItem.timestamp) normalizedItem.timestamp = Date.now()
} else {
normalizedItem = {
msgText: String(rawItem),
fromFlag: '2',
reqAndResType: '01',
msgType: '01',
timestamp: Date.now(),
}
}
chatList.value.push(normalizedItem)
let message = formatConversationMessage(normalizedItem, 'bot')
if (!message && normalizedItem?.msgText) {
if (!message) {
const fallbackText = getConversationMessageText(normalizedItem)
if (!fallbackText && !getConversationImageSource(normalizedItem)) return
message = formatConversationMessage(
{
...normalizedItem,
...(typeof normalizedItem === 'object' ? normalizedItem : {}),
msgText: fallbackText || String(normalizedItem?.msgText || ''),
fromFlag: '2',
reqAndResType: '01',
msgType: '01',
reqAndResType: normalizedItem?.reqAndResType || '01',
msgType: normalizedItem?.msgType || '01',
timestamp: normalizedItem?.timestamp || Date.now(),
},
'bot',
)
@ -796,8 +821,7 @@ export const useAppStore = defineStore('app', () => {
})
if (appended.length) {
// 用新数组赋值,避免个别打包环境下 push 对视图更新不稳定
chatArr.value = chatArr.value.concat(appended)
appendChatArr(appended)
isChatLoading.value = false
}
@ -813,8 +837,8 @@ export const useAppStore = defineStore('app', () => {
}
function delAllChatList() {
chatList.value.splice(0, chatList.value.length)
chatArr.value.splice(0, chatArr.value.length)
chatList.value = []
chatArr.value = []
isChatLoading.value = false
}

@ -1,8 +1,8 @@
import { describe, it, expect } from 'vitest'
import { createPinia, setActivePinia } from 'pinia'
import { useAppStore } from '@/store/index.js'
import { useAppStore } from '@/store/app.js'
describe('store/index.js smoke', () => {
describe('store/app.js smoke', () => {
it('初始化并调用 camelCase setter', () => {
setActivePinia(createPinia())
const store = useAppStore()

@ -106,13 +106,13 @@ export function setFontScale(fontSize) {
var oWidth = document.body.clientWidth || document.documentElement.clientWidth
// 设置最大宽度限制(例如 375px,与聊天框最大宽度保持一致)
var maxWidth = 430
var maxWidth = import.meta.env.VITE_USER_NODE_ENV === 'development' ? 375 : 430
if (oWidth > maxWidth) {
oWidth = maxWidth
}
// 可选:设置最小宽度限制
var minWidth = 320
var minWidth = import.meta.env.VITE_USER_NODE_ENV === 'development' ? 375 : 320
if (oWidth < minWidth) {
oWidth = minWidth
}

Loading…
Cancel
Save