feat(dealer): 新增银行卡管理功能
- 添加银行卡管理页面和相关API - 实现银行卡列表展示、添加、编辑和删除功能 - 优化提现页面,支持选择银行卡进行提现 - 新增 FixedButton 组件用于底部固定按钮
This commit is contained in:
@@ -4,22 +4,23 @@ import {
|
||||
Cell,
|
||||
Space,
|
||||
Button,
|
||||
Form,
|
||||
Input,
|
||||
CellGroup,
|
||||
Radio,
|
||||
Tabs,
|
||||
Tag,
|
||||
Empty,
|
||||
ActionSheet,
|
||||
Loading,
|
||||
PullToRefresh
|
||||
} 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 Taro from '@tarojs/taro'
|
||||
import {useDealerUser} from '@/hooks/useDealerUser'
|
||||
import {pageShopDealerWithdraw, addShopDealerWithdraw} from '@/api/shop/shopDealerWithdraw'
|
||||
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 {
|
||||
accountDisplay?: string
|
||||
@@ -31,6 +32,9 @@ const DealerWithdraw: React.FC = () => {
|
||||
const [loading, setLoading] = useState<boolean>(false)
|
||||
const [refreshing, setRefreshing] = 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 [withdrawRecords, setWithdrawRecords] = useState<WithdrawRecordWithDetails[]>([])
|
||||
const formRef = useRef<any>(null)
|
||||
@@ -88,6 +92,21 @@ const DealerWithdraw: React.FC = () => {
|
||||
}
|
||||
}, [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) => {
|
||||
if (record.payType === 10) {
|
||||
@@ -107,11 +126,22 @@ const DealerWithdraw: React.FC = () => {
|
||||
setRefreshing(false)
|
||||
}
|
||||
|
||||
const handleSelect = (item: ShopDealerBank) => {
|
||||
if(item.type === 'add'){
|
||||
return Taro.navigateTo({
|
||||
url: '/dealer/bank/index'
|
||||
})
|
||||
}
|
||||
setBank(item)
|
||||
setIsVisible(false)
|
||||
}
|
||||
|
||||
// 初始化加载数据
|
||||
useEffect(() => {
|
||||
if (dealerUser?.userId) {
|
||||
fetchBalance().then()
|
||||
fetchWithdrawRecords().then()
|
||||
fetchBanks()
|
||||
}
|
||||
}, [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) => {
|
||||
if (!money) return '0.00'
|
||||
@@ -303,121 +323,55 @@ const DealerWithdraw: React.FC = () => {
|
||||
borderTop: '1px solid rgba(255, 255, 255, 0.3)'
|
||||
}}>
|
||||
<Text className="text-white text-opacity-80 text-xs">
|
||||
最低提现金额:¥100 | 手续费:每笔3元
|
||||
最低提现金额:¥100
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<Form
|
||||
ref={formRef}
|
||||
onFinish={handleSubmit}
|
||||
labelPosition="top"
|
||||
>
|
||||
<CellGroup>
|
||||
<Form.Item name="amount" label="提现金额" required>
|
||||
<CellGroup>
|
||||
<Cell style={{
|
||||
padding: '36px 12px'
|
||||
}} title={
|
||||
<View className="flex items-center justify-between">
|
||||
<Text className={'text-xl'}>¥</Text>
|
||||
<Input
|
||||
placeholder="请输入提现金额"
|
||||
placeholder="提现金额"
|
||||
type="number"
|
||||
onChange={(value) => {
|
||||
// 实时验证提现金额
|
||||
const amount = parseFloat(value)
|
||||
const available = parseFloat(availableAmount.replace(/,/g, ''))
|
||||
if (!isNaN(amount) && amount > available) {
|
||||
// 可以在这里添加实时提示,但不阻止输入
|
||||
}
|
||||
maxLength={7}
|
||||
style={{
|
||||
padding: '0 10px',
|
||||
fontSize: '20px'
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
{/* 快捷金额 */}
|
||||
<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>
|
||||
<Button fill="none" size={'small'}><Text className={'text-blue-500'}>全部提现</Text></Button>
|
||||
</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>
|
||||
<Radio.Group value={selectedAccount} onChange={() => setSelectedAccount}>
|
||||
<Cell.Group>
|
||||
<Cell>
|
||||
<Radio value="wechat">微信钱包</Radio>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Radio value="alipay">支付宝</Radio>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Radio value="bank">银行卡</Radio>
|
||||
</Cell>
|
||||
<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 className="mt-6 px-4">
|
||||
<Button
|
||||
block
|
||||
type="primary"
|
||||
nativeType="submit"
|
||||
loading={submitting}
|
||||
disabled={submitting || !selectedAccount}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
{submitting ? '提交中...' : '申请提现'}
|
||||
</Button>
|
||||
</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 (
|
||||
<View className="bg-gray-50 min-h-screen">
|
||||
<Tabs value={activeTab} onChange={handleTabChange}>
|
||||
@@ -495,6 +440,12 @@ const DealerWithdraw: React.FC = () => {
|
||||
{renderWithdrawRecords()}
|
||||
</Tabs.TabPane>
|
||||
</Tabs>
|
||||
<ActionSheet
|
||||
visible={isVisible}
|
||||
options={banks}
|
||||
onSelect={handleSelect}
|
||||
onCancel={() => setIsVisible(false)}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user