import React, { useEffect, useState, useCallback } from "react"; import { View, Text, Input, Button, Image, ScrollView } from "@tarojs/components"; import Taro, { useDidShow } from "@tarojs/taro"; import "./index.scss"; import { CommonPopup, EmptyState } from "@/components"; import httpService from "@/services/httpService"; import { withAuth, GeneralNavbar } from "@/components"; import { PopupPicker } from "@/components/Picker/index"; import { handleCustomerService } from "@/services/userService"; import { useGlobalState } from "@/store/global"; import img from "@/config/images"; // 交易记录类型 interface Transaction { id: number; user_id: number; transaction_type: string; freeze_action: string | null; amount: string; description: string; create_time: string; last_modify_time: string; related_id: number; type_text: string | null; total_balance_after: string; } // 钱包信息类型 interface WalletInfo { balance: number; frozen_balance?: number; total_balance?: number; total_income?: number; total_withdraw?: number; } export enum TransactionType { All = "", Income = "income", Expense = "expense", } export enum TransactionSubType { All = "", GameActivity = "game_activity", Withdrawal = "withdrawal", Refund = "refund", Compensation = "compensation", } interface TransactionLoadParams { page: number; limit: number; type: TransactionType; transaction_sub_type: TransactionSubType; keyword?: string; date?: string; } interface Option { label: string; value: T; } const income_expense_options: Option[] = [ { label: "全部", value: TransactionType.All, }, { label: "支出", value: TransactionType.Expense, }, { label: "收入", value: TransactionType.Income, }, ]; const transaction_type_options: Option[] = [ { label: "全部", value: TransactionSubType.All, }, { label: "组织活动", value: TransactionSubType.GameActivity, }, { label: "提现", value: TransactionSubType.Withdrawal, }, { label: "退款", value: TransactionSubType.Refund, }, { label: "企业赔付", value: TransactionSubType.Compensation, }, ]; const WalletPage: React.FC = () => { // 获取导航栏高度信息 const { statusNavbarHeightInfo } = useGlobalState() || {}; const { totalHeight = 98 } = statusNavbarHeightInfo || {}; // 获取当前页面的配置 const currentPage = Taro.getCurrentInstance(); const pageConfig = currentPage.page?.config; const pageTitle = pageConfig?.navigationBarTitleText; // 钱包信息状态 const [wallet_info, set_wallet_info] = useState({ balance: 0, }); // 提现弹窗状态 const [show_withdraw_popup, set_show_withdraw_popup] = useState(false); const [withdraw_amount, set_withdraw_amount] = useState(""); const [submitting, set_submitting] = useState(false); const [password_status, set_password_status] = useState(false); // 交易记录状态 const [transactions, set_transactions] = useState([]); const [loading_transactions, set_loading_transactions] = useState(false); // 交易记录过滤状态 const [showFilterPopup, setShowFilterPopup] = useState(false); const [showMonthPicker, setShowMonthPicker] = useState(false); const [filterParams, setFilterParams] = useState({ type: TransactionType.All, transaction_sub_type: TransactionSubType.All, }); const now = new Date(); const year = now.getFullYear(); const month = String(now.getMonth() + 1).padStart(2, "0"); const [load_transactions_params, set_load_transactions_params] = useState({ page: 1, limit: 20, type: TransactionType.All, transaction_sub_type: TransactionSubType.All, keyword: "", date: `${year}-${month}`, }); const [totalPages, setTotalPages] = useState(1); const [refreshing, setRefreshing] = useState(false); useEffect(() => { load_transactions(); }, [load_transactions_params]); // 页面显示时加载数据 useDidShow(() => { const currentPage = Taro.getCurrentInstance().page; const updateList = currentPage.data.updateList; if (updateList) { set_transactions([]); // 直接使用新参数调用加载方法 const newParams = { ...load_transactions_params, page: 1, }; set_load_transactions_params(newParams); load_transactions(); // 立即调用 // 清除标记 currentPage.setData({ updateList: null }); } load_wallet_data(); check_password_status(); }); const modify_load_transactions_params = () => { set_transactions([]); const { type, transaction_sub_type } = filterParams; set_load_transactions_params((prev) => { return { ...prev, page: 1, type, transaction_sub_type, }; }); }; const check_password_status = async () => { try { const res = await httpService.post("/wallet/check_password_status"); set_password_status(res.data.is_password_set); } catch (e) { console.error("检查交易密码状态失败:", e); } }; // 加载钱包数据 const load_wallet_data = async () => { try { const response = await httpService.post("/wallet/balance"); const { balance, frozen_balance, total_balance, total_income, total_withdraw, } = response.data; set_wallet_info({ balance, frozen_balance, total_balance, total_income, total_withdraw, }); } catch (error: any) { console.error("加载钱包数据失败:", error); let errorMessage = "加载失败,请重试"; if ( error && error.response && error.response.data && error.response.data.message ) { errorMessage = error.response.data.message; } else if (error && error.data && error.data.message) { errorMessage = error.data.message; } Taro.showToast({ title: errorMessage, icon: "error", duration: 2000, }); } }; // 加载交易记录 const load_transactions = async () => { setShowFilterPopup(false); // set_load_transactions_params({ ...load_transactions_params, page: 1 }); try { if (!transactions.length) set_loading_transactions(true); console.log("开始加载交易记录..."); const response = await httpService.post("/wallet/transactions", { ...load_transactions_params, }); console.log("交易记录响应:", response); if (response && response.data && response.data.list) { set_transactions([...transactions, ...response.data.list]); setTotalPages(response.data.totalPages); console.log("设置交易记录:", response.data.list); } else { console.log("响应数据格式异常:", response); set_transactions([]); } } catch (error: any) { console.error("加载交易记录失败:", error); set_transactions([]); let errorMessage = "加载交易记录失败"; if ( error && error.response && error.response.data && error.response.data.message ) { errorMessage = error.response.data.message; } else if (error && error.data && error.data.message) { errorMessage = error.data.message; } Taro.showToast({ title: errorMessage, icon: "error", duration: 2000, }); } finally { console.log("加载交易记录完成,设置loading为false"); set_loading_transactions(false); } }; const navigateToSetTransactionPassword = (type: "set" | "reset") => { let url = ""; if (type === "set") { url = `/user_pages/setTransactionPassword/index?type=${type}`; } else if (type === "reset") { url = `/user_pages/validPhone/index`; } Taro.navigateTo({ url, }); }; // 处理提现 const handle_withdraw = () => { if (!password_status) { navigateToSetTransactionPassword("set"); return; } if (wallet_info.balance <= 0) { Taro.showToast({ title: "可提现金额不足", icon: "error", duration: 2000, }); return; } Taro.navigateTo({ url: "/user_pages/withdrawal/index", }); // set_show_withdraw_popup(true); }; // 提交提现申请 const submit_withdraw = async () => { if (!withdraw_amount || parseFloat(withdraw_amount) <= 0) { Taro.showToast({ title: "请输入有效金额", icon: "error", duration: 2000, }); return; } if (parseFloat(withdraw_amount) > wallet_info.balance) { Taro.showToast({ title: "提现金额不能超过余额", icon: "error", duration: 2000, }); return; } set_submitting(true); // 先调用后端接口获取提现参数 const response = await httpService.post("/wallet/withdraw", { amount: parseFloat(withdraw_amount), transfer_remark: "用户申请提现", }); // 根据后端返回的数据结构解析参数 const { mch_id, app_id, package_info, open_id } = response.data; console.log("/wallet/withdraw:", response.data); // 调用微信商户转账接口 (Taro as any).requestMerchantTransfer({ mchId: mch_id, appId: app_id, package: package_info, openId: open_id, success: (res) => { console.log("微信转账成功:", res); Taro.showToast({ title: "提现成功", icon: "success", duration: 2000, }); // 关闭弹窗并重置状态 set_show_withdraw_popup(false); set_withdraw_amount(""); // 重新加载数据 load_wallet_data(); }, fail: (res) => { console.log("微信转账失败:", res); }, }); }; // 格式化金额显示 const format_amount = (amount: number | string) => { const numAmount = typeof amount === "string" ? parseFloat(amount) : amount; return numAmount.toFixed(2); }; // 格式化时间显示 const format_time = (time: string) => { time = time.replace(/-/g, "/"); const date = new Date(time); const year = String(date.getFullYear()); const month = String(date.getMonth() + 1).padStart(2, "0"); const day = String(date.getDate()).padStart(2, "0"); const hours = String(date.getHours()).padStart(2, "0"); const minutes = String(date.getMinutes()).padStart(2, "0"); const seconds = String(date.getSeconds()).padStart(2, "0"); return { date: `${year}-${month}-${day}`, time: `${hours}:${minutes}:${seconds}`, }; }; // 获取交易类型文字 const get_transaction_type_text = (transaction: Transaction) => { // 如果有描述信息,优先使用描述 if (transaction.description) { return transaction.description; } const typeMap: { [key: string]: string } = { income: "收入", expense: "支出", freeze: "冻结", unfreeze: "解冻", }; let typeText = typeMap[transaction.transaction_type] || transaction.transaction_type; // 如果有冻结操作,添加到类型文字中 if (transaction.freeze_action) { const freezeMap: { [key: string]: string } = { freeze: "冻结", unfreeze: "解冻", }; typeText += `(${freezeMap[transaction.freeze_action]})`; } return typeText; }; // 获取金额显示(带符号) const get_amount_display = (transaction: Transaction) => { const isPositive = transaction.transaction_type === "income"; const prefix = isPositive ? "+" : "-"; return `${prefix}${format_amount(transaction.amount)}`; }; const show_filter_popup = () => { setShowFilterPopup(true); }; // 下拉刷新:刷新钱包余额和交易记录 const handle_refresh = useCallback(async () => { setRefreshing(true); try { await load_wallet_data(); set_transactions([]); set_load_transactions_params((prev) => ({ ...prev, page: 1 })); } catch (error) { Taro.showToast({ title: "刷新失败,请重试", icon: "none", duration: 2000, }); } finally { setRefreshing(false); } }, []); // 滚动到底部加载更多交易记录 const handle_scroll_to_lower = useCallback(() => { if (load_transactions_params.page >= totalPages) return; set_load_transactions_params((prev) => ({ ...prev, page: prev.page + 1, })); }, [load_transactions_params.page, totalPages]); const handleFilterCancel = () => { setShowFilterPopup(false); setFilterParams({ type: load_transactions_params.type, transaction_sub_type: load_transactions_params.transaction_sub_type, }); }; return ( {/* 导航栏 */} {/* { Taro.navigateBack(); }} > {pageTitle} */} {/* 顶部导航栏 */} { Taro.navigateBack(); }} /> {/* 钱包主卡片 */} {/* 头部信息 */} 我的现金 navigateToSetTransactionPassword("reset")} > 修改交易密码 {/* 余额显示 */} ¥ {wallet_info.total_balance?.toFixed(2)} {/* . {((wallet_info.balance % 1) * 100) .toFixed(0) .padStart(2, "0")} */} 可提现金额:¥{format_amount(wallet_info.balance)} {/* 功能按钮区域 */} 全部账单 Taro.navigateTo({ url: "/user_pages/queryTransactions/index" }) } > 查询交易 Taro.navigateTo({ url: "/user_pages/downloadBill/index" }) } > 下载账单 {/* 客服中心 */} 客服中心 {/* 现金明细 */} {/* 标题栏 */} 现金明细 setShowMonthPicker(true)} > {load_transactions_params.date} {/* 交易记录列表 */} {loading_transactions ? ( 加载中... ) : transactions.length > 0 ? ( transactions.map((transaction) => { const timeInfo = format_time(transaction.create_time); return ( { Taro.navigateTo({ url: `/user_pages/billDetail/index?id=${transaction.id}`, }); }} > {get_transaction_type_text(transaction)} {timeInfo.date} {timeInfo.time} {transaction.type_text} {get_amount_display(transaction)} 余额 ¥{format_amount(transaction.total_balance_after)} ); }) ) : ( // // 暂无交易记录 // )} {/* 提现弹窗 */} set_show_withdraw_popup(false)} onConfirm={submit_withdraw} title="申请提现" className="withdraw_popup" > {/* 提现金额 */} 提现金额 ¥ set_withdraw_amount(e.detail.value)} /> 可提现余额:¥{format_amount(wallet_info.balance)} {/* 提现说明 */} 提现说明 提现申请提交后,我们将在1-3个工作日内处理并转账到您的账户 {/* 选择月份弹窗 */} {showMonthPicker && ( { set_transactions([]); const [year, month] = e; set_load_transactions_params({ ...load_transactions_params, page: 1, date: `${year}-${String(month).padStart(2, "0")}`, }); }} /> )} {/* 筛选账单弹窗 */} 收支类型 {income_expense_options.map( (option: Option) => ( { setFilterParams({ ...filterParams, type: option.value, }); }} > {option.label} ) )} 交易类型 {transaction_type_options.map( (option: Option) => ( { setFilterParams({ ...filterParams, transaction_sub_type: option.value, }); }} > {option.label} ) )} ); }; export default withAuth(WalletPage);