150 lines
4.4 KiB
JavaScript
150 lines
4.4 KiB
JavaScript
/**
|
|
* 活动相关工具函数
|
|
* 从 yifanshang/duiduipeng/wuxianshang 页面中提取的公共逻辑
|
|
*/
|
|
|
|
/**
|
|
* 解包API返回的数据
|
|
* @param {any} list - API返回的数据
|
|
* @returns {Array} 数组
|
|
*/
|
|
export function unwrap(list) {
|
|
if (Array.isArray(list)) return list
|
|
const obj = list || {}
|
|
const data = obj.data || {}
|
|
const arr = obj.list || obj.items || data.list || data.items || data
|
|
return Array.isArray(arr) ? arr : []
|
|
}
|
|
|
|
/**
|
|
* 判断真值(支持多种格式)
|
|
* @param {any} v - 待判断的值
|
|
* @returns {boolean}
|
|
*/
|
|
export function truthy(v) {
|
|
if (typeof v === 'boolean') return v
|
|
const s = String(v || '').trim().toLowerCase()
|
|
if (!s) return false
|
|
return s === '1' || s === 'true' || s === 'yes' || s === 'y' || s === '是' || s === 'boss是真的' || s === 'boss' || s === '大boss'
|
|
}
|
|
|
|
/**
|
|
* 检测是否为BOSS奖
|
|
* @param {Object} item - 奖品对象
|
|
* @returns {boolean}
|
|
*/
|
|
export function detectBoss(item) {
|
|
const i = item || {}
|
|
return truthy(i.is_boss) || truthy(i.boss) || truthy(i.isBoss) || truthy(i.boss_true) || truthy(i.boss_is_true) || truthy(i.bossText) || truthy(i.tag)
|
|
}
|
|
|
|
/**
|
|
* 等级数字转字母 (1 -> A, 2 -> B, ...)
|
|
* @param {number|string} level - 等级
|
|
* @returns {string}
|
|
*/
|
|
export function levelToAlpha(level) {
|
|
if (level === 'BOSS') return 'BOSS'
|
|
const n = Number(level)
|
|
if (isNaN(n) || n <= 0) return String(level || '赏')
|
|
return String.fromCharCode(64 + n)
|
|
}
|
|
|
|
/**
|
|
* 状态转文本
|
|
* @param {number} status - 状态码
|
|
* @returns {string}
|
|
*/
|
|
export function statusToText(status) {
|
|
if (status === 1) return '进行中'
|
|
if (status === 0) return '未开始'
|
|
if (status === 2) return '已结束'
|
|
return String(status || '')
|
|
}
|
|
|
|
/**
|
|
* 标准化期列表数据
|
|
* @param {any} list - API返回的期列表
|
|
* @returns {Array}
|
|
*/
|
|
export function normalizeIssues(list) {
|
|
const arr = unwrap(list)
|
|
return arr.map((i, idx) => ({
|
|
id: i.id ?? String(idx),
|
|
title: i.title ?? i.name ?? '',
|
|
no: i.no ?? i.index ?? i.issue_no ?? i.issue_number ?? null,
|
|
status_text: i.status_text ?? (i.status === 1 ? '进行中' : i.status === 0 ? '未开始' : i.status === 2 ? '已结束' : '')
|
|
}))
|
|
}
|
|
|
|
/**
|
|
* 标准化奖励列表数据
|
|
* @param {any} list - API返回的奖励列表
|
|
* @param {Function} cleanUrl - URL清理函数
|
|
* @returns {Array}
|
|
*/
|
|
export function normalizeRewards(list, cleanUrl = (u) => u) {
|
|
const arr = unwrap(list)
|
|
const items = arr.map((i, idx) => ({
|
|
id: i.product_id ?? i.id ?? String(idx),
|
|
title: i.name ?? i.title ?? '',
|
|
image: cleanUrl(i.product_image ?? i.image ?? i.img ?? i.pic ?? i.banner ?? ''),
|
|
weight: Number(i.weight) || 0,
|
|
boss: detectBoss(i),
|
|
level: levelToAlpha(i.prize_level ?? i.level ?? (detectBoss(i) ? 'BOSS' : '赏'))
|
|
}))
|
|
const total = items.reduce((acc, it) => acc + (it.weight > 0 ? it.weight : 0), 0)
|
|
const enriched = items.map(it => ({
|
|
...it,
|
|
percent: total > 0 ? Math.round((it.weight / total) * 1000) / 10 : 0
|
|
}))
|
|
enriched.sort((a, b) => (b.percent - a.percent))
|
|
return enriched
|
|
}
|
|
|
|
/**
|
|
* 查找最新的期ID
|
|
* @param {Array} list - 期列表
|
|
* @returns {string}
|
|
*/
|
|
export function pickLatestIssueId(list) {
|
|
const arr = Array.isArray(list) ? list : []
|
|
let latest = arr[arr.length - 1] && arr[arr.length - 1].id
|
|
let maxNo = -Infinity
|
|
arr.forEach(i => {
|
|
const n = Number(i.no)
|
|
if (!Number.isNaN(n) && Number.isFinite(n) && n > maxNo) {
|
|
maxNo = n
|
|
latest = i.id
|
|
}
|
|
})
|
|
return latest || (arr[0] && arr[0].id) || ''
|
|
}
|
|
|
|
/**
|
|
* 按等级分组奖励
|
|
* @param {Array} rewards - 奖励列表
|
|
* @returns {Array} 分组后的奖励
|
|
*/
|
|
export function groupRewardsByLevel(rewards) {
|
|
const groups = {}
|
|
; (rewards || []).forEach(item => {
|
|
const level = item.level || '赏'
|
|
if (!groups[level]) groups[level] = []
|
|
groups[level].push(item)
|
|
})
|
|
return Object.keys(groups).sort((a, b) => {
|
|
if (a === 'BOSS') return -1
|
|
if (b === 'BOSS') return 1
|
|
return a.localeCompare(b)
|
|
}).map(key => {
|
|
const levelRewards = groups[key]
|
|
const total = levelRewards.reduce((sum, item) => sum + (Number(item.percent) || 0), 0)
|
|
return {
|
|
level: key,
|
|
rewards: levelRewards,
|
|
totalPercent: total.toFixed(1)
|
|
}
|
|
})
|
|
}
|