Commit 64fe8a7f by Apple\Apple

📱 feat(TopUp): enhance mobile UX with responsive layout and bottom fixed payment panel

- Convert copy button to Input suffix for cleaner UI design
- Add responsive grid layout for balance cards and preset amounts
  - Mobile (< md): single column layout for better readability
  - Desktop (>= md): multi-column layout for space efficiency
- Implement bottom fixed payment panel on mobile devices
  - Fixed positioning for easy access to payment options
  - Includes custom amount input and payment method buttons
  - Auto-hide on desktop to maintain original layout
- Improve mobile payment flow with sticky bottom controls
- Add proper spacing to prevent content overlap with fixed elements
- Maintain consistent functionality across all breakpoints

This update significantly improves the mobile user experience by making
payment controls easily accessible without scrolling, while preserving
the desktop layout and functionality.
parent d5222743
...@@ -136,9 +136,8 @@ const PageLayout = () => { ...@@ -136,9 +136,8 @@ const PageLayout = () => {
flex: '1 0 auto', flex: '1 0 auto',
overflowY: styleState.isMobile ? 'visible' : 'auto', overflowY: styleState.isMobile ? 'visible' : 'auto',
WebkitOverflowScrolling: 'touch', WebkitOverflowScrolling: 'touch',
padding: shouldInnerPadding ? '24px' : '0', padding: shouldInnerPadding ? (styleState.isMobile ? '5px' : '24px') : '0',
position: 'relative', position: 'relative',
marginTop: styleState.isMobile ? '2px' : '0',
}} }}
> >
<App /> <App />
......
...@@ -46,8 +46,7 @@ import { ...@@ -46,8 +46,7 @@ import {
Gift, Gift,
User, User,
Settings, Settings,
CircleUser, CircleUser
Users
} from 'lucide-react'; } from 'lucide-react';
// 侧边栏图标颜色映射 // 侧边栏图标颜色映射
......
...@@ -971,6 +971,8 @@ ...@@ -971,6 +971,8 @@
"最低": "lowest", "最低": "lowest",
"划转额度": "Transfer amount", "划转额度": "Transfer amount",
"邀请链接": "Invitation link", "邀请链接": "Invitation link",
"划转邀请额度": "Transfer invitation quota",
"可用邀请额度": "Available invitation quota",
"更多优惠": "More offers", "更多优惠": "More offers",
"企业微信": "Enterprise WeChat", "企业微信": "Enterprise WeChat",
"点击解绑WxPusher": "Click to unbind WxPusher", "点击解绑WxPusher": "Click to unbind WxPusher",
......
...@@ -347,7 +347,7 @@ const TopUp = () => { ...@@ -347,7 +347,7 @@ const TopUp = () => {
}; };
return ( return (
<div className="mx-auto"> <div className="mx-auto relative min-h-screen lg:min-h-0">
{/* 划转模态框 */} {/* 划转模态框 */}
<Modal <Modal
title={ title={
...@@ -485,7 +485,7 @@ const TopUp = () => { ...@@ -485,7 +485,7 @@ const TopUp = () => {
> >
<div className="space-y-4"> <div className="space-y-4">
{/* 账户余额信息 */} {/* 账户余额信息 */}
<div className="grid grid-cols-2 gap-4 mb-2"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-2">
<Card className="!rounded-2xl"> <Card className="!rounded-2xl">
<Text type="tertiary" className="mb-1"> <Text type="tertiary" className="mb-1">
{t('当前余额')} {t('当前余额')}
...@@ -517,7 +517,7 @@ const TopUp = () => { ...@@ -517,7 +517,7 @@ const TopUp = () => {
{/* 预设充值额度卡片网格 */} {/* 预设充值额度卡片网格 */}
<div> <div>
<Text strong className="block mb-3">{t('选择充值额度')}</Text> <Text strong className="block mb-3">{t('选择充值额度')}</Text>
<div className="grid grid-cols-2 sm:grid-cols-4 gap-3"> <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-3">
{presetAmounts.map((preset, index) => ( {presetAmounts.map((preset, index) => (
<Card <Card
key={index} key={index}
...@@ -539,7 +539,8 @@ const TopUp = () => { ...@@ -539,7 +539,8 @@ const TopUp = () => {
))} ))}
</div> </div>
</div> </div>
{/* 桌面端显示的自定义金额和支付按钮 */}
<div className="hidden md:block space-y-4">
<Divider style={{ margin: '24px 0' }}> <Divider style={{ margin: '24px 0' }}>
<Text className="text-sm font-medium">{t('或输入自定义金额')}</Text> <Text className="text-sm font-medium">{t('或输入自定义金额')}</Text>
</Divider> </Divider>
...@@ -606,13 +607,14 @@ const TopUp = () => { ...@@ -606,13 +607,14 @@ const TopUp = () => {
<span className="ml-2">{t('微信')}</span> <span className="ml-2">{t('微信')}</span>
</Button> </Button>
</div> </div>
</div>
</> </>
)} )}
{!enableOnlineTopUp && ( {!enableOnlineTopUp && (
<Banner <Banner
type="warning" type="warning"
description={t('管理员未开启在线充值功能,请联系管理员或使用兑换码充值。')} description={t('管理员未开启在线充值功能,请联系管理员开启或使用兑换码充值。')}
closeIcon={null} closeIcon={null}
className="!rounded-2xl" className="!rounded-2xl"
/> />
...@@ -735,22 +737,21 @@ const TopUp = () => { ...@@ -735,22 +737,21 @@ const TopUp = () => {
<div className="space-y-4"> <div className="space-y-4">
<Title heading={6}>{t('邀请链接')}</Title> <Title heading={6}>{t('邀请链接')}</Title>
<div className="relative">
<Input <Input
value={affLink} value={affLink}
readOnly readOnly
size="large" size="large"
/> suffix={
<Button <Button
type="primary" type="primary"
theme="light" theme="light"
onClick={handleAffLinkClick} onClick={handleAffLinkClick}
className="absolute right-1 top-1 bottom-1"
icon={<Copy size={14} />} icon={<Copy size={14} />}
> >
{t('复制')} {t('复制')}
</Button> </Button>
</div> }
/>
<div className="mt-4"> <div className="mt-4">
<Card className="!rounded-2xl"> <Card className="!rounded-2xl">
...@@ -781,6 +782,71 @@ const TopUp = () => { ...@@ -781,6 +782,71 @@ const TopUp = () => {
</Card> </Card>
</div> </div>
</div> </div>
{/* 移动端底部固定的自定义金额和支付区域 */}
{enableOnlineTopUp && (
<div className="md:hidden fixed bottom-0 left-0 right-0 p-4 shadow-lg z-50" style={{ background: 'var(--semi-color-bg-0)' }}>
<div className="space-y-4">
<div>
<div className="flex justify-between mb-2">
<Text strong>{t('充值数量')}</Text>
{amountLoading ? (
<Skeleton.Title style={{ width: '80px', height: '16px' }} />
) : (
<Text type="tertiary">{t('实付金额:') + renderAmount()}</Text>
)}
</div>
<InputNumber
disabled={!enableOnlineTopUp}
placeholder={t('充值数量,最低 ') + renderQuotaWithAmount(minTopUp)}
value={topUpCount}
min={minTopUp}
max={999999999}
step={1}
precision={0}
onChange={async (value) => {
if (value && value >= 1) {
setTopUpCount(value);
setSelectedPreset(null);
await getAmount(value);
}
}}
onBlur={(e) => {
const value = parseInt(e.target.value);
if (!value || value < 1) {
setTopUpCount(1);
getAmount(1);
}
}}
className="w-full"
formatter={(value) => value ? `${value}` : ''}
parser={(value) => value ? parseInt(value.replace(/[^\d]/g, '')) : 0}
/>
</div>
<div className="grid grid-cols-2 gap-4">
<Button
type="primary"
onClick={() => preTopUp('zfb')}
disabled={!enableOnlineTopUp}
loading={paymentLoading && payWay === 'zfb'}
icon={<SiAlipay size={18} />}
>
<span className="ml-2">{t('支付宝')}</span>
</Button>
<Button
type="primary"
onClick={() => preTopUp('wx')}
disabled={!enableOnlineTopUp}
loading={paymentLoading && payWay === 'wx'}
icon={<SiWechat size={18} />}
>
<span className="ml-2">{t('微信')}</span>
</Button>
</div>
</div>
</div>
)}
</div> </div>
); );
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment