| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 |
- import { View, Text, Input } from '@tarojs/components';
- import { useState } from 'react';
- import Taro from '@tarojs/taro';
- import {
- Button,
- Input as NutInput,
- Dialog,
- Toast,
- TextArea,
- ToastOptions,
- Radio,
- } from '@nutui/nutui-react-taro';
- import { AlipayIcon, BackCardIcon } from '@/components/Icon';
- import { transferApi } from '@/services/apis';
- import { useUserStore } from '@/stores/user';
- import { BankcardExtInfoSchema } from '@/schemas/account';
- import './index.less';
- export default function Transfer() {
- // 状态管理
- const [showConfirm, setShowConfirm] = useState<boolean>(false);
- const [isLoading, setIsLoading] = useState<boolean>(false);
- const [transferData, setTransferData] = useState<{
- amount: string;
- identity: string;
- name: string;
- identityType: string;
- remark: string;
- bankcardExtInfo: BankcardExtInfoSchema;
- }>({
- amount: '',
- identity: '',
- name: '',
- identityType: 'alipay',
- remark: '',
- bankcardExtInfo: {
- account_type: '1',
- },
- });
- // 常用金额选项
- const quickAmounts = ['10000', '20000', '30000'];
- // 常用备注选项
- const quickRemarks = ['消费', '工资', '奖金', '其他'];
- // 处理金额输入
- const handleAmountChange = (value: string) => {
- // 只允许输入数字和小数点
- let filtered = value.replace(/[^0-9.]/g, '');
- // 限制只有一个小数点
- const parts = filtered.split('.');
- if (parts.length > 2) {
- filtered = parts[0] + '.' + parts.slice(1).join('');
- }
- // 限制小数点后两位
- if (parts.length === 2 && parts[1].length > 2) {
- filtered = parts[0] + '.' + parts[1].substring(0, 2);
- }
- // 限制最大金额
- const numValue = parseFloat(filtered);
- if (!Number.isNaN(numValue) && numValue > 10000000) {
- showToast({
- content: '单笔转账金额不能超过1000万元',
- });
- filtered = '';
- }
- console.log(filtered);
- handleQuickAmount(filtered);
- };
- // 选择常用金额
- const handleQuickAmount = (value: string) => {
- setTransferData({ ...transferData, amount: value });
- };
- // 处理收款方姓名输入
- const handleNameChange = (value: string) => {
- setTransferData({ ...transferData, name: value });
- };
- // 处理收款方账号输入
- const handleIdentityChange = (value: string) => {
- setTransferData({ ...transferData, identity: value });
- };
- // 选择账户类型
- const handleidentityType = (type: string) => {
- setTransferData({
- ...transferData,
- identityType: type,
- identity: '',
- bankcardExtInfo: {
- account_type: '1',
- },
- });
- };
- // 选择常用备注
- const handleQuickRemark = (value: string) => {
- setTransferData({ ...transferData, remark: value });
- };
- // 处理银行卡账户类型选择
- const handleAccountTypeChange = (value: string) => {
- setTransferData({
- ...transferData,
- bankcardExtInfo: {
- ...transferData.bankcardExtInfo,
- account_type: value,
- },
- });
- };
- // 处理银行卡机构名称输入
- const handleInstNameChange = (value: string) => {
- setTransferData({
- ...transferData,
- bankcardExtInfo: {
- ...transferData.bankcardExtInfo,
- inst_name: value,
- },
- });
- };
- const showToast = (options: ToastOptions) => {
- Toast.show('transfer-toast', options);
- };
- // 打开确认弹窗
- const handleOpenConfirm = () => {
- // 验证输入
- if (!transferData.amount || parseFloat(transferData.amount) <= 0) {
- showToast({
- content: '请输入转账金额',
- });
- return;
- }
- if (!transferData.name) {
- showToast({
- content: `请输入收款方真实姓名`,
- });
- return;
- }
- if (!transferData.identity) {
- showToast({
- content: `请输入收款方${transferData.identityType === 'alipay' ? '支付宝' : '银行卡'}账号`,
- });
- return;
- }
- if (
- transferData.identityType === 'bank' &&
- transferData.bankcardExtInfo.account_type === '1' &&
- !transferData.bankcardExtInfo.inst_name
- ) {
- showToast({
- content: '请输入银行卡机构名称',
- });
- return;
- }
- setShowConfirm(true);
- };
- // 确认转账
- const handleConfirmTransfer = async () => {
- setIsLoading(true);
- setShowConfirm(false);
- try {
- const response = await transferApi({
- enterpriseId: useUserStore.getState().enterpriseId,
- amount: transferData.amount,
- payeeInfo: {
- identityType: transferData.identityType,
- name: transferData.name,
- identity: transferData.identity,
- bankcardExtInfo:
- transferData.identityType === 'alipay' ? undefined : transferData.bankcardExtInfo,
- },
- });
- // 显示成功提示
- showToast({
- icon: 'success',
- content: '转账成功',
- });
- // 清空输入
- setTransferData({
- amount: '',
- identity: '',
- name: '',
- identityType: 'alipay',
- remark: '',
- bankcardExtInfo: {
- account_type: '1',
- },
- });
- // 跳转到转账记录页面
- Taro.navigateTo({ url: '/pages/transfer/record/index' });
- } catch (error: unknown) {
- showToast({
- icon: 'error',
- content: error instanceof Error ? error.message : '转账失败',
- });
- } finally {
- setIsLoading(false);
- }
- };
- return (
- <View className="transfer">
- <Toast id="transfer-toast" />
- {/* 金额输入区域 */}
- <View className="amount-section">
- <Text className="amount-label">转账金额(元)</Text>
- <Input
- className="amount-input"
- value={transferData.amount}
- onInput={(e) => handleAmountChange(e.detail.value)}
- placeholder="0.00"
- type="digit"
- maxlength={16}
- disabled={isLoading}
- focus
- />
- <View className="quick-amounts">
- {quickAmounts.map((item) => (
- <View
- key={item}
- className={`quick-amount-btn ${transferData.amount === item ? 'active' : ''} ${isLoading ? 'disabled' : ''}`}
- onClick={() => handleQuickAmount(item)}
- >
- {item}元
- </View>
- ))}
- </View>
- </View>
- {/* 收款方信息区域 */}
- <View className="recipient-section">
- <View className="section-title">收款方信息</View>
- <View style={{ padding: '10px 20px' }}>
- <View className="recipient-input">
- <View className="nut-input-label">收款方姓名</View>
- <NutInput
- value={transferData.name}
- onChange={(value) => handleNameChange(value)}
- placeholder="请输入真实姓名"
- disabled={isLoading}
- maxLength={20}
- clearable
- />
- </View>
- <View className="account-type">
- <Text className="nut-input-label">账户类型</Text>
- <View className="type-options">
- <View
- className={`type-option ${transferData.identityType === 'alipay' ? 'active' : ''} ${isLoading ? 'disabled' : ''}`}
- onClick={() => handleidentityType('alipay')}
- >
- <View style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
- <AlipayIcon size={16} /> <Text style={{ marginLeft: '5px' }}>支付宝</Text>
- </View>
- </View>
- <View
- className={`type-option ${transferData.identityType === 'bank' ? 'active' : ''} ${isLoading ? 'disabled' : ''}`}
- onClick={() => handleidentityType('bank')}
- >
- <View style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
- <BackCardIcon size={20} /> <Text style={{ marginLeft: '5px' }}>银行卡</Text>
- </View>
- </View>
- </View>
- </View>
- <View className="recipient-input">
- <View className="nut-input-label">
- {transferData.identityType === 'alipay' ? '支付宝账号' : '银行卡账号'}
- </View>
- <NutInput
- value={transferData.identity}
- onChange={(value) => handleIdentityChange(value)}
- placeholder={
- transferData.identityType === 'alipay' ? '请输入支付宝账号' : '请输入银行卡号'
- }
- disabled={isLoading}
- maxLength={30}
- clearable
- />
- </View>
- {transferData.identityType === 'bank' && (
- <>
- <View className="recipient-input">
- <View className="nut-input-label">银行卡类型</View>
- <Radio.Group
- value={transferData.bankcardExtInfo.account_type}
- onChange={(value) => handleAccountTypeChange(value as string)}
- direction="horizontal"
- style={
- {
- // '--nutui-radio-button-border-radius': '8px',
- } as any
- }
- >
- <Radio shape="button" value="1">
- 公司账户
- </Radio>
- <Radio shape="button" value="2">
- 个人账户
- </Radio>
- </Radio.Group>
- </View>
- {transferData.bankcardExtInfo.account_type === '1' && (
- <View className="recipient-input">
- <View className="nut-input-label">银行卡机构名称</View>
- <NutInput
- value={transferData.bankcardExtInfo.inst_name || ''}
- onChange={(value) => handleInstNameChange(value)}
- placeholder="请输入机构名称"
- disabled={isLoading}
- maxLength={20}
- clearable
- />
- </View>
- )}
- </>
- )}
- </View>
- </View>
- {/* 备注区域 */}
- <View className="remark-section">
- <View className="section-title">
- 转账备注<Text style={{ color: '#b6b4b4' }}>(可选)</Text>
- </View>
- <View style={{ padding: '0px 20px' }}>
- <TextArea
- className="remark-input"
- value={transferData.remark}
- onChange={(value) => handleQuickRemark(value)}
- disabled={isLoading}
- maxLength={300}
- />
- <View className="quick-remarks">
- {quickRemarks.map((item) => (
- <View
- key={item}
- className={`quick-remark ${transferData.remark === item ? 'active' : ''} ${isLoading ? 'disabled' : ''}`}
- onClick={() => handleQuickRemark(item)}
- >
- {item}
- </View>
- ))}
- </View>
- </View>
- </View>
- {/* 提交按钮 */}
- <View className="submit-section">
- <Button
- className="submit-btn"
- type="primary"
- size="large"
- block
- loading={isLoading}
- onClick={handleOpenConfirm}
- >
- {isLoading ? '提交中...' : '确认转账'}
- </Button>
- </View>
- {/* 确认弹窗 */}
- <Dialog
- visible={showConfirm}
- title="确认转账"
- confirmText="确认"
- cancelText="取消"
- onConfirm={handleConfirmTransfer}
- onCancel={() => setShowConfirm(false)}
- >
- <View className="modal-info">
- <View className="info-item">
- <Text className="label">转账金额:</Text>
- <Text className="value">¥{transferData.amount}</Text>
- </View>
- <View className="info-item">
- <Text className="label">
- {transferData.identityType === 'alipay' ? '支付宝账号' : '银行卡账号'}:
- </Text>
- <Text className="value">{transferData.identity}</Text>
- </View>
- <View className="info-item">
- <Text className="label">备注:</Text>
- <Text className="value">{transferData.remark || '无'}</Text>
- </View>
- </View>
- </Dialog>
- </View>
- );
- }
|