diff --git a/app/api/admin/users/[[...path]]/route.ts b/app/api/admin/users/[[...path]]/route.ts index 95e989ac8..ebe9cc7e6 100644 --- a/app/api/admin/users/[[...path]]/route.ts +++ b/app/api/admin/users/[[...path]]/route.ts @@ -95,7 +95,16 @@ async function handle( if (method === "PUT") { try { const userId = params.path[0]; - return await changeUserInfo(userId, await req.json()); + let new_user_info: Partial = Object.entries( + await req.json(), + ).reduce((acc, [key, value]) => { + if (value !== null) { + // @ts-ignore + acc[key] = value; + } + return acc; + }, {}); + return await changeUserInfo(userId, new_user_info); } catch { return NextResponse.json({ error: "未知错误" }, { status: 500 }); } @@ -103,16 +112,18 @@ async function handle( return NextResponse.json({ error: "当前方法不支持" }, { status: 405 }); } -async function changeUserInfo(id: string, info: User) { - const hashDPassword = hashPassword(info?.password ?? ""); - console.log("-----------", id, info, hashDPassword); - if (hashDPassword) { +async function changeUserInfo(id: string, info: Partial) { + if (info.password) { + info["password"] = hashPassword(info.password); + } + // console.log("-----------", id, info, hashDPassword); + if (info) { await prisma.user.update({ where: { id: id, }, data: { - password: hashDPassword, + ...info, }, }); return NextResponse.json({ result: "ok" }); diff --git a/app/api/test/route.ts b/app/api/test/route.ts new file mode 100644 index 000000000..51174a6da --- /dev/null +++ b/app/api/test/route.ts @@ -0,0 +1,10 @@ +import { NextRequest, NextResponse } from "next/server"; + +async function handle( + req: NextRequest, + { params }: { params: { path: string[] } }, +) { + return NextResponse.json({}); +} + +export const GET = handle; diff --git a/app/app/(admin)/components/admin-setting-table.tsx b/app/app/(admin)/components/admin-setting-table.tsx index a75691e8b..43cfb5327 100644 --- a/app/app/(admin)/components/admin-setting-table.tsx +++ b/app/app/(admin)/components/admin-setting-table.tsx @@ -20,13 +20,13 @@ function SettingForm() { const [form] = Form.useForm(); const [setting, setSetting] = useState([]); - const [isModalVisible, setIsModalVisible] = useState(false); - const openModal = () => setIsModalVisible(true); - const closeModal = () => setIsModalVisible(false); - - const handleFormSubmit = async (record: Setting) => { - console.log("-------", record); - }; + // const [isModalVisible, setIsModalVisible] = useState(false); + // const openModal = () => setIsModalVisible(true); + // const closeModal = () => setIsModalVisible(false); + // + // const handleFormSubmit = async (record: Setting) => { + // console.log("-------", record); + // }; const handelDel = (record: Setting) => { fetch(`/api/admin/setting/${record.key}`, { diff --git a/app/app/(admin)/components/users-table.tsx b/app/app/(admin)/components/users-table.tsx index 2756085a5..84c3ac0a0 100644 --- a/app/app/(admin)/components/users-table.tsx +++ b/app/app/(admin)/components/users-table.tsx @@ -5,20 +5,21 @@ import { User } from "@prisma/client"; import { Space, Table, - Tag, Input, Button, - notification, - Popconfirm, + notification as notificationModule, Checkbox, + Modal, + Form, } from "antd"; import type { GetRef, TableColumnsType } from "antd"; +import { LockOutlined } from "@ant-design/icons"; // import { headers } from 'next/headers' import type { NotificationArgsProps } from "antd"; -import Highlighter from "react-highlight-words"; +// import Highlighter from "react-highlight-words"; // 后期考虑删除该依赖 -type NotificationPlacement = NotificationArgsProps["placement"]; +// type NotificationPlacement = NotificationArgsProps["placement"]; import type { SearchProps } from "antd/es/input/Search"; @@ -37,9 +38,6 @@ interface SearchTextProps { setSearchText: Dispatch>; } -type DataIndex = keyof User; -type InputRef = GetRef; - function UserTableSearchInput({ users, setUsers, setLoading }: UserInterface) { const [searchText, setSearchText] = useState(""); // 这里直接搜索,并获取数据不传递搜索的值给表格了。 @@ -82,63 +80,114 @@ function UserTableSearchInput({ users, setUsers, setLoading }: UserInterface) { } function UsersTable({ users, setUsers, loading }: UserInterface) { - const [api, contextHolder] = notification.useNotification(); + const [notification, notificationContextHolder] = + notificationModule.useNotification(); + const [editUserModal, editUserModalContextHolder] = Modal.useModal(); + const [editUserForm] = Form.useForm(); - const [newPassword, setNewPassword] = useState(""); + const handleUserEdit = (method: "POST" | "PUT", record: User | undefined) => { + editUserModal.confirm({ + title: "编辑用户", + content: ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - const newPasswordChange = (e: React.ChangeEvent) => { - // if ((e.nativeEvent as InputEvent).isComposing) { - // return; - // } - setNewPassword(e.target.value.trim()); - }; - - const confirmPassword = async (id: string) => { - console.log("-----", newPassword, id); - try { - fetch(`/api/admin/users/${id}`, { - method: "put", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - password: newPassword, - }), - credentials: "include", - }) - .then((response) => response.json()) - .then((res) => { - if (res["result"] == "ok") { - openNotification("info", { - message: "修改密码", - description: `${id} 密码修改成功`, + + } + type="password" + placeholder="Password" + autoComplete="new-password" + /> + + + ), + onOk: () => { + const setting_key = method === "PUT" ? record?.id : ""; + editUserForm.validateFields().then((values) => { + const dataToSubmit = { + username: values.username ?? null, + email: values.email ?? null, + allowToLogin: values.allowToLogin ?? true, + isAdmin: values.isAdmin ?? false, + password: values.password ?? null, + }; + fetch(`/api/admin/users/${values.id}`, { + method: method, + credentials: "include", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(dataToSubmit), + }) + .then((response) => response.json()) + .then((result) => { + if (result["result"] == "ok") { + openNotification("info", { + message: "修改信息", + description: `${values.id} 信息修改成功`, + }); + } + }) + .catch((error) => { + console.log("e", error); + openNotification("error", { + message: "修改信息", + description: `${values.id} 信息修改失败`, + }); }); - } - }) - .catch((error) => { - console.log("e", error); - openNotification("error", { - message: "修改密码", - description: `${id} 密码修改失败`, - }); }); - } catch { - openNotification("error", { - message: "修改密码", - description: `${id} 密码修改失败`, - }); - } - setNewPassword(""); + }, + }); }; const openNotification = (level: string, arms: NotificationArgsProps) => { if (level === "error") { - api.error({ + notification.error({ ...arms, placement: "topRight", }); } else { - api.info({ + notification.info({ ...arms, placement: "topRight", }); @@ -189,7 +238,7 @@ function UsersTable({ users, setUsers, loading }: UserInterface) { render: (value) => getCurrentTime(new Date(value)), }, { - title: "isAdmin", + title: "管理员", dataIndex: "isAdmin", width: 80, render: (value) => { @@ -201,9 +250,9 @@ function UsersTable({ users, setUsers, loading }: UserInterface) { }, }, { - title: "allowToLogin", + title: "允许登录", dataIndex: "allowToLogin", - width: 120, + width: 80, render: (value) => { return (
@@ -217,29 +266,13 @@ function UsersTable({ users, setUsers, loading }: UserInterface) { dataIndex: "", key: "id", render: (_, record) => ( - - {contextHolder} - - e.preventDefault()} - onChange={newPasswordChange} - /> - - } - onConfirm={() => confirmPassword(record.id)} - onOpenChange={() => console.log("open change")} - > - - - handleDeleteUser(record)}>删除 + + + ), }, @@ -247,16 +280,20 @@ function UsersTable({ users, setUsers, loading }: UserInterface) { // console.log(users, "users2"); return ( - + <> + {notificationContextHolder} + {editUserModalContextHolder} +
+ ); } diff --git a/lib/auth.ts b/lib/auth.ts index 9f18f918e..f7f12944f 100644 --- a/lib/auth.ts +++ b/lib/auth.ts @@ -10,7 +10,7 @@ import {createTransport} from "nodemailer"; import { comparePassword, hashPassword } from "@/lib/utils"; import {getCurStartEnd} from "@/app/utils/custom"; const SECURE_COOKIES:boolean = !!process.env.SECURE_COOKIES; -type PartialUser = Partial; + export const authOptions: NextAuthOptions = { @@ -89,7 +89,7 @@ export const authOptions: NextAuthOptions = { // 判断姓名格式是否符合要求,不符合则拒绝 if (username && isName(username)) { // Any object returned will be saved in `user` property of the JWT - let user: PartialUser = {} + let user: Partial = {} if (isEmail(username)) { user['email'] = username; } else { @@ -228,7 +228,7 @@ async function getSetting(key: string) { } } -async function existUser(user: PartialUser ) { +async function existUser(user: Partial ) { const conditions = []; if (user?.name) { conditions.push({ name: user.name }); @@ -243,7 +243,7 @@ async function existUser(user: PartialUser ) { }) : null } -export async function insertUser(user: PartialUser ) { +export async function insertUser(user: Partial ) { console.log('------------', user) try { return await prisma.user.create({