重构项目结构,将数据层集中在 lib 包中;resource 类型更新,支持多个子套餐类型分别表示;新增长效套餐的购买流程,以及已购查询功能
This commit is contained in:
167
src/components/composites/purchase/short/right.tsx
Normal file
167
src/components/composites/purchase/short/right.tsx
Normal file
@@ -0,0 +1,167 @@
|
||||
'use client'
|
||||
import {useMemo} 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 '@/components/composites/purchase/_assets/alipay.svg'
|
||||
import wechat from '@/components/composites/purchase/_assets/wechat.svg'
|
||||
import balance from '@/components/composites/purchase/_assets/balance.svg'
|
||||
import {useProfileStore} from '@/components/providers/StoreProvider'
|
||||
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} from 'react-hook-form'
|
||||
|
||||
export default function Right() {
|
||||
const profile = useProfileStore(store => store.profile)
|
||||
|
||||
const form = useFormContext<Schema>()
|
||||
|
||||
const method = form.watch('pay_type')
|
||||
const live = form.watch('live')
|
||||
const mode = form.watch('type')
|
||||
const dailyLimit = form.watch('daily_limit')
|
||||
const expire = form.watch('expire')
|
||||
const quota = form.watch('quota')
|
||||
|
||||
const price = useMemo(() => {
|
||||
// var factor int32
|
||||
// switch data.Mode {
|
||||
// case 1:
|
||||
// factor = data.DailyLimit * data.Expire
|
||||
// case 2:
|
||||
// factor = data.Quota
|
||||
// }
|
||||
//
|
||||
// var base = data.Live
|
||||
// if base == 180 {
|
||||
// base = 150
|
||||
// }
|
||||
//
|
||||
// var dec = decimal.Decimal{}.
|
||||
// Add(decimal.NewFromInt32(base * factor)).
|
||||
// Div(decimal.NewFromInt(30000))
|
||||
// data.price = &dec
|
||||
const base = live === '180' ? 150 : Number(live) * 60
|
||||
const factor = {
|
||||
'1': Number(expire) * dailyLimit,
|
||||
'2': quota,
|
||||
}[mode]
|
||||
return (base * factor / 30000).toFixed(2)
|
||||
}, [dailyLimit, expire, live, quota, mode])
|
||||
|
||||
return (
|
||||
<div className={merge(
|
||||
`flex-none basis-90 p-6 flex flex-col gap-6 relative`,
|
||||
`after:absolute after:inset-0 after:my-6 after:border-l after:border-gray-200 after:select-none after:pointer-events-none`,
|
||||
)}>
|
||||
<h3>订单详情</h3>
|
||||
<ul className={`flex flex-col gap-3`}>
|
||||
<li className={`flex justify-between items-center`}>
|
||||
<span className={`text-sm text-gray-500`}>套餐名称</span>
|
||||
<span className={`text-sm`}>
|
||||
{mode === '2' ? `包量套餐` : `包时套餐`}
|
||||
</span>
|
||||
</li>
|
||||
<li className={`flex justify-between items-center`}>
|
||||
<span className={`text-sm text-gray-500`}>IP 时效</span>
|
||||
<span className={`text-sm`}>
|
||||
{Number(live) / 60} 分钟
|
||||
</span>
|
||||
</li>
|
||||
{mode === '2' ? (
|
||||
<li className={`flex justify-between items-center`}>
|
||||
<span className={`text-sm text-gray-500`}>购买 IP 量</span>
|
||||
<span className={`text-sm`}>
|
||||
{quota}个
|
||||
</span>
|
||||
</li>
|
||||
) : <>
|
||||
<li className={`flex justify-between items-center`}>
|
||||
<span className={`text-sm text-gray-500`}>套餐时长</span>
|
||||
<span className={`text-sm`}>
|
||||
{expire}天
|
||||
</span>
|
||||
</li>
|
||||
<li className={`flex justify-between items-center`}>
|
||||
<span className={`text-sm text-gray-500`}>每日限额</span>
|
||||
<span className={`text-sm`}>
|
||||
{dailyLimit}个
|
||||
</span>
|
||||
</li>
|
||||
</>}
|
||||
</ul>
|
||||
<div className={`border-b border-gray-200`}></div>
|
||||
<p className={`flex justify-between items-center`}>
|
||||
<span>价格</span>
|
||||
<span className={`text-xl text-orange-500`}>¥{price}</span>
|
||||
</p>
|
||||
{profile ? <>
|
||||
<FormField name={`pay_type`} label={`支付方式`} className={`flex flex-col gap-6`}>
|
||||
{({id, field}) => (
|
||||
<RadioGroup
|
||||
id={id}
|
||||
defaultValue={field.value}
|
||||
onValueChange={field.onChange}
|
||||
className={`flex flex-col gap-3`}>
|
||||
|
||||
<div className={`w-full p-3 flex flex-col gap-4 bg-gray-100 rounded-md`}>
|
||||
<p className={`flex items-center gap-3`}>
|
||||
<Image src={balance} alt={`余额icon`}/>
|
||||
<span className={`text-sm text-gray-500`}>账户余额</span>
|
||||
</p>
|
||||
<p className={`flex justify-between items-center`}>
|
||||
<span className={`text-xl`}>{profile?.balance}</span>
|
||||
<RechargeModal/>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<FormOption
|
||||
id={`${id}-balance`}
|
||||
value={`balance`}
|
||||
compare={field.value}
|
||||
className={`p-3 w-full flex-row gap-2 justify-center`}>
|
||||
<Image src={balance} alt={`余额 icon`}/>
|
||||
<span>余额</span>
|
||||
</FormOption>
|
||||
<FormOption
|
||||
id={`${id}-wechat`}
|
||||
value={`wechat`}
|
||||
compare={field.value}
|
||||
className={`p-3 w-full flex-row gap-2 justify-center`}>
|
||||
<Image src={wechat} alt={`微信 logo`}/>
|
||||
<span>微信</span>
|
||||
</FormOption>
|
||||
<FormOption
|
||||
id={`${id}-alipay`}
|
||||
value={`alipay`}
|
||||
compare={field.value}
|
||||
className={`p-3 w-full flex-row gap-2 justify-center`}>
|
||||
<Image src={alipay} alt={`支付宝 logo`}/>
|
||||
<span>支付宝</span>
|
||||
</FormOption>
|
||||
</RadioGroup>
|
||||
)}
|
||||
</FormField>
|
||||
<Pay method={method} amount={price} resource={{
|
||||
type: 1,
|
||||
short: {
|
||||
mode: Number(mode),
|
||||
live: Number(live),
|
||||
quota: quota,
|
||||
expire: Number(expire),
|
||||
daily_limit: dailyLimit,
|
||||
},
|
||||
}}/>
|
||||
</> : (
|
||||
<Link href={`/login`} className={buttonVariants()}>
|
||||
登录后支付
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user