日期范围选择器、账单筛选

This commit is contained in:
2025-09-26 00:01:27 +08:00
parent 19a51fc679
commit 9ba0b8eb8a
4 changed files with 205 additions and 53 deletions

View File

@@ -4,26 +4,26 @@
min-height: 100vh;
background-color: #f5f5f5;
padding: 5px;
.wallet_main_card {
background: #000;
border-radius: 20px;
padding: 12px 20px 32px;
margin-bottom: 8px;
color: #fff;
.card_header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 32px;
.header_title {
font-size: 12px;
font-weight: 400;
line-height: 1.5;
}
.modify_password {
font-size: 12px;
font-weight: 400;
@@ -31,37 +31,37 @@
line-height: 1.5;
}
}
.balance_display {
.amount_section {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
.amount_container {
display: flex;
align-items: flex-end;
gap: 8px;
.currency_symbol {
font-family: 'DingTalk JinBuTi', sans-serif;
font-size: 32px;
font-weight: 400;
line-height: 0.8;
}
.amount_group {
display: flex;
align-items: flex-end;
.main_amount {
font-family: 'DingTalk JinBuTi', sans-serif;
font-size: 32px;
font-weight: 400;
line-height: 0.75;
}
.decimal_amount {
font-family: 'DingTalk JinBuTi', sans-serif;
font-size: 32px;
@@ -70,7 +70,7 @@
}
}
}
.withdraw_btn {
background: #fff;
border: none;
@@ -86,7 +86,7 @@
align-items: center;
}
}
.available_amount {
font-size: 12px;
font-weight: 400;
@@ -95,13 +95,13 @@
}
}
}
.function_buttons {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 8px;
.function_item {
background: white;
border: 0.5px solid #EBEBEB;
@@ -114,19 +114,19 @@
box-shadow: 0px 4px 36px 0px rgba(0, 0, 0, 0.05);
height: 24px;
flex: 1;
.function_icon {
width: 16px;
height: 16px;
display: flex;
align-items: center;
justify-content: center;
.icon_text {
font-size: 8px;
}
}
.function_text {
font-size: 12px;
font-weight: 600;
@@ -134,7 +134,7 @@
line-height: 1.33;
white-space: nowrap;
}
&:active {
background: #f8f8f8;
}
@@ -169,7 +169,8 @@
position: relative;
padding-right: 16px;
&::before, &::after {
&::before,
&::after {
content: '';
display: block;
width: 2px;
@@ -195,6 +196,7 @@
}
.transaction_list {
.loading_state,
.empty_state {
padding: 40px 20px;
@@ -277,21 +279,21 @@
.popup_content {
padding: 12px;
overflow: hidden;
.form_section {
.form_item {
margin-bottom: 12px;
.form_label {
font-size: 12px;
color: #333;
margin-bottom: 6px;
font-weight: 500;
}
.input_wrapper {
position: relative;
.amount_input {
box-sizing: border-box;
width: 100%;
@@ -301,17 +303,17 @@
padding: 0 10px;
font-size: 14px;
color: #333;
&:focus {
border-color: #667eea;
box-shadow: none;
}
&::placeholder {
color: #bbb;
}
}
.currency_symbol {
position: absolute;
left: 10px;
@@ -321,24 +323,24 @@
color: #999;
pointer-events: none;
}
.amount_input.with_symbol {
padding-left: 28px;
}
}
.balance_tip {
font-size: 10px;
color: #999;
margin-top: 4px;
}
.withdraw_desc {
padding: 8px;
background: #f8f9fa;
border-radius: 4px;
border: 1px solid #e9ecef;
.desc_text {
font-size: 10px;
color: #666;
@@ -349,3 +351,40 @@
}
}
}
// 过滤弹窗
.filter_popup {
padding: 20px;
.popup_content {
.form_section {
.form_item {
margin-bottom: 20px;
.form_label {
display: inline-block;
font-family: PingFang SC;
font-weight: 600;
font-style: Semibold;
font-size: 16px;
margin-bottom: 20px;
}
.options_wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px;
.option_item {
background-color: #0000000D;
text-align: center;
padding: 8px;
border-radius: 4px;
&.active {
background-color: #000000;
color: #fff;
}
}
}
}
}
}
}

View File

@@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import { View, Text, Input, Button, Image } from "@tarojs/components";
import Taro, { useDidShow } from "@tarojs/taro";
import "./index.scss";
@@ -28,6 +28,71 @@ interface WalletInfo {
total_withdraw?: number;
}
enum TransactionType {
All = '',
Income = 'income',
Expense = 'expense',
}
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<T> {
label: string;
value: T;
}
const income_expense_options: Option<TransactionType>[] = [
{
label: '全部',
value: TransactionType.All
},
{
label: '支出',
value: TransactionType.Expense
},
{
label: '收入',
value: TransactionType.Income
},
];
const transaction_type_options: Option<TransactionSubType>[] = [
{
label: '全部',
value: TransactionSubType.All
},
{
label: '组织活动',
value: TransactionSubType.GameActivity
},
{
label: '提现',
value: TransactionSubType.Withdrawal
},
{
label: '退款',
value: TransactionSubType.Refund
},
{
label: '企业赔付',
value: TransactionSubType.Compensation
},
];
const WalletPage: React.FC = () => {
// 钱包信息状态
@@ -44,6 +109,18 @@ const WalletPage: React.FC = () => {
const [transactions, set_transactions] = useState<Transaction[]>([]);
const [loading_transactions, set_loading_transactions] = useState(false);
// 交易记录过滤状态
const [showFilterPopup, setShowFilterPopup] = useState(false);
const [load_transactions_params, set_load_transactions_params] = useState<TransactionLoadParams>({
page: 1,
limit: 20,
type: TransactionType.All,
transaction_sub_type: TransactionSubType.All,
keyword: "",
date: ""
});
// 页面显示时加载数据
useDidShow(() => {
load_wallet_data();
@@ -82,14 +159,13 @@ const WalletPage: React.FC = () => {
// 加载交易记录
const load_transactions = async () => {
setShowFilterPopup(false);
set_load_transactions_params({ ...load_transactions_params, page: 1 });
try {
set_loading_transactions(true);
console.log("开始加载交易记录...");
const response = await httpService.post("/wallet/transactions", {
page: 1,
limit: 20
});
const response = await httpService.post("/wallet/transactions", { ...load_transactions_params });
console.log("交易记录响应:", response);
@@ -165,7 +241,7 @@ const WalletPage: React.FC = () => {
});
// 根据后端返回的数据结构解析参数
const { mch_id, app_id, package_info, open_id } = response.data;
const { mch_id, app_id, package_info, open_id } = response.data;
console.log("/wallet/withdraw:", response.data);
@@ -255,6 +331,10 @@ const WalletPage: React.FC = () => {
return `${prefix}${format_amount(transaction.amount)}`;
};
const show_filter_popup = () => {
setShowFilterPopup(true)
}
return (
<View className="wallet_page">
{/* 钱包主卡片 */}
@@ -285,7 +365,7 @@ const WalletPage: React.FC = () => {
{/* 功能按钮区域 */}
<View className="function_buttons">
<View className="function_item">
<View className="function_item" onClick={show_filter_popup}>
<Text className="function_text"></Text>
<Image className="function_icon" src={require("@/static/wallet/arrow-down.svg")} />
</View>
@@ -392,6 +472,37 @@ const WalletPage: React.FC = () => {
</View>
</View>
</CommonPopup>
{/* 筛选账单弹窗 */}
<CommonPopup
visible={showFilterPopup}
onClose={() => setShowFilterPopup(false)}
onConfirm={load_transactions}
title="选择筛选项"
className="filter_popup"
>
<View className="popup_content">
<View className="form_section">
<View className="form_item">
<Text className="form_label"></Text>
<View className="options_wrapper">
{income_expense_options.map((option: Option<TransactionType>) => (
<View className={load_transactions_params.type === option.value ? "option_item active" : "option_item"} key={option.value} onClick={() => { set_load_transactions_params({ ...load_transactions_params, type: option.value }) }}>{option.label}</View>
))}
</View>
</View>
<View className="form_item">
<Text className="form_label"></Text>
<View className="options_wrapper">
{transaction_type_options.map((option: Option<TransactionSubType>) => (
<View className={load_transactions_params.transaction_sub_type === option.value ? "option_item active" : "option_item"} key={option.value} onClick={() => { set_load_transactions_params({ ...load_transactions_params, transaction_sub_type: option.value }) }}>{option.label}</View>
))}
</View>
</View>
</View>
</View>
</CommonPopup>
</View>
);
};