diff --git a/README.md b/README.md index 41986e5..6f89b30 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ ## TODO +- 导航栏 +- 账单页面 +- 实名认证响应 + 分离公共 api 接口 env 定义 统一前端基础库(类型,api) @@ -127,11 +131,3 @@ stores:共享状态组件 - 图片使用 Next.js Image 组件自动优化 - 动态导入 (next/dynamic) 实现纯客户端组件 - - - - - - - - diff --git a/src/components/composites/payment/desktop-payment.tsx b/src/components/composites/payment/desktop-payment.tsx index 959167e..b493eee 100644 --- a/src/components/composites/payment/desktop-payment.tsx +++ b/src/components/composites/payment/desktop-payment.tsx @@ -5,8 +5,10 @@ import {Loader} from 'lucide-react' import {useState} from 'react' import Image from 'next/image' import {PaymentModalProps} from './payment-modal' +import {getTradeMethodDecoration} from '@/lib/models/trade' export function DesktopPayment(props: PaymentModalProps) { + const decoration = getTradeMethodDecoration(props.method) const [loading, setLoading] = useState(false) const onSubmit = async () => { @@ -19,10 +21,10 @@ export function DesktopPayment(props: PaymentModalProps) { - {props.decoration.icon ? ( + {decoration.icon ? ( {props.decoration.text} )} - {props.decoration.text} + {decoration.text} @@ -43,7 +45,7 @@ export function DesktopPayment(props: PaymentModalProps) { />

请使用 - {props.decoration.text} + {decoration.text} 扫码支付

diff --git a/src/components/composites/payment/mobile-payment.tsx b/src/components/composites/payment/mobile-payment.tsx index e554c9f..196c7d0 100644 --- a/src/components/composites/payment/mobile-payment.tsx +++ b/src/components/composites/payment/mobile-payment.tsx @@ -6,8 +6,10 @@ import {CreditCard, Loader} from 'lucide-react' import {useState} from 'react' import Image from 'next/image' import {PaymentModalProps} from './payment-modal' +import {getTradeMethodDecoration} from '@/lib/models/trade' export function MobilePayment(props: PaymentModalProps) { + const decoration = getTradeMethodDecoration(props.method) const [loading, setLoading] = useState(false) // 加载状态 const [paymentInitiated, setPaymentInitiated] = useState(false) // 是否已发起支付 @@ -54,16 +56,16 @@ export function MobilePayment(props: PaymentModalProps) {
支付方式
- {props.decoration.icon && ( + {decoration.icon && ( {props.decoration.text} )} - {props.decoration.text} + {decoration.text}
diff --git a/src/components/composites/payment/payment-modal.tsx b/src/components/composites/payment/payment-modal.tsx index 1e27f6d..9d8920b 100644 --- a/src/components/composites/payment/payment-modal.tsx +++ b/src/components/composites/payment/payment-modal.tsx @@ -6,7 +6,7 @@ import {Dialog} from '@/components/ui/dialog' import {PaymentProps} from './type' import {payClose} from '@/actions/resource' import {useEffect} from 'react' -import {useRouter} from 'next/navigation' +import {UniversalDesktopPayment} from './universal-desktop-payment' export type PaymentModalProps = { onConfirm: (showFail: boolean) => Promise @@ -61,17 +61,13 @@ export function PaymentModal(props: PaymentModalProps) { onOpenChange={(open) => { if (!open) handleClose() }}> - {props.platform === TradePlatform.Mobile ? ( - - ) : ( - - )} + + {/* {props.platform === TradePlatform.Mobile + ? + : + } */} + + ) } diff --git a/src/components/composites/payment/type.ts b/src/components/composites/payment/type.ts index 106d0b4..55db036 100644 --- a/src/components/composites/payment/type.ts +++ b/src/components/composites/payment/type.ts @@ -8,8 +8,4 @@ export type PaymentProps = { amount: number platform: TradePlatform method: TradeMethod - decoration: { - icon: StaticImageData - text: string - } } diff --git a/src/components/composites/payment/universal-desktop-payment.tsx b/src/components/composites/payment/universal-desktop-payment.tsx new file mode 100644 index 0000000..2a8d9d9 --- /dev/null +++ b/src/components/composites/payment/universal-desktop-payment.tsx @@ -0,0 +1,83 @@ +'use client' +import {DialogClose, DialogContent, DialogHeader, DialogTitle} from '@/components/ui/dialog' +import {Button} from '@/components/ui/button' +import {Loader} from 'lucide-react' +import {useState} from 'react' +import Image from 'next/image' +import {PaymentModalProps} from './payment-modal' +import {getTradeMethodDecoration, TradePlatform} from '@/lib/models/trade' + +export function UniversalDesktopPayment(props: PaymentModalProps) { + const decoration = getTradeMethodDecoration(props.method) + const [loading, setLoading] = useState(false) + + const onSubmit = async () => { + setLoading(true) + await props.onConfirm(true) + setLoading(false) + } + + return ( + + + + {decoration.icon ? ( + {decoration.text} + ) : ( +
+ )} + {decoration.text} + + + +
+ 二维码 +
+

+ 请使用 微信 或 支付宝 扫码支付 +

+

+ 手机端长按二维码下载并识图 +

+
+ +
+

+ 支付金额: + + ¥ + {props.amount?.toFixed(2) || '0.00'} + +

+

+ 订单号: + {props.inner_no} +

+
+ +
+ + + + +
+
+ + ) +} diff --git a/src/components/composites/purchase/form.tsx b/src/components/composites/purchase/form.tsx deleted file mode 100644 index e69de29..0000000 diff --git a/src/components/composites/purchase/long/form.tsx b/src/components/composites/purchase/long/form.tsx index ef6d268..f41df10 100644 --- a/src/components/composites/purchase/long/form.tsx +++ b/src/components/composites/purchase/long/form.tsx @@ -1,6 +1,5 @@ 'use client' -import {createContext} from 'react' -import {useForm, UseFormReturn} from 'react-hook-form' +import {useForm} from 'react-hook-form' import Center from '@/components/composites/purchase/long/center' import Right from '@/components/composites/purchase/long/right' import {Form} from '@/components/ui/form' @@ -20,13 +19,6 @@ const schema = z.object({ // 从架构中推断类型 export type Schema = z.infer -type PurchaseFormContextType = { - form: UseFormReturn - onSubmit?: () => void -} - -export const LongFormContext = createContext(undefined) - export default function LongForm() { const form = useForm({ resolver: zodResolver(schema), @@ -36,16 +28,14 @@ export default function LongForm() { quota: 500, expire: '30', // 天 daily_limit: 100, - pay_type: 'balance', // 余额支付 + pay_type: 'wechat', // 余额支付 }, }) return (
- -
- - +
+ ) } diff --git a/src/components/composites/purchase/long/right.tsx b/src/components/composites/purchase/long/right.tsx index 42aacc9..9c7924d 100644 --- a/src/components/composites/purchase/long/right.tsx +++ b/src/components/composites/purchase/long/right.tsx @@ -1,15 +1,6 @@ 'use client' -import {Suspense, use, useContext, useEffect, useMemo, useState} from 'react' -import {PurchaseFormContext} from '@/components/composites/purchase/short/form' -import {RadioGroup} from '@/components/ui/radio-group' -import {FormField} from '@/components/ui/form' -import FormOption from '@/components/composites/purchase/option' -import Image from 'next/image' -import alipay from '../_assets/alipay.svg' -import wechat from '../_assets/wechat.svg' -import balance from '../_assets/balance.svg' +import {Suspense, use, useEffect, useState} from 'react' import {useProfileStore} from '@/components/stores/profile' -import RechargeModal from '@/components/composites/recharge' import Pay from '@/components/composites/purchase/pay' import {buttonVariants} from '@/components/ui/button' import Link from 'next/link' @@ -17,8 +8,9 @@ import {merge} from '@/lib/utils' import {useFormContext, useWatch} from 'react-hook-form' import {Schema} from '@/components/composites/purchase/long/form' import {Card} from '@/components/ui/card' -import {getPrice, CreateResourceReq} from '@/actions/resource' +import {getPrice} from '@/actions/resource' import {ExtraResp} from '@/lib/api' +import {FieldPayment} from '../shared/field-payment' export default function Right() { const {control} = useFormContext() @@ -164,52 +156,7 @@ function BalanceOrLogin(props: { const profile = use(useProfileStore(store => store.profile)) return profile ? ( <> - - {({id, field}) => ( - - - {/*
-

- 余额icon - 账户余额 -

-

- {profile?.balance} - -

-
*/} - - {/* - 余额 icon - 余额 - */} - - 微信 logo - 微信 - - - 支付宝 logo - 支付宝 - -
- )} -
+ {/* */} (null) const router = useRouter() - const platform = usePlatformType() + // const platform = usePlatformType() const onOpen = async () => { setOpen(true) @@ -45,7 +45,7 @@ export default function Pay(props: PayProps) { const req = { ...props.resource, payment_method: method, - payment_platform: platform, + payment_platform: TradePlatform.Desktop, } const resp = await prepareResource(req) @@ -60,9 +60,8 @@ export default function Pay(props: PayProps) { inner_no: resp.data.trade_no, pay_url: resp.data.pay_url, amount: Number(props.amount), - platform: platform, + platform: TradePlatform.Desktop, method: method, - decoration: TradeMethodDecoration[props.method], }) } diff --git a/src/components/composites/purchase/shared/field-payment.tsx b/src/components/composites/purchase/shared/field-payment.tsx new file mode 100644 index 0000000..79be16b --- /dev/null +++ b/src/components/composites/purchase/shared/field-payment.tsx @@ -0,0 +1,57 @@ +import FormOption from '../option' +import {RadioGroup} from '@/components/ui/radio-group' +import {FormField} from '@/components/ui/form' +import Image from 'next/image' +import alipay from '../_assets/alipay.svg' +import wechat from '../_assets/wechat.svg' + +export function FieldPayment() { + return ( + + {({id, field}) => ( + + + {/*
+

+ 余额icon + 账户余额 +

+

+ {profile.balance} + +

+
*/} + + {/* + 余额 icon + 余额 + */} + + 微信 logo + 微信 + + + 支付宝 logo + 支付宝 + +
+ )} +
+ ) +} diff --git a/src/components/composites/purchase/short/form.tsx b/src/components/composites/purchase/short/form.tsx index 8893fa7..edad434 100644 --- a/src/components/composites/purchase/short/form.tsx +++ b/src/components/composites/purchase/short/form.tsx @@ -1,6 +1,5 @@ 'use client' -import {createContext} from 'react' -import {useForm, UseFormReturn} from 'react-hook-form' +import {useForm} from 'react-hook-form' import Center from '@/components/composites/purchase/short/center' import Right from '@/components/composites/purchase/short/right' import {Form} from '@/components/ui/form' @@ -20,16 +19,7 @@ const schema = z.object({ // 从架构中推断类型 export type Schema = z.infer -type PurchaseFormContextType = { - form: UseFormReturn - onSubmit?: () => void -} - -export const PurchaseFormContext = createContext(undefined) - -export type PurchaseFormProps = {} - -export default function PurchaseForm(props: PurchaseFormProps) { +export default function ShortForm() { const form = useForm({ resolver: zodResolver(schema), defaultValues: { @@ -38,7 +28,7 @@ export default function PurchaseForm(props: PurchaseFormProps) { quota: 10_000, // >= 10000 expire: '30', // 天 daily_limit: 2_000, // >= 2000 - pay_type: 'balance', // 余额支付 + pay_type: 'wechat', // 余额支付 }, }) diff --git a/src/components/composites/purchase/short/right.tsx b/src/components/composites/purchase/short/right.tsx index 101efd1..00a5444 100644 --- a/src/components/composites/purchase/short/right.tsx +++ b/src/components/composites/purchase/short/right.tsx @@ -1,23 +1,16 @@ 'use client' -import {Suspense, use, useEffect, useMemo, useState} from 'react' +import {Suspense, use, useEffect, useState} from 'react' import {Schema} from '@/components/composites/purchase/short/form' -import {RadioGroup} from '@/components/ui/radio-group' -import {FormField} from '@/components/ui/form' -import FormOption from '@/components/composites/purchase/option' -import Image from 'next/image' -import alipay from '../_assets/alipay.svg' -import wechat from '../_assets/wechat.svg' -import balance from '../_assets/balance.svg' import {useProfileStore} from '@/components/stores/profile' -import RechargeModal from '@/components/composites/recharge' import {buttonVariants} from '@/components/ui/button' import Link from 'next/link' import {merge} from '@/lib/utils' import Pay from '@/components/composites/purchase/pay' import {useFormContext, useWatch} from 'react-hook-form' import {Card} from '@/components/ui/card' -import {CreateResourceReq, getPrice} from '@/actions/resource' +import {getPrice} from '@/actions/resource' import {ExtraResp} from '@/lib/api' +import {FieldPayment} from '../shared/field-payment' export default function Right() { const {control} = useFormContext() @@ -165,52 +158,7 @@ function BalanceOrLogin(props: { const profile = use(useProfileStore(store => store.profile)) return profile ? ( <> - - {({id, field}) => ( - - - {/*
-

- 余额icon - 账户余额 -

-

- {profile.balance} - -

-
*/} - - {/* - 余额 icon - 余额 - */} - - 微信 logo - 微信 - - - 支付宝 logo - 支付宝 - -
- )} -
+ {/* */} { // 在SSR环境下返回默认值 const [platform, setPlatform] = useState(() => { if (typeof window === 'undefined') return TradePlatform.Desktop - // return window.matchMedia('(max-width: 768px)').matches - // ? TradePlatform.Mobile - // : TradePlatform.Desktop - return TradePlatform.Desktop + return window.matchMedia('(max-width: 768px)').matches + ? TradePlatform.Mobile + : TradePlatform.Desktop }) useEffect(() => { diff --git a/src/lib/models/trade.ts b/src/lib/models/trade.ts index fbc8a95..da4ed58 100644 --- a/src/lib/models/trade.ts +++ b/src/lib/models/trade.ts @@ -1,16 +1,26 @@ import {StaticImageData} from 'next/image' import wechat from '@/components/composites/purchase/_assets/wechat.svg' import alipay from '@/components/composites/purchase/_assets/alipay.svg' +import balance from '@/components/composites/purchase/_assets/balance.svg' -export const TradeMethodDecoration = { - alipay: { - text: '支付宝', - icon: alipay, - }, - wechat: { - text: '微信支付', - icon: wechat, - }, +export function getTradeMethodDecoration(method: TradeMethod) { + switch (method) { + case TradeMethod.Alipay: + return { + text: '支付宝', + icon: alipay, + } + case TradeMethod.Wechat: + return { + text: '微信支付', + icon: wechat, + } + default: + return { + text: '扫码支付', + icon: balance, + } + } } // 支付方法枚举