Files
Canto/qwen3-tts-frontend/src/components/users/ChangePasswordDialog.tsx
bdim404 d8a9f277be feat: improve accessibility and mobile responsiveness across UI components
Enhanced dialog accessibility by adding descriptive text to all dialog components. Implemented responsive layouts for mobile devices including card-based user table, adaptive navigation bar, and improved dialog spacing. Fixed Aliyun TTS health check to use WebSocket-based connectivity testing.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-03 18:03:38 +08:00

163 lines
4.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import * as z from 'zod'
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog'
import { Button } from '@/components/ui/button'
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form'
import { Input } from '@/components/ui/input'
import type { PasswordChangeRequest } from '@/types/auth'
const passwordChangeSchema = z.object({
current_password: z.string().min(1, '请输入当前密码'),
new_password: z
.string()
.min(8, '密码至少8个字符')
.regex(/[A-Z]/, '密码必须包含至少一个大写字母')
.regex(/[a-z]/, '密码必须包含至少一个小写字母')
.regex(/\d/, '密码必须包含至少一个数字'),
confirm_password: z.string().min(1, '请确认新密码'),
}).refine((data) => data.new_password === data.confirm_password, {
message: '两次输入的密码不一致',
path: ['confirm_password'],
})
type PasswordChangeFormValues = z.infer<typeof passwordChangeSchema>
interface ChangePasswordDialogProps {
open: boolean
onOpenChange: (open: boolean) => void
onSubmit: (data: PasswordChangeRequest) => Promise<void>
isLoading: boolean
}
export function ChangePasswordDialog({
open,
onOpenChange,
onSubmit,
isLoading,
}: ChangePasswordDialogProps) {
const form = useForm<PasswordChangeFormValues>({
resolver: zodResolver(passwordChangeSchema),
defaultValues: {
current_password: '',
new_password: '',
confirm_password: '',
},
})
const handleSubmit = async (data: PasswordChangeFormValues) => {
await onSubmit(data)
form.reset()
}
const handleOpenChange = (open: boolean) => {
if (!open && !isLoading) {
form.reset()
}
onOpenChange(open)
}
return (
<Dialog open={open} onOpenChange={handleOpenChange}>
<DialogContent className="sm:max-w-[425px] max-h-[90vh] overflow-y-auto">
<DialogHeader>
<DialogTitle></DialogTitle>
<DialogDescription>
8
</DialogDescription>
</DialogHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-4">
<FormField
control={form.control}
name="current_password"
render={({ field }) => (
<FormItem>
<FormLabel></FormLabel>
<FormControl>
<Input
type="password"
placeholder="请输入当前密码"
disabled={isLoading}
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="new_password"
render={({ field }) => (
<FormItem>
<FormLabel></FormLabel>
<FormControl>
<Input
type="password"
placeholder="请输入新密码"
disabled={isLoading}
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="confirm_password"
render={({ field }) => (
<FormItem>
<FormLabel></FormLabel>
<FormControl>
<Input
type="password"
placeholder="请再次输入新密码"
disabled={isLoading}
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<DialogFooter className="flex-col sm:flex-row gap-2">
<Button
type="button"
variant="outline"
onClick={() => handleOpenChange(false)}
disabled={isLoading}
className="w-full sm:w-auto"
>
</Button>
<Button type="submit" disabled={isLoading} className="w-full sm:w-auto">
{isLoading ? '提交中...' : '确认修改'}
</Button>
</DialogFooter>
</form>
</Form>
</DialogContent>
</Dialog>
)
}