feat(dealer): 新增银行卡管理功能
- 添加银行卡管理页面和相关API - 实现银行卡列表展示、添加、编辑和删除功能 - 优化提现页面,支持选择银行卡进行提现 - 新增 FixedButton 组件用于底部固定按钮
This commit is contained in:
101
src/api/shop/shopDealerBank/index.ts
Normal file
101
src/api/shop/shopDealerBank/index.ts
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import type { ApiResult, PageResult } from '@/api';
|
||||||
|
import type { ShopDealerBank, ShopDealerBankParam } from './model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询分销商银行卡
|
||||||
|
*/
|
||||||
|
export async function pageShopDealerBank(params: ShopDealerBankParam) {
|
||||||
|
const res = await request.get<ApiResult<PageResult<ShopDealerBank>>>(
|
||||||
|
'/shop/shop-dealer-bank/page',
|
||||||
|
params
|
||||||
|
);
|
||||||
|
if (res.code === 0) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询分销商银行卡列表
|
||||||
|
*/
|
||||||
|
export async function listShopDealerBank(params?: ShopDealerBankParam) {
|
||||||
|
const res = await request.get<ApiResult<ShopDealerBank[]>>(
|
||||||
|
'http://127.0.0.1:9200/api/shop/shop-dealer-bank',
|
||||||
|
params
|
||||||
|
);
|
||||||
|
if (res.code === 0 && res.data) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加分销商银行卡
|
||||||
|
*/
|
||||||
|
export async function addShopDealerBank(data: ShopDealerBank) {
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-dealer-bank',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.code === 0) {
|
||||||
|
return res.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改分销商银行卡
|
||||||
|
*/
|
||||||
|
export async function updateShopDealerBank(data: ShopDealerBank) {
|
||||||
|
const res = await request.put<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-dealer-bank',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.code === 0) {
|
||||||
|
return res.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除分销商银行卡
|
||||||
|
*/
|
||||||
|
export async function removeShopDealerBank(id?: number) {
|
||||||
|
const res = await request.del<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-dealer-bank/' + id
|
||||||
|
);
|
||||||
|
if (res.code === 0) {
|
||||||
|
return res.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除分销商银行卡
|
||||||
|
*/
|
||||||
|
export async function removeBatchShopDealerBank(data: (number | undefined)[]) {
|
||||||
|
const res = await request.del<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-dealer-bank/batch',
|
||||||
|
{
|
||||||
|
data
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.code === 0) {
|
||||||
|
return res.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据id查询分销商银行卡
|
||||||
|
*/
|
||||||
|
export async function getShopDealerBank(id: number) {
|
||||||
|
const res = await request.get<ApiResult<ShopDealerBank>>(
|
||||||
|
'/shop/shop-dealer-bank/' + id
|
||||||
|
);
|
||||||
|
if (res.code === 0 && res.data) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.message));
|
||||||
|
}
|
||||||
45
src/api/shop/shopDealerBank/model/index.ts
Normal file
45
src/api/shop/shopDealerBank/model/index.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import type { PageParam } from '@/api';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分销商提现银行卡
|
||||||
|
*/
|
||||||
|
export interface ShopDealerBank {
|
||||||
|
// 主键ID
|
||||||
|
id?: number;
|
||||||
|
// 分销商用户ID
|
||||||
|
userId?: number;
|
||||||
|
// 开户行名称
|
||||||
|
bankName?: string;
|
||||||
|
// 银行开户名
|
||||||
|
bankAccount?: string;
|
||||||
|
// 银行卡号
|
||||||
|
bankCard?: string;
|
||||||
|
// 申请状态 (10待审核 20审核通过 30驳回)
|
||||||
|
applyStatus?: number;
|
||||||
|
// 审核时间
|
||||||
|
auditTime?: number;
|
||||||
|
// 驳回原因
|
||||||
|
rejectReason?: string;
|
||||||
|
// 是否默认
|
||||||
|
isDefault?: boolean;
|
||||||
|
// 租户id
|
||||||
|
tenantId?: number;
|
||||||
|
// 创建时间
|
||||||
|
createTime?: string;
|
||||||
|
// 修改时间
|
||||||
|
updateTime?: string;
|
||||||
|
// 类型
|
||||||
|
type?: string;
|
||||||
|
// 名称
|
||||||
|
name?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分销商提现银行卡搜索条件
|
||||||
|
*/
|
||||||
|
export interface ShopDealerBankParam extends PageParam {
|
||||||
|
id?: number;
|
||||||
|
userId?: number;
|
||||||
|
isDefault?: boolean;
|
||||||
|
keywords?: string;
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { PageParam } from '@/api/index';
|
import type { PageParam } from '@/api';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分销商提现明细表
|
* 分销商提现明细表
|
||||||
|
|||||||
@@ -67,7 +67,9 @@ export default defineAppConfig({
|
|||||||
"customer/index",
|
"customer/index",
|
||||||
"customer/add",
|
"customer/add",
|
||||||
"customer/trading",
|
"customer/trading",
|
||||||
"wechat/index"
|
"wechat/index",
|
||||||
|
"bank/index",
|
||||||
|
"bank/add"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
|
|||||||
4
src/dealer/bank/add.config.ts
Normal file
4
src/dealer/bank/add.config.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export default definePageConfig({
|
||||||
|
navigationBarTitleText: '添加银行卡',
|
||||||
|
navigationBarTextStyle: 'black'
|
||||||
|
})
|
||||||
142
src/dealer/bank/add.tsx
Normal file
142
src/dealer/bank/add.tsx
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
import {useEffect, useState, useRef} from "react";
|
||||||
|
import {useRouter} from '@tarojs/taro'
|
||||||
|
import {Loading, CellGroup, Input, Form} from '@nutui/nutui-react-taro'
|
||||||
|
import Taro from '@tarojs/taro'
|
||||||
|
import {
|
||||||
|
getShopDealerBank,
|
||||||
|
listShopDealerBank,
|
||||||
|
updateShopDealerBank,
|
||||||
|
addShopDealerBank
|
||||||
|
} from "@/api/shop/shopDealerBank";
|
||||||
|
import FixedButton from "@/components/FixedButton";
|
||||||
|
import {ShopDealerBank} from "@/api/shop/shopDealerBank/model";
|
||||||
|
|
||||||
|
const AddUserAddress = () => {
|
||||||
|
const {params} = useRouter();
|
||||||
|
const [loading, setLoading] = useState<boolean>(true)
|
||||||
|
const [FormData, setFormData] = useState<ShopDealerBank>()
|
||||||
|
const formRef = useRef<any>(null)
|
||||||
|
|
||||||
|
// 判断是编辑还是新增模式
|
||||||
|
const isEditMode = !!params.id
|
||||||
|
const bankId = params.id ? Number(params.id) : undefined
|
||||||
|
|
||||||
|
const reload = async () => {
|
||||||
|
// 如果是编辑模式,加载地址数据
|
||||||
|
if (isEditMode && bankId) {
|
||||||
|
try {
|
||||||
|
const bank = await getShopDealerBank(bankId)
|
||||||
|
setFormData(bank)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载地址失败:', error)
|
||||||
|
Taro.showToast({
|
||||||
|
title: '加载地址失败',
|
||||||
|
icon: 'error'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交表单
|
||||||
|
const submitSucceed = async (values: any) => {
|
||||||
|
console.log('.>>>>>>,....')
|
||||||
|
try {
|
||||||
|
// 准备提交的数据
|
||||||
|
const submitData = {
|
||||||
|
...values,
|
||||||
|
isDefault: true // 新增或编辑的地址都设为默认地址
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log('提交数据:', submitData)
|
||||||
|
|
||||||
|
// 如果是编辑模式,添加id
|
||||||
|
if (isEditMode && bankId) {
|
||||||
|
submitData.id = bankId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 先处理默认地址逻辑
|
||||||
|
const defaultAddress = await listShopDealerBank({isDefault: true});
|
||||||
|
if (defaultAddress && defaultAddress.length > 0) {
|
||||||
|
// 如果当前编辑的不是默认地址,或者是新增地址,需要取消其他默认地址
|
||||||
|
if (!isEditMode || (isEditMode && defaultAddress[0].id !== bankId)) {
|
||||||
|
await updateShopDealerBank({
|
||||||
|
...defaultAddress[0],
|
||||||
|
isDefault: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行新增或更新操作
|
||||||
|
if (isEditMode) {
|
||||||
|
await updateShopDealerBank(submitData);
|
||||||
|
} else {
|
||||||
|
await addShopDealerBank(submitData);
|
||||||
|
}
|
||||||
|
|
||||||
|
Taro.showToast({
|
||||||
|
title: `${isEditMode ? '更新' : '保存'}成功`,
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
Taro.navigateBack();
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('保存失败:', error);
|
||||||
|
Taro.showToast({
|
||||||
|
title: `${isEditMode ? '更新' : '保存'}失败`,
|
||||||
|
icon: 'error'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitFailed = (error: any) => {
|
||||||
|
console.log(error, 'err...')
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// 动态设置页面标题
|
||||||
|
Taro.setNavigationBarTitle({
|
||||||
|
title: isEditMode ? '编辑银行卡' : '添加银行卡'
|
||||||
|
});
|
||||||
|
|
||||||
|
reload().then(() => {
|
||||||
|
setLoading(false)
|
||||||
|
})
|
||||||
|
}, [isEditMode]);
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return <Loading className={'px-2'}>加载中</Loading>
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Form
|
||||||
|
ref={formRef}
|
||||||
|
divider
|
||||||
|
initialValues={FormData}
|
||||||
|
labelPosition="left"
|
||||||
|
onFinish={(values) => submitSucceed(values)}
|
||||||
|
onFinishFailed={(errors) => submitFailed(errors)}
|
||||||
|
>
|
||||||
|
<CellGroup style={{padding: '4px 0'}}>
|
||||||
|
<Form.Item name="bankName" label="开户行名称" initialValue={FormData?.bankName} required>
|
||||||
|
<Input placeholder="开户行名称" maxLength={10}/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name="bankAccount" label="银行开户名" initialValue={FormData?.bankAccount} required>
|
||||||
|
<Input placeholder="银行开户名" maxLength={10}/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name="bankCard" label="银行卡号" initialValue={FormData?.bankCard} required>
|
||||||
|
<Input placeholder="银行卡号" maxLength={11}/>
|
||||||
|
</Form.Item>
|
||||||
|
</CellGroup>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
{/* 底部浮动按钮 */}
|
||||||
|
<FixedButton text={isEditMode ? '更新地址' : '保存并使用'} onClick={() => formRef.current?.submit()}/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddUserAddress;
|
||||||
4
src/dealer/bank/index.config.ts
Normal file
4
src/dealer/bank/index.config.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export default definePageConfig({
|
||||||
|
navigationBarTitleText: '银行卡管理',
|
||||||
|
navigationBarTextStyle: 'black'
|
||||||
|
})
|
||||||
134
src/dealer/bank/index.tsx
Normal file
134
src/dealer/bank/index.tsx
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import {useState} from "react";
|
||||||
|
import Taro, {useDidShow} from '@tarojs/taro'
|
||||||
|
import {Button, Cell, Space, Empty, ConfigProvider} from '@nutui/nutui-react-taro'
|
||||||
|
import {CheckNormal, Checked} from '@nutui/icons-react-taro'
|
||||||
|
import {View} from '@tarojs/components'
|
||||||
|
import {ShopDealerBank} from "@/api/shop/shopDealerBank/model";
|
||||||
|
import {listShopDealerBank, removeShopDealerBank, updateShopDealerBank} from "@/api/shop/shopDealerBank";
|
||||||
|
import FixedButton from "@/components/FixedButton";
|
||||||
|
|
||||||
|
const DealerBank = () => {
|
||||||
|
const [list, setList] = useState<ShopDealerBank[]>([])
|
||||||
|
const [bank, setAddress] = useState<ShopDealerBank>()
|
||||||
|
|
||||||
|
const reload = () => {
|
||||||
|
listShopDealerBank({})
|
||||||
|
.then(data => {
|
||||||
|
setList(data || [])
|
||||||
|
// 默认地址
|
||||||
|
setAddress(data.find(item => item.isDefault))
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
Taro.showToast({
|
||||||
|
title: '获取地址失败',
|
||||||
|
icon: 'error'
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const onDefault = async (item: ShopDealerBank) => {
|
||||||
|
if (bank) {
|
||||||
|
await updateShopDealerBank({
|
||||||
|
...bank,
|
||||||
|
isDefault: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await updateShopDealerBank({
|
||||||
|
id: item.id,
|
||||||
|
isDefault: true
|
||||||
|
})
|
||||||
|
Taro.showToast({
|
||||||
|
title: '设置成功',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
const onDel = async (id?: number) => {
|
||||||
|
await removeShopDealerBank(id)
|
||||||
|
Taro.showToast({
|
||||||
|
title: '删除成功',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectAddress = async (item: ShopDealerBank) => {
|
||||||
|
if (bank) {
|
||||||
|
await updateShopDealerBank({
|
||||||
|
...bank,
|
||||||
|
isDefault: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await updateShopDealerBank({
|
||||||
|
id: item.id,
|
||||||
|
isDefault: true
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
Taro.navigateBack()
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
|
||||||
|
useDidShow(() => {
|
||||||
|
reload()
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.length == 0) {
|
||||||
|
return (
|
||||||
|
<ConfigProvider>
|
||||||
|
<div className={'h-full flex flex-col justify-center items-center'} style={{
|
||||||
|
height: 'calc(100vh - 300px)',
|
||||||
|
}}>
|
||||||
|
<Empty
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'transparent'
|
||||||
|
}}
|
||||||
|
description="您还没有地址哦"
|
||||||
|
/>
|
||||||
|
<Space>
|
||||||
|
<Button onClick={() => Taro.navigateTo({url: '/dealer/bank/add'})}>新增地址</Button>
|
||||||
|
<Button type="success" fill="dashed"
|
||||||
|
onClick={() => Taro.navigateTo({url: '/dealer/bank/wxAddress'})}>获取微信地址</Button>
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
|
</ConfigProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View className={'p-3'}>
|
||||||
|
{list.map((item, _) => (
|
||||||
|
<Cell.Group>
|
||||||
|
<Cell className={'flex flex-col gap-1'} extra={item.bankAccount} onClick={() => selectAddress(item)}>
|
||||||
|
<View>
|
||||||
|
<View className={'font-medium text-sm'}>{item.bankName}</View>
|
||||||
|
</View>
|
||||||
|
<View className={'text-xs'}>
|
||||||
|
{item.bankCard} {item.bankAccount}
|
||||||
|
</View>
|
||||||
|
</Cell>
|
||||||
|
<Cell
|
||||||
|
align="center"
|
||||||
|
title={
|
||||||
|
<View className={'flex items-center gap-1'} onClick={() => onDefault(item)}>
|
||||||
|
{item.isDefault ? <Checked className={'text-green-600'} size={16}/> : <CheckNormal size={16}/>}
|
||||||
|
<View className={'text-gray-400'}>选择</View>
|
||||||
|
</View>
|
||||||
|
}
|
||||||
|
extra={
|
||||||
|
<>
|
||||||
|
<View className={'text-gray-400'} onClick={() => onDel(item.id)}>
|
||||||
|
删除
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Cell.Group>
|
||||||
|
))}
|
||||||
|
{/* 底部浮动按钮 */}
|
||||||
|
<FixedButton text={'新增银行卡'} onClick={() => Taro.navigateTo({url: '/dealer/bank/add'})} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DealerBank;
|
||||||
@@ -122,7 +122,7 @@ const CustomerTrading = () => {
|
|||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<Space direction={'vertical'}>
|
<Space direction={'vertical'}>
|
||||||
<Text className="text-xs text-gray-500">统一代码:{customer.dealerCode}</Text>
|
{/*<Text className="text-xs text-gray-500">统一代码:{customer.dealerCode}</Text>*/}
|
||||||
<Text className="text-xs text-gray-500">
|
<Text className="text-xs text-gray-500">
|
||||||
入市时间:{customer.createTime}
|
入市时间:{customer.createTime}
|
||||||
</Text>
|
</Text>
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ const DealerIndex: React.FC = () => {
|
|||||||
<Text className="font-semibold text-gray-800">佣金统计</Text>
|
<Text className="font-semibold text-gray-800">佣金统计</Text>
|
||||||
</View>
|
</View>
|
||||||
<View className="grid grid-cols-3 gap-3">
|
<View className="grid grid-cols-3 gap-3">
|
||||||
<View className="text-center p-3 rounded-lg" style={{
|
<View className="text-center p-3 rounded-lg flex flex-col" style={{
|
||||||
background: businessGradients.money.available
|
background: businessGradients.money.available
|
||||||
}}>
|
}}>
|
||||||
<Text className="text-lg font-bold mb-1 text-white">
|
<Text className="text-lg font-bold mb-1 text-white">
|
||||||
@@ -140,7 +140,7 @@ const DealerIndex: React.FC = () => {
|
|||||||
</Text>
|
</Text>
|
||||||
<Text className="text-xs" style={{ color: 'rgba(255, 255, 255, 0.9)' }}>可提现</Text>
|
<Text className="text-xs" style={{ color: 'rgba(255, 255, 255, 0.9)' }}>可提现</Text>
|
||||||
</View>
|
</View>
|
||||||
<View className="text-center p-3 rounded-lg" style={{
|
<View className="text-center p-3 rounded-lg flex flex-col" style={{
|
||||||
background: businessGradients.money.frozen
|
background: businessGradients.money.frozen
|
||||||
}}>
|
}}>
|
||||||
<Text className="text-lg font-bold mb-1 text-white">
|
<Text className="text-lg font-bold mb-1 text-white">
|
||||||
@@ -148,7 +148,7 @@ const DealerIndex: React.FC = () => {
|
|||||||
</Text>
|
</Text>
|
||||||
<Text className="text-xs" style={{ color: 'rgba(255, 255, 255, 0.9)' }}>冻结中</Text>
|
<Text className="text-xs" style={{ color: 'rgba(255, 255, 255, 0.9)' }}>冻结中</Text>
|
||||||
</View>
|
</View>
|
||||||
<View className="text-center p-3 rounded-lg" style={{
|
<View className="text-center p-3 rounded-lg flex flex-col" style={{
|
||||||
background: businessGradients.money.total
|
background: businessGradients.money.total
|
||||||
}}>
|
}}>
|
||||||
<Text className="text-lg font-bold mb-1 text-white">
|
<Text className="text-lg font-bold mb-1 text-white">
|
||||||
|
|||||||
@@ -133,15 +133,6 @@ const DealerOrders: React.FC = () => {
|
|||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!dealerUser) {
|
|
||||||
return (
|
|
||||||
<View className="bg-gray-50 min-h-screen flex items-center justify-center">
|
|
||||||
<Loading/>
|
|
||||||
<Text className="text-gray-500 mt-2">加载中...</Text>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className="min-h-screen bg-gray-50">
|
<View className="min-h-screen bg-gray-50">
|
||||||
<PullToRefresh
|
<PullToRefresh
|
||||||
|
|||||||
@@ -290,7 +290,7 @@ const DealerTeam: React.FC = () => {
|
|||||||
|
|
||||||
if (!dealerUser) {
|
if (!dealerUser) {
|
||||||
return (
|
return (
|
||||||
<Space className="bg-gray-50 flex items-center justify-center">
|
<Space className="flex items-center justify-center">
|
||||||
<Empty description="您还不是业务人员" style={{
|
<Empty description="您还不是业务人员" style={{
|
||||||
backgroundColor: 'transparent'
|
backgroundColor: 'transparent'
|
||||||
}} actions={[{ text: '立即申请', onClick: () => navTo(`/dealer/apply/add`,true)}]}
|
}} actions={[{ text: '立即申请', onClick: () => navTo(`/dealer/apply/add`,true)}]}
|
||||||
|
|||||||
@@ -4,22 +4,23 @@ import {
|
|||||||
Cell,
|
Cell,
|
||||||
Space,
|
Space,
|
||||||
Button,
|
Button,
|
||||||
Form,
|
|
||||||
Input,
|
Input,
|
||||||
CellGroup,
|
CellGroup,
|
||||||
Radio,
|
|
||||||
Tabs,
|
Tabs,
|
||||||
Tag,
|
Tag,
|
||||||
Empty,
|
Empty,
|
||||||
|
ActionSheet,
|
||||||
Loading,
|
Loading,
|
||||||
PullToRefresh
|
PullToRefresh
|
||||||
} from '@nutui/nutui-react-taro'
|
} from '@nutui/nutui-react-taro'
|
||||||
import {Wallet} from '@nutui/icons-react-taro'
|
import {Wallet, ArrowRight} from '@nutui/icons-react-taro'
|
||||||
import {businessGradients} from '@/styles/gradients'
|
import {businessGradients} from '@/styles/gradients'
|
||||||
import Taro from '@tarojs/taro'
|
import Taro from '@tarojs/taro'
|
||||||
import {useDealerUser} from '@/hooks/useDealerUser'
|
import {useDealerUser} from '@/hooks/useDealerUser'
|
||||||
import {pageShopDealerWithdraw, addShopDealerWithdraw} from '@/api/shop/shopDealerWithdraw'
|
import {pageShopDealerWithdraw, addShopDealerWithdraw} from '@/api/shop/shopDealerWithdraw'
|
||||||
import type {ShopDealerWithdraw} from '@/api/shop/shopDealerWithdraw/model'
|
import type {ShopDealerWithdraw} from '@/api/shop/shopDealerWithdraw/model'
|
||||||
|
import {ShopDealerBank} from "@/api/shop/shopDealerBank/model";
|
||||||
|
import {listShopDealerBank} from "@/api/shop/shopDealerBank";
|
||||||
|
|
||||||
interface WithdrawRecordWithDetails extends ShopDealerWithdraw {
|
interface WithdrawRecordWithDetails extends ShopDealerWithdraw {
|
||||||
accountDisplay?: string
|
accountDisplay?: string
|
||||||
@@ -31,6 +32,9 @@ const DealerWithdraw: React.FC = () => {
|
|||||||
const [loading, setLoading] = useState<boolean>(false)
|
const [loading, setLoading] = useState<boolean>(false)
|
||||||
const [refreshing, setRefreshing] = useState<boolean>(false)
|
const [refreshing, setRefreshing] = useState<boolean>(false)
|
||||||
const [submitting, setSubmitting] = useState<boolean>(false)
|
const [submitting, setSubmitting] = useState<boolean>(false)
|
||||||
|
const [banks, setBanks] = useState<any[]>([])
|
||||||
|
const [bank, setBank] = useState<ShopDealerBank>()
|
||||||
|
const [isVisible, setIsVisible] = useState<boolean>(false)
|
||||||
const [availableAmount, setAvailableAmount] = useState<string>('0.00')
|
const [availableAmount, setAvailableAmount] = useState<string>('0.00')
|
||||||
const [withdrawRecords, setWithdrawRecords] = useState<WithdrawRecordWithDetails[]>([])
|
const [withdrawRecords, setWithdrawRecords] = useState<WithdrawRecordWithDetails[]>([])
|
||||||
const formRef = useRef<any>(null)
|
const formRef = useRef<any>(null)
|
||||||
@@ -88,6 +92,21 @@ const DealerWithdraw: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}, [dealerUser?.userId])
|
}, [dealerUser?.userId])
|
||||||
|
|
||||||
|
function fetchBanks() {
|
||||||
|
listShopDealerBank({}).then(data => {
|
||||||
|
const list = data.map(d => {
|
||||||
|
d.name = d.bankName;
|
||||||
|
d.type = d.bankName;
|
||||||
|
return d;
|
||||||
|
})
|
||||||
|
setBanks(list.concat({
|
||||||
|
name: '管理银行卡',
|
||||||
|
type: 'add'
|
||||||
|
}))
|
||||||
|
setBank(data[0])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 格式化账户显示
|
// 格式化账户显示
|
||||||
const getAccountDisplay = (record: ShopDealerWithdraw) => {
|
const getAccountDisplay = (record: ShopDealerWithdraw) => {
|
||||||
if (record.payType === 10) {
|
if (record.payType === 10) {
|
||||||
@@ -107,11 +126,22 @@ const DealerWithdraw: React.FC = () => {
|
|||||||
setRefreshing(false)
|
setRefreshing(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleSelect = (item: ShopDealerBank) => {
|
||||||
|
if(item.type === 'add'){
|
||||||
|
return Taro.navigateTo({
|
||||||
|
url: '/dealer/bank/index'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
setBank(item)
|
||||||
|
setIsVisible(false)
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化加载数据
|
// 初始化加载数据
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (dealerUser?.userId) {
|
if (dealerUser?.userId) {
|
||||||
fetchBalance().then()
|
fetchBalance().then()
|
||||||
fetchWithdrawRecords().then()
|
fetchWithdrawRecords().then()
|
||||||
|
fetchBanks()
|
||||||
}
|
}
|
||||||
}, [fetchBalance, fetchWithdrawRecords])
|
}, [fetchBalance, fetchWithdrawRecords])
|
||||||
|
|
||||||
@@ -259,16 +289,6 @@ const DealerWithdraw: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const quickAmounts = ['100', '300', '500', '1000']
|
|
||||||
|
|
||||||
const setQuickAmount = (amount: string) => {
|
|
||||||
formRef.current?.setFieldsValue({amount})
|
|
||||||
}
|
|
||||||
|
|
||||||
const setAllAmount = () => {
|
|
||||||
formRef.current?.setFieldsValue({amount: availableAmount.replace(/,/g, '')})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 格式化金额
|
// 格式化金额
|
||||||
const formatMoney = (money?: string) => {
|
const formatMoney = (money?: string) => {
|
||||||
if (!money) return '0.00'
|
if (!money) return '0.00'
|
||||||
@@ -303,121 +323,55 @@ const DealerWithdraw: React.FC = () => {
|
|||||||
borderTop: '1px solid rgba(255, 255, 255, 0.3)'
|
borderTop: '1px solid rgba(255, 255, 255, 0.3)'
|
||||||
}}>
|
}}>
|
||||||
<Text className="text-white text-opacity-80 text-xs">
|
<Text className="text-white text-opacity-80 text-xs">
|
||||||
最低提现金额:¥100 | 手续费:每笔3元
|
最低提现金额:¥100
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Form
|
<CellGroup>
|
||||||
ref={formRef}
|
<Cell style={{
|
||||||
onFinish={handleSubmit}
|
padding: '36px 12px'
|
||||||
labelPosition="top"
|
}} title={
|
||||||
>
|
<View className="flex items-center justify-between">
|
||||||
<CellGroup>
|
<Text className={'text-xl'}>¥</Text>
|
||||||
<Form.Item name="amount" label="提现金额" required>
|
|
||||||
<Input
|
<Input
|
||||||
placeholder="请输入提现金额"
|
placeholder="提现金额"
|
||||||
type="number"
|
type="number"
|
||||||
onChange={(value) => {
|
maxLength={7}
|
||||||
// 实时验证提现金额
|
style={{
|
||||||
const amount = parseFloat(value)
|
padding: '0 10px',
|
||||||
const available = parseFloat(availableAmount.replace(/,/g, ''))
|
fontSize: '20px'
|
||||||
if (!isNaN(amount) && amount > available) {
|
|
||||||
// 可以在这里添加实时提示,但不阻止输入
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
<Button fill="none" size={'small'}><Text className={'text-blue-500'}>全部提现</Text></Button>
|
||||||
|
|
||||||
{/* 快捷金额 */}
|
|
||||||
<View className="px-4 py-2">
|
|
||||||
<Text className="text-sm text-gray-600 mb-2">快捷金额</Text>
|
|
||||||
<View className="flex flex-wrap gap-2">
|
|
||||||
{quickAmounts.map(amount => (
|
|
||||||
<Button
|
|
||||||
key={amount}
|
|
||||||
size="small"
|
|
||||||
fill="outline"
|
|
||||||
onClick={() => setQuickAmount(amount)}
|
|
||||||
>
|
|
||||||
{amount}
|
|
||||||
</Button>
|
|
||||||
))}
|
|
||||||
<Button
|
|
||||||
size="small"
|
|
||||||
fill="outline"
|
|
||||||
onClick={setAllAmount}
|
|
||||||
>
|
|
||||||
全部
|
|
||||||
</Button>
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Cell title={'提现到'} onClick={() => setIsVisible(true)} extra={
|
||||||
|
<View className="flex items-center justify-between gap-1">
|
||||||
|
{bank ? <Text className={'text-gray-800'}>{bank.bankName}</Text> : <Text className={'text-gray-400'}>请选择</Text>}
|
||||||
|
<ArrowRight className={'text-gray-300'} size={15}/>
|
||||||
|
</View>
|
||||||
|
}/>
|
||||||
|
<Cell title={'预计到账金额'} description={'提现费率 16% +3元'} extra={
|
||||||
|
<View className="flex items-center justify-between gap-1">
|
||||||
|
<Text className={'text-orange-500 px-2 text-lg'}>¥2141.41</Text>
|
||||||
|
</View>
|
||||||
|
}/>
|
||||||
|
</CellGroup>
|
||||||
|
|
||||||
<Form.Item name="accountType" label="提现方式" required>
|
<View className="mt-6 px-4">
|
||||||
<Radio.Group value={selectedAccount} onChange={() => setSelectedAccount}>
|
<Button
|
||||||
<Cell.Group>
|
block
|
||||||
<Cell>
|
type="primary"
|
||||||
<Radio value="wechat">微信钱包</Radio>
|
nativeType="submit"
|
||||||
</Cell>
|
loading={submitting}
|
||||||
<Cell>
|
disabled={submitting || !selectedAccount}
|
||||||
<Radio value="alipay">支付宝</Radio>
|
onClick={handleSubmit}
|
||||||
</Cell>
|
>
|
||||||
<Cell>
|
{submitting ? '提交中...' : '申请提现'}
|
||||||
<Radio value="bank">银行卡</Radio>
|
</Button>
|
||||||
</Cell>
|
</View>
|
||||||
<Cell>
|
|
||||||
<Radio value="bank">对公转账</Radio>
|
|
||||||
</Cell>
|
|
||||||
</Cell.Group>
|
|
||||||
</Radio.Group>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
{selectedAccount === 'alipay' && (
|
|
||||||
<>
|
|
||||||
<Form.Item name="account" label="支付宝账号" required>
|
|
||||||
<Input placeholder="请输入支付宝账号"/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item name="accountName" label="支付宝姓名" required>
|
|
||||||
<Input placeholder="请输入支付宝实名姓名"/>
|
|
||||||
</Form.Item>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{selectedAccount === 'bank' && (
|
|
||||||
<>
|
|
||||||
<Form.Item name="bankName" label="开户银行" required>
|
|
||||||
<Input placeholder="请输入开户银行名称"/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item name="account" label="银行卡号" required>
|
|
||||||
<Input placeholder="请输入银行卡号"/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item name="accountName" label="开户姓名" required>
|
|
||||||
<Input placeholder="请输入银行卡开户姓名"/>
|
|
||||||
</Form.Item>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{selectedAccount === 'wechat' && (
|
|
||||||
<View className="px-4 py-2">
|
|
||||||
<Text className="text-sm text-gray-500">
|
|
||||||
微信钱包提现将直接转入您的微信零钱
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
</CellGroup>
|
|
||||||
|
|
||||||
<View className="mt-6 px-4">
|
|
||||||
<Button
|
|
||||||
block
|
|
||||||
type="primary"
|
|
||||||
nativeType="submit"
|
|
||||||
loading={submitting}
|
|
||||||
disabled={submitting || !selectedAccount}
|
|
||||||
>
|
|
||||||
{submitting ? '提交中...' : '申请提现'}
|
|
||||||
</Button>
|
|
||||||
</View>
|
|
||||||
</Form>
|
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -475,15 +429,6 @@ const DealerWithdraw: React.FC = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dealerUser) {
|
|
||||||
return (
|
|
||||||
<View className="bg-gray-50 min-h-screen flex items-center justify-center">
|
|
||||||
<Loading/>
|
|
||||||
<Text className="text-gray-500 mt-2">加载中...</Text>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className="bg-gray-50 min-h-screen">
|
<View className="bg-gray-50 min-h-screen">
|
||||||
<Tabs value={activeTab} onChange={handleTabChange}>
|
<Tabs value={activeTab} onChange={handleTabChange}>
|
||||||
@@ -495,6 +440,12 @@ const DealerWithdraw: React.FC = () => {
|
|||||||
{renderWithdrawRecords()}
|
{renderWithdrawRecords()}
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
<ActionSheet
|
||||||
|
visible={isVisible}
|
||||||
|
options={banks}
|
||||||
|
onSelect={handleSelect}
|
||||||
|
onCancel={() => setIsVisible(false)}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user