ai-c/utils/api.js
2026-02-02 18:21:32 +08:00

1857 lines
48 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* API服务层
* 封装所有后端API调用
*/
const config = require('../config/index')
// ==================== 请求封装 ====================
/**
* 基础请求方法
* @param {string} url - API路径
* @param {object} options - 请求选项
* @returns {Promise}
*/
const request = (url, options = {}) => {
return new Promise((resolve, reject) => {
const token = wx.getStorageSync(config.STORAGE_KEYS.TOKEN)
wx.request({
url: config.API_BASE_URL + url,
method: options.method || 'GET',
data: options.data,
timeout: config.REQUEST_TIMEOUT,
header: {
'Authorization': token ? `Bearer ${token}` : '',
'Content-Type': 'application/json',
// 注意x-user-id 已废弃,后端通过 Token 验证用户身份
...options.header
},
success: (res) => {
// 始终打印简短的请求和响应信息用于调试
console.log(`[API] ${options.method || 'GET'} ${url} -> ${res.statusCode}`)
// 如果返回的是 HTML (通常是 404 页面),打印简短提示而非全文
const isHtml = typeof res.data === 'string' && res.data.trim().startsWith('<!DOCTYPE')
if (isHtml) {
console.warn(`[API] ${url} 返回了 HTML 页面,可能是 404 或服务器错误`)
} else if (config.DEBUG) {
console.log(`[API] Response Data:`, JSON.stringify(res.data).substring(0, 200))
}
if (res.statusCode === 200) {
resolve(res.data)
} else if (res.statusCode === 401) {
// Token过期或无效
console.warn('[API] 401 错误Token 可能已过期:', url)
// 静默模式下不清除登录状态,只返回错误
if (options.silent) {
reject({ code: 401, message: '登录已过期' })
return
}
// 非静默模式:清除登录状态并提示用户
wx.removeStorageSync(config.STORAGE_KEYS.TOKEN)
wx.removeStorageSync(config.STORAGE_KEYS.USER_INFO)
wx.removeStorageSync(config.STORAGE_KEYS.USER_ID)
wx.removeStorageSync(config.STORAGE_KEYS.TOKEN_EXPIRY)
// 更新全局登录状态
const app = getApp()
if (app && app.globalData) {
app.globalData.isLoggedIn = false
app.globalData.userInfo = null
app.globalData.userId = null
}
// 触发登录弹窗
const pages = getCurrentPages()
const currentPage = pages[pages.length - 1]
if (currentPage && currentPage.onAuthRequired) {
currentPage.onAuthRequired()
}
reject({ code: 401, message: '登录已过期,请重新登录' })
} else {
reject(res.data || { code: res.statusCode, message: '请求失败' })
}
},
fail: (err) => {
console.error(`[API Error] ${url}`, err)
// 不自动显示toast让调用方处理错误
reject({
code: -1,
message: '网络错误',
errMsg: err.errMsg || 'request:fail',
error: err
})
}
})
})
}
/**
* 文件上传
* @param {string} filePath - 本地文件路径
* @param {string} folder - 存储目录 (avatar/image/audio)
* @returns {Promise}
*/
const uploadFile = (filePath, folder = 'uploads') => {
return new Promise((resolve, reject) => {
console.log('[uploadFile] ========== 开始上传任务 ==========')
console.log('[uploadFile] 文件路径:', filePath)
console.log('[uploadFile] 目标目录:', folder)
// 验证目录是否合法,不合法则使用默认的 uploads
const allowedFolders = ['uploads', 'image', 'images', 'avatars', 'characters', 'audio', 'documents', 'temp', 'assets']
if (!allowedFolders.includes(folder)) {
console.warn(`[uploadFile] 目录 "${folder}" 不在允许列表中,将使用 "uploads"`)
folder = 'uploads'
}
const token = wx.getStorageSync(config.STORAGE_KEYS.TOKEN)
const userId = wx.getStorageSync(config.STORAGE_KEYS.USER_ID)
const deviceId = wx.getStorageSync('deviceId') || userId || 'unknown'
// 始终包含 x-device-id如果有 token 则包含 Authorization
const header = {
'x-device-id': deviceId
}
if (token) {
header['Authorization'] = `Bearer ${token}`
console.log('[uploadFile] 使用Token认证')
} else {
header['x-device-id'] = deviceId
console.log('[uploadFile] 使用DeviceId认证:', deviceId)
}
wx.uploadFile({
url: config.API_BASE_URL + '/upload',
filePath: filePath,
name: 'file',
formData: { folder },
header: header,
success: (res) => {
console.log('[uploadFile] ========== 上传响应 ==========')
console.log('[uploadFile] 状态码:', res.statusCode)
console.log('[uploadFile] 响应头:', JSON.stringify(res.header))
console.log('[uploadFile] 响应体:', res.data)
if (res.statusCode === 200) {
try {
const data = JSON.parse(res.data)
console.log('[uploadFile] 解析后的数据:', JSON.stringify(data))
// 兼容两种响应格式
if (data.code === 0 && data.data) {
console.log('[uploadFile] ✓ 上传成功 (code=0):', data.data.url)
resolve({ success: true, data: data.data })
} else if (data.success && data.data) {
console.log('[uploadFile] ✓ 上传成功 (success=true):', data.data.url)
resolve(data)
} else {
const errMsg = data.message || '上传失败'
console.error('[uploadFile] ✗ 业务错误:', errMsg)
reject({ code: data.code || -1, message: errMsg })
}
} catch (e) {
console.error('[uploadFile] ✗ 解析响应JSON失败:', e)
reject({ code: -1, message: '服务器响应格式错误' })
}
} else if (res.statusCode === 500) {
let errorData = {}
try {
errorData = JSON.parse(res.data)
} catch (e) {}
console.error('[uploadFile] ✗ 服务器内部错误 (500):', errorData)
reject({
code: 500,
message: errorData.message || '服务器内部错误,请稍后重试',
detail: errorData
})
} else if (res.statusCode === 413) {
console.error('[uploadFile] ✗ 文件太大 (413)')
reject({ code: 413, message: '文件太大,请选择较小的图片' })
} else if (res.statusCode === 401 || res.statusCode === 403) {
console.error('[uploadFile] ✗ 权限错误 (401/403)')
reject({ code: res.statusCode, message: '权限不足,请重新登录' })
} else {
console.error('[uploadFile] ✗ HTTP错误:', res.statusCode)
reject({ code: res.statusCode, message: `上传失败 (${res.statusCode})` })
}
},
fail: (err) => {
console.error('[uploadFile] ✗ wx.uploadFile 接口调用失败:', err)
reject({ code: -1, message: '网络连接失败,请检查网络' })
}
})
})
}
// ==================== 认证模块 API ====================
const auth = {
/**
* 发送短信验证码
* @param {string} phone - 手机号
*/
sendSms: (phone) => request('/auth/send-sms', {
method: 'POST',
data: { phone }
}),
/**
* 手机号登录
* @param {string} phone - 手机号
* @param {string} code - 验证码
*/
phoneLogin: (phone, code) => request('/auth/phone-login', {
method: 'POST',
data: { phone, code }
}),
/**
* 微信手机号快速登录
* @param {string} code - 微信getPhoneNumber返回的code
*/
wxPhoneLogin: (code, loginCode) => request('/auth/wx-phone-login', {
method: 'POST',
data: { code, loginCode }
}),
/**
* 微信登录
* @param {string} code - 微信登录code
* @param {object} userInfo - 用户信息(可选)
*/
wxLogin: (code, userInfo = null) => request('/auth/wx-login', {
method: 'POST',
data: { code, userInfo }
}),
/**
* 获取当前用户信息
*/
getCurrentUser: () => request('/auth/me'),
/**
* 退出登录
*/
logout: () => request('/auth/logout', { method: 'POST' })
}
// ==================== 用户模块 API ====================
const user = {
/**
* 获取用户资料
*/
getProfile: () => request('/users/profile'),
/**
* 更新用户资料
* @param {object} data - 用户资料
*/
updateProfile: (data) => request('/users/profile', {
method: 'PUT',
data
}),
/**
* 获取用户余额
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getBalance: () => request('/user/balance'),
/**
* 获取余额历史
* @param {object} params - 分页参数
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getBalanceHistory: (params = {}) => request('/user/balance/history', {
data: params
}),
/**
* 绑定手机号(微信授权方式)
* @param {object} data - { code: 微信授权code }
*/
bindPhone: (data) => request('/users/bindPhone', {
method: 'POST',
data: data
}),
/**
* 获取用户记忆/档案
* @param {string} characterId - 角色ID可选
*/
getMemories: (characterId = null) => {
const params = characterId ? { character_id: characterId } : {}
return request('/memory/memories', { data: params })
},
/**
* 获取用户档案
*/
getMemoryProfile: () => request('/memory/profile')
}
// ==================== 角色模块 API ====================
const character = {
/**
* 获取角色列表
* @param {object} params - 查询参数 { page, limit, gender, category }
*/
getList: (params = {}) => request('/characters', {
data: { page: 1, limit: 20, ...params }
}),
/**
* 获取角色详情
* @param {string} id - 角色ID
*/
getDetail: (id) => request(`/characters/${id}`),
/**
* 随机推荐角色
* @param {number} count - 数量
* @param {object} options - 可选参数
* @param {Array<string>} options.excludeIds - 排除的角色ID列表
* @param {string} options.gender - 性别筛选 (male/female)
*/
getRandom: (count = 6, options = {}) => {
const params = { count }
if (options.excludeIds && options.excludeIds.length > 0) {
params.excludeIds = options.excludeIds.join(',')
}
if (options.gender) {
params.gender = options.gender
}
return request('/characters/random', { data: params })
},
/**
* 喜欢/取消喜欢角色
* @param {string} id - 角色ID
*/
toggleLike: (id) => request(`/characters/${id}/like`, {
method: 'POST'
}),
/**
* 获取喜欢的角色列表
*/
getLikedList: () => request('/characters/liked'),
/**
* 解锁角色
* @param {object} data - { character_id, unlock_type: 'hearts'|'payment' }
*/
unlock: (data) => request('/characters/unlock', {
method: 'POST',
data
}),
/**
* 检查角色是否已解锁
* @param {string} id - 角色ID
*/
checkUnlockStatus: (id) => request(`/characters/${id}/unlock-status`, {
silent: true
})
}
// ==================== 聊天模块 API ====================
const chat = {
/**
* 发送AI聊天消息使用简化版非流式API
* @param {object} data - { character_id, message, conversation_id }
*/
sendMessage: (data) => request('/chat/simple', {
method: 'POST',
data
}),
/**
* 获取聊天配额状态
* @param {string} characterId - 角色ID
*/
getQuota: (characterId) => request('/chat/quota', {
data: { character_id: characterId },
silent: true
}),
/**
* 消费聊天配额
* @param {string} characterId - 角色ID
*/
consumeQuota: (characterId) => request('/chat/quota/consume', {
method: 'POST',
data: { character_id: characterId }
}),
/**
* 获取会话列表
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getConversations: () => request('/conversations', { silent: true }),
/**
* 删除会话
* @param {string} conversationId - 会话ID
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
deleteConversation: (conversationId) => request(`/conversations/${conversationId}`, {
method: 'DELETE'
}),
/**
* 清空聊天记录(保留会话)
* @param {string} characterId - 角色ID
* 注意:只清空聊天记录,会话仍然显示在消息列表中
* 使用后端提供的 /api/memory/chat-history/by-character 接口
*/
clearChatHistory: (characterId) => request(`/memory/chat-history/by-character?character_id=${characterId}&action=clear`, {
method: 'POST'
}),
/**
* 创建会话
* @param {string} characterId - 角色ID
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
createConversation: (characterId) => request('/conversations', {
method: 'POST',
data: {
targetId: characterId,
targetType: 'character'
}
}),
/**
* 获取聊天历史通过会话ID
* @param {string} conversationId - 会话ID
* @param {object} params - 分页参数
*/
getChatHistory: (conversationId, params = {}) => request('/memory/chat-history', {
data: { conversation_id: conversationId, ...params }
}),
/**
* 获取聊天历史通过角色ID
* @param {string} characterId - 角色ID
* @param {object} params - 分页参数
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getChatHistoryByCharacter: (characterId, params = {}) => {
// 手动构建查询参数字符串(微信小程序不支持 URLSearchParams
const queryParts = [`character_id=${encodeURIComponent(characterId)}`]
// 添加其他参数
Object.keys(params).forEach(key => {
if (params[key] !== undefined && params[key] !== null) {
queryParts.push(`${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
}
})
const queryString = queryParts.join('&')
const fullUrl = `/memory/chat-history/by-character?${queryString}`
console.log('[API] getChatHistoryByCharacter 请求URL:', fullUrl)
console.log('[API] characterId:', characterId, 'params:', params)
return request(fullUrl, {
method: 'GET',
silent: true // 静默模式401时不清除登录状态
})
},
/**
* 标记会话已读
* @param {string} conversationId - 会话ID
*/
markAsRead: (conversationId) => request(`/conversations/${conversationId}/read`, {
method: 'POST',
silent: true // 静默模式401时不弹出登录提示
}),
/**
* 切换聊天模式AI/真人)
* @param {string} conversationId - 会话ID
* @param {string} mode - 模式 (ai/human)
*/
switchMode: (conversationId, mode) => request(`/conversations/${conversationId}/switch-mode`, {
method: 'POST',
data: { mode }
}),
/**
* 发送图片消息
* @param {object} data - { character_id, conversation_id, image_url }
*/
sendImage: (data) => request('/chat/send-image', {
method: 'POST',
data
}),
/**
* 获取免费畅聊时间
*/
getFreeTime: () => request('/chat/free-time', {
silent: true
}),
/**
* 领取免费畅聊时间
*/
claimFreeTime: () => request('/chat/free-time/claim', {
method: 'POST'
})
}
// ==================== 陪聊模块 API ====================
const companion = {
/**
* 发送陪聊消息
* @param {object} data - { order_id, message }
*/
sendMessage: (data) => request('/companion-chat', {
method: 'POST',
data
}),
/**
* 获取陪聊师列表
* 返回数据包含等级信息levelCode, levelName, textPrice, voicePrice
* @param {object} params - 查询参数 { status, gender, sortBy, page, pageSize }
*/
getList: (params = {}) => request('/companions', {
data: { page: 1, pageSize: 20, ...params }
}),
/**
* 获取陪聊师详情
* 返回数据包含等级信息levelCode, levelName, textPrice, voicePrice
* @param {string} id - 陪聊师ID
*/
getDetail: (id) => request(`/companions/${id}`),
/**
* 获取陪聊师状态(包含等级信息)
* 返回数据包含isCompanion, companionId, levelCode, levelName, textPrice, voicePrice
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getStatus: () => request('/companion/status'),
/**
* 更新在线状态
* @param {string} status - 状态 (online/busy/offline)
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
updateStatus: (status) => request('/companion/status', {
method: 'POST',
data: { status }
}),
/**
* 获取申请状态
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getApplyStatus: () => request('/companion/apply'),
/**
* 申请成为陪聊师
* @param {object} data - 申请资料
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
apply: (data) => request('/companion/apply', {
method: 'POST',
data
}),
/**
* AI辅助回复
* @param {object} data - { message, context }
*/
aiAssist: (data) => request('/companion/ai-assist', {
method: 'POST',
data
}),
/**
* 获取工作台数据(包含等级信息)
* 返回数据包含levelCode, levelName, textPrice, voicePrice
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getWorkbench: () => request('/companion/workbench'),
/**
* 获取客户列表
* @param {object} params - 查询参数 { keyword, page, pageSize }
*/
getCustomers: (params = {}) => request('/companion/customers', {
data: params
}),
/**
* 获取陪聊师订单列表
* @param {object} params - 查询参数 { status, page, pageSize }
*/
getOrders: (params = {}) => request('/companion/orders', {
data: params
}),
/**
* 获取陪聊师订单统计
*/
getOrderStats: () => request('/companion/orders/stats'),
/**
* 获取所有等级配置
* 返回等级列表:[{ levelCode, levelName, textPrice, voicePrice }]
*/
getLevels: () => request('/companion/levels'),
/**
* 获取陪聊师评价列表
* @param {string} companionId - 陪聊师ID
* @param {object} params - 查询参数 { page, limit }
*/
getReviews: (companionId, params = {}) => request(`/companions/${companionId}/reviews`, {
data: { page: 1, limit: 10, ...params }
}),
/**
* 点赞评价
* @param {string} reviewId - 评价ID
*/
likeReview: (reviewId) => request(`/reviews/${reviewId}/like`, {
method: 'POST'
}),
/**
* 陪聊师回复评价
* @param {string} reviewId - 评价ID
* @param {string} reply - 回复内容
*/
replyReview: (reviewId, reply) => request(`/reviews/${reviewId}/reply`, {
method: 'POST',
data: { reply }
})
}
// ==================== 语音合成 API ====================
const tts = {
/**
* 文字转语音
* @param {object} data - { text, voice_id, character_id }
*/
synthesize: (data) => request('/tts', {
method: 'POST',
data
}),
/**
* 查询TTS状态
* @param {string} taskId - 任务ID
*/
getStatus: (taskId) => request('/tts/status', {
data: { task_id: taskId }
})
}
// ==================== 语音识别 API ====================
const speech = {
/**
* 语音识别 - 将语音转换为文字
* @param {object} data - { audio: base64编码的音频, format: 音频格式(mp3/wav/pcm) }
* @returns {Promise<{success: boolean, data: {text: string}}>}
*/
recognize: (data) => request('/speech/recognize', {
method: 'POST',
data
})
}
// ==================== 支付模块 API ====================
const payment = {
/**
* 获取充值套餐
*/
getPackages: () => request('/payment/packages'),
/**
* 创建充值订单
* @param {object} data - { packageId, amount, paymentMethod }
*/
createRechargeOrder: (data) => request('/payment/recharge', {
method: 'POST',
data
}),
/**
* 创建VIP订单
* @param {object} data - { planId, duration, paymentMethod }
*/
createVipOrder: (data) => request('/payment/vip', {
method: 'POST',
data
}),
/**
* 获取支付参数(统一下单)
* @param {object} data - { orderId, orderType }
*/
prepay: (data) => request('/payment/prepay', {
method: 'POST',
data
}),
/**
* 查询订单状态
* @param {string} orderId - 订单ID
* @param {object} params - 查询参数 { confirm: 1 }
*/
queryOrder: (orderId, params = {}) => request(`/payment/orders/${orderId}`, {
method: 'GET',
data: params
}),
/**
* 取消订单
* @param {string} orderId - 订单ID
*/
cancelOrder: (orderId) => request(`/payment/orders/${orderId}/cancel`, {
method: 'POST'
}),
/**
* 测试模式充值 - 直接增加爱心余额(仅测试环境使用)
* @param {object} data - 充值参数
* @param {number} data.amount - 充值爱心数量
* @param {string} data.package_name - 套餐名称(可选)
*/
testRecharge: (data) => request('/payment/test-recharge', {
method: 'POST',
data
}),
/**
* 测试模式支付 - 直接标记订单为已支付(仅测试环境使用)
* @param {object} data - 支付参数
* @param {string} data.orderId - 订单ID
*/
testPay: (data) => request('/payment/test-pay', {
method: 'POST',
data
}),
/**
* 创建统一支付订单
* @param {object} data - 订单参数
* @param {string} data.orderType - 订单类型: recharge|vip|companion_chat|agent_purchase|identity_card
* @param {number} data.amount - 支付金额
* @param {number} data.rechargeValue - 充值金额(充值订单)
* @param {string} data.vipType - VIP类型: month|quarter|yearVIP订单
* @param {string} data.agentId - 智能体ID智能体订单
* @param {string} data.companionId - 陪聊师ID陪聊订单
* @param {number} data.duration - 陪聊时长(陪聊订单)
* @param {string} data.cardType - 身份卡类型: basic|premium身份卡订单
* @param {string} data.referralCode - 推荐码(可选)
* @param {string} data.promotionLinkCode - 推广链接码(可选)
* @param {string} data.confirm - 是否主动确认支付状态 (1)
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
createUnifiedOrder: (data) => request('/payment/unified-order', {
method: 'POST',
data
}),
/**
* 创建支付订单(兼容旧接口)
* @param {object} data - { package_id, payment_method }
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
createOrder: (data) => request('/payment/unified-order', {
method: 'POST',
data
}),
/**
* 获取订单列表
* @param {object} params - 查询参数
* @param {string} params.orderType - 订单类型(可选)
* @param {string} params.status - 订单状态(可选)
* @param {number} params.page - 页码
* @param {number} params.pageSize - 每页数量
* @param {string} params.confirm - 是否主动确认支付状态 (1)
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getOrders: (params = {}) => request('/payment/unified-order', {
data: { page: 1, pageSize: 20, ...params }
}),
/**
* 获取订单详情
* @param {string} orderId - 订单ID
* @param {object} params - { confirm: 1 }
*/
getOrderDetail: (orderId, params = {}) => request('/payment/unified-order', {
data: { orderId, ...params }
}),
/**
* 查询支付状态
* @param {string} orderId - 订单ID
* @param {object} params - { confirm: 1 }
*/
checkStatus: (orderId, params = {}) => request('/payment/unified-order', {
data: { orderId, ...params }
}),
/**
* 使用爱心值兑换套餐
* @param {object} data - 兑换参数
* @param {string} data.packageId - 套餐ID (first/month/quarter/year)
* @param {number} data.heartCost - 需要的爱心值数量
*/
exchangeWithHeart: (data) => request('/payment/exchange-with-heart', {
method: 'POST',
data
})
}
// ==================== 智能体商品 API ====================
const agentProduct = {
/**
* 获取商品列表
* @param {object} params - 查询参数
* @param {string} params.status - 状态默认active
* @param {number} params.page - 页码
* @param {number} params.pageSize - 每页数量
*/
getList: (params = {}) => request('/agent-products', {
data: { status: 'active', page: 1, pageSize: 20, ...params }
}),
/**
* 获取商品详情
* @param {string} id - 商品ID
*/
getDetail: (id) => request(`/agent-products/${id}`),
/**
* 购买智能体
* @param {string} id - 商品ID
* @param {object} options - 可选参数
* @param {string} options.referralCode - 推荐码
* @param {string} options.promotionLinkCode - 推广链接码
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
purchase: (id, options = {}) => request(`/agent-products/${id}/purchase`, {
method: 'POST',
data: options
}),
/**
* 获取用户已购智能体列表
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getPurchased: () => request('/user/purchased-agents'),
/**
* 检查是否有权访问某角色
* @param {string} characterId - 角色ID
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
checkAccess: (characterId) => request('/user/purchased-agents', {
data: { action: 'checkAccess', characterId }
}),
/**
* 获取可访问的角色ID列表
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getAccessibleIds: () => request('/user/purchased-agents', {
data: { action: 'accessibleIds' }
})
}
// ==================== 页面素材 API ====================
const pageAssets = {
/**
* 获取通用素材配置
* @param {string} group - 素材分组
*/
getAssets: (group = null) => {
const url = group ? `/page-assets?group=${group}` : '/page-assets'
return request(url)
},
/**
* 获取服务页在线Banner列表
*/
getServiceBanners: () => request('/page-assets/service-banners'),
/**
* 获取娱乐页在线Banner列表
*/
getEntertainmentBanners: () => request('/page-assets/entertainment-banners'),
/**
* 获取合作入驻页在线Banner列表
*/
getCooperationBanners: () => request('/page-assets/cooperation-banners')
}
// ==================== 推广系统 API ====================
const promotion = {
/**
* 创建推广链接
* @param {object} data - 链接参数
* @param {string} data.targetType - 目标类型: agent|vip|recharge|general
* @param {string} data.targetId - 目标ID智能体推广时需要
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
createLink: (data) => request('/promotion', {
method: 'POST',
data
}),
/**
* 获取推广链接列表
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getLinks: () => request('/promotion'),
/**
* 获取推广统计
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getStats: () => request('/promotion', {
data: { action: 'stats' }
}),
/**
* 获取链接详情
* @param {string} linkId - 链接ID
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getLinkDetail: (linkId) => request('/promotion', {
data: { action: 'detail', linkId }
}),
/**
* 获取分销商排行榜
* @param {object} params - 查询参数
* @param {string} params.period - 周期: day|week|month|all
* @param {number} params.limit - 返回数量
*/
getRanking: (params = {}) => request('/promotion', {
data: { action: 'ranking', period: 'month', limit: 10, ...params }
}),
/**
* 获取分享配置
* @param {string} pageKey - 页面标识: index|promote 等
* 返回: { title, desc, path, imageUrl }
*/
getShareConfig: (pageKey) => request('/promotion/share-config', {
data: { page: pageKey }
}),
/**
* 记录分享行为
* @param {object} data - 分享参数
* @param {string} data.type - 分享类型: app_message|timeline
* @param {string} data.page - 页面路径
* @param {string} data.referralCode - 推荐码(可选)
*/
recordShare: (data) => request('/promotion', {
method: 'POST',
data: { action: 'recordShare', ...data }
})
}
// ==================== 订单模块 API ====================
const order = {
/**
* 获取订单列表
* @param {object} params - { type, status, page, limit }
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getList: (params = {}) => request('/orders', {
data: { page: 1, pageSize: 20, ...params }
}),
/**
* 获取订单详情
* @param {string} id - 订单ID
*/
getDetail: (id) => request(`/orders/${id}`),
/**
* 创建陪聊订单
* @param {object} data - { companion_id, duration, message }
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
createCompanionOrder: (data) => request('/orders/companion', {
method: 'POST',
data
}),
/**
* 取消订单
* @param {string} id - 订单ID
* @param {string} reason - 取消原因
*/
cancel: (id, reason = '') => request(`/orders/${id}/cancel`, {
method: 'POST',
data: { reason }
}),
/**
* 评价订单
* @param {string} id - 订单ID
* @param {object} data - { rating, content, tags, isAnonymous }
*/
review: (id, data) => request(`/orders/${id}/review`, {
method: 'POST',
data
}),
/**
* 获取订单大厅(陪聊师用)
*/
getHall: () => request('/orders/hall'),
/**
* 接受订单
* @param {string} id - 订单ID
*/
accept: (id) => request(`/orders/${id}/accept`, { method: 'POST' }),
/**
* 拒绝订单
* @param {string} id - 订单ID
* @param {string} reason - 拒绝原因
*/
reject: (id, reason) => request(`/orders/${id}/reject`, {
method: 'POST',
data: { reason }
}),
/**
* 开始服务
* @param {string} id - 订单ID
*/
startService: (id) => request(`/orders/${id}/start-service`, { method: 'POST' }),
/**
* 结束服务
* @param {string} id - 订单ID
*/
endService: (id) => request(`/orders/${id}/end-service`, { method: 'POST' })
}
// ==================== 佣金与提现 API ====================
const commission = {
/**
* 获取佣金统计
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getStats: () => request('/commission', { data: { action: 'stats' } }),
/**
* 获取佣金记录
* @param {object} params - 分页参数 { page, pageSize }
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getRecords: (params = {}) => request('/commission', {
data: { action: 'records', ...params }
}),
/**
* 获取推荐列表
* @param {object} params - 分页参数 { page, pageSize }
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getReferrals: (params = {}) => request('/commission', {
data: { action: 'referrals', ...params }
}),
/**
* 获取提现记录
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getWithdrawals: () => request('/commission', {
data: { action: 'withdrawals' }
}),
/**
* 绑定推荐码
* @param {string} referralCode - 推荐码
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
bindReferral: (referralCode) => request('/commission', {
method: 'POST',
data: { action: 'bindReferral', referralCode }
}),
/**
* 申请提现
* @param {object} data - 提现参数
* @param {number} data.amount - 提现金额
* @param {string} data.withdrawType - 提现方式: wechat|alipay|bank
* @param {object} data.accountInfo - 账户信息 { name, account }
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
withdraw: (data) => request('/commission', {
method: 'POST',
data: { action: 'withdraw', ...data }
})
}
// ==================== 交易流水 API ====================
const transaction = {
/**
* 获取交易流水
* @param {object} params - 查询参数
* @param {string} params.type - 交易类型(可选)
* @param {string} params.status - 状态(可选)
* @param {number} params.page - 页码
* @param {number} params.pageSize - 每页数量
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getList: (params = {}) => request('/user/transactions', {
data: { page: 1, pageSize: 20, ...params }
}),
/**
* 获取余额统计
* 注意:后端通过 Token 验证用户身份,不再需要传递 userId
*/
getStats: () => request('/user/transactions', {
data: { action: 'stats' }
})
}
const withdraw = {
/**
* 申请提现
* @param {object} data - { amount, account_type, account_info }
*/
apply: (data) => request('/withdraw/apply', {
method: 'POST',
data
}),
/**
* 获取提现记录
* @param {object} params - 分页参数
*/
getRecords: (params = {}) => request('/withdraw/records', {
data: params
})
}
// ==================== 社交广场 API ====================
const post = {
/**
* 获取动态列表
* @param {object} params - { page, limit, type }
*/
getList: (params = {}) => request('/posts', {
data: { page: 1, limit: 20, ...params }
}),
/**
* 发布动态
* @param {object} data - { content, images }
*/
create: (data) => request('/posts', {
method: 'POST',
data
}),
/**
* 获取动态详情
* @param {string} id - 动态ID
*/
getDetail: (id) => request(`/posts/${id}`),
/**
* 删除动态
* @param {string} id - 动态ID
*/
delete: (id) => request(`/posts/${id}`, { method: 'DELETE' }),
/**
* 点赞/取消点赞
* @param {string} id - 动态ID
*/
toggleLike: (id) => request(`/posts/${id}/like`, { method: 'POST' }),
/**
* 发表评论
* @param {string} postId - 动态ID
* @param {string} content - 评论内容
*/
addComment: (postId, content) => request(`/posts/${postId}/comments`, {
method: 'POST',
data: { content }
}),
/**
* 删除评论
* @param {string} postId - 动态ID
* @param {string} commentId - 评论ID
*/
deleteComment: (postId, commentId) => request(`/posts/${postId}/comments/${commentId}`, {
method: 'DELETE'
})
}
// ==================== 背包道具 API ====================
const backpack = {
/**
* 获取背包物品
*/
getItems: () => request('/backpack'),
/**
* 使用物品
* @param {string} itemId - 物品ID
*/
useItem: (itemId) => request('/backpack/use', {
method: 'POST',
data: { item_id: itemId }
}),
/**
* 赠送礼物
* @param {object} data - { item_id, target_id, target_type, quantity }
*/
giftItem: (data) => request('/backpack/gift', {
method: 'POST',
data
}),
/**
* 装备道具
* @param {string} itemId - 物品ID
*/
equipItem: (itemId) => request('/backpack/equip', {
method: 'POST',
data: { item_id: itemId }
})
}
// ==================== 商城 API ====================
const shop = {
/**
* 获取商城物品
* @param {object} params - { category }
*/
getItems: (params = {}) => request('/shop/items', {
data: params
}),
/**
* 购买物品
* @param {object} data - { item_id, quantity }
*/
buyItem: (data) => request('/shop/buy', {
method: 'POST',
data
})
}
// ==================== 客服系统 API ====================
const customerService = {
/**
* 创建咨询 (开启新会话)
* @param {object} data - { category, content, userName, userPhone, subject, guestId }
*/
create: (data) => request('/customer-service', {
method: 'POST',
data: { action: 'create', ...data }
}),
/**
* 发送回复消息
* @param {object} data - { ticketId, content, userName }
*/
reply: (data) => request('/customer-service', {
method: 'POST',
data: { action: 'reply', ...data }
}),
/**
* 获取咨询列表
* @param {string} guestId - 访客唯一ID
*/
getList: (guestId) => request(`/customer-service?guestId=${guestId}`),
/**
* 获取咨询详情及消息记录
* @param {string} ticketId - 工单ID
*/
getDetail: (ticketId) => request(`/customer-service?ticketId=${ticketId}`)
}
// ==================== 系统设置 API ====================
const settings = {
/**
* 获取用户设置
*/
get: () => request('/settings'),
/**
* 更新用户设置
* @param {object} data - 设置数据
*/
update: (data) => request('/settings', {
method: 'PUT',
data
}),
/**
* 获取黑名单
*/
getBlacklist: () => request('/settings/blacklist'),
/**
* 添加黑名单
* @param {string} userId - 用户ID
*/
addToBlacklist: (userId) => request('/settings/blacklist', {
method: 'POST',
data: { user_id: userId }
}),
/**
* 移除黑名单
* @param {string} userId - 用户ID
*/
removeFromBlacklist: (userId) => request(`/settings/blacklist/${userId}`, {
method: 'DELETE'
}),
/**
* 清除缓存
*/
clearCache: () => request('/settings/clear-cache', { method: 'POST' }),
/**
* 检查更新
*/
checkUpdate: () => request('/settings/check-update'),
/**
* 提交反馈
* @param {object} data - { type, content, contact }
*/
submitFeedback: (data) => request('/settings/feedback', {
method: 'POST',
data
})
}
// ==================== 公共接口 API ====================
const common = {
/**
* 获取审核状态
* 1 表示开启审核中0 表示关闭(正式环境)
*/
getAuditStatus: () => request('/common/audit-status'),
/**
* 获取品牌配置
* 返回品牌故事、介绍等内容
*/
getBrandConfig: () => request('/public/brand-config'),
/**
* 获取公告列表
* 返回启用的公告列表(按 sortOrder 升序排列)
*/
getNotices: () => request('/public/entertainment/notices'),
/**
* 获取公告详情
* @param {number} id - 公告ID
*/
getNoticeDetail: (id) => request(`/public/entertainment/notices/${id}`)
}
// ==================== 协议模块 API ====================
const agreement = {
/**
* 获取协议内容
* @param {string} code - 协议代码 (phone-guide, user-agreement, privacy-policy)
*/
get: (code) => request(`/agreements/${code}`)
}
// ==================== 图片回复话术 API ====================
const imageReply = {
/**
* 获取随机图片回复话术
* 用于用户发送图片时AI返回预设的话术回复
*/
getRandom: () => request('/image-reply/random')
}
// ==================== 主动推送消息 API ====================
const proactiveMessage = {
/**
* 获取待推送消息
* 返回AI角色主动发送的消息列表跟进消息和打招呼消息
* 只返回未读read_at IS NULL的消息
*/
getPending: () => request('/proactive-messages/pending', { silent: true }),
/**
* 标记消息已读
* @param {object} data - 参数(二选一)
* @param {string} data.character_id - 按角色ID标记推荐
* @param {Array<number>} data.message_ids - 按消息ID列表标记
*/
markAsRead: (data) => request('/proactive-messages/read', {
method: 'POST',
data,
silent: true
})
}
// ==================== 活动模块 API ====================
const activity = {
/**
* 获取活动列表
* @param {object} params - 查询参数
* @param {string} params.tab - 活动标签featured(精选)、newbie(新手)
* @param {string} params.category - 活动分类city(同城)、outdoor(户外)、travel(旅行)、featured(精选)
* @param {string} params.city - 城市筛选
* @param {string} params.keyword - 关键词搜索
* @param {string} params.priceType - 价格类型free(免费)、paid(付费)
* @param {string} params.dateFrom - 开始日期筛选 (YYYY-MM-DD)
* @param {string} params.dateTo - 结束日期筛选 (YYYY-MM-DD)
* @param {string} params.sortBy - 排序方式date(日期)、likes(点赞数)、participants(参与人数)
* @param {number} params.page - 页码
* @param {number} params.limit - 每页数量
*/
getList: (params = {}) => request('/entertainment/activities', { data: params }),
/**
* 获取活动详情
* @param {string} id - 活动ID
*/
getDetail: (id) => request(`/entertainment/activities/${id}`),
/**
* 获取活动参与者列表
* @param {string} id - 活动ID
* @param {object} params - 分页参数 { page, limit }
*/
getParticipants: (id, params = {}) => request(`/entertainment/activities/${id}/registrations`, {
data: params
}),
/**
* 报名活动
* @param {string} id - 活动ID
*/
signup: (id) => request(`/entertainment/activities/${id}/signup`, {
method: 'POST'
}),
/**
* 取消报名
* @param {string} id - 活动ID
*/
cancelSignup: (id) => request(`/entertainment/activities/${id}/signup`, {
method: 'DELETE'
}),
/**
* 点赞/收藏活动
* @param {string} id - 活动ID
*/
favorite: (id) => request(`/entertainment/activities/${id}/like`, {
method: 'POST'
}),
/**
* 取消点赞/收藏活动
* @param {string} id - 活动ID
*/
unfavorite: (id) => request(`/entertainment/activities/${id}/like`, {
method: 'POST'
}),
/**
* 取消点赞/取消点赞活动
* @param {string} id - 活动ID
*/
toggleLike: (id) => request(`/entertainment/activities/${id}/like`, {
method: 'POST'
}),
/**
* 获取我的报名列表
* @param {object} params - { status, page, limit }
*/
getMyRegistrations: (params = {}) => request('/my-registrations', { data: params })
}
// ==================== 兴趣搭子 API ====================
const interest = {
/**
* 获取兴趣分类列表
*/
getCategories: () => request('/interest-categories'),
/**
* 获取兴趣搭子列表
* @param {object} params - 查询参数
* @param {number} params.page - 页码
* @param {number} params.limit - 每页数量
* @param {string} params.city - 城市筛选
* @param {string} params.province - 省份筛选
* @param {number} params.category_id - 分类ID筛选
*/
getList: (params = {}) => request('/interest-partners', { data: params }),
/**
* 获取兴趣搭子详情
* @param {number} id - 搭子ID
*/
getDetail: (id) => request(`/interest-partners/${id}`)
}
// ==================== 文娱页面 API ====================
const entertainment = {
/**
* 获取首页数据(包含轮播图、分类、公告、精选活动、新手活动)
* @param {string} city - 城市名称(可选)
*/
getHome: (city = null) => {
const params = city ? { city } : {}
return request('/entertainment/home', { data: params })
},
/**
* 获取轮播Banner
*/
getBanners: () => request('/entertainment/banners'),
/**
* 获取滚动公告
*/
getNotices: () => request('/entertainment/notices'),
/**
* 每日签到
*/
checkin: () => request('/entertainment/checkin', {
method: 'POST'
}),
/**
* 获取签到记录
* @param {string} month - 月份 (YYYY-MM)
*/
getCheckinRecords: (month) => request('/entertainment/checkin/records', {
data: { month }
}),
/**
* 爱心传递
* @param {object} data - 传递信息
*/
transferLove: (data) => request('/entertainment/love/transfer', {
method: 'POST',
data
}),
/**
* 获取爱心榜
* @param {string} type - 榜单类型 (day/week/month)
* @param {number} limit - 返回数量
*/
getLoveRanking: (type = 'day', limit = 10) =>
request('/entertainment/love/ranking', {
data: { type, limit }
})
}
// ==================== 爱心值系统 API ====================
const lovePoints = {
/**
* 记录分享获得爱心值
*/
share: () => request('/love-points/share', {
method: 'POST'
}),
/**
* 登录获得爱心值B自己+100分享人也可获得+100
* 后端会检查是否有inviter参数给分享人也+100
*/
login: () => request('/love-points/login', {
method: 'POST'
}),
/**
* 获取邀请码
*/
getInvitationCode: () => request('/love-points/invitation-code'),
/**
* 完善资料获得爱心值
*/
profileComplete: () => request('/love-points/profile-complete', {
method: 'POST'
}),
/**
* 获取爱心值流水记录
* @param {object} params - 查询参数 { page, limit }
*/
getTransactions: (params = {}) => request('/love-points/transactions', {
data: { limit: 100, ...params }
}),
/**
* 检查注册奖励领取资格
*/
checkRegistrationReward: () => request('/love-points/registration-reward/check'),
/**
* 领取注册奖励
*/
claimRegistrationReward: () => request('/love-points/registration-reward', {
method: 'POST'
}),
/**
* 检查 GF100 弹窗领取资格
*/
checkGf100Status: () => request('/love-points/gf100'),
/**
* 领取 GF100 奖励
*/
claimGf100: () => request('/love-points/gf100', {
method: 'POST'
})
}
const loveExchange = {
/**
* 获取可兑换选项(包含当前爱心值余额)
*/
getOptions: () => request('/love-exchange/options'),
/**
* 使用爱心值兑换会员
* @param {object} data - { package_id, love_cost }
*/
exchangeVip: (data) => request('/love-exchange/vip', {
method: 'POST',
data
})
}
const gifts = {
/**
* 获取礼品列表
* @param {object} params - 查询参数 { category, page, limit }
*/
getList: (params = {}) => request('/gifts', {
data: params
}),
/**
* 获取礼品详情
* @param {string} id - 礼品ID
*/
getDetail: (id) => request(`/gifts/${id}`),
/**
* 兑换礼品
* @param {object} data - { giftId, shippingInfo: { name, phone, address } }
*/
exchange: (data) => request('/gifts/exchange', {
method: 'POST',
data
}),
/**
* 获取我的兑换记录
* @param {object} params - 查询参数 { page, limit }
*/
getMyExchanges: (params = {}) => request('/gifts/my-exchanges', {
data: { limit: 50, ...params }
})
}
// ==================== 推荐关系 API ====================
const referral = {
/**
* 绑定推荐关系
* @param {object} data - 绑定参数
* @param {string} data.userId - 用户ID
* @param {string} data.referralCode - 推荐码
*/
bind: (data) => request('/referral/bind', {
method: 'POST',
data
}),
/**
* 保存待绑定推荐码
* @param {object} data - 参数
* @param {string} data.userId - 用户ID
* @param {string} data.referralCode - 推荐码
*/
savePending: (data) => request('/referral/pending', {
method: 'POST',
data
}),
/**
* 获取待绑定推荐码
* @param {string} userId - 用户ID
*/
getPending: (userId) => request('/referral/pending', {
data: { userId }
})
}
// ==================== 快乐学堂 API ====================
const happySchool = {
/**
* 获取分类列表
*/
getCategories: () => request('/xinban/categories'),
/**
* 获取文章列表
* @param {object} params - 查询参数
* @param {number} params.categoryId - 分类ID
* @param {string} params.keyword - 关键词搜索
* @param {number} params.page - 页码
* @param {number} params.limit - 每页数量
*/
getArticles: (params = {}) => request('/xinban/articles', {
data: { page: 1, limit: 20, ...params }
}),
/**
* 获取文章详情
* @param {number} id - 文章ID
*/
getArticleDetail: (id) => request(`/xinban/articles/${id}`),
/**
* 点赞/取消点赞文章
* @param {number} id - 文章ID
*/
toggleLike: (id) => request(`/xinban/articles/${id}/like`, {
method: 'POST'
}),
/**
* 记录阅读
* @param {number} id - 文章ID
* @param {number} readDuration - 阅读时长(秒)
*/
recordRead: (id, readDuration = 0) => request(`/xinban/articles/${id}/read`, {
method: 'POST',
data: { readDuration }
})
}
// ==================== 导出所有API ====================
module.exports = {
// 基础方法
request,
uploadFile,
// 模块API
auth,
user,
character,
chat,
companion,
tts,
speech,
payment,
agentProduct,
pageAssets,
promotion,
order,
commission,
transaction,
withdraw,
post,
backpack,
shop,
customerService,
settings,
common,
agreement,
imageReply,
proactiveMessage,
// 娱乐页面相关API
activity,
interest,
entertainment,
// 爱心值系统API
lovePoints,
loveExchange,
gifts,
// 推荐关系API
referral,
// 快乐学堂API
happySchool
}