更新资源列表接口,调整相关数据结构,优化页面布局和样式

This commit is contained in:
2025-05-19 11:04:40 +08:00
parent 52c0184482
commit 9652181fe4
14 changed files with 105 additions and 230 deletions

View File

@@ -206,24 +206,24 @@ export default function Extract(props: ExtractProps) {
<SelectItem
key={`${resource.id}`} value={String(resource.id)} className={`p-3`}>
<div className={`flex flex-col gap-2 w-72`}>
{resource.type === 1 && resource.pss.type === 1 && (<>
{resource.type === 1 && resource.short.type === 1 && (<>
<div className={`flex gap-2 items-center bg-green-50 w-fit px-2 py-1 rounded-md text-sm`}>
<Timer size={20}/>
<span>{name(resource)}</span>
</div>
<div className={`flex justify-between gap-2 text-xs text-weak`}>
<span>{format(resource.pss.expire, 'yyyy-MM-dd HH:mm')}</span>
<span>{intlFormatDistance(resource.pss.expire, new Date())}</span>
<span>{format(resource.short.expire, 'yyyy-MM-dd HH:mm')}</span>
<span>{intlFormatDistance(resource.short.expire, new Date())}</span>
</div>
</>)}
{resource.type === 1 && resource.pss.type === 2 && (<>
{resource.type === 1 && resource.short.type === 2 && (<>
<div className={`flex gap-2 items-center bg-blue-50 w-fit px-2 py-1 rounded-md text-sm`}>
<Box size={20}/>
<span>{name(resource)}</span>
</div>
<div className={`flex justify-between gap-2 text-xs text-weak`}>
<span>{resource.pss.used} / {resource.pss.quota}</span>
<span> {resource.pss.quota - resource.pss.used}</span>
<span>{resource.short.used} / {resource.short.quota}</span>
<span> {resource.short.quota - resource.short.used}</span>
</div>
</>)}
</div>

View File

@@ -210,9 +210,6 @@ export default function Center() {
</p>
</div>
</div>
{/* 左右的边框 */}
<div className={`absolute inset-0 my-8 border-l border-r border-gray-200 pointer-events-none`}></div>
</div>
)
}

View File

@@ -1,16 +1,11 @@
'use client'
import {createContext, useContext} from 'react'
import {createContext} from 'react'
import {useForm, UseFormReturn} from 'react-hook-form'
import Center from '@/components/composites/purchase/_client/center'
import Right from '@/components/composites/purchase/_client/right'
import Left from '@/components/composites/purchase/_client/left'
import {Form} from '@/components/ui/form'
import * as z from 'zod'
import {zodResolver} from '@hookform/resolvers/zod'
import {createResourceByBalance} from '@/actions/resource'
import {toast} from 'sonner'
import {useRouter} from 'next/navigation'
import {StoreContext} from '@/components/providers/StoreProvider'
// 定义表单验证架构
const schema = z.object({
@@ -51,7 +46,6 @@ export default function PurchaseForm(props: PurchaseFormProps) {
<section role={`tabpanel`} className={`bg-white rounded-lg`}>
<Form form={form} className={`flex flex-row`}>
<PurchaseFormContext.Provider value={{form}}>
<Left/>
<Center/>
<Right/>
</PurchaseFormContext.Provider>

View File

@@ -1,124 +0,0 @@
'use client'
import {useState} from 'react'
import Image from 'next/image'
import banner from '@/components/composites/purchase/_assets/banner.webp'
export type LeftProps = {
}
export default function Left(props: LeftProps) {
return (
<div className="flex-none basis-56 p-8 flex flex-col gap-4">
<Image src={banner} alt={`banner`} className={`w-full`}/>
<h3 className={`text-lg`}></h3>
<ul className={`flex flex-col gap-3`}>
<Combo name={`3分钟`} level={[
{number: 30000, discount: 10},
{number: 80000, discount: 20},
{number: 200000, discount: 30},
{number: 450000, discount: 40},
{number: 1000000, discount: 50},
{number: 1600000, discount: 65},
]}/>
<Combo name={`5分钟`} level={[
{number: 30000, discount: 10},
{number: 80000, discount: 20},
{number: 200000, discount: 30},
{number: 450000, discount: 40},
{number: 1000000, discount: 50},
{number: 1600000, discount: 65},
]}/>
<Combo name={`10分钟`} level={[
{number: 30000, discount: 10},
{number: 80000, discount: 20},
{number: 200000, discount: 30},
{number: 450000, discount: 40},
{number: 1000000, discount: 50},
{number: 1600000, discount: 65},
]}/>
<Combo name={`15分钟`} level={[
{number: 30000, discount: 10},
{number: 80000, discount: 20},
{number: 200000, discount: 30},
{number: 450000, discount: 40},
{number: 1000000, discount: 50},
{number: 1600000, discount: 65},
]}/>
<Combo name={`30分钟`} level={[
{number: 30000, discount: 10},
{number: 80000, discount: 20},
{number: 200000, discount: 30},
{number: 450000, discount: 40},
{number: 1000000, discount: 50},
{number: 1600000, discount: 65},
]}/>
</ul>
<div className={`border-b border-gray-200`}></div>
<h3 className={`text-lg`}></h3>
<ul className={`flex flex-col gap-3`}>
<li className={`flex justify-between`}>
<span className={`text-sm text-gray-500`}>7</span>
<span className={`text-orange-500 text-xs text-light px-2 py-1 bg-orange-50 rounded-full`}>9</span>
</li>
<li className={`flex justify-between`}>
<span className={`text-sm text-gray-500`}>30</span>
<span className={`text-orange-500 text-xs text-light px-2 py-1 bg-orange-50 rounded-full`}>8</span>
</li>
<li className={`flex justify-between`}>
<span className={`text-sm text-gray-500`}>90</span>
<span className={`text-orange-500 text-xs text-light px-2 py-1 bg-orange-50 rounded-full`}>7</span>
</li>
<li className={`flex justify-between`}>
<span className={`text-sm text-gray-500`}>180</span>
<span className={`text-orange-500 text-xs text-light px-2 py-1 bg-orange-50 rounded-full`}>6</span>
</li>
<li className={`flex justify-between`}>
<span className={`text-sm text-gray-500`}>360</span>
<span className={`text-orange-500 text-xs text-light px-2 py-1 bg-orange-50 rounded-full`}>5</span>
</li>
</ul>
</div>
)
}
function Combo(props: {
name: string
level?: {
number: number
discount: number
}[]
}) {
const [open, setOpen] = useState(false)
return (
<li>
<p className={`flex justify-between items-center`}>
<span>{props.name}</span>
<button
className={`text-gray-500 text-sm`}
onClick={() => setOpen(!open)}
>
{open ? '收起' : '展开'}
</button>
</p>
{props.level && (
<ul className={[
`flex flex-col gap-3 overflow-hidden`,
`transition-[opacity,padding,max-height] transition-discrete duration-200 ease-in-out`,
open
? 'delay-[0s, 0s] opacity-100 py-3 max-h-80'
: 'delay-[0s, 0.2s] opacity-0 p-0 max-h-0',
].join(' ')}>
{props.level.map((item, index) => (
<li key={index} className={`flex flex-row justify-between items-center`}>
<span className={`text-gray-500 text-sm`}>{item.number}</span>
<span className={`text-orange-500 text-xs text-light px-2 py-1 bg-orange-50 rounded-full`}> {item.discount} %</span>
</li>
))}
</ul>
)}
</li>
)
}

View File

@@ -0,0 +1,27 @@
'use client'
import {ReactNode, useState} from 'react'
export type NavProps = {
}
export default function Nav(props: NavProps) {
const [type, setType] = useState()
return (
<ul role={`tablist`} className={`flex justify-center items-stretch bg-white rounded-lg`}>
<li role={`tab`}>
<button className={`h-14 px-8 text-lg`}></button>
</li>
<li role={`tab`}>
<button className={`h-14 px-8 text-lg`}></button>
</li>
<li role={`tab`}>
<button className={`h-14 px-8 text-lg`}></button>
</li>
<li role={`tab`}>
<button className={`h-14 px-8 text-lg`}></button>
</li>
</ul>
)
}

View File

@@ -32,8 +32,8 @@ export type PayProps = {
export default function Pay(props: PayProps) {
const profile = useProfileStore(store=>store.profile)
const refreshProfile = useProfileStore(store=>store.refreshProfile)
const profile = useProfileStore(store => store.profile)
const refreshProfile = useProfileStore(store => store.refreshProfile)
const [open, setOpen] = useState(false)
const [payInfo, setPayInfo] = useState<CreateResourceResp | undefined>()
@@ -185,7 +185,7 @@ export default function Pay(props: PayProps) {
<div className="bg-gray-100 size-50 flex items-center justify-center">
{payInfo ? (
props.method === 'alipay'
? <iframe src={payInfo.pay_url} className="w-full h-full" />
? <iframe src={payInfo.pay_url} className="w-full h-full"/>
: <canvas ref={canvas} className="w-full h-full"/>
) : (
<Loader size={40} className={`animate-spin text-weak`}/>

View File

@@ -13,6 +13,7 @@ import RechargeModal from '@/components/composites/recharge'
import Pay from '@/components/composites/purchase/_client/pay'
import {buttonVariants} from '@/components/ui/button'
import Link from 'next/link'
import {merge} from '@/lib/utils'
export type RightProps = {}
@@ -48,7 +49,10 @@ export default function Right(props: RightProps) {
}, [watchDailyLimit, watchExpire, watchLive, watchQuota, watchType])
return (
<div className={`flex-none basis-80 p-6 flex flex-col gap-6`}>
<div className={merge(
`flex-none basis-80 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`}>

View File

@@ -1,4 +1,7 @@
import PurchaseForm from '@/components/composites/purchase/_client/form'
import {Tabs, TabsContent, TabsList, TabsTrigger} from '@/components/ui/tabs'
import {ReactNode} from 'react'
import {merge} from '@/lib/utils'
export type PurchaseProps = {}
@@ -6,22 +9,35 @@ export default async function Purchase(props: PurchaseProps) {
return (
<div className="flex flex-col gap-4">
{/*<ul role={`tablist`} className={`flex justify-center items-stretch bg-white rounded-lg`}>*/}
{/* <li role={`tab`}>*/}
{/* <button className={`h-14 px-8 text-lg`}>短效动态套餐</button>*/}
{/* </li>*/}
{/* <li role={`tab`}>*/}
{/* <button className={`h-14 px-8 text-lg`}>长效静态套餐</button>*/}
{/* </li>*/}
{/* <li role={`tab`}>*/}
{/* <button className={`h-14 px-8 text-lg`}>固定套餐</button>*/}
{/* </li>*/}
{/* <li role={`tab`}>*/}
{/* <button className={`h-14 px-8 text-lg`}>定制套餐</button>*/}
{/* </li>*/}
{/*</ul>*/}
<PurchaseForm/>
<Tabs defaultValue={`short`} className={`gap-4`}>
<TabsList className={`w-full p-2 bg-white rounded-lg justify-center`}>
<Tab value={`short`}></Tab>
<Tab value={`long`}></Tab>
<Tab value={`fixed`}></Tab>
<Tab value={`custom`}></Tab>
</TabsList>
<TabsContent value={`short`}>
<PurchaseForm/>
</TabsContent>
<TabsContent value={`long`}>
<PurchaseForm/>
</TabsContent>
</Tabs>
</div>
)
}
function Tab(props: {
value: string
children: ReactNode
}) {
return (
<TabsTrigger className={merge(
`w-36 h-12 text-base font-normal flex-none`,
`data-[state=active]:text-primary data-[state=active]:bg-primary-muted`,
)} value={props.value}>
{props.children}
</TabsTrigger>
)
}