feat: migrate app routes and business modules
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
import { createRequestError } from './request-client.js'
|
||||
import { normalizeOptionalNumericId } from './response-normalizers.js'
|
||||
|
||||
const normalizeVipText = (value, field, { required = false } = {}) => {
|
||||
if (value === undefined || value === null) {
|
||||
if (required) throw createRequestError(`VIP 响应缺少 ${field}`, 'VIP_RESPONSE_INVALID')
|
||||
return ''
|
||||
}
|
||||
if (typeof value !== 'string') {
|
||||
throw createRequestError(`VIP 响应 ${field} 无效`, 'VIP_RESPONSE_INVALID')
|
||||
}
|
||||
const text = value.trim()
|
||||
if (required && !text) throw createRequestError(`VIP 响应缺少 ${field}`, 'VIP_RESPONSE_INVALID')
|
||||
return text
|
||||
}
|
||||
|
||||
const normalizeVipAmount = (value, field, { required = false } = {}) => {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
if (required) throw createRequestError(`VIP 响应缺少 ${field}`, 'VIP_RESPONSE_INVALID')
|
||||
return ''
|
||||
}
|
||||
const text = typeof value === 'number' && Number.isFinite(value) ? String(value) : value
|
||||
if (typeof text !== 'string') throw createRequestError(`VIP 响应 ${field} 无效`, 'VIP_RESPONSE_INVALID')
|
||||
const match = text.trim().match(/^(0|[1-9]\d*)(?:\.(\d{1,2}))?$/)
|
||||
if (!match) throw createRequestError(`VIP 响应 ${field} 无效`, 'VIP_RESPONSE_INVALID')
|
||||
return `${match[1]}.${(match[2] || '').padEnd(2, '0')}`
|
||||
}
|
||||
|
||||
const vipOrderStatusFallbackLabels = Object.freeze({
|
||||
'0': '待支付',
|
||||
'1': '已支付',
|
||||
'2': '已关闭',
|
||||
'3': '已退款'
|
||||
})
|
||||
|
||||
const normalizeVipOrderStatus = (value) => {
|
||||
const status = normalizeVipText(value, 'payStatus', { required: true })
|
||||
return {
|
||||
status,
|
||||
statusLabel: vipOrderStatusFallbackLabels[status] || '状态待确认'
|
||||
}
|
||||
}
|
||||
|
||||
export const normalizeVipPackages = (value) => {
|
||||
if (!Array.isArray(value)) throw createRequestError('VIP 套餐响应不是列表', 'VIP_RESPONSE_INVALID')
|
||||
const packages = value.map((item) => {
|
||||
if (!item || typeof item !== 'object' || Array.isArray(item)) {
|
||||
throw createRequestError('VIP 套餐响应包含无效条目', 'VIP_RESPONSE_INVALID')
|
||||
}
|
||||
const id = normalizeOptionalNumericId(item.packageId, 'VIP 套餐标识', 'VIP_RESPONSE_INVALID')
|
||||
if (!id) throw createRequestError('VIP 套餐响应缺少稳定标识', 'VIP_RESPONSE_INVALID')
|
||||
return {
|
||||
key: `vip-package-${id}`,
|
||||
id,
|
||||
name: normalizeVipText(item.packageName, 'packageName', { required: true }),
|
||||
description: normalizeVipText(item.packageDesc, 'packageDesc'),
|
||||
price: normalizeVipAmount(item.price, 'price', { required: true }),
|
||||
originalPrice: normalizeVipAmount(item.originalPrice, 'originalPrice')
|
||||
}
|
||||
})
|
||||
if (new Set(packages.map((item) => item.id)).size !== packages.length) {
|
||||
throw createRequestError('VIP 套餐响应包含重复标识', 'VIP_RESPONSE_INVALID')
|
||||
}
|
||||
return packages
|
||||
}
|
||||
|
||||
export const normalizeVipOrders = (value) => {
|
||||
if (!Array.isArray(value)) throw createRequestError('VIP 订单响应不是列表', 'VIP_RESPONSE_INVALID')
|
||||
const orders = value.map((item) => {
|
||||
if (!item || typeof item !== 'object' || Array.isArray(item)) {
|
||||
throw createRequestError('VIP 订单响应包含无效条目', 'VIP_RESPONSE_INVALID')
|
||||
}
|
||||
const id = normalizeOptionalNumericId(item.orderId, 'VIP 订单标识', 'VIP_RESPONSE_INVALID')
|
||||
if (!id) throw createRequestError('VIP 订单响应缺少稳定标识', 'VIP_RESPONSE_INVALID')
|
||||
const { status, statusLabel } = normalizeVipOrderStatus(item.payStatus)
|
||||
return {
|
||||
key: `vip-order-${id}`,
|
||||
id,
|
||||
packageName: normalizeVipText(item.packageName, 'packageName', { required: true }),
|
||||
amount: normalizeVipAmount(item.payAmount ?? item.orderAmount, 'payAmount', { required: true }),
|
||||
status,
|
||||
statusLabel,
|
||||
paidAt: normalizeVipText(item.payTime, 'payTime'),
|
||||
expiresAt: normalizeVipText(item.expireTime, 'expireTime')
|
||||
}
|
||||
})
|
||||
if (new Set(orders.map((item) => item.id)).size !== orders.length) {
|
||||
throw createRequestError('VIP 订单响应包含重复标识', 'VIP_RESPONSE_INVALID')
|
||||
}
|
||||
return orders
|
||||
}
|
||||
|
||||
export const normalizeVipCapability = (value) => {
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value) || typeof value.enabled !== 'boolean') {
|
||||
throw createRequestError('VIP 购买能力响应无效', 'VIP_RESPONSE_INVALID')
|
||||
}
|
||||
return {
|
||||
enabled: value.enabled,
|
||||
disabledReason: normalizeVipText(value.disabledReason, 'disabledReason')
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user