142 lines
3.8 KiB
TypeScript
142 lines
3.8 KiB
TypeScript
import { create } from "zustand"
|
|
import { generateId } from "@/lib/id"
|
|
import { mockTransactions, walletBalance } from "@/lib/mock"
|
|
import type { WalletTransaction } from "@/lib/types"
|
|
|
|
interface WalletState {
|
|
balance: number
|
|
transactions: WalletTransaction[]
|
|
topUp: (amount: number) => void
|
|
withdraw: (amount: number) => void
|
|
deductBalance: (orderId: string, amount: number) => boolean
|
|
refundPayment: (orderId: string, amount: number) => boolean
|
|
addIncome: (orderId: string, amount: number) => void
|
|
addTransaction: (transaction: WalletTransaction) => void
|
|
}
|
|
|
|
export const useWalletStore = create<WalletState>((set, get) => ({
|
|
balance: walletBalance,
|
|
transactions: mockTransactions,
|
|
topUp: (amount) => {
|
|
if (!Number.isFinite(amount) || amount <= 0) return
|
|
const now = new Date().toISOString()
|
|
set((state) => ({
|
|
balance: state.balance + amount,
|
|
transactions: [
|
|
{
|
|
id: generateId("tx"),
|
|
type: "topup",
|
|
amount,
|
|
description: "充值",
|
|
createdAt: now,
|
|
},
|
|
...state.transactions,
|
|
],
|
|
}))
|
|
},
|
|
withdraw: (amount) => {
|
|
if (!Number.isFinite(amount) || amount <= 0) return
|
|
const now = new Date().toISOString()
|
|
set((state) => ({
|
|
transactions: [
|
|
{
|
|
id: generateId("tx"),
|
|
type: "withdrawal",
|
|
amount: -amount,
|
|
description: "提现到银行卡",
|
|
createdAt: now,
|
|
},
|
|
...state.transactions,
|
|
],
|
|
}))
|
|
},
|
|
deductBalance: (orderId, amount) => {
|
|
if (!Number.isFinite(amount) || amount <= 0) return false
|
|
|
|
const state = get()
|
|
const paid = state.transactions.some(
|
|
(transaction) => transaction.type === "payment" && transaction.description.includes(orderId),
|
|
)
|
|
if (paid || state.balance < amount) {
|
|
return false
|
|
}
|
|
|
|
const now = new Date().toISOString()
|
|
set((prev) => ({
|
|
balance: prev.balance - amount,
|
|
transactions: [
|
|
{
|
|
id: generateId("tx"),
|
|
type: "payment",
|
|
amount: -amount,
|
|
description: `支付订单 ${orderId}`,
|
|
createdAt: now,
|
|
},
|
|
...prev.transactions,
|
|
],
|
|
}))
|
|
return true
|
|
},
|
|
refundPayment: (orderId, amount) => {
|
|
if (!Number.isFinite(amount) || amount <= 0) return false
|
|
|
|
const state = get()
|
|
const paid = state.transactions.some(
|
|
(transaction) => transaction.type === "payment" && transaction.description.includes(orderId),
|
|
)
|
|
const refunded = state.transactions.some(
|
|
(transaction) => transaction.type === "refund" && transaction.description.includes(orderId),
|
|
)
|
|
|
|
if (!paid || refunded) {
|
|
return false
|
|
}
|
|
|
|
const now = new Date().toISOString()
|
|
set((prev) => ({
|
|
balance: prev.balance + amount,
|
|
transactions: [
|
|
{
|
|
id: generateId("tx"),
|
|
type: "refund",
|
|
amount,
|
|
description: `订单 ${orderId} 退款`,
|
|
createdAt: now,
|
|
},
|
|
...prev.transactions,
|
|
],
|
|
}))
|
|
|
|
return true
|
|
},
|
|
addIncome: (orderId, amount) => {
|
|
if (!Number.isFinite(amount) || amount <= 0) return
|
|
|
|
const state = get()
|
|
const exists = state.transactions.some(
|
|
(transaction) => transaction.type === "income" && transaction.description.includes(orderId),
|
|
)
|
|
if (exists) return
|
|
|
|
const now = new Date().toISOString()
|
|
const income = Number((amount * 0.85).toFixed(2))
|
|
set((prev) => ({
|
|
transactions: [
|
|
{
|
|
id: generateId("tx"),
|
|
type: "income",
|
|
amount: income,
|
|
description: `订单 ${orderId} 收入(扣除15%抽成)`,
|
|
createdAt: now,
|
|
},
|
|
...prev.transactions,
|
|
],
|
|
}))
|
|
},
|
|
addTransaction: (transaction) => {
|
|
set((state) => ({
|
|
transactions: [transaction, ...state.transactions],
|
|
}))
|
|
},
|
|
}))
|