动态生成购买套餐 & 取消初次进后台修改密码的弹窗 & 添加总折扣字段 & 发布v1.5.0版本

This commit is contained in:
Eamon-meng
2026-04-16 14:41:42 +08:00
parent 319baea5e8
commit 5607217625
25 changed files with 619 additions and 273 deletions

View File

@@ -4,7 +4,7 @@ import {Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTr
import {Button} from '@/components/ui/button'
import {Form, FormField} from '@/components/ui/form'
import {Input} from '@/components/ui/input'
import {useForm, useFormContext, useWatch} from 'react-hook-form'
import {useForm, useFormContext} from 'react-hook-form'
import {zodResolver} from '@hookform/resolvers/zod'
import * as z from 'zod'
import {toast} from 'sonner'
@@ -14,7 +14,6 @@ import dynamic from 'next/dynamic'
// 表单验证规则
const schema = z.object({
phone: z.string().regex(/^1\d{10}$/, `请输入正确的手机号`),
captcha: z.string().nonempty('请输入验证码'),
code: z.string().regex(/^\d{6}$/, `请输入正确的验证码`),
password: z.string().min(6, `密码至少6位`),
@@ -32,6 +31,7 @@ interface ChangePasswordDialogProps {
defaultOpen?: boolean
onOpenChange?: (open: boolean) => void
onSuccess?: () => void
phone?: string
}
export function ChangePasswordDialog({
@@ -40,12 +40,28 @@ export function ChangePasswordDialog({
defaultOpen,
onOpenChange,
onSuccess,
phone,
}: ChangePasswordDialogProps) {
const [internalOpen, setInternalOpen] = useState(defaultOpen || false)
const router = useRouter()
const actualOpen = open !== undefined ? open : internalOpen
const actualOnOpenChange = onOpenChange || setInternalOpen
const actualOnOpenChange = (open: boolean) => {
if (!open) {
form.reset({
captcha: '',
code: '',
password: '',
confirm_password: '',
})
}
if (onOpenChange) {
onOpenChange(open)
}
else {
setInternalOpen(open)
}
}
// 表单初始化
const form = useForm<Schema>({
@@ -59,7 +75,6 @@ export function ChangePasswordDialog({
),
),
defaultValues: {
phone: '',
captcha: '',
code: '',
password: '',
@@ -71,7 +86,6 @@ export function ChangePasswordDialog({
const handler = async (value: Schema) => {
try {
const resp = await updatePassword({
phone: value.phone,
code: value.code,
password: value.password,
})
@@ -108,14 +122,12 @@ export function ChangePasswordDialog({
<DialogHeader>
<DialogTitle></DialogTitle>
</DialogHeader>
{/* 手机号输入 */}
<FormField<Schema> name="phone" label="手机号" className="flex-auto">
{({field}) => (
<Input {...field} placeholder="请输入手机号" autoComplete="tel-national"/>
)}
</FormField>
{/* 短信验证码 */}
{phone && (
<div className="flex items-center gap-2 p-3 bg-gray-50 rounded-lg">
<span className="text-sm text-gray-500"></span>
<span className="text-sm font-medium">{phone}</span>
</div>
)}
<div className="flex gap-4 items-end">
<FormField<Schema> name="code" label="验证码" className="flex-auto">
{({field}) => (
@@ -124,15 +136,11 @@ export function ChangePasswordDialog({
</FormField>
<SendMsgByPhone/>
</div>
{/* 新密码 */}
<FormField<Schema> name="password" label="新密码" className="flex-auto">
{({field}) => (
<Input {...field} placeholder="请输入新密码" type="password" autoComplete="new-password"/>
)}
</FormField>
{/* 确认密码 */}
<FormField<Schema> name="confirm_password" label="确认密码" className="flex-auto">
{({field}) => (
<Input {...field} placeholder="请再次输入新密码" type="password" autoComplete="new-password"/>
@@ -144,8 +152,13 @@ export function ChangePasswordDialog({
theme="outline"
type="button"
onClick={() => {
form.reset({
captcha: '',
code: '',
password: '',
confirm_password: '',
})
actualOnOpenChange(false)
form.reset()
}}>
</Button>
@@ -159,8 +172,7 @@ export function ChangePasswordDialog({
function SendMsgByPhone() {
const {control} = useFormContext<Schema>()
const phone = useWatch({control, name: 'phone'})
return <SendMsg phone={phone}/>
return <SendMsg/>
}
const SendMsg = dynamic(() => import('@/components/send-msg'), {ssr: false})
const SendMsg = dynamic(() => import('@/components/updateSend-msg'), {ssr: false})