feat(header): modify_password
This commit is contained in:
@@ -38,6 +38,15 @@ export const userEditById = (data: User.EditProps, id: number) => {
|
||||
})
|
||||
}
|
||||
|
||||
// 修改用户密码
|
||||
export const userModifyPassword = (data: User.ModifyPasswordProps) => {
|
||||
return httpFetch({
|
||||
url: BASE_LABEL_API + `/api/v1/label_server/user/modify_password`,
|
||||
method: "PUT",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
// 编辑用户组织
|
||||
export const userUpdateGroup = (data: User.UpdateGroupProps) => {
|
||||
return httpFetch({
|
||||
@@ -65,16 +74,7 @@ export const userGroupAdd = (data: Organization.CreateProps) => {
|
||||
}
|
||||
|
||||
// 修改用户密码
|
||||
export const modifyUserPassword = (data: {
|
||||
old_password: string
|
||||
new_password: string
|
||||
}) => {
|
||||
return httpFetch({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/user/modify_password",
|
||||
method: "PUT",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
export const modifyUserPassword = userModifyPassword
|
||||
|
||||
/* ****************************** Options ****************************** */
|
||||
interface Option {
|
||||
|
||||
@@ -41,6 +41,11 @@ export namespace User {
|
||||
work_status?: number
|
||||
}
|
||||
|
||||
export interface ModifyPasswordProps {
|
||||
new_password: string
|
||||
old_password: string
|
||||
}
|
||||
|
||||
export interface UpdateGroupProps {
|
||||
user_id: number
|
||||
group_uuid: string
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Button,
|
||||
AppShell,
|
||||
Box,
|
||||
Burger,
|
||||
Divider,
|
||||
Flex,
|
||||
Group,
|
||||
Modal,
|
||||
Menu,
|
||||
NavLink,
|
||||
PasswordInput,
|
||||
ScrollArea,
|
||||
Space,
|
||||
Stack,
|
||||
@@ -20,10 +24,13 @@ import {
|
||||
import Avvvatars from "avvvatars-react"
|
||||
|
||||
import { useDisclosure, useMediaQuery } from "@mantine/hooks"
|
||||
import { useForm } from "@mantine/form"
|
||||
import { notifications } from "@mantine/notifications"
|
||||
import {
|
||||
IconChevronDown,
|
||||
IconChevronLeft,
|
||||
IconChevronRight,
|
||||
IconLock,
|
||||
IconLogout,
|
||||
IconMoon,
|
||||
IconSun,
|
||||
@@ -36,7 +43,14 @@ import headerLinkClasses from "./HeaderLink.module.css"
|
||||
import { useUserStore } from "@/app/store/user"
|
||||
import { usePathname, useRouter } from "next/navigation"
|
||||
import { usePermissionStore } from "../label/store/auth"
|
||||
import { userModifyPassword } from "../label/api/user"
|
||||
import { deleteCookie } from "../login/api"
|
||||
import {
|
||||
settingModalActionsClassName,
|
||||
settingModalClassNames,
|
||||
settingModalFormClassName,
|
||||
settingModalMetaTextClassName,
|
||||
} from "../setting/PageSurface"
|
||||
import classes from "./AppLayout.module.css"
|
||||
import { MenuItem, withoutLayoutRoutes } from "./common"
|
||||
import { ClientIcon } from "./components/ClientIcon"
|
||||
@@ -149,6 +163,10 @@ export default function AppLayout({
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
const [mobileOpened, { toggle: toggleMobile }] = useDisclosure()
|
||||
const [
|
||||
passwordModalOpened,
|
||||
{ open: openPasswordModal, close: closePasswordModal },
|
||||
] = useDisclosure(false)
|
||||
|
||||
const { updateIsOpen } = useAppLayoutStore.getState()
|
||||
const { isOpen } = useAppLayoutStore()
|
||||
@@ -178,6 +196,67 @@ export default function AppLayout({
|
||||
|
||||
const { menuDefaultRouter } = useAppLayoutStore.getState()
|
||||
|
||||
const passwordForm = useForm({
|
||||
initialValues: {
|
||||
old_password: "",
|
||||
new_password: "",
|
||||
confirm_new_password: "",
|
||||
},
|
||||
validate: {
|
||||
old_password: (value) => (value ? null : "请输入当前密码"),
|
||||
new_password: (value) => (value ? null : "请输入新密码"),
|
||||
confirm_new_password: (value) => (value ? null : "请再次确认新密码"),
|
||||
},
|
||||
validateInputOnChange: true,
|
||||
validateInputOnBlur: true,
|
||||
clearInputErrorOnChange: true,
|
||||
})
|
||||
|
||||
const [passwordSubmitting, setPasswordSubmitting] = useState(false)
|
||||
|
||||
const handleOpenPasswordModal = () => {
|
||||
passwordForm.reset()
|
||||
openPasswordModal()
|
||||
}
|
||||
|
||||
const handleClosePasswordModal = () => {
|
||||
passwordForm.reset()
|
||||
closePasswordModal()
|
||||
}
|
||||
|
||||
const handlePasswordSubmit = passwordForm.onSubmit(async (values) => {
|
||||
if (values.new_password !== values.confirm_new_password) {
|
||||
passwordForm.setFieldError(
|
||||
"confirm_new_password",
|
||||
"两次输入的新密码不一致"
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
setPasswordSubmitting(true)
|
||||
try {
|
||||
await userModifyPassword({
|
||||
old_password: values.old_password,
|
||||
new_password: values.new_password,
|
||||
})
|
||||
handleClosePasswordModal()
|
||||
notifications.show({
|
||||
color: "green",
|
||||
title: "修改成功",
|
||||
message: "密码已更新",
|
||||
})
|
||||
} catch (error) {
|
||||
notifications.show({
|
||||
color: "red",
|
||||
title: "修改失败",
|
||||
message:
|
||||
error instanceof Error ? error.message : "密码修改失败,请重试",
|
||||
})
|
||||
} finally {
|
||||
setPasswordSubmitting(false)
|
||||
}
|
||||
})
|
||||
|
||||
const headItems = menu.map((item) => (
|
||||
<a
|
||||
key={item.url}
|
||||
@@ -374,6 +453,11 @@ export default function AppLayout({
|
||||
</Box>
|
||||
<Menu.Divider />
|
||||
<Menu.Label>操作</Menu.Label>
|
||||
<Menu.Item
|
||||
leftSection={<IconLock size={14} />}
|
||||
onClick={handleOpenPasswordModal}>
|
||||
修改密码
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
leftSection={<IconLogout size={14} />}
|
||||
onClick={handleLogout}>
|
||||
@@ -381,6 +465,54 @@ export default function AppLayout({
|
||||
</Menu.Item>
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
<Modal
|
||||
opened={passwordModalOpened}
|
||||
onClose={handleClosePasswordModal}
|
||||
title="修改密码"
|
||||
centered
|
||||
size={440}
|
||||
classNames={settingModalClassNames}>
|
||||
<form onSubmit={handlePasswordSubmit}>
|
||||
<Stack gap={12} className={settingModalFormClassName}>
|
||||
<Text className={settingModalMetaTextClassName}>
|
||||
请输入当前密码,并再次确认新密码后提交修改。
|
||||
</Text>
|
||||
<PasswordInput
|
||||
withAsterisk
|
||||
data-autofocus
|
||||
label="当前密码"
|
||||
placeholder="请输入当前密码"
|
||||
{...passwordForm.getInputProps("old_password")}
|
||||
/>
|
||||
<PasswordInput
|
||||
withAsterisk
|
||||
label="新密码"
|
||||
placeholder="请输入新密码"
|
||||
{...passwordForm.getInputProps("new_password")}
|
||||
/>
|
||||
<PasswordInput
|
||||
withAsterisk
|
||||
label="确认新密码"
|
||||
placeholder="请再次输入新密码"
|
||||
{...passwordForm.getInputProps("confirm_new_password")}
|
||||
/>
|
||||
<Group
|
||||
justify="flex-end"
|
||||
gap={12}
|
||||
className={settingModalActionsClassName}>
|
||||
<Button
|
||||
variant="default"
|
||||
onClick={handleClosePasswordModal}
|
||||
type="button">
|
||||
取消
|
||||
</Button>
|
||||
<Button type="submit" loading={passwordSubmitting}>
|
||||
确认修改
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</form>
|
||||
</Modal>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</AppShell.Header>
|
||||
|
||||
Reference in New Issue
Block a user