import { defineStore } from 'pinia' import { ref } from 'vue' import { fetchPost, upLoadImgHttp } from '@/utils/https' import wsConnection from '@/utils/socket' import FormatDate from '@/utils/filters' import utils from '@/utils/utils' import { Decryption, DecryptionECB, Encrypt } from '@/utils' import _ from 'lodash' import { postConversation, sendRobotMessage, sendVoiceMessage, uploadConversationImage, connectHumanService, updateReadMessages, submitUserBehavior, submitSatisfaction, loadSystemConfig, loadHeaderAvatar, loadTipsConfig, } from '@/utils/conversationApi' // 幂等键统一采用用户消息前缀,便于和后端日志对齐排查。 const createIdempotentKey = () => `user_msg_${Date.now()}` export const UPDATE_DIRECTION = 'UPDATE_DIRECTION' // —— 模块级初始值(加 initial 前缀,避免与 setup 内同名 ref 产生 TDZ/遮蔽问题)—— const initialToken = sessionStorage.token ? sessionStorage.token : '' const initialUserId = localStorage.userId ? localStorage.userId : '' const initialSource = localStorage.source ? localStorage.source : '' const initialPlanCode = localStorage.planCode ? localStorage.planCode : '' const initialEntrance = localStorage.entrance ? localStorage.entrance : '' // 取到身份证后解密 const initialUserInfo = localStorage.userInfo ? JSON.parse(localStorage.userInfo) : {} // try { // if(!!userInfo.versionNo1){ // const year = new Date().getFullYear() // const versionNo1 = DecryptionECB(`${year}${year}${year}${year}`,userInfo.versionNo1) // const key = versionNo1.substring(0, 16) // const iv = versionNo1.substring(16, 32) // if (!!userInfo.encryptPhone) { // userInfo.decryptPhone = Decryption(key,iv,userInfo.encryptPhone) // } // if (!!userInfo.idnum) { // userInfo.idnum = Decryption(key,iv,userInfo.idnum) // console.log("取到后解密====", userInfo.idnum) // } // } // } catch (error) { } const initialConfigId = localStorage.configId ? localStorage.configId : '' const initialSessionId = localStorage.sessionId ? localStorage.sessionId : '' const initialHtmlExtParams = localStorage.htmlExtParams ? localStorage.htmlExtParams : '' const initialComplaint = localStorage.complaint ? localStorage.complaint : '' const initialNavigationCorpus = localStorage.navigationCorpus ? localStorage.navigationCorpus : '' const initialHeaderAvatar = localStorage.headerAvatar ? JSON.parse(localStorage.headerAvatar) : {} const initialSysConfig = localStorage.sysConfig ? localStorage.sysConfig : '' const initialIsLeaveMessageSuccess = sessionStorage.isLeaveMessageSuccess ? sessionStorage.isLeaveMessageSuccess : false //留言是否成功 // 聊天消息 数据 const initialChatList = localStorage.chatList ? JSON.parse(localStorage.chatList) : [] const initialSendMessageList = localStorage.sendMessageList ? JSON.parse(localStorage.sendMessageList) : [] const initialReceiveMessageList = localStorage.receiveMessageList ? JSON.parse(localStorage.receiveMessageList) : [] export const useAppStore = defineStore('app', () => { // Session 相关状态(原 apiState) const token = ref(initialToken) const userId = ref(initialUserId) const configId = ref(initialConfigId) const sessionId = ref(initialSessionId) const source = ref(initialSource) const planCode = ref(initialPlanCode) const entrance = ref(initialEntrance) const elder = ref(true) const notitle = ref('') const userInfo = ref(initialUserInfo) const sysConfig = ref(initialSysConfig) const headerAvatar = ref(initialHeaderAvatar) const htmlExtParams = ref(initialHtmlExtParams) const complaint = ref(initialComplaint) const navigationCorpus = ref(initialNavigationCorpus) const routeAction = ref('push') const direction = ref('forward') const mescrollContent = ref('') const isLeaveMessage = ref(false) const isLeaveMessageSuccess = ref(initialIsLeaveMessageSuccess) const manualService = ref(1) const queuedTimeout = ref(false) const sendLoading = ref(false) const isSendSuccess = ref(false) const timestamp = ref(0) const sendParmas = ref({}) const chatList = ref(initialChatList) const sendMessageList = ref(initialSendMessageList) const receiveMessageList = ref(initialReceiveMessageList) const chatId = ref([]) const currentItemId = ref('') const issubmit = ref(true) const otherTips = ref('') const lastMessage = ref({}) const asrConfig = ref({}) const sendFailList = ref([]) const isLostMessage = ref('') const hxSessionId = ref('') const qaId = ref('') const problemFeedback = ref(false) const isBackstage = ref(false) const sdkLoaded = ref(false) const chatArr = ref([]) const isChatLoading = ref(false) const bpErrorInfo = ref([]) const voiceDataList = ref([]) const hxOpenSucceseds = ref([]) const pcaData = ref([]) const appentry = ref('') const tts = ref('') const flagType = ref('') const msgStatus = ref('') const channelReform = ref(false) const isHumanChat = ref(false) const gaokeUser = ref(false) const hotUser = ref(false) const reviewRestricted = ref(false) const integratedUser = ref(false) const showHumanAppraise = ref(false) const mydFlag = ref(false) const isBqCalcClaim = ref(false) const msgReply = ref(true) const hotUserData = ref(null) const branchCompany = ref('') const messageId = ref('') const serverLastMessageId = ref('') const idempotentKey = ref(createIdempotentKey()) // —— Session —— function setIsBqCalcClaim(payload) { isBqCalcClaim.value = payload } function setToken(payload) { token.value = payload try { sessionStorage.token = payload } catch (e) { console.log(e) } } function setSessionId(payload) { sessionId.value = payload try { localStorage.sessionId = payload } catch (e) { console.log(e) } } function setConfigId(payload) { configId.value = payload try { localStorage.configId = payload } catch (e) { console.log(e) } } function setAppentry(payload) { appentry.value = payload } function setBpErrorInfo(payload) { bpErrorInfo.value = payload } function delToken() { token.value = '' } // Vuex 版本通过 resetStore 清理登录态;保留同名 action 方便旧工具函数继续工作。 function resetStore() { token.value = '' userId.value = '' sessionId.value = '' userInfo.value = {} chatList.value = [] chatArr.value = [] isChatLoading.value = false sendMessageList.value = [] receiveMessageList.value = [] sendFailList.value = [] manualService.value = 1 isHumanChat.value = false try { sessionStorage.removeItem('token') localStorage.removeItem('userId') localStorage.removeItem('sessionId') localStorage.removeItem('userInfo') localStorage.removeItem('chatList') localStorage.removeItem('sendMessageList') localStorage.removeItem('receiveMessageList') } catch (e) { console.log(e) } } function setUserId(payload) { userId.value = payload try { localStorage.userId = payload } catch (e) { console.log(e) } } function setSource(payload) { source.value = payload try { localStorage.source = payload } catch (e) { console.log(e) } } function setNotitle(payload) { notitle.value = payload try { localStorage.notitle = payload } catch (e) { console.log(e) } } function setElder(payload) { elder.value = payload try { localStorage.elder = payload } catch (e) { console.log(e) } } function setPlanCode(payload) { planCode.value = payload try { localStorage.planCode = payload } catch (e) { console.log(e) } } function setEntrance(payload) { entrance.value = payload try { localStorage.entrance = payload } catch (e) { console.log(e) } } function setUserInfo(payload) { userInfo.value = payload try { localStorage.userInfo = JSON.stringify(payload) } catch (e) { console.log(e) } } function setHtmlExtParams(payload) { htmlExtParams.value = payload try { localStorage.htmlExtParams = payload } catch (e) { console.log(e) } } function setComplaint(payload) { complaint.value = payload try { localStorage.complaint = payload } catch (e) { console.log(e) } } function setNavigationCorpus(payload) { navigationCorpus.value = payload try { localStorage.navigationCorpus = payload } catch (e) { console.log(e) } } function setManualService(payload) { manualService.value = payload try { localStorage.manualService = JSON.stringify(payload) } catch (e) { console.log(e) } } function setSysConfig(payload) { sysConfig.value = payload try { localStorage.sysConfig = payload } catch (e) { console.log(e) } } function setHeaderAvatar(payload) { headerAvatar.value = payload try { localStorage.headerAvatar = JSON.stringify(payload) } catch (e) { console.log(e) } } // —— 新聊天界面消息 —— // 消息先写入本地列表,再由调用方异步请求接口。接口失败只追加错误提示, // 不回滚用户已经发出的消息,保证前端始终能立即展示发送内容。 function pushUserMessage(content, messageType = 'user', systemType = 'CARD') { if (!content) return null const message = { type: messageType, system: systemType, isSendSuccess: true, message: [ { value: '', param: '', type: 'text', options: { label: content, readOnly: false, placeholder: '', }, }, ], } chatArr.value.push(message) isChatLoading.value = messageType === 'user' return message } function getConversationMessageText(payload) { if (typeof payload === 'string' || typeof payload === 'number') return String(payload) return ( payload?.msgText ?? payload?.answer ?? payload?.content ?? payload?.text ?? payload?.message?.[0]?.options?.label ?? '' ) } // liics 的 qaChat 使用 msgText/fromFlag,chat-new 使用 message/type。 // 在 store 边界统一转换,旧聊天组件继续读取 chatList,新页面读取 chatArr。 function pushConversationMessage(payload, fallbackType = 'bot') { const payloadList = Array.isArray(payload) ? payload : [payload] let lastMessage = null payloadList.forEach((item) => { if (item == null) return const content = getConversationMessageText(item) const imageUrl = typeof item === 'object' ? item.imageUrl || item.imgUrl || item?.message?.[0]?.options?.imageUrl || '' : '' if (!content && !imageUrl) return const fromFlag = typeof item === 'object' ? String(item.fromFlag || '') : '' const messageType = fromFlag === '1' ? 'user' : fromFlag === '2' ? 'bot' : fallbackType const message = { type: messageType, system: item?.system || 'LIICS', isSendSuccess: item?.isSendSuccess !== false, imageUrl, raw: item, message: [ { value: '', param: '', type: imageUrl ? 'image' : 'text', options: { label: content || '[图片]', imageUrl, readOnly: messageType !== 'user', placeholder: '', }, }, ], } chatArr.value.push(message) isChatLoading.value = messageType === 'user' lastMessage = message }) if (fallbackType === 'bot') isChatLoading.value = false return lastMessage } function pushImageMessage({ localId, imageUrl, fileName = '' } = {}) { if (!localId || !imageUrl) return null const message = { localId, type: 'user', system: 'IMAGE', isSendSuccess: true, uploadStatus: 'uploading', imageUrl, fileName, message: [ { value: '', param: '', type: 'image', options: { label: '[图片]', imageUrl, readOnly: true, placeholder: '', }, }, ], } chatArr.value.push(message) return message } function updateImageMessage(localId, payload = {}) { const message = chatArr.value.find((item) => item.localId === localId) if (!message) return Object.assign(message, payload) if (payload.uploadStatus === 'failed') message.isSendSuccess = false if (payload.uploadStatus === 'success') message.isSendSuccess = true const options = message.message?.[0]?.options if (options && payload.imageUrl) options.imageUrl = payload.imageUrl } // —— 消息发送状态 —— function setSendLoading(payload) { sendLoading.value = payload } function setIsSendSuccess(payload) { isSendSuccess.value = payload } function setQaId(payload) { qaId.value = payload } function setProblemFeedback(payload) { problemFeedback.value = payload } function setOtherTips(payload) { otherTips.value = payload } function setLastMessage(payload) { lastMessage.value = payload } function setSendFailList(payload) { sendFailList.value.push(payload) } function setIsLostMessage(payload) { isLostMessage.value = payload } function delSendFailList(payload) { sendFailList.value = payload } function setLeaveMessage(payload) { isLeaveMessage.value = payload } function setIsLeaveMessageSuccess(payload) { isLeaveMessageSuccess.value = payload try { sessionStorage.isLeaveMessageSuccess = payload } catch (e) { console.log(e) } } function setMescrollContent(payload) { mescrollContent.value = payload } function setSendMessageList(payload) { sendMessageList.value = payload } function setReceiveMessageList(payload) { receiveMessageList.value = payload } function setTts(payload) { tts.value = payload } function setHxOpenSuccesed(payload) { hxOpenSucceseds.value = payload } function setTimestamp(payload) { timestamp.value = payload } function setSendParmas(payload) { sendParmas.value = payload } function setQueuedTimeout(payload) { queuedTimeout.value = payload } // 存储发送的消息到 chatList function addSendMessageList(payload = {}) { console.log('接收发送的消息===', payload) sendParmas.value = { token: token.value, fromFlag: payload.fromFlag || 1, // 1为自己 2为其他 other提示消息 userId: userId.value, sessionId: sessionId.value, reqAndResType: payload.reqAndResType, // 1文本 2图片 3问提评价 msgType: payload.msgType || '', msgText: payload.msgText, file: payload.file || '', filename: payload.filename || '', formData: payload.formData || '', source: source.value, timestamp: payload.timestamp || new Date().valueOf(), msgSource: manualService.value, // 1机器人 2人工 cmd: payload.cmd || '', sendLoading: payload.sendLoading, isSendSuccess: payload.isSendSuccess, voiceNo: payload.voiceNo, quoteData: payload.quoteData || null, bpErrorContent: payload.bpErrorContent || '', // 电子回访断点服务 } console.log('发送消息==', sendParmas.value) timestamp.value = sendParmas.value.timestamp // 存储正在发送的那条数据 setCurrentItemId(sendParmas.value.timestamp) chatList.value.push(sendParmas.value) pushConversationMessage(sendParmas.value, 'user') } // 消息列表 function setChatList(payload) { const normalizedItem = utils.normalizeMessage(payload) chatList.value.push(normalizedItem) pushConversationMessage(normalizedItem, 'bot') } function delChatList(index) { chatList.value.splice(index, 1) } function delAllChatList() { chatList.value.splice(0, chatList.value.length) chatArr.value.splice(0, chatArr.value.length) isChatLoading.value = false } function delSendFailListById(delId) { if (sendFailList.value && sendFailList.value.length > 0) { sendFailList.value.forEach((item, index) => { if (delId === item.timestamp) { sendFailList.value.splice(index, 1) } }) } } // 存储到消息队列中 function setChatId(payload) { chatId.value.push(payload) } function setCurrentItemId(payload) { currentItemId.value = payload } function setFindActiveItem(findActiveItem) { if (chatList.value && chatList.value.length > 0) { chatList.value.forEach((item) => { if (currentItemId.value == item.timestamp) { item.isSendSuccess = findActiveItem item.sendLoading = false } }) } } function setActiveItemExtra(data) { if (chatList.value && chatList.value.length > 0) { chatList.value.forEach((item) => { if (currentItemId.value == item.timestamp) { if (data && data.imgKey) { item.imgKey = data.imgKey } if (data && data.imgUrl) { item.imgUrl = data.imgUrl } } }) } } function setReSendMessage(reSendMessageId) { if (chatList.value && chatList.value.length > 0) { chatList.value.forEach((item, index) => { if (reSendMessageId === item.timestamp) { chatList.value.splice(index, 1) } }) } delSendFailListById(reSendMessageId) } function scrollBottom() { setTimeout(() => { try { mescrollContent.value.scrollTop = mescrollContent.value.scrollHeight || 0 } catch (error) { console.log(error.message) } }, 500) } // —— 其他状态 —— function setIsBackstage(payload) { isBackstage.value = payload } // 存储语音 function setVoiceData(payload) { voiceDataList.value.push(payload) } // sdk是否已加载好 function setSdkLoaded(payload) { sdkLoaded.value = payload } function setPcaData(payload) { pcaData.value = payload } function setChannelReform(payload) { channelReform.value = payload } function setMsgStatus(payload) { msgStatus.value = payload } function setMsgReply(payload) { msgReply.value = payload } function setIsHumanChat(payload) { isHumanChat.value = payload } function setGaokeUser(payload) { gaokeUser.value = payload } function setBranchCompany(payload) { branchCompany.value = payload } function setHotUser(payload) { hotUser.value = payload } function setHotUserData(payload) { hotUserData.value = payload } function setReviewRestricted(payload) { reviewRestricted.value = payload } function setIntegratedUser(payload) { integratedUser.value = payload } function setHxSessionId(payload) { hxSessionId.value = payload } function setShowHumanAppraise(payload) { showHumanAppraise.value = payload } function setMessageId(payload) { messageId.value = payload || '' } function setServerLastMessageId(payload) { serverLastMessageId.value = payload || '' } function setAsrConfig(payload) { asrConfig.value = payload || {} } function setFlagType(payload) { flagType.value = payload || '' } function setMydFlag(payload) { mydFlag.value = payload } function getIdempotentKey() { return idempotentKey.value } function refreshIdempotentKey() { idempotentKey.value = createIdempotentKey() return idempotentKey.value } function updateChatMessageSendStatus(localId, success, requestParams) { const message = chatArr.value.find((item) => item.localId === localId || item.idempotentKey === localId) if (!message) return message.isSendSuccess = success if (!success && requestParams) message.requestParams = requestParams } // —— liics 对话接口迁移 —— // The Vue 2 components still dispatch these names. They are kept as // explicit Pinia actions so old chat cards and the new Vue 3 shell share // the same request/response contract during the migration. function setTransferCustomer(payload) { setManualService(payload) return Promise.resolve(payload) } function post(url, data = {}) { return postConversation(url, data) } function buildMessagePayload(payload = {}) { return { token: token.value, fromFlag: payload.fromFlag || 1, userId: userId.value, sessionId: sessionId.value, reqAndResType: payload.reqAndResType, msgType: payload.msgType || '', msgText: payload.msgText, intentId: payload.intentId || '', source: source.value, timestamp: payload.timestamp || Date.now(), msgSource: payload.msgSource || manualService.value, cmd: payload.cmd || '', sendLoading: payload.sendLoading, isSendSuccess: payload.isSendSuccess, questionType: payload.questionType || '', multipleError: payload.multipleError || '', bpErrorCode: payload.bpErrorCode || '', bpErrorContent: payload.bpErrorContent || '', voiceNo: payload.voiceNo, voiceData: payload.voiceData, quoteData: payload.quoteData || null, flagType: flagType.value, } } function getResponsePayload(response) { return response?.data ?? response } function assertConversationSuccess(response) { if (response && response.code != null && Number(response.code) !== 0) { throw new Error(response.msg || '消息发送失败') } return getResponsePayload(response) } async function sendHttpMessage(payload) { try { const response = await sendRobotMessage({ ...payload, flagType: flagType.value }) const result = assertConversationSuccess(response) issubmit.value = true setFindActiveItem(false) if (result?.cmd === 'SFRZSB') { setProblemFeedback(true) setQaId(result.qaId) } if (result) setChatList(result) scrollBottom() return result } catch (error) { issubmit.value = true setFindActiveItem(true) isChatLoading.value = false throw error } } function sendWebsocketMessage(payload) { return new Promise((resolve, reject) => { const socket = wsConnection.$ws if (!socket || socket.readyState !== 1) { setFindActiveItem(true) sendFailList.value.push(payload) issubmit.value = true reject(new Error('当前会话已断开,请检查您的网络设置')) return } const message = { ...payload, sendLoading: false } setFindActiveItem(false) if (channelReform.value && msgStatus.value === '1' && msgReply.value) { post('config/getHXReplyMessage', { key: 'HUANXIN:HUMAN:QUEUE_AUTOMATIC_REPLY_MESSAGE:', }) .then((response) => { if (response?.code === 0 && response.data) { setChatList({ answerType: 'text', fromFlag: 2, userId: userId.value, sessionId: sessionId.value, reqAndResType: '08', msgType: '01', msgText: response.data, source: source.value, timestamp: Date.now(), msgSource: manualService.value, }) setMsgReply(false) scrollBottom() } }) .catch(() => { }) } if (msgStatus.value !== '1') setIsHumanChat(true) wsConnection.sendMessage(JSON.stringify(message), (ack) => { if (!ack || String(ack) !== String(payload.timestamp)) { setFindActiveItem(true) sendFailList.value.push(payload) } resolve(ack) }) }).finally(() => { issubmit.value = true }) } async function sendingRobot(payload = {}) { if (!issubmit.value) return Promise.reject(new Error('消息正在发送')) issubmit.value = false const sendparam = buildMessagePayload(payload) try { if (Number(manualService.value) === 1) { if (payload.msgText !== '&转人工服务&') addSendMessageList(sendparam) return await sendHttpMessage(sendparam) } addSendMessageList(sendparam) return await sendWebsocketMessage(sendparam) } catch (error) { issubmit.value = true throw error } } async function ResendMessage(payload = {}) { setCurrentItemId(payload.timestamp) return sendingRobot({ ...payload, sendLoading: true, isSendSuccess: false }) } async function addUpLoadImg(payload = {}) { const formData = payload.formData if (!formData) throw new Error('缺少图片数据') formData.append('fromFlag', '1') formData.append('userId', userId.value || '') formData.append('token', token.value || '') formData.append('sessionId', sessionId.value || '') formData.append('reqAndResType', payload.reqAndResType || '2') formData.append('source', source.value || '') formData.append('timestamp', String(Date.now())) formData.append('msgSource', String(manualService.value || '1')) addSendMessageList(payload) try { const response = await uploadConversationImage(formData) const result = assertConversationSuccess(response) setFindActiveItem(false) setActiveItemExtra(result) if (result) setChatList(result) scrollBottom() return result } catch (error) { setFindActiveItem(true) throw error } } async function addUpLoadVoice(payload = {}) { if (!issubmit.value) return Promise.reject(new Error('消息正在发送')) issubmit.value = false return sendVoice({ ...payload, reqAndResType: payload.reqAndResType || '5' }) } async function sendVoice(payload = {}) { try { const result = await sendVoiceMessage(buildMessagePayload(payload)) const data = assertConversationSuccess(result) if (data?.voiceNo != null) data.voiceNo = Number(data.voiceNo) issubmit.value = true setFindActiveItem(false) if (data) setChatList(data) scrollBottom() return data } catch (error) { issubmit.value = true setFindActiveItem(true) throw error } } async function sendmessageContent(payload = {}) { if (!wsConnection.$ws || wsConnection.$ws.readyState !== 1) { throw new Error('当前会话已断开,请检查您的网络设置') } const sendparam = buildMessagePayload(payload) addSendMessageList(sendparam) return sendWebsocketMessage(sendparam) } async function sendingDrtificial(payload) { if (!payload) return null const message = utils.normalizeMessage(payload) if (message.chatId && chatId.value.includes(message.chatId)) { wsConnection.sendMessage(JSON.stringify(message), '') return message } if (message.chatId) setChatId(message.chatId) if (!isBackstage.value && message.fromFlag == 2 && message.seatNum !== '调度员') { updateReadStatus([message.chatId]).catch(() => { }) message.readStatus = 1 } setChatList(message) sendLoading.value = false scrollBottom() return message } async function transferCustomer(payload = {}) { const response = await sendRobotMessage({ ...buildMessagePayload(payload), cmd: payload.cmd || 'ZJSXRGFW' }) return assertConversationSuccess(response) } async function connectionArtificial(payload = {}) { const response = await sendRobotMessage(buildMessagePayload(payload)) const result = assertConversationSuccess(response) if (result) { setChatList(result) scrollBottom() } return result } async function setConnectToEasemob() { const response = await connectHumanService({ userId: userId.value, sessionId: sessionId.value, source: source.value, }) const result = assertConversationSuccess(response) if (result?.connection === true) setManualService(result.msgSource || 2) else if (result) setChatList(result) return result } async function complaintCall(payload = {}) { const text = payload.msgText || '' const markedText = text ? `&${text.split('').join('&')}&` : text const response = await sendRobotMessage({ ...buildMessagePayload(payload), msgText: payload.navigationCorpus ? `${markedText}-${payload.navigationCorpus}` : markedText, }) const result = assertConversationSuccess(response) if (result) setChatList(result) return result } async function brokenPointCall(payload = {}) { const text = payload.msgText || '' const markedText = text ? `&${text.split('').join('&')}&` : text const response = await sendRobotMessage({ ...buildMessagePayload(payload), msgText: markedText, bpErrorCode: payload.bpErrorCode || '', bpErrorContent: payload.bpErrorContent || '', }) const result = assertConversationSuccess(response) if (result) setChatList(result) return result } function userBehavior(payload = {}) { return submitUserBehavior({ userInfoId: userId.value, sessionId: sessionId.value || '', qaId: payload.qaId || '', eventType: payload.eventType, source: source.value, eventMsg: payload.eventMsg, }) } function changeReadStatus() { const unread = chatList.value .filter((item) => item.fromFlag == 2 && item.seatNum !== '调度员' && item.readStatus === 0) .map((item) => item.chatId) unread.forEach((id) => { const item = chatList.value.find((entry) => entry.chatId === id) if (item) item.readStatus = 1 }) return updateReadStatus(unread) } function updateReadStatus(messageIds = []) { if (!messageIds?.length) return Promise.resolve([]) return updateReadMessages({ userInfoId: userId.value, msgList: messageIds }) } function savePaperResult(payload = {}) { return submitSatisfaction({ oprUser: `${payload.userId || userId.value}`, userType: 'C', selectedSeq: payload.evaluation === 2 ? '2' : '4', content: payload.evaluation === 2 ? '不满意' : '满意', sceneNo: 2, oprIdType: 'userID', }) } async function getSysConfig() { const response = await loadSystemConfig({ source: source.value }) const result = assertConversationSuccess(response) setSysConfig(result) return result } async function getHeaderUrl() { const response = await loadHeaderAvatar({ source: source.value }) const result = assertConversationSuccess(response) let avatar = result if (typeof avatar === 'string') { try { avatar = JSON.parse(avatar) } catch (_) { /* keep string */ } } setHeaderAvatar(avatar) return avatar } function getTipsConfig(payload) { return loadTipsConfig({ cmd: payload }) } function appraiseEvaluate(payload) { return post('evaluation/evaluateAnswer', payload) } function updateClickTime(payload) { return post('config/updateClickTime', payload) } function leaveMessage() { setLeaveMessage(true) return Promise.resolve() } function exitMessage() { setLeaveMessage(false) return post('HumanChat/closeEvent', { userId: userId.value }) } const legacyState = new Proxy({}, { get(_target, key) { const refs = { token, userId, userInfo, configId, sessionId, source, planCode, entrance, elder, notitle, headerAvatar, htmlExtParams, complaint, navigationCorpus, mescrollContent, isLeaveMessage, isLeaveMessageSuccess, manualService, queuedTimeout, sendLoading, isSendSuccess, timestamp, sendParmas, chatList, sendMessageList, receiveMessageList, chatId, currentItemId, issubmit, otherTips, lastMessage, asrConfig, sendFailList, isLostMessage, qaId, problemFeedback, isBackstage, sdkLoaded, bpErrorInfo, voiceDataList, hxOpenSucceseds, pcaData, appentry, tts, flagType, msgStatus, channelReform, isHumanChat, gaokeUser, hotUser, reviewRestricted, integratedUser, showHumanAppraise, mydFlag, isBqCalcClaim, msgReply, hotUserData, branchCompany, messageId, serverLastMessageId, idempotentKey, } const value = refs[key] return value && typeof value === 'object' && 'value' in value ? value.value : value }, }) const mutationMap = { set_token: setToken, set_sessionId: setSessionId, set_configId: setConfigId, set_appentry: setAppentry, del_token: delToken, resetStore, set_userid: setUserId, set_source: setSource, set_notitle: setNotitle, set_elder: setElder, set_plan_code: setPlanCode, set_entrance: setEntrance, set_userInfo: setUserInfo, set_htmlExtParams: setHtmlExtParams, set_complaint: setComplaint, set_navigationCorpus: setNavigationCorpus, set_manualService: setManualService, set_sysConfig: setSysConfig, set_headerAvatar: setHeaderAvatar, set_sendLoading: setSendLoading, set_isSendSuccess: setIsSendSuccess, set_qaId: setQaId, set_problemFeedback: setProblemFeedback, set_otherTips: setOtherTips, set_lastMessage: setLastMessage, set_sendFailList: setSendFailList, set_isLostMessage: setIsLostMessage, del_sendFailList: delSendFailList, set_leaveMessage: setLeaveMessage, set_isLeaveMessageSuccess: setIsLeaveMessageSuccess, set_mescrollContent: setMescrollContent, set_sendMessageList: setSendMessageList, set_receiveMessageList: setReceiveMessageList, set_tts: setTts, set_hxOpenSuccesed: setHxOpenSuccesed, set_timestamp: setTimestamp, set_sendParmas: setSendParmas, set_queuedTimeout: setQueuedTimeout, set_chatList: setChatList, del_chatList: delChatList, delall_chatList: delAllChatList, set_chatId: setChatId, set_currentItemId: setCurrentItemId, set_findActiveItem: setFindActiveItem, set_activeItemExtra: setActiveItemExtra, set_reSendMessage: setReSendMessage, set_isBackstage: setIsBackstage, set_VoiceData: setVoiceData, set_sdkLoaded: setSdkLoaded, set_pcaData: setPcaData, set_channelReform: setChannelReform, set_msgStatus: setMsgStatus, set_msgReply: setMsgReply, set_isHumanChat: setIsHumanChat, set_gaokeUser: setGaokeUser, set_branchCompany: setBranchCompany, set_hotUser: setHotUser, set_hotUserData: setHotUserData, set_reviewRestricted: setReviewRestricted, set_integratedUser: setIntegratedUser, set_hxSessionId: setHxSessionId, set_showHumanAppraise: setShowHumanAppraise, set_mydFlag: setMydFlag, set_messageId: setMessageId, set_serverLastMessageId: setServerLastMessageId, set_AsrConfig: setAsrConfig, set_flagType: setFlagType, set_isBqCalcClaim: setIsBqCalcClaim, scrollBottom, del_set_sendFailList: delSendFailListById, } function commit(type, payload) { const mutation = mutationMap[type] if (!mutation) return undefined return mutation(payload) } const actionMap = { post, setTransferCustomer, addSendMessageList, sendHttpMessage, sendVoice, sendWebsocketMessage, sendingRobot, ResendMessage, addUpLoadImg, addUpLoadVoice, sendmessageContent, sendingDrtificial, transferCustomer, connectionArtificial, setConnectToEasemob, complaintCall, brokenPointCall, userBehavior, getSysConfig, getHeaderUrl, changeReadStatus, updateReadStatus, savePaperResult, getTipsConfig, appraiseEvaluate, updateClickTime, leaveMessage, exitMessage, } function dispatch(type, payload) { const action = actionMap[type] if (!action) return Promise.reject(new Error(`未知对话 action: ${type}`)) const result = typeof action === 'function' ? action(payload) : action return Promise.resolve(result) } return { // State token, userId, configId, sessionId, source, planCode, entrance, elder, notitle, userInfo, sysConfig, headerAvatar, htmlExtParams, complaint, navigationCorpus, routeAction, direction, mescrollContent, isLeaveMessage, isLeaveMessageSuccess, manualService, queuedTimeout, sendLoading, isSendSuccess, timestamp, sendParmas, chatList, sendMessageList, receiveMessageList, chatId, currentItemId, issubmit, otherTips, lastMessage, asrConfig, sendFailList, isLostMessage, hxSessionId, qaId, problemFeedback, isBackstage, sdkLoaded, chatArr, isChatLoading, bpErrorInfo, voiceDataList, hxOpenSucceseds, pcaData, appentry, tts, flagType, msgStatus, channelReform, isHumanChat, gaokeUser, hotUser, reviewRestricted, integratedUser, showHumanAppraise, mydFlag, isBqCalcClaim, msgReply, hotUserData, branchCompany, messageId, serverLastMessageId, idempotentKey, // Actions setIsBqCalcClaim, setToken, setSessionId, setConfigId, setAppentry, setBpErrorInfo, delToken, del_token: delToken, resetStore, setUserId, setSource, setNotitle, setElder, setPlanCode, setEntrance, setUserInfo, setHtmlExtParams, setComplaint, setNavigationCorpus, setManualService, setSysConfig, setHeaderAvatar, pushUserMessage, pushImageMessage, updateImageMessage, setSendLoading, setIsSendSuccess, setQaId, setProblemFeedback, setOtherTips, setLastMessage, setSendFailList, setIsLostMessage, delSendFailList, delSendFailListById, setLeaveMessage, setIsLeaveMessageSuccess, setMescrollContent, setSendMessageList, setReceiveMessageList, setTts, setHxOpenSuccesed, setTimestamp, setSendParmas, setQueuedTimeout, addSendMessageList, setChatList, delChatList, delAllChatList, setChatId, setCurrentItemId, setFindActiveItem, setActiveItemExtra, setReSendMessage, scrollBottom, setIsBackstage, setVoiceData, setSdkLoaded, setPcaData, setChannelReform, setMsgStatus, setMsgReply, setIsHumanChat, setGaokeUser, setBranchCompany, setHotUser, setHotUserData, setReviewRestricted, setIntegratedUser, setHxSessionId, setShowHumanAppraise, set_data: setShowHumanAppraise, setMessageId, setServerLastMessageId, setAsrConfig, setFlagType, setMydFlag, getIdempotentKey, refreshIdempotentKey, updateChatMessageSendStatus, // Legacy Vuex compatibility used by the migrated components. state: legacyState, commit, dispatch, setTransferCustomer, post, sendHttpMessage, sendWebsocketMessage, sendingRobot, ResendMessage, addUpLoadImg, addUpLoadVoice, sendVoice, sendmessageContent, sendingDrtificial, transferCustomer, connectionArtificial, setConnectToEasemob, complaintCall, brokenPointCall, userBehavior, getSysConfig, getHeaderUrl, changeReadStatus, updateReadStatus, savePaperResult, getTipsConfig, appraiseEvaluate, updateClickTime, leaveMessage, exitMessage, // A few Vue 2 components call these methods directly instead of through // commit; keep the aliases until those templates are fully rewritten. set_mescrollContent: setMescrollContent, set_problemFeedback: setProblemFeedback, delall_chatList: delAllChatList, del_chatList: delChatList, del_set_sendFailList: delSendFailListById, } }) export default useAppStore