You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
customAgent/src/store/app.js

1394 lines
39 KiB

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