import request from '@/utils/request.js' import { BASE_URL, KEFU_BASE_URL, Authorization } from '@/utils/config.js' import { getStorageFun, TOKEN_NAME } from '@/utils/auth.js' export const CONTENT_TYPE = Object.freeze({ TEXT: 1, IMAGE: 2, FILE: 3, AUDIO: 4, PRODUCT: 10, ORDER: 11, QUOTE: 12, RECALLED: 99 }) function kefuRequest({ url, method = 'GET', data = {} }) { const token = getStorageFun(TOKEN_NAME) return new Promise((resolve, reject) => { uni.request({ url: `${KEFU_BASE_URL}${url}`, method, data, header: { Authorization, 'HSM-AUTH': token || '', 'content-type': 'application/json' }, success: response => { const body = response.data || {} if (response.statusCode >= 200 && response.statusCode < 300 && body.bizcode === 100) { resolve(body) return } const error = new Error(body.msg || `客服接口请求失败(${response.statusCode})`) error.statusCode = response.statusCode error.response = body reject(error) }, fail: error => reject(new Error(error.errMsg || '客服接口连接失败')) }) }) } export function getCurrentMember() { return request({ url: '/user/getUserInfo', method: 'get', isShowLoading: false }).then(result => result.data) } export function getMessages({ userId, conversationId, page = 1, pageSize = 20 }) { const data = conversationId ? { userId, conversationId, page, pageSize } : { userId, page, pageSize } return kefuRequest({ url: '/kefu/user/messages', method: 'get', data: data }).then(result => result.data || {}) } export function sendMessage(data) { return kefuRequest({ url: '/kefu/user/send', method: 'post', data }).then(result => result.data) } export function transferToHuman({ userId, conversationId, reason = '用户点击转人工' }) { return kefuRequest({ url: '/kefu/user/transfer-human', method: 'post', data: { userId, conversationId, reason } }).then(result => result.data) } export function recallMessage({ userId, messageId }) { const data = { userId, messageId } return kefuRequest({ url: '/kefu/user/message/recall', method: 'post', data }).catch(error => { if (!error || error.statusCode !== 404) throw error return kefuRequest({ url: '/kefu/user/recall', method: 'post', data }) }) .then(result => result.data) } export function deleteMessageForMember({ userId, messageId }) { return kefuRequest({ url: '/kefu/user/message/delete', method: 'post', data: { userId, messageId } }).then(result => result.data) } export function transcribeMessage({ userId, messageId }) { return kefuRequest({ url: '/kefu/user/message/transcribe', method: 'post', data: { userId, messageId } }).then(result => result.data) } export function getUnreadCount(userId) { return kefuRequest({ url: '/kefu/user/unread-count', method: 'get', data: { userId } }).then(result => Number(result.data || 0)) } export function markMemberMessagesRead({ userId, conversationId }) { return kefuRequest({ url: '/kefu/user/read', method: 'post', data: { userId, conversationId } }).then(result => result.data) } export function getBrowseHistory({ userId, page = 1, pageSize = 10 }) { return kefuRequest({ url: '/kefu/user/browse-history', method: 'get', data: { userId, page, pageSize } }).then(result => result.data) } export function getOrders({ userId, page = 1, pageSize = 10 }) { return kefuRequest({ url: '/kefu/user/orders', method: 'get', data: { userId, page, pageSize } }).then(result => result.data) } export function uploadMessageImage(filePath) { const token = getStorageFun(TOKEN_NAME) return new Promise((resolve, reject) => { uni.uploadFile({ url: `${BASE_URL}/common/upload/image`, filePath, name: 'file', formData: { type: 'COMMON' }, header: { Authorization, 'HSM-AUTH': token || '' }, success: response => { try { const body = typeof response.data === 'string' ? JSON.parse(response.data) : response.data if (!body || body.bizcode !== 100) throw new Error((body && body.msg) || '图片上传失败') const data = body.data || {} const url = data.accessUrl || data.dbUrl || data.url || data.fileUrl || data.path if (!url) throw new Error('图片上传后未返回访问地址') resolve(url) } catch (error) { reject(error) } }, fail: error => reject(new Error(error.errMsg || '图片上传失败')) }) }) } function resolveUploadResult(response, fallbackMessage) { const body = typeof response.data === 'string' ? JSON.parse(response.data) : response.data if (!body || body.bizcode !== 100) throw new Error((body && body.msg) || fallbackMessage) const data = body.data || {} const url = data.accessUrl || data.dbUrl || data.url || data.fileUrl || data.path if (!url) throw new Error('上传成功但未返回访问地址') return url } export function uploadMessageAsset(source, kind = 'file') { const token = getStorageFun(TOKEN_NAME) const endpoints = [...new Set([ `${String(KEFU_BASE_URL).replace(/\/$/, '')}/kefu/user/upload/${kind}`, `${String(BASE_URL).replace(/\/$/, '')}/common/upload/${kind}` ])] // #ifdef H5 if (typeof Blob !== 'undefined' && source instanceof Blob) { const formData = new FormData() formData.append('file', source, source.name || `${kind}-${Date.now()}`) return (async () => { let lastError = null for (const endpoint of endpoints) { const response = await fetch(endpoint, { method: 'POST', headers: { Authorization, 'HSM-AUTH': token || '' }, body: formData }) if (response.status === 404) { lastError = new Error(`${kind === 'audio' ? '语音' : '文件'}上传接口不存在`) continue } return resolveUploadResult({ data: await response.text() }, `${kind === 'audio' ? '语音' : '文件'}上传失败`) } throw lastError || new Error(`${kind === 'audio' ? '语音' : '文件'}上传失败`) })() } // #endif const filePath = typeof source === 'string' ? source : (source.tempFilePath || source.path) return new Promise((resolve, reject) => { const uploadAt = index => { uni.uploadFile({ url: endpoints[index], filePath, name: 'file', header: { Authorization, 'HSM-AUTH': token || '' }, success: response => { if (Number(response.statusCode) === 404 && index + 1 < endpoints.length) { uploadAt(index + 1) return } try { resolve(resolveUploadResult(response, `${kind === 'audio' ? '语音' : '文件'}上传失败`)) } catch (error) { reject(error) } }, fail: error => reject(new Error(error.errMsg || `${kind === 'audio' ? '语音' : '文件'}上传失败`)) }) } uploadAt(0) }) } export const uploadMessageFile = source => uploadMessageAsset(source, 'file') export const uploadMessageAudio = source => uploadMessageAsset(source, 'audio')