重构认证逻辑,优化登录和用户信息获取流程,新增全局缓存支持

This commit is contained in:
2025-04-23 19:00:53 +08:00
parent 22d3b8f3e3
commit 9473413def
23 changed files with 438 additions and 474 deletions

View File

@@ -10,7 +10,7 @@ import {zodResolver} from '@hookform/resolvers/zod'
import {createResourceByBalance} from '@/actions/resource'
import {toast} from 'sonner'
import {useRouter} from 'next/navigation'
import {AuthContext} from '@/components/providers/AuthProvider'
import {StoreContext} from '@/components/providers/StoreProvider'
// 定义表单验证架构
const schema = z.object({

View File

@@ -6,7 +6,7 @@ import wechat from '../_assets/wechat.svg'
import balance from '../_assets/balance.svg'
import Image from 'next/image'
import {useContext, useRef, useState} from 'react'
import {AuthContext} from '@/components/providers/AuthProvider'
import {StoreContext, useProfileStore} from '@/components/providers/StoreProvider'
import {Alert, AlertDescription} from '@/components/ui/alert'
import {
prepareResourceByAlipay,
@@ -32,7 +32,9 @@ export type PayProps = {
export default function Pay(props: PayProps) {
const ctx = useContext(AuthContext)
const profile = useProfileStore(store=>store.profile)
const refreshProfile = useProfileStore(store=>store.refreshProfile)
const [open, setOpen] = useState(false)
const [payInfo, setPayInfo] = useState<CreateResourceResp | undefined>()
const canvas = useRef<HTMLCanvasElement>(null)
@@ -97,7 +99,7 @@ export default function Pay(props: PayProps) {
})
setOpen(false)
await ctx.refreshProfile()
await refreshProfile()
}
catch (e) {
console.log(e)
@@ -133,12 +135,12 @@ export default function Pay(props: PayProps) {
</DialogHeader>
{props.method === 'balance' ? (
ctx.profile && (
profile && (
<div className="flex flex-col gap-4">
<div className="flex flex-col gap-1">
<div className="flex justify-between items-center">
<span className="text-weak text-sm"></span>
<span className={`text-lg`}>{ctx.profile.balance}</span>
<span className={`text-lg`}>{profile.balance}</span>
</div>
<div className="flex justify-between items-center">
<span className="text-weak text-sm"></span>
@@ -147,13 +149,13 @@ export default function Pay(props: PayProps) {
<hr className="my-2"/>
<div className="flex justify-between items-center">
<span className="text-weak text-sm"></span>
<span className={`text-lg ${ctx.profile.balance > props.amount ? 'text-done' : `text-fail`}`}>
{ctx.profile.balance - props.amount}
<span className={`text-lg ${profile.balance > props.amount ? 'text-done' : `text-fail`}`}>
{profile.balance - props.amount}
</span>
</div>
</div>
{ctx.profile.balance < props.amount && (
{profile.balance < props.amount && (
<Alert variant="fail">
<AlertDescription>
@@ -161,7 +163,7 @@ export default function Pay(props: PayProps) {
</Alert>
)}
{ctx.profile.balance >= props.amount && (
{profile.balance >= props.amount && (
<Alert>
<AlertDescription>
@@ -200,7 +202,7 @@ export default function Pay(props: PayProps) {
<DialogFooter>
<Button
type="button"
disabled={props.method === 'balance' && !!ctx.profile && ctx.profile.balance < props.amount}
disabled={props.method === 'balance' && !!profile && profile.balance < props.amount}
onClick={onSubmit}
>
{props.method === 'balance' ? '确认支付' : '已完成支付'}

View File

@@ -21,7 +21,7 @@ import {useContext, useRef, useState} from 'react'
import {Loader} from 'lucide-react'
import {RechargeByAlipay, RechargeByAlipayConfirm, RechargeByWechat, RechargeByWechatConfirm} from '@/actions/user'
import * as qrcode from 'qrcode'
import {AuthContext} from '@/components/providers/AuthProvider'
import {StoreContext, useProfileStore} from '@/components/providers/StoreProvider'
const schema = zod.object({
method: zod.enum(['alipay', 'wechat']),
@@ -53,7 +53,7 @@ export default function RechargeModal(props: RechargeModelProps) {
pay_url: string
}>()
const ctx = useContext(AuthContext)
const refreshProfile = useProfileStore(store => store.refreshProfile)
const createRecharge = async (data: Schema) => {
try {
@@ -124,7 +124,7 @@ export default function RechargeModal(props: RechargeModelProps) {
}
toast.success(`充值成功`)
closeDialog()
await ctx.refreshProfile()
await refreshProfile()
}
catch (e) {
toast.error(`充值失败`, {

View File

@@ -8,15 +8,16 @@ 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 {AuthContext} from '@/components/providers/AuthProvider'
import {useProfileStore} from '@/components/providers/StoreProvider'
import RechargeModal from '@/components/composites/purchase/_client/recharge'
import Pay from '@/components/composites/purchase/_client/pay'
import {Button, buttonVariants} from '@/components/ui/button'
import Link from 'next/link'
export type RightProps = {}
export default function Right(props: RightProps) {
const authCtx = useContext(AuthContext)
const profile = authCtx.profile
const profile = useProfileStore(store => store.profile)
const form = useContext(PurchaseFormContext)?.form
if (!form) {
@@ -89,58 +90,65 @@ export default function Right(props: RightProps) {
<span></span>
<span className={`text-xl text-orange-500`}>{price}</span>
</p>
<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>
{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>
<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={payType} amount={price} resource={{
type: Number(watchType),
live: Number(watchLive) * 60,
quota: watchQuota,
expire: Number(watchExpire),
daily_limit: watchDailyLimit,
}}/>
<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={payType} amount={price} resource={{
type: Number(watchType),
live: Number(watchLive) * 60,
quota: watchQuota,
expire: Number(watchExpire),
daily_limit: watchDailyLimit,
}}/>
</> : (
<Link href={`/login`} className={buttonVariants()}>
</Link>
)}
</div>
)
}