feat:0820需求

This commit is contained in:
2026-08-21 14:10:43 +08:00
parent 619c0cacc5
commit e8d4fd6cd4
31 changed files with 9112 additions and 3658 deletions
@@ -0,0 +1,97 @@
import { getStorageFun, TOKEN_NAME, USER_DATA } from '@/utils/auth.js'
import { getCurrentMember } from './api.js'
import { KefuSocket } from './kefu-socket.js'
export const KEFU_REALTIME_EVENT = 'kefu-realtime-event'
export const KEFU_REALTIME_STATUS = 'kefu-realtime-status'
let socket = null
let connectionParams = null
let startingPromise = null
function storedMember() {
const value = getStorageFun(USER_DATA)
if (!value) return null
if (typeof value === 'object') return value
try {
return JSON.parse(value)
} catch (error) {
return null
}
}
async function resolveMemberId(explicitUserId) {
if (explicitUserId) return explicitUserId
const cached = storedMember()
if (cached && (cached.id || cached.userId)) return cached.id || cached.userId
const member = await getCurrentMember()
return member && (member.id || member.userId)
}
function createSocket() {
const instance = new KefuSocket({
onStatus(status) {
uni.$emit(KEFU_REALTIME_STATUS, status)
},
onEvent(event) {
uni.$emit(KEFU_REALTIME_EVENT, event)
},
})
socket = instance
instance.connect(connectionParams)
return instance
}
/**
* Start the foreground customer-service connection. Calls are idempotent so
* several pages can consume the same stream without opening duplicate sockets.
*/
export function startKefuRealtime(options = {}) {
if (!getStorageFun(TOKEN_NAME)) {
resetKefuRealtime()
return Promise.resolve(null)
}
if (startingPromise) return startingPromise
startingPromise = resolveMemberId(options.userId)
.then((userId) => {
if (!userId) return null
const nextParams = {
userId,
mchId: options.mchId || (connectionParams && connectionParams.mchId) || 1002,
}
const sameMember = connectionParams && String(connectionParams.userId) === String(userId)
connectionParams = nextParams
if (socket && sameMember) {
socket.reconnectNow()
return socket
}
if (socket) socket.close()
socket = null
return createSocket()
})
.catch(() => null)
.finally(() => {
startingPromise = null
})
return startingPromise
}
export function suspendKefuRealtime() {
if (socket) socket.close()
socket = null
uni.$emit(KEFU_REALTIME_STATUS, 'closed')
}
export function resumeKefuRealtime() {
if (!getStorageFun(TOKEN_NAME)) {
resetKefuRealtime()
return Promise.resolve(null)
}
return startKefuRealtime(connectionParams || {})
}
export function resetKefuRealtime() {
suspendKefuRealtime()
connectionParams = null
}