topfans/frontend/utils/api.js
2026-06-03 23:25:08 +08:00

1072 lines
28 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 基础配置
// 自动检测后端环境:探测开发服务器是否可用,能连通则用开发地址,否则用生产地址
// 团队开发机Gateway + 团队数据库;注册/登录/余额/铸造)
// const DEV_BASE = 'http://192.168.110.60:8080'
const DEV_BASE = 'http://localhost:8081'
const SEGMENT_BASE = 'http://localhost:8081'
const LASER_BASE = 'http://localhost:8081' // 镭射 AI 生成 + compositor 走本地 Gateway
const PROD_BASE = 'http://101.132.250.62:8080' // 生产环境
const HEALTH_URL = DEV_BASE + '/health'
<<<<<<< HEAD
// 默认生产H5 本地开发先走 DEV避免 health 探测完成前请求打到生产(生产暂无 /segment
=======
// 是否使用模拟数据(开发调试时设为 true后端API准备好后改为 false
const USE_MOCK_API = true
// 环境检测状态0=检测中, 1=开发环境, 2=生产环境
let envStatus = 0
>>>>>>> 0284bd6951fafc8a3862644ede979dc44eb6efe8
let baseURL = PROD_BASE
// #ifdef H5
if (import.meta.env.DEV) {
baseURL = DEV_BASE
console.log('[API] H5 开发模式,默认地址:', DEV_BASE)
}
// #endif
<<<<<<< HEAD
// 启动时探测开发环境是否可用(异步,不阻塞后续逻辑)
uni.request({
url: HEALTH_URL,
method: 'GET',
timeout: 2000,
success: (res) => {
if (res.statusCode === 200) {
baseURL = DEV_BASE
console.log('[API] 使用开发环境地址:', DEV_BASE)
}
},
fail: () => {
// #ifdef H5
if (import.meta.env.DEV) {
console.warn('[API] 开发 Gateway 不可达:', DEV_BASE, '— 请确认团队开发机在线,或改 DEV_BASE 为本机 8081')
return
}
// #endif
baseURL = PROD_BASE
console.log('[API] 开发环境不可用,使用生产环境地址:', PROD_BASE)
}
=======
// 环境检测 Promise确保 getApiBaseUrl / getWebSocketBaseUrl 等待检测完成
const envReadyPromise = new Promise((resolve) => {
uni.request({
url: HEALTH_URL,
method: 'GET',
timeout: 2000,
success: (res) => {
if (res.statusCode === 200) {
baseURL = DEV_BASE
envStatus = 1
console.log('[API] 使用开发环境地址:', DEV_BASE)
} else {
envStatus = 2
console.log('[API] 开发环境返回非200使用生产环境地址:', PROD_BASE)
}
resolve(envStatus)
},
fail: () => {
envStatus = 2
console.log('[API] 开发环境不可用,使用生产环境地址:', PROD_BASE)
resolve(envStatus)
}
})
>>>>>>> 0284bd6951fafc8a3862644ede979dc44eb6efe8
})
/** 等待环境检测完成(返回 'dev' | 'prod' */
export async function waitForEnvReady() {
await envReadyPromise
return envStatus === 1 ? 'dev' : 'prod'
}
/** 网关根地址(供 uni.uploadFile 等无法走 request 封装的场景拼接完整 URL */
export async function getApiBaseUrl() {
await envReadyPromise
return String(baseURL).replace(/\/+$/, '')
}
/** 获取 WebSocket 基础地址(将 http:// 替换为 ws:// */
export async function getWebSocketBaseUrl() {
await envReadyPromise
const httpUrl = String(baseURL).replace(/\/+$/, '')
return httpUrl.replace(/^http:/, 'ws:').replace(/^https:/, 'wss:')
}
// 兼容旧代码:同步版本在环境检测完成前返回默认值(生产地址)
export function getApiBaseUrlSync() {
return String(baseURL).replace(/\/+$/, '')
}
/** 抠图专用 Gateway可与 DEV_BASE 不同业务走团队库segment 走本机) */
export function getSegmentApiBaseUrl() {
return String(SEGMENT_BASE).replace(/\/+$/, '')
}
/** 镭射专用 GatewayAI 生成 + compositor 走本地,其他业务走远程) */
export function getLaserApiBaseUrl() {
return String(LASER_BASE).replace(/\/+$/, '')
}
// 模拟网络延迟
function mockDelay(ms = 800) {
return new Promise(resolve => setTimeout(resolve, ms))
}
// 请求封装
export function request(options) {
return new Promise((resolve, reject) => {
// 构建请求头
const headers = {
'Content-Type': 'application/json',
...options.header
}
// 判断是否为登录或注册接口
const isAuthRequest = options.url.includes('/api/v1/auth/login') || options.url.includes(
'/api/v1/auth/register') || options.url.includes('/api/v1/auth/send-code') || options.url.includes('/api/v1/auth/verify-code')
// 如果不是登录/注册接口则自动添加JWT token
if (!isAuthRequest) {
const token = uni.getStorageSync('access_token')
if (token) {
headers['Authorization'] = `Bearer ${token}`
}
}
uni.request({
url: baseURL + options.url,
method: options.method || 'GET',
data: options.data || {},
header: headers,
timeout: 60000,
success: (res) => {
// 处理token过期HTTP 401未授权
if (res.statusCode === 401) {
// 清除本地存储的token和用户信息
uni.removeStorageSync('access_token')
uni.removeStorageSync('user')
// 跳转到登录页
uni.reLaunch({
url: '/pages/login/login'
})
reject(new Error('登录已过期,请重新登录'))
return
}
// 可以在这里统一处理响应
if (res.statusCode === 200 || res.statusCode === 202) {
// 检查业务状态码
if (res.data && res.data.code !== undefined) {
if (res.data.code === 200) {
resolve(res.data)
} else if (res.data.code === 401 || res.data.code === 400 || res.data
.code === 403) {
// 业务状态码401/400/403未授权/冻结/封号),清除缓存并跳转到登录页
uni.removeStorageSync('access_token')
uni.removeStorageSync('user')
// 保留错误消息用于显示
const errorMsg = res.data.message || '登录已过期,请重新登录'
uni.reLaunch({
url: '/pages/login/login?error=' + encodeURIComponent(
errorMsg)
})
reject(new Error(errorMsg))
return
} else {
// 其他业务错误,返回包含 message 的错误
reject(new Error(res.data.message || '请求失败'))
}
} else {
resolve(res.data)
}
} else {
// HTTP 错误,尝试从响应中获取 message
const errorMessage = res.data?.message || `请求失败 (${res.statusCode})`
reject(new Error(errorMessage))
}
},
fail: (err) => {
reject(err)
}
})
})
}
// 登录接口
export function loginApi(mobile, password) {
return request({
url: '/api/v1/auth/login',
method: 'POST',
data: {
mobile,
password
}
})
}
// 检查昵称是否已被注册
export function checkNicknameApi(nickname) {
return request({
url: '/api/v1/auth/check-nickname',
method: 'POST',
data: {
nickname
}
})
}
// 检查手机号是否已被注册
export function checkmobileApi(mobile) {
return request({
url: '/api/v1/auth/check-mobile',
method: 'POST',
data: {
mobile
}
})
}
// 注册接口
export function registerApi(mobile, password, star_id, nickname, verify_token = '', avatar_url = '') {
return request({
url: '/api/v1/auth/register',
method: 'POST',
data: {
mobile,
password,
star_id,
nickname,
verify_token,
avatar_url
}
})
}
// 发送验证码
export function sendCodeApi(mobile, scene = 'register') {
return request({
url: '/api/v1/auth/send-code',
method: 'POST',
data: {
mobile,
scene
}
});
}
// 验证验证码
export function verifyCodeApi(mobile, code, scene = 'register') {
return request({
url: '/api/v1/auth/verify-code',
method: 'POST',
data: {
mobile,
code,
scene
}
});
}
// 更新用户信息接口
export function updateUserInfoApi(nickname) {
return request({
url: '/api/user/update',
method: 'POST',
data: {
nickname
}
})
}
// 获取随机用户列表(广场页面使用)
export function getRandomUsersApi(page = 1, pageSize) {
return request({
url: `/api/v1/social/users?page=${page}&page_size=${pageSize}`,
method: 'GET'
})
}
// 好友列表接口
export function friendListApi(page = 1, pageSize = 10) {
return request({
url: `/api/v1/social/friends?page=${page}&page_size=${pageSize}`,
method: 'GET'
})
}
// 获取用户信息接口从缓存或API
export function getUserProfileApi() {
return request({
url: '/api/v1/auth/me',
method: 'GET'
})
}
// 修改昵称接口
export function updateNicknameApi(nickname) {
return request({
url: '/api/v1/me/nickname',
method: 'PUT',
data: {
nickname
}
})
}
// 模拟注销账号接口
async function mockDeleteAccountApi() {
await mockDelay(600) // 模拟网络延迟
return {
code: 200,
message: '账号注销成功',
data: null
}
}
// 注销账号接口
export function deleteAccountApi() {
if (USE_MOCK_API) {
return mockDeleteAccountApi()
}
return request({
url: '/api/user/delete-account',
method: 'POST'
})
}
// 修改密码接口
export function updatePasswordApi(oldPassword, newPassword) {
return request({
url: '/api/v1/account/password',
method: 'POST',
data: {
old_password: oldPassword,
new_password: newPassword
}
})
}
// 搜索用户
export function searchUserApi(friendUserId) {
return request({
url: `/api/v1/social/search-user?friend_fan_profile_id=${friendUserId}`,
method: 'GET'
})
}
// 获取已发送的好友请求
export function getSentFriendRequestsApi(page = 1, pageSize = 10) {
return request({
url: `/api/v1/social/friend-requests?type=sent&status=pending&page=${page}&page_size=${pageSize}`,
method: 'GET'
})
}
// 发送好友请求(添加好友)
export function sendFriendRequestApi(friendUserId) {
return request({
url: '/api/v1/social/friend-requests',
method: 'POST',
data: {
friend_user_id: friendUserId
}
})
}
// 获取收到的好友请求
export function getReceivedFriendRequestsApi(page = 1, pageSize = 10) {
return request({
url: `/api/v1/social/friend-requests?type=received&status=pending&page=${page}&page_size=${pageSize}`,
method: 'GET'
})
}
// 处理好友请求(接受/拒绝)
export function handleFriendRequestApi(requestId, action) {
return request({
url: '/api/v1/social/friend-requests/handle',
method: 'POST',
data: {
request_id: requestId,
action: action
}
})
}
// 删除好友
export function deleteFriendApi(friendUserId) {
return request({
url: '/api/v1/social/friends',
method: 'DELETE',
data: {
friend_user_id: friendUserId
}
})
}
// 获取可选的粉丝身份列表
export function getFanIdentitiesApi() {
return request({
url: '/api/v1/fan-identities',
method: 'GET'
})
}
// 添加新的粉丝身份
export function addFanIdentityApi(starId, nickname) {
return request({
url: '/api/v1/my/fan-identities',
method: 'POST',
data: {
star_id: starId,
nickname: nickname
}
})
}
// 获取用户当前拥有的所有粉丝身份
export function getMyFanIdentitiesApi() {
return request({
url: '/api/v1/my/fan-identities',
method: 'GET'
})
}
// 切换粉丝身份
export function switchFanIdentityApi(newStarId) {
return request({
url: '/api/v1/my/fan-identities/switch',
method: 'POST',
data: {
new_star_id: newStarId
}
})
}
// 获取用户藏品列表
export function getMyAssetsApi(page = 1, pageSize = 20) {
return request({
url: `/api/v1/assets/me/items?page=${page}&page_size=${pageSize}`,
method: 'GET'
})
}
// 获取藏品详情
export function getAssetDetailApi(assetId) {
return request({
url: `/api/v1/assets/${assetId}`,
method: 'GET'
})
}
// 点赞藏品
export function likeAssetApi(assetId) {
return request({
url: `/api/v1/social/assets/${assetId}/like`,
method: 'POST'
})
}
// 取消点赞藏品
export function unlikeAssetApi(assetId) {
return request({
url: `/api/v1/social/assets/${assetId}/like`,
method: 'DELETE'
})
}
// 获取资产点赞用户列表
export function getAssetLikersApi(assetId, pageSize = 6, cursor = 0) {
return request({
url: `/api/v1/social/assets/${assetId}/likers?page_size=${pageSize}&cursor=${cursor}`,
method: 'GET'
})
}
// 获取我的展馆槽位信息
export function getMyGalleriesApi() {
return request({
url: '/api/v1/mygalleries',
method: 'GET'
})
}
// 获取指定用户的展馆槽位信息
export function getUserGalleriesApi(targetUid) {
return request({
url: `/api/v1/galleries/${targetUid}`,
method: 'GET'
})
}
// 获取随机用户的展馆槽位信息
export function getRandomGalleryApi() {
return request({
url: '/api/v1/galleries/random',
method: 'GET'
})
}
// 放置藏品到展馆
export function placeAssetToGalleryApi(assetId, galleryOwnerId, slotId) {
return request({
url: '/api/v1/galleries/place',
method: 'POST',
data: {
asset_id: assetId,
gallery_owner_id: galleryOwnerId,
slot_id: slotId
}
})
}
// 下架藏品
export function removeAssetFromGalleryApi(slotId) {
return request({
url: `/api/v1/galleries/slots/${slotId}/asset`,
method: 'DELETE'
})
}
/**
* 获取 OSS 浏览器直传凭证PostObject 表单字段)
* 对应网关GET /api/v1/assets/oss/upload-signature与 /oss/signature 同一处理逻辑,此处走阶段一推荐路径)
* @param {'avatar'|'asset'} [type='asset'] 上传目录类型
* @param {string} [orderId] 可选;传入则与后续 POST /api/v1/assets/mints 使用同一 order_id后端 InitMintOrder
*/
export function getOssSignatureApi(type = 'asset', orderId = '') {
let url = `/api/v1/assets/oss/upload-signature?type=${encodeURIComponent(type)}`
if (orderId) {
url += `&order_id=${encodeURIComponent(orderId)}`
}
return request({
url,
method: 'GET'
})
}
/** 兼容旧调用名:与 getOssSignatureApi 相同 */
export const getOssUploadSignatureApi = getOssSignatureApi
/**
* 获取公开 OSS 上传签名(注册等未登录场景用)
* 对应网关GET /api/v1/public/oss/upload-signature
* @param {string} scene 场景,目前固定为 'register'
* @param {string} key 命名空间,注册场景下传 mobile用于服务端限定上传目录
*/
export function getPublicOssSignatureApi(scene, key) {
return request({
url: `/api/v1/public/oss/upload-signature?scene=${encodeURIComponent(scene)}&key=${encodeURIComponent(key)}`,
method: 'GET'
})
}
/**
* 获取 OSS 预签名 GET URL私有桶读图
* 对应网关GET /api/v1/assets/oss/presigned-url
*/
export function getOssPresignedUrlApi(fileName, expires = 3600, type = 'avatar') {
return request({
url: `/api/v1/assets/oss/presigned-url?file_name=${encodeURIComponent(fileName)}&expires=${expires}&type=${type}`,
method: 'GET'
})
}
/**
* 批量预签名读 URL
* 对应网关GET /api/v1/assets/oss/batch-presigned-urls
*/
export function getBatchOssPresignedUrlsApi(files, expires = 3600, type = 'asset') {
return request({
url: `/api/v1/assets/oss/batch-presigned-urls?files=${encodeURIComponent(JSON.stringify(files))}&expires=${expires}&type=${type}`,
method: 'GET'
})
}
/**
* 使用网关下发的 Post 策略将本地临时文件直传 OSSApp / 小程序等)
* @param {string} filePath uni.chooseImage 等返回的 tempFilePaths 项
* @param {{ type?: 'avatar'|'asset', orderId?: string, fileName?: string }} [options]
* @returns {Promise<{ imageUrl: string, orderId?: string, data: object }>}
*/
export function uploadLocalFileToOss(filePath, options = {}) {
const {
type = 'asset', orderId = '', fileName
} = options
const objectName = fileName || `${Date.now()}.jpg`
return new Promise((resolve, reject) => {
getOssSignatureApi(type, orderId)
.then((signRes) => {
if (!signRes || signRes.code !== 200 || !signRes.data) {
reject(new Error((signRes && signRes.message) || '获取 OSS 签名失败'))
return
}
const d = signRes.data
const host = d.host
const dir = d.dir || ''
if (!host) {
reject(new Error('签名数据缺少 host'))
return
}
uni.uploadFile({
url: host,
filePath,
name: 'file',
formData: {
key: dir + objectName,
policy: d.policy,
success_action_status: '200',
'x-oss-credential': d.x_oss_credential,
'x-oss-date': d.x_oss_date,
'x-oss-security-token': d.security_token,
'x-oss-signature': d.signature,
'x-oss-signature-version': d.x_oss_signature_version
},
success: (uploadRes) => {
const ok = uploadRes.statusCode === 200 || uploadRes.statusCode === 204
if (!ok) {
reject(new Error(`OSS 上传失败 HTTP ${uploadRes.statusCode}`))
return
}
const imageUrl = `${host.replace(/\/+$/, '')}/${dir}${objectName}`
resolve({
imageUrl,
orderId: d.order_id,
data: d
})
},
fail: (e) => {
reject(new Error(e.errMsg || 'OSS 上传失败'))
}
})
})
.catch(reject)
})
}
// 更新用户头像
export function updateAvatarApi(avatarUrl) {
return request({
url: '/api/v1/me/avatar',
method: 'PUT',
data: {
avatar_url: avatarUrl
}
})
}
// 创建铸造订单
export function createMintOrderApi(orderData) {
return request({
url: '/api/v1/assets/mints',
method: 'POST',
data: orderData
})
}
// 删除铸造订单
export function deleteMintOrderApi(orderId) {
return request({
url: `/api/v1/assets/mints/${orderId}`,
method: 'DELETE'
})
}
// 获取铸造订单详情
export function getMintOrderDetailApi(orderId) {
return request({
url: `/api/v1/assets/mints/${orderId}`,
method: 'GET'
})
}
// 估算铸造费用(显示消耗和余额)
export function estimateMintCostApi() {
return request({
url: '/api/v1/assets/mints/cost-estimate',
method: 'POST'
})
}
// 上传素材(返回 material_id
export function uploadMaterialApi(data) {
return request({
url: '/api/v1/assets/materials/upload',
method: 'POST',
data
})
}
// 绑定资产素材关联
export function bindAssetMaterialsApi(assetId, materials) {
return request({
url: `/api/v1/assets/${assetId}/materials`,
method: 'POST',
data: { materials }
})
}
// 获取资产素材列表
export function getAssetMaterialsApi(assetId) {
return request({
url: `/api/v1/assets/${assetId}/materials`,
method: 'GET'
})
}
/**
* 解析抠图接口 JSON 响应
*/
function parseSegmentPortraitResponse(statusCode, rawBody) {
let body = rawBody
try {
body = typeof body === 'string' ? JSON.parse(body) : body
} catch (e) {
if (statusCode === 404) {
throw new Error(
'抠图接口 404团队 Gateway 暂无 /segment请在本机执行 start-all.ps1 并确认 SEGMENT_BASE 指向 8081'
)
}
throw new Error('抠图接口返回非 JSON')
}
if (statusCode === 401) {
throw new Error('登录已过期')
}
if (statusCode < 200 || statusCode >= 300) {
const msg = body?.message || `抠图失败 HTTP ${statusCode}`
throw new Error(msg)
}
if (body?.code !== undefined && body.code !== 200) {
throw new Error(body.message || '抠图失败')
}
return body
}
function isH5SpecialImagePath(path) {
return /^blob:/i.test(path) || /^data:image\//i.test(path)
}
/**
* H5blob/data URL 无法用 uni.uploadFile改 fetch + FormData
* @param {string} filePath
* @param {string} [imageBase64]
*/
async function segmentPortraitApiH5(filePath, imageBase64) {
const token = uni.getStorageSync('access_token')
const source = (imageBase64 && String(imageBase64).startsWith('data:'))
? String(imageBase64)
: filePath
const res = await fetch(source)
const blob = await res.blob()
const fd = new FormData()
const ext = (blob.type || '').includes('png') ? 'png' : 'jpg'
fd.append('image', blob, `upload.${ext}`)
fd.append('scene', 'portrait')
const headers = {}
if (token) {
headers.Authorization = `Bearer ${token}`
}
const uploadRes = await fetch(`${getSegmentApiBaseUrl()}/api/v1/segment`, {
method: 'POST',
headers,
body: fd,
})
const text = await uploadRes.text()
return parseSegmentPortraitResponse(uploadRes.status, text)
}
/**
* 人像抠图multipart— POST /api/v1/segment?scene=portrait
* @param {string} filePath 本地图片路径
* @param {{ imageBase64?: string }} [options] H5 可传 data URL 作兜底
* @returns {Promise<{ code: number, data: { success: boolean, cutout_oss_key?: string, cutout_url_signed?: string, error_code?: string, message?: string } }>}
*/
export function segmentPortraitApi(filePath, options = {}) {
const path = String(filePath || '').trim()
const imageBase64 = options.imageBase64 || ''
// #ifdef H5
if (isH5SpecialImagePath(path) || (imageBase64 && imageBase64.startsWith('data:'))) {
return segmentPortraitApiH5(path, imageBase64)
}
// #endif
return new Promise((resolve, reject) => {
const token = uni.getStorageSync('access_token')
uni.uploadFile({
url: `${getSegmentApiBaseUrl()}/api/v1/segment`,
filePath: path,
name: 'image',
formData: { scene: 'portrait' },
timeout: 120000,
header: token ? { Authorization: `Bearer ${token}` } : {},
success: (res) => {
try {
resolve(parseSegmentPortraitResponse(res.statusCode, res.data))
} catch (e) {
reject(e)
}
},
fail: (err) => reject(new Error(err?.errMsg || '抠图请求失败')),
})
})
}
// 图生图
export function imageGenerationApi(params) {
return request({
url: '/api/v1/assets/mints/image/generation',
method: 'POST',
data: params
})
}
// 获取热度排行榜
export function getHotRankingApi(dimension = 'total', starId = null, page = 1, pageSize = 10) {
let url = `/api/v1/rankings/hot?dimension=${dimension}&page=${page}&page_size=${pageSize}`
if (starId) {
url += `&star_id=${starId}`
}
return request({
url: url,
method: 'GET'
})
}
// 获取自制排行榜
export function getOriginalRankingApi(dimension = 'total', starId = null, page = 1, pageSize = 10) {
let url = `/api/v1/rankings/original?dimension=${dimension}&page=${page}&page_size=${pageSize}`
if (starId) {
url += `&star_id=${starId}`
}
return request({
url: url,
method: 'GET'
})
}
// ==================== 活动相关接口 ====================
// 获取活动列表
export function getActivityListApi(starId, page = 1, pageSize = 10) {
let url = `/api/v1/activities?star_id=${starId}&page=${page}&page_size=${pageSize}`
// if (status) {
// url += `&status=${status}`
// }
return request({
url: url,
method: 'GET'
})
}
// 获取活动详情
export function getActivityDetailApi(activityId) {
return request({
url: `/api/v1/activities/${activityId}`,
method: 'GET'
})
}
// 获取活动道具列表
export function getActivityItemsApi(activityId) {
return request({
url: `/api/v1/activities/${activityId}/items`,
method: 'GET'
})
}
// 获取活动进度
export function getActivityProgressApi(activityId) {
return request({
url: `/api/v1/activities/${activityId}/progress`,
method: 'GET'
})
}
// 购买活动道具
export function purchaseActivityItemApi(activityId, itemType, quantity = 1) {
return request({
url: `/api/v1/activities/${activityId}/purchase`,
method: 'POST',
data: {
item_type: itemType,
quantity: quantity
}
})
}
// 批量购买活动道具
export function batchPurchaseActivityItemsApi(activityId, items) {
return request({
url: `/api/v1/activities/${activityId}/batch-purchase`,
method: 'POST',
data: {
items: items
}
})
}
// 获取活动最新贡献记录(实时轮询用)
export function getActivityContributionsLatestApi(activityId, sinceTimestamp = 0, sinceId = 0, limit = 5) {
return request({
url: `/api/v1/activities/${activityId}/contributions/latest?since_timestamp=${sinceTimestamp}&since_id=${sinceId}&limit=${limit}`,
method: 'GET'
})
}
// 获取活动贡献点排名
export function getActivityRankingApi(activityId, starId = null, page = 1, pageSize = 10) {
let url = `/api/v1/activities/${activityId}/ranking?page=${page}&page_size=${pageSize}`
if (starId) {
url += `&star_id=${starId}`
}
return request({
url: url,
method: 'GET'
})
}
// ==================== 星册相关接口 ====================
// 获取星册首页数据
export function getStarbookHomeApi() {
return request({
url: '/api/v1/starbook/home',
method: 'GET'
})
}
// 获取星册藏品列表(分页)
export function getStarbookItemsApi(type, category, grade = null, page = 1, pageSize = 20) {
let url = `/api/v1/starbook/items?type=${type}&category=${category}&page=${page}&page_size=${pageSize}`
if (grade !== null) {
url += `&grade=${grade}`
}
return request({
url: url,
method: 'GET'
})
}
// ==================== 他人作品统计接口 ====================
// 获取他人点赞的作品列表
export function getUserLikedAssetsApi(userId, page = 1, pageSize = 20) {
return request({
url: `/api/v1/users/${userId}/liked-assets?page=${page}&page_size=${pageSize}`,
method: 'GET'
})
}
// 获取他人展出的作品列表
export function getUserExhibitedAssetsApi(userId, page = 1, pageSize = 20) {
return request({
url: `/api/v1/users/${userId}/exhibited-assets?page=${page}&page_size=${pageSize}`,
method: 'GET'
})
}
// ==================== 我的作品统计接口 ====================
// 获取我展出的作品列表
export function getMyExhibitedAssetsApi(page = 1, pageSize = 20) {
return request({
url: `/api/v1/me/exhibited-assets?page=${page}&page_size=${pageSize}`,
method: 'GET'
})
}
// 获取我点赞的作品列表
export function getMyLikedAssetsApi(page = 1, pageSize = 20) {
return request({
url: `/api/v1/me/liked-assets?page=${page}&page_size=${pageSize}`,
method: 'GET'
})
}
// 获取我今日点赞的作品列表
export function getMyTodayLikedAssetsApi(page = 1, pageSize = 20) {
return request({
url: `/api/v1/me/today-liked-assets?page=${page}&page_size=${pageSize}`,
method: 'GET'
})
}
// 获取我本周点赞的作品列表
export function getMyWeekLikedAssetsApi(page = 1, pageSize = 20) {
return request({
url: `/api/v1/me/week-liked-assets?page=${page}&page_size=${pageSize}`,
method: 'GET'
})
}
// ==================== 灵感瀑布相关接口 ====================
// 获取灵感瀑布藏品列表
export function getInspirationFlowApi(params) {
return request({
url: '/api/v1/inspiration-flow',
method: 'GET',
data: params
})
}
// ==================== 铸造活动相关接口运营banner====================
// 获取铸造活动列表
export function getMintingActivitiesApi(starId = null, page = 1, pageSize = 10) {
let url = `/api/v1/minting-activities?page=${page}&page_size=${pageSize}`
if (starId) {
url += `&star_id=${starId}`
}
return request({
url: url,
method: 'GET'
})
}
// 获取收益汇总接口
export function getEarningsSummaryApi() {
return request({
url: '/api/v1/assets/me/earnings-summary',
method: 'GET'
})
}
// ==================== 数据看板 ====================
import { mockRouter } from './mock/dashboard'
const DASHBOARD_PREFIX = '/api/v1/dashboard'
// mock 触发器:当 USE_MOCK_API 为 true 时短路返回 mock 数据
// 后端就绪后将 USE_MOCK_API 改为 false 即可
async function dashboardRequest(endpoint, params = {}) {
if (USE_MOCK_API) {
const factory = mockRouter[`${DASHBOARD_PREFIX}${endpoint}`]
if (factory) return factory(params)
}
return request({ url: `${DASHBOARD_PREFIX}${endpoint}`, method: 'GET', data: params })
}
export const dashboardApi = {
getTodayOverview: (starId) => dashboardRequest('/today-overview', { star_id: starId }),
get7DayIncomeCurve: (starId) => dashboardRequest('/income-curve', { star_id: starId }),
getExhibitionSummary: (starId) => dashboardRequest('/exhibition-summary', { star_id: starId }),
getLikeIncomeByLevel: (starId) => dashboardRequest('/like-income-by-level', { star_id: starId }),
getTopAssets: (starId) => dashboardRequest('/top-assets', { star_id: starId }),
getLevelDistribution: (starId) => dashboardRequest('/level-distribution', { star_id: starId }),
getUpgradeProgress: (starId) => dashboardRequest('/upgrade-progress', { star_id: starId }),
}