2026-07-20 15:31:52 +08:00
|
|
|
|
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)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-09 11:46:36 +08:00
|
|
|
|
export function getMessages({ userId, conversationId, page = 1, pageSize = 20 }) {
|
2026-07-27 15:14:36 +08:00
|
|
|
|
const data = conversationId ? { userId, conversationId, page, pageSize } : { userId, page, pageSize }
|
2026-07-20 15:31:52 +08:00
|
|
|
|
return kefuRequest({
|
|
|
|
|
|
url: '/kefu/user/messages',
|
|
|
|
|
|
method: 'get',
|
2026-07-27 15:14:36 +08:00
|
|
|
|
data: data
|
2026-07-20 15:31:52 +08:00
|
|
|
|
}).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')
|