refactor(game): 重构项目结构,优化链路, 移动端适配

- 移除 useGameBoardVm 数据层实施说明文档
- 移除核心玩法与前端规则摘要文档
- 移除游戏模块数据与界面分层第一阶段实施稿文档
- 清理与数据层重构相关的技术方案说明
- 删除关于 PC 和 Mobile 界面分离的设计规划
- 移除 view-model hooks 架构设计相关内容
This commit is contained in:
JiaJun
2026-06-03 17:21:13 +08:00
parent 3efcb3bba6
commit bfb4b76611
129 changed files with 4534 additions and 4227 deletions

377
src/api/finance-api.ts Normal file
View File

@@ -0,0 +1,377 @@
import {
API_SUCCESS_CODE,
DEFAULT_LIST_PAGE_SIZE,
FINANCE_API_ENDPOINTS,
} from '@/constants'
import { api } from '@/lib/api/api-client'
import { ApiError } from '@/lib/api/api-error'
import type {
ApiResponse,
DepositCreateRequestDto,
DepositCreateResponseDto,
DepositTierItem,
DepositTierItemDto,
DepositWithdrawConfig,
DepositWithdrawConfigDto,
FinanceCurrencyConfigDto,
FinanceOrderItemDto,
FinanceOrderList,
FinanceOrderListDto,
FinancePayChannelDto,
FinanceRateConfigDto,
FinanceWithdrawBankDto,
FinanceWithdrawConfigDto,
WalletRecordItemDto,
WalletRecordList,
WalletRecordListDto,
WalletRecordType,
WithdrawCreateRequestDto,
WithdrawCreateResponseDto,
} from '@/type'
function unwrapFinanceEnvelope<T>(
response: ApiResponse<T>,
fallbackMessage = 'Finance request failed',
) {
if (response.code === API_SUCCESS_CODE) {
return response.data
}
const responseMessage =
typeof response.message === 'string' && response.message.length > 0
? response.message
: typeof response.msg === 'string' && response.msg.length > 0
? response.msg
: fallbackMessage
throw new ApiError({
data: response,
message: responseMessage,
})
}
function toFiniteNumber(value: string | number | null | undefined) {
const numericValue = Number(value)
return Number.isFinite(numericValue) ? numericValue : 0
}
function normalizeCurrency(dto: FinanceCurrencyConfigDto) {
return {
code: dto.code,
depositCoinsPerFiat: dto.deposit_coins_per_fiat,
depositCoinsPerFiatValue: toFiniteNumber(dto.deposit_coins_per_fiat),
label: dto.label,
withdrawCoinsPerFiat: dto.withdraw_coins_per_fiat,
withdrawCoinsPerFiatValue: toFiniteNumber(dto.withdraw_coins_per_fiat),
}
}
function normalizeRate(dto: FinanceRateConfigDto) {
return {
currency: dto.currency,
diamondsPerFiatUnit: dto.diamonds_per_fiat_unit,
diamondsPerFiatUnitValue: toFiniteNumber(dto.diamonds_per_fiat_unit),
}
}
function normalizePayChannel(dto: FinancePayChannelDto) {
return {
code: dto.code,
name: dto.name,
sort: Number.isFinite(dto.sort) ? dto.sort : 0,
status: dto.status,
tierIds: Array.isArray(dto.tier_ids) ? dto.tier_ids : [],
}
}
function normalizeWithdrawBank(dto: FinanceWithdrawBankDto, index: number) {
const code = dto.code ?? dto.id ?? dto.name ?? `bank-${index + 1}`
const label = dto.label ?? dto.name ?? code
return {
code,
label,
sort:
typeof dto.sort === 'number' && Number.isFinite(dto.sort)
? dto.sort
: index,
status: typeof dto.status === 'number' ? dto.status : 1,
}
}
function normalizeWithdrawConfig(dto: FinanceWithdrawConfigDto) {
return {
banks: (dto.banks ?? []).map(normalizeWithdrawBank),
feeNote: dto.fee_note,
minBank: dto.min_bank,
minEwallet: dto.min_ewallet,
processingNote: dto.processing_note,
rateHint: dto.rate_hint,
rateMode: dto.rate_mode,
}
}
function normalizeDepositWithdrawConfig(
dto: DepositWithdrawConfigDto,
): DepositWithdrawConfig {
return {
currencies: (dto.currencies ?? []).map(normalizeCurrency),
payChannels: (dto.pay_channels ?? []).map(normalizePayChannel),
platformCoinLabel: dto.platform_coin_label,
rates: (dto.rates ?? []).map(normalizeRate),
withdraw: normalizeWithdrawConfig(dto.withdraw),
}
}
function normalizeDepositTierItem(
dto: DepositTierItemDto,
index: number,
): DepositTierItem {
const id = String(dto.id ?? dto.tier_id ?? `tier-${index + 1}`)
const amount = toFiniteNumber(dto.amount)
const bonusAmount = toFiniteNumber(dto.bonus_amount ?? dto.bonus_coins)
const payAmount = toFiniteNumber(dto.pay_amount ?? dto.amount)
const totalAmount = toFiniteNumber(
dto.total_amount ?? dto.coins ?? amount + bonusAmount,
)
const coins = totalAmount
const currency =
typeof dto.currency === 'string' && dto.currency.length > 0
? dto.currency
: null
const payChannelCode =
typeof dto.pay_channel_code === 'string' && dto.pay_channel_code.length > 0
? dto.pay_channel_code
: null
const sort = toFiniteNumber(dto.sort ?? dto.pay_amount ?? dto.amount)
const status = toFiniteNumber(dto.status ?? 1)
const channels = (dto.channels ?? [])
.map((channel, channelIndex) => ({
code: channel.code ?? `channel-${channelIndex + 1}`,
name: channel.name ?? channel.code ?? '--',
sort: toFiniteNumber(channel.sort ?? channelIndex),
}))
.sort((left, right) => left.sort - right.sort)
return {
amount,
bonusAmount,
channels,
coins,
currency,
desc: dto.desc ?? '',
id,
name:
typeof dto.name === 'string' && dto.name.length > 0
? dto.name
: `${amount}`,
payAmount,
payChannelCode,
sort,
status,
tierKey:
typeof dto.tier_key === 'string' && dto.tier_key.length > 0
? dto.tier_key
: null,
totalAmount,
title:
typeof dto.title === 'string' && dto.title.length > 0
? dto.title
: typeof dto.name === 'string' && dto.name.length > 0
? dto.name
: `${amount}`,
}
}
function normalizeFinanceOrderItem(dto: FinanceOrderItemDto) {
return {
amount: String(dto.amount ?? ''),
bonusAmount: String(dto.bonus_amount ?? ''),
orderNo: dto.order_no,
}
}
function normalizeFinanceOrderList(dto: FinanceOrderListDto): FinanceOrderList {
return {
list: (dto.list ?? []).map(normalizeFinanceOrderItem),
pagination: {
page: dto.pagination?.page ?? 1,
page_size: dto.pagination?.page_size ?? DEFAULT_LIST_PAGE_SIZE,
total: dto.pagination?.total ?? 0,
},
}
}
function stringifyNullableValue(value: unknown) {
return value === null || value === undefined ? '' : String(value)
}
function normalizeWalletRecordItem(dto: WalletRecordItemDto, index: number) {
const createdAt = dto.created_at ?? dto.create_time ?? dto.time ?? null
const id =
dto.id ??
dto.record_id ??
dto.wallet_record_id ??
dto.order_no ??
`${createdAt ?? 'wallet-record'}-${index + 1}`
return {
amount: stringifyNullableValue(
dto.amount ?? dto.change_amount ?? dto.coin ?? '',
),
balanceAfter: stringifyNullableValue(
dto.balance_after ?? dto.after_balance ?? dto.balance ?? '',
),
balanceBefore: stringifyNullableValue(
dto.balance_before ?? dto.before_balance ?? '',
),
createdAt,
id: String(id),
remark: stringifyNullableValue(dto.remark ?? dto.description ?? dto.memo),
type: stringifyNullableValue(
dto.type ?? dto.change_type ?? dto.biz_type ?? dto.scene,
),
}
}
function normalizeWalletRecordList(dto: WalletRecordListDto): WalletRecordList {
return {
list: (dto.list ?? []).map(normalizeWalletRecordItem),
pagination: {
page: dto.pagination?.page ?? dto.page ?? 1,
page_size:
dto.pagination?.page_size ?? dto.page_size ?? DEFAULT_LIST_PAGE_SIZE,
total: dto.pagination?.total ?? dto.total ?? 0,
},
}
}
export async function getDepositWithdrawConfig() {
const response = await api.post<DepositWithdrawConfigDto>(
FINANCE_API_ENDPOINTS.depositWithdrawConfig,
)
const dto = unwrapFinanceEnvelope(
response as ApiResponse<DepositWithdrawConfigDto>,
'Failed to load deposit and withdrawal config',
)
return normalizeDepositWithdrawConfig(dto)
}
export async function getDepositTierList() {
const response = await api.post<
| DepositTierItemDto[]
| { items?: DepositTierItemDto[]; list?: DepositTierItemDto[] },
undefined
>(FINANCE_API_ENDPOINTS.depositTierList)
const dto = unwrapFinanceEnvelope(
response as ApiResponse<
| DepositTierItemDto[]
| { items?: DepositTierItemDto[]; list?: DepositTierItemDto[] }
>,
'Failed to load deposit tier list',
)
const tierItems = Array.isArray(dto) ? dto : (dto?.list ?? dto?.items ?? [])
return tierItems
.map(normalizeDepositTierItem)
.filter((item) => item.status === 1)
.sort((left, right) => left.sort - right.sort)
}
export async function createDeposit(payload: DepositCreateRequestDto) {
const response = await api.post<
DepositCreateResponseDto,
DepositCreateRequestDto
>(FINANCE_API_ENDPOINTS.depositCreate, {
json: payload,
})
const dto = unwrapFinanceEnvelope(
response as ApiResponse<DepositCreateResponseDto>,
'Failed to create deposit',
)
return dto
}
export async function getDepositOrderList(params?: {
page?: number
pageSize?: number
}) {
const response = await api.get<FinanceOrderListDto>(
FINANCE_API_ENDPOINTS.depositList,
{
searchParams: {
page: String(params?.page ?? 1),
page_size: String(params?.pageSize ?? DEFAULT_LIST_PAGE_SIZE),
},
},
)
const dto = unwrapFinanceEnvelope(
response as ApiResponse<FinanceOrderListDto>,
'Failed to load deposit order list',
)
return normalizeFinanceOrderList(dto)
}
export async function getWithdrawOrderList(params?: {
page?: number
pageSize?: number
}) {
const response = await api.get<FinanceOrderListDto>(
FINANCE_API_ENDPOINTS.withdrawList,
{
searchParams: {
page: String(params?.page ?? 1),
page_size: String(params?.pageSize ?? DEFAULT_LIST_PAGE_SIZE),
},
},
)
const dto = unwrapFinanceEnvelope(
response as ApiResponse<FinanceOrderListDto>,
'Failed to load withdraw order list',
)
return normalizeFinanceOrderList(dto)
}
export async function getWalletRecordList(params?: {
page?: number
pageSize?: number
type?: WalletRecordType
}) {
const response = await api.get<WalletRecordListDto>(
FINANCE_API_ENDPOINTS.walletRecordList,
{
searchParams: {
page: String(params?.page ?? 1),
page_size: String(params?.pageSize ?? DEFAULT_LIST_PAGE_SIZE),
type: params?.type ?? 'payout',
},
},
)
const dto = unwrapFinanceEnvelope(
response as ApiResponse<WalletRecordListDto>,
'Failed to load wallet record list',
)
return normalizeWalletRecordList(dto)
}
export async function createWithdraw(payload: WithdrawCreateRequestDto) {
const response = await api.post<
WithdrawCreateResponseDto,
WithdrawCreateRequestDto
>(FINANCE_API_ENDPOINTS.withdrawCreate, {
json: payload,
})
const dto = unwrapFinanceEnvelope(
response as ApiResponse<WithdrawCreateResponseDto>,
'Failed to create withdraw',
)
return dto
}