From e5c0c354e56857cfa5f6145f9173bf1450333fad Mon Sep 17 00:00:00 2001 From: tone <3341154833@qq.com> Date: Mon, 12 May 2025 10:27:50 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=AE=A1=E7=90=86=E5=91=98us?= =?UTF-8?q?er-list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/console/(with-menu)/page.tsx | 6 +- .../user/components/user-info-editor.tsx | 69 +++++++++ .../app/console/(with-menu)/user/page.tsx | 70 ++++++++- tone-page-web/app/console/login/page.tsx | 51 ++++--- tone-page-web/components/ui/dialog.tsx | 135 ++++++++++++++++++ tone-page-web/components/ui/pagination.tsx | 127 ++++++++++++++++ tone-page-web/components/ui/table.tsx | 116 +++++++++++++++ .../hooks/admin/user/use-user-list.ts | 32 +++++ tone-page-web/lib/api/admin/index.ts | 1 + tone-page-web/lib/api/admin/user/index.ts | 1 + tone-page-web/lib/api/admin/user/list.ts | 22 +++ tone-page-web/lib/api/auth/login.ts | 24 ++-- tone-page-web/lib/api/fetcher.ts | 20 ++- tone-page-web/lib/api/index.ts | 3 +- tone-page-web/lib/api/verification/send.ts | 2 +- tone-page-web/lib/types/user.ts | 10 ++ 16 files changed, 648 insertions(+), 41 deletions(-) create mode 100644 tone-page-web/app/console/(with-menu)/user/components/user-info-editor.tsx create mode 100644 tone-page-web/components/ui/dialog.tsx create mode 100644 tone-page-web/components/ui/pagination.tsx create mode 100644 tone-page-web/components/ui/table.tsx create mode 100644 tone-page-web/hooks/admin/user/use-user-list.ts create mode 100644 tone-page-web/lib/api/admin/index.ts create mode 100644 tone-page-web/lib/api/admin/user/index.ts create mode 100644 tone-page-web/lib/api/admin/user/list.ts create mode 100644 tone-page-web/lib/types/user.ts diff --git a/tone-page-web/app/console/(with-menu)/page.tsx b/tone-page-web/app/console/(with-menu)/page.tsx index 136b4fe..04eee48 100644 --- a/tone-page-web/app/console/(with-menu)/page.tsx +++ b/tone-page-web/app/console/(with-menu)/page.tsx @@ -1,3 +1,7 @@ export default function Page() { - return
console
+ return ( +
+ page +
+ ) } \ No newline at end of file diff --git a/tone-page-web/app/console/(with-menu)/user/components/user-info-editor.tsx b/tone-page-web/app/console/(with-menu)/user/components/user-info-editor.tsx new file mode 100644 index 0000000..8408f83 --- /dev/null +++ b/tone-page-web/app/console/(with-menu)/user/components/user-info-editor.tsx @@ -0,0 +1,69 @@ +'use client'; +import * as React from "react" + +import { cn } from "@/lib/utils" +import { Button } from "@/components/ui/button" +import { + Drawer, + DrawerClose, + DrawerContent, + DrawerDescription, + DrawerFooter, + DrawerHeader, + DrawerTitle, +} from "@/components/ui/drawer" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" + +export function UserInfoEditor({ + onClose, + userId, +}: { + onClose: () => void, + userId: string +}) { + return ( + + + + 编辑用户信息 + 确保你在保存之前检查所有更改 + + + + + + + + + + ) +} + +function ProfileForm({ className }: React.ComponentProps<"form">) { + return ( +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ ) +} \ No newline at end of file diff --git a/tone-page-web/app/console/(with-menu)/user/page.tsx b/tone-page-web/app/console/(with-menu)/user/page.tsx index 3995d69..cc5f114 100644 --- a/tone-page-web/app/console/(with-menu)/user/page.tsx +++ b/tone-page-web/app/console/(with-menu)/user/page.tsx @@ -1,5 +1,73 @@ +'use client'; +import { Button } from "@/components/ui/button"; +import { Skeleton } from "@/components/ui/skeleton"; +import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; +import { TooltipContent, TooltipProvider, TooltipTrigger, Tooltip } from "@/components/ui/tooltip"; +import { useUserList } from "@/hooks/admin/user/use-user-list"; +import { useState } from "react"; +import { UserInfoEditor } from "./components/user-info-editor"; + + export default function Page() { + const { users, isLoading, error, total, page, pageSize } = useUserList(); + const [editorUserId, setEditorUserId] = useState(""); + return ( -
user
+ <> + + {error && {error.message}} + + + userId + 账户 + 昵称 + 邮箱 + 手机号 + 操作 + + + + { + users.map((user) => ( + + + + + +
{user.userId}
+
+ +

{user.userId}

+
+
+
+
+ {user.username} + {user.nickname} + {user.email} + {user.phone} + + + +
+ )) + } + + {isLoading && ( + + { + Array.from({ length: 6 }).map((_, index) => ( + + + + )) + } + + )} +
+
+ + setEditorUserId('')} userId={editorUserId} /> + ) } \ No newline at end of file diff --git a/tone-page-web/app/console/login/page.tsx b/tone-page-web/app/console/login/page.tsx index bdc3384..053bda8 100644 --- a/tone-page-web/app/console/login/page.tsx +++ b/tone-page-web/app/console/login/page.tsx @@ -15,6 +15,7 @@ import { LoginFormData, SendCodeFormData, SubmitMode } from "./components/types" import { useCallback, useState } from "react"; import LoginBG from './components/login-bg.jpg'; import Image from "next/image"; +import { ApiError } from "@/lib/api/fetcher"; export default function Login() { const router = useRouter(); @@ -25,34 +26,42 @@ export default function Login() { }, []); const handleSendCode = async (data: SendCodeFormData) => { - const res = await verificationApi.send({ - type: 'login', - targetType: data.type, - phone: data.phone, - email: data.email, - }) + try { + const res = await verificationApi.send({ + type: 'login', + targetType: data.type, + phone: data.phone, + email: data.email, + }) - if (res.statusCode === 200) { - toast.success('验证码已发送,请注意查收'); - return true; - } else { - toast.error(res.message || '验证码发送失败,请稍后再试'); + if (res) { + toast.success('验证码已发送,请注意查收'); + return true; + } else { + throw new Error(); + } + } catch (error) { + toast.error((error as ApiError).message || '验证码发送失败,请稍后再试'); return false; } } const handleSubmit = async (data: LoginFormData) => { - const res = await authApi.login({ - ...data, - }); + try { + const res = await authApi.login({ + ...data, + }); - if (res.statusCode === 200 && res.data) { - toast.success('登录成功'); - localStorage.setItem('token', res.data.token); - router.replace('/console'); - return true; - } else { - toast.error(res.message || '登录失败,请稍后再试'); + if (res.token) { + toast.success('登录成功'); + localStorage.setItem('token', res.token); + router.replace('/console'); + return true; + } else { + throw new Error(); + } + } catch (error) { + toast.error((error as ApiError).message || '登录失败,请稍后再试'); return false; } } diff --git a/tone-page-web/components/ui/dialog.tsx b/tone-page-web/components/ui/dialog.tsx new file mode 100644 index 0000000..7d7a9d3 --- /dev/null +++ b/tone-page-web/components/ui/dialog.tsx @@ -0,0 +1,135 @@ +"use client" + +import * as React from "react" +import * as DialogPrimitive from "@radix-ui/react-dialog" +import { XIcon } from "lucide-react" + +import { cn } from "@/lib/utils" + +function Dialog({ + ...props +}: React.ComponentProps) { + return +} + +function DialogTrigger({ + ...props +}: React.ComponentProps) { + return +} + +function DialogPortal({ + ...props +}: React.ComponentProps) { + return +} + +function DialogClose({ + ...props +}: React.ComponentProps) { + return +} + +function DialogOverlay({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DialogContent({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + + + {children} + + + Close + + + + ) +} + +function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function DialogFooter({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function DialogTitle({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DialogDescription({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogOverlay, + DialogPortal, + DialogTitle, + DialogTrigger, +} diff --git a/tone-page-web/components/ui/pagination.tsx b/tone-page-web/components/ui/pagination.tsx new file mode 100644 index 0000000..0d18541 --- /dev/null +++ b/tone-page-web/components/ui/pagination.tsx @@ -0,0 +1,127 @@ +import * as React from "react" +import { + ChevronLeftIcon, + ChevronRightIcon, + MoreHorizontalIcon, +} from "lucide-react" + +import { cn } from "@/lib/utils" +import { Button, buttonVariants } from "@/components/ui/button" + +function Pagination({ className, ...props }: React.ComponentProps<"nav">) { + return ( +