Skip to content

Commit 93b7e62

Browse files
committed
file:补充忘记add的文件
1 parent 78b1d8d commit 93b7e62

11 files changed

Lines changed: 3809 additions & 0 deletions

File tree

app/backup/components/notification-settings.tsx

Lines changed: 471 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
"use client";
2+
3+
import {
4+
Avatar,
5+
Button,
6+
Card,
7+
CardBody,
8+
Input
9+
} from "@heroui/react";
10+
import React from "react";
11+
12+
export default function ProfileSettings() {
13+
return (
14+
<div className="space-y-4">
15+
<Card className="p-2">
16+
<CardBody>
17+
<div className="flex flex-col md:flex-row gap-8">
18+
<div className="flex flex-col items-center justify-center md:w-1/3 md:border-r md:pr-8">
19+
<div className="flex flex-col items-center gap-4">
20+
<Avatar
21+
isBordered
22+
className="w-32 h-32"
23+
src="https://i.pravatar.cc/150?img=3"
24+
/>
25+
<Button color="primary" variant="flat" className="w-full">
26+
更换头像
27+
</Button>
28+
</div>
29+
</div>
30+
31+
<div className="flex-1 space-y-6">
32+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
33+
<div className="space-y-2">
34+
<label className="text-sm text-default-700">用户名</label>
35+
<Input
36+
placeholder="输入用户名"
37+
defaultValue="Admin"
38+
variant="bordered"
39+
/>
40+
</div>
41+
<div className="space-y-2">
42+
<label className="text-sm text-default-700">显示名称</label>
43+
<Input
44+
placeholder="输入显示名称"
45+
defaultValue="系统管理员"
46+
variant="bordered"
47+
/>
48+
</div>
49+
</div>
50+
51+
<div className="space-y-2">
52+
<label className="text-sm text-default-700">职位</label>
53+
<Input
54+
placeholder="输入您的职位"
55+
defaultValue="系统管理员"
56+
variant="bordered"
57+
/>
58+
</div>
59+
60+
<div className="space-y-2">
61+
<label className="text-sm text-default-700">电子邮箱</label>
62+
<Input
63+
placeholder="输入电子邮箱"
64+
type="email"
65+
defaultValue="admin@example.com"
66+
variant="bordered"
67+
/>
68+
</div>
69+
70+
<div className="space-y-2">
71+
<label className="text-sm text-default-700">所在地</label>
72+
<Input
73+
placeholder="输入您的所在地"
74+
variant="bordered"
75+
/>
76+
</div>
77+
78+
<div className="space-y-2">
79+
<label className="text-sm text-default-700">个人简介</label>
80+
<Input
81+
placeholder="简单介绍一下自己"
82+
variant="bordered"
83+
/>
84+
</div>
85+
</div>
86+
</div>
87+
</CardBody>
88+
</Card>
89+
</div>
90+
);
91+
}
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
"use client";
2+
3+
import {
4+
Button,
5+
Card,
6+
CardBody,
7+
Divider,
8+
Input,
9+
Modal,
10+
ModalBody,
11+
ModalContent,
12+
ModalFooter,
13+
ModalHeader,
14+
Switch
15+
} from "@heroui/react";
16+
import React, { forwardRef, useImperativeHandle } from "react";
17+
18+
import { z } from "zod";
19+
import { useForm } from "react-hook-form";
20+
import { zodResolver } from "@hookform/resolvers/zod";
21+
22+
// 定义表单验证 schema
23+
const securitySettingsSchema = z.object({
24+
twoFactorEnabled: z.boolean(),
25+
});
26+
27+
type SecuritySettingsForm = z.infer<typeof securitySettingsSchema>;
28+
29+
// 定义组件 ref 类型
30+
export type SecuritySettingsRef = {
31+
submitForm: () => Promise<void>;
32+
resetForm: () => void;
33+
};
34+
35+
const SecuritySettings = forwardRef<SecuritySettingsRef>((props, ref) => {
36+
const [isChangePasswordOpen, setIsChangePasswordOpen] = React.useState(false);
37+
const [currentPassword, setCurrentPassword] = React.useState("");
38+
const [newPassword, setNewPassword] = React.useState("");
39+
const [confirmPassword, setConfirmPassword] = React.useState("");
40+
41+
// 初始化表单
42+
const {
43+
register,
44+
handleSubmit,
45+
reset,
46+
formState: { errors },
47+
} = useForm<SecuritySettingsForm>({
48+
resolver: zodResolver(securitySettingsSchema),
49+
defaultValues: {
50+
twoFactorEnabled: true,
51+
},
52+
});
53+
54+
const handleChangePassword = () => {
55+
// TODO: 实现密码修改逻辑
56+
console.log("修改密码", { currentPassword, newPassword, confirmPassword });
57+
setIsChangePasswordOpen(false);
58+
// 重置表单
59+
setCurrentPassword("");
60+
setNewPassword("");
61+
setConfirmPassword("");
62+
};
63+
64+
// 处理表单提交
65+
const onSubmit = async (data: SecuritySettingsForm) => {
66+
try {
67+
// TODO: 调用后端 API 保存设置
68+
console.log("保存设置:", data);
69+
} catch (error) {
70+
console.error("保存设置失败:", error);
71+
throw error;
72+
}
73+
};
74+
75+
// 暴露方法给父组件
76+
useImperativeHandle(ref, () => ({
77+
submitForm: () => handleSubmit(onSubmit)(),
78+
resetForm: () => reset(),
79+
}));
80+
81+
return (
82+
<form>
83+
<Card className="mt-5 p-2">
84+
<CardBody className="gap-8">
85+
<div className="space-y-6">
86+
<div className="flex items-center justify-between">
87+
<div className="space-y-1">
88+
<h3 className="text-base font-medium">修改密码</h3>
89+
<p className="text-sm text-default-500">定期更新密码以提高账户安全性</p>
90+
</div>
91+
<Button
92+
color="primary"
93+
variant="flat"
94+
onPress={() => setIsChangePasswordOpen(true)}
95+
>
96+
修改密码
97+
</Button>
98+
</div>
99+
<Divider />
100+
<div className="flex items-center justify-between">
101+
<div className="space-y-1">
102+
<h3 className="text-base font-medium">双因素认证</h3>
103+
<p className="text-sm text-default-500">使用验证器应用进行双重身份验证</p>
104+
</div>
105+
<Switch {...register("twoFactorEnabled")} />
106+
</div>
107+
<Divider />
108+
<div className="flex items-center justify-between">
109+
<div className="space-y-1">
110+
<h3 className="text-base font-medium">登录设备管理</h3>
111+
<p className="text-sm text-default-500">查看并管理已登录的设备</p>
112+
</div>
113+
<Button color="primary" variant="flat">
114+
查看设备
115+
</Button>
116+
</div>
117+
<Divider />
118+
<div className="flex items-center justify-between">
119+
<div className="space-y-1">
120+
<h3 className="text-base font-medium">登录历史记录</h3>
121+
<p className="text-sm text-default-500">查看近期的登录活动</p>
122+
</div>
123+
<Button color="primary" variant="flat">
124+
查看记录
125+
</Button>
126+
</div>
127+
</div>
128+
</CardBody>
129+
</Card>
130+
131+
<Modal
132+
isOpen={isChangePasswordOpen}
133+
onOpenChange={setIsChangePasswordOpen}
134+
placement="center"
135+
backdrop="blur"
136+
>
137+
<ModalContent>
138+
{(onClose) => (
139+
<>
140+
<ModalHeader className="flex flex-col gap-1">
141+
<h3 className="text-lg font-medium">修改密码</h3>
142+
<p className="text-sm text-default-500">请输入您的当前密码和新密码</p>
143+
</ModalHeader>
144+
<ModalBody>
145+
<div className="space-y-4">
146+
<div className="space-y-2">
147+
<label className="text-sm text-default-700">当前密码</label>
148+
<Input
149+
type="password"
150+
variant="bordered"
151+
placeholder="输入当前密码"
152+
value={currentPassword}
153+
onValueChange={setCurrentPassword}
154+
/>
155+
</div>
156+
<div className="space-y-2">
157+
<label className="text-sm text-default-700">新密码</label>
158+
<Input
159+
type="password"
160+
variant="bordered"
161+
placeholder="输入新密码"
162+
value={newPassword}
163+
onValueChange={setNewPassword}
164+
/>
165+
</div>
166+
<div className="space-y-2">
167+
<label className="text-sm text-default-700">确认新密码</label>
168+
<Input
169+
type="password"
170+
variant="bordered"
171+
placeholder="再次输入新密码"
172+
value={confirmPassword}
173+
onValueChange={setConfirmPassword}
174+
isInvalid={confirmPassword !== "" && newPassword !== confirmPassword}
175+
errorMessage={
176+
confirmPassword !== "" &&
177+
newPassword !== confirmPassword &&
178+
"两次输入的密码不一致"
179+
}
180+
/>
181+
</div>
182+
</div>
183+
</ModalBody>
184+
<ModalFooter>
185+
<Button
186+
color="danger"
187+
variant="light"
188+
onPress={onClose}
189+
>
190+
取消
191+
</Button>
192+
<Button
193+
color="primary"
194+
onPress={handleChangePassword}
195+
isDisabled={
196+
!currentPassword ||
197+
!newPassword ||
198+
!confirmPassword ||
199+
newPassword !== confirmPassword
200+
}
201+
>
202+
确认修改
203+
</Button>
204+
</ModalFooter>
205+
</>
206+
)}
207+
</ModalContent>
208+
</Modal>
209+
</form>
210+
);
211+
});
212+
213+
SecuritySettings.displayName = "SecuritySettings";
214+
215+
export default SecuritySettings;

0 commit comments

Comments
 (0)