From 29dd65651fbbe73046b3c447c8a41620ead4acd6 Mon Sep 17 00:00:00 2001 From: hyh Date: Thu, 15 May 2025 19:33:39 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E5=8C=BA=E7=A9=BA=E7=99=BD=E5=92=8C=E9=A1=B5=E9=9D=A2=E5=B8=83?= =?UTF-8?q?=E5=B1=80=EF=BC=8CDashboardHome/rolesView=E4=BD=93=E9=AA=8C?= =?UTF-8?q?=E6=8F=90=E5=8D=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/layout/Content.tsx | 9 +--- .../src/components/layout/DashboardLayout.tsx | 2 +- .../src/components/layout/Tabs.tsx | 2 +- .../src/components/ui/button.tsx | 41 ++++++++++++++ .../src/components/ui/dialog.tsx | 26 +++++++++ .../src/constants/menuConfig.ts | 2 +- .../src/pages/dashboard/DashboardHome.tsx | 6 +-- .../src/pages/dashboard/UserManagePage.tsx | 5 ++ .../src/pages/roles/RoleForm.tsx | 43 +++++++++++++++ .../src/pages/roles/RoleTable.tsx | 45 ++++++++++++++++ .../src/pages/roles/RolesView.tsx | 53 +++++++++++++++++++ .../src/routes/AppRouter.tsx | 5 ++ .../src/services/roleService.ts | 6 +++ 13 files changed, 230 insertions(+), 15 deletions(-) create mode 100644 src/CellularManagement.WebUI/src/components/ui/button.tsx create mode 100644 src/CellularManagement.WebUI/src/components/ui/dialog.tsx create mode 100644 src/CellularManagement.WebUI/src/pages/dashboard/UserManagePage.tsx create mode 100644 src/CellularManagement.WebUI/src/pages/roles/RoleForm.tsx create mode 100644 src/CellularManagement.WebUI/src/pages/roles/RoleTable.tsx create mode 100644 src/CellularManagement.WebUI/src/pages/roles/RolesView.tsx create mode 100644 src/CellularManagement.WebUI/src/services/roleService.ts diff --git a/src/CellularManagement.WebUI/src/components/layout/Content.tsx b/src/CellularManagement.WebUI/src/components/layout/Content.tsx index dd558fe..9e1662c 100644 --- a/src/CellularManagement.WebUI/src/components/layout/Content.tsx +++ b/src/CellularManagement.WebUI/src/components/layout/Content.tsx @@ -10,13 +10,8 @@ export function Content({ children }: ContentProps) { const { isCollapsed } = useSidebarToggle(); return ( -
-
+
+
{children}
diff --git a/src/CellularManagement.WebUI/src/components/layout/DashboardLayout.tsx b/src/CellularManagement.WebUI/src/components/layout/DashboardLayout.tsx index bd82634..34a0e97 100644 --- a/src/CellularManagement.WebUI/src/components/layout/DashboardLayout.tsx +++ b/src/CellularManagement.WebUI/src/components/layout/DashboardLayout.tsx @@ -18,7 +18,7 @@ export function DashboardLayout({ children }: DashboardLayoutProps) {
-
+
{children} diff --git a/src/CellularManagement.WebUI/src/components/layout/Tabs.tsx b/src/CellularManagement.WebUI/src/components/layout/Tabs.tsx index a65e8fb..3b9f06c 100644 --- a/src/CellularManagement.WebUI/src/components/layout/Tabs.tsx +++ b/src/CellularManagement.WebUI/src/components/layout/Tabs.tsx @@ -172,7 +172,7 @@ export function Tabs() { return (
-
+
{tabs.map(tab => (
{ + asChild?: boolean; + variant?: 'default' | 'destructive' | 'outline' | 'secondary'; + size?: 'default' | 'sm' | 'lg'; +} + +const buttonVariants = { + default: 'bg-blue-600 text-white hover:bg-blue-700', + destructive: 'bg-red-600 text-white hover:bg-red-700', + outline: 'border border-gray-300 text-gray-700 bg-white hover:bg-gray-50', + secondary: 'bg-gray-100 text-gray-800 hover:bg-gray-200', +}; + +const sizeVariants = { + default: 'px-4 py-2 text-sm', + sm: 'px-3 py-1 text-xs', + lg: 'px-6 py-3 text-base', +}; + +export const Button = React.forwardRef( + ({ className, variant = 'default', size = 'default', asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : 'button'; + return ( + + ); + } +); +Button.displayName = 'Button'; \ No newline at end of file diff --git a/src/CellularManagement.WebUI/src/components/ui/dialog.tsx b/src/CellularManagement.WebUI/src/components/ui/dialog.tsx new file mode 100644 index 0000000..ee4a6a4 --- /dev/null +++ b/src/CellularManagement.WebUI/src/components/ui/dialog.tsx @@ -0,0 +1,26 @@ +import * as React from 'react'; +import * as DialogPrimitive from '@radix-ui/react-dialog'; +import { cn } from '@/lib/utils'; + +export const Dialog = DialogPrimitive.Root; +export const DialogTrigger = DialogPrimitive.Trigger; + +export const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + +)); +DialogContent.displayName = 'DialogContent'; \ No newline at end of file diff --git a/src/CellularManagement.WebUI/src/constants/menuConfig.ts b/src/CellularManagement.WebUI/src/constants/menuConfig.ts index 5380624..1dae0b3 100644 --- a/src/CellularManagement.WebUI/src/constants/menuConfig.ts +++ b/src/CellularManagement.WebUI/src/constants/menuConfig.ts @@ -44,7 +44,7 @@ export const menuItems: MenuItem[] = [ }, { title: '角色管理', - href: '/dashboard/users/roles', + href: '/dashboard/user/roles', permission: 'roles.view', }, { diff --git a/src/CellularManagement.WebUI/src/pages/dashboard/DashboardHome.tsx b/src/CellularManagement.WebUI/src/pages/dashboard/DashboardHome.tsx index 5b24163..5f5c5c1 100644 --- a/src/CellularManagement.WebUI/src/pages/dashboard/DashboardHome.tsx +++ b/src/CellularManagement.WebUI/src/pages/dashboard/DashboardHome.tsx @@ -1,13 +1,12 @@ export function DashboardHome() { return ( -
+

仪表盘

欢迎使用管理系统

-
@@ -36,7 +35,6 @@ export function DashboardHome() {
-
@@ -61,7 +59,6 @@ export function DashboardHome() {
-
@@ -87,7 +84,6 @@ export function DashboardHome() {
-
diff --git a/src/CellularManagement.WebUI/src/pages/dashboard/UserManagePage.tsx b/src/CellularManagement.WebUI/src/pages/dashboard/UserManagePage.tsx new file mode 100644 index 0000000..ee64fdc --- /dev/null +++ b/src/CellularManagement.WebUI/src/pages/dashboard/UserManagePage.tsx @@ -0,0 +1,5 @@ +import { Outlet } from 'react-router-dom'; + +export default function UserManagePage() { + return ; +} \ No newline at end of file diff --git a/src/CellularManagement.WebUI/src/pages/roles/RoleForm.tsx b/src/CellularManagement.WebUI/src/pages/roles/RoleForm.tsx new file mode 100644 index 0000000..3eb7d37 --- /dev/null +++ b/src/CellularManagement.WebUI/src/pages/roles/RoleForm.tsx @@ -0,0 +1,43 @@ +import React, { useState } from 'react'; +import { Button } from '@/components/ui/button'; + +interface RoleFormProps { + onSubmit: (data: { name: string; description?: string }) => void; +} + +export default function RoleForm({ onSubmit }: RoleFormProps) { + const [name, setName] = useState(''); + const [description, setDescription] = useState(''); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + onSubmit({ name, description }); + setName(''); + setDescription(''); + }; + + return ( +
+
+ + setName(e.target.value)} + required + /> +
+
+ + setDescription(e.target.value)} + /> +
+
+ +
+
+ ); +} \ No newline at end of file diff --git a/src/CellularManagement.WebUI/src/pages/roles/RoleTable.tsx b/src/CellularManagement.WebUI/src/pages/roles/RoleTable.tsx new file mode 100644 index 0000000..6e5e8a7 --- /dev/null +++ b/src/CellularManagement.WebUI/src/pages/roles/RoleTable.tsx @@ -0,0 +1,45 @@ +import React from 'react'; +import { Button } from '@/components/ui/button'; + +interface RoleTableProps { + roles: any[]; + loading: boolean; + onDelete: (roleId: string) => void; +} + +export default function RoleTable({ roles, loading, onDelete }: RoleTableProps) { + return ( +
+ + + + + + + + + + {loading ? ( + + + + ) : roles.length === 0 ? ( + + + + ) : ( + roles.map((role) => ( + + + + + + )) + )} + +
角色名描述
加载中...
暂无数据
{role.name}{role.description} + +
+
+ ); +} \ No newline at end of file diff --git a/src/CellularManagement.WebUI/src/pages/roles/RolesView.tsx b/src/CellularManagement.WebUI/src/pages/roles/RolesView.tsx new file mode 100644 index 0000000..6a84453 --- /dev/null +++ b/src/CellularManagement.WebUI/src/pages/roles/RolesView.tsx @@ -0,0 +1,53 @@ +import React, { useEffect, useState } from 'react'; +import { Button } from '@/components/ui/button'; +import { Dialog, DialogContent, DialogTrigger } from '@/components/ui/dialog'; +import { getAllRoles, createRole, deleteRole } from '@/services/roleService'; +import RoleTable from './RoleTable'; +import RoleForm from './RoleForm'; + +export default function RolesView() { + const [roles, setRoles] = useState([]); + const [loading, setLoading] = useState(false); + const [open, setOpen] = useState(false); + + const fetchRoles = async () => { + setLoading(true); + const res = await getAllRoles(); + setRoles(res.data || []); + setLoading(false); + }; + + useEffect(() => { + fetchRoles(); + }, []); + + const handleCreate = async (data: { name: string; description?: string }) => { + await createRole(data); + setOpen(false); + fetchRoles(); + }; + + const handleDelete = async (roleId: string) => { + await deleteRole(roleId); + fetchRoles(); + }; + + return ( +
+
+
+

角色管理

+ + + + + + + + +
+ +
+
+ ); +} \ No newline at end of file diff --git a/src/CellularManagement.WebUI/src/routes/AppRouter.tsx b/src/CellularManagement.WebUI/src/routes/AppRouter.tsx index cada335..5bcffe1 100644 --- a/src/CellularManagement.WebUI/src/routes/AppRouter.tsx +++ b/src/CellularManagement.WebUI/src/routes/AppRouter.tsx @@ -7,6 +7,8 @@ import { ProtectedRoute } from '@/components/auth/ProtectedRoute'; const LoginPage = lazy(() => import('@/pages/auth/LoginPage').then(module => ({ default: module.LoginPage }))); const DashboardHome = lazy(() => import('@/pages/dashboard/DashboardHome').then(module => ({ default: module.DashboardHome }))); const ForbiddenPage = lazy(() => import('@/pages/auth/ForbiddenPage')); +const UserManagePage = lazy(() => import('@/pages/dashboard/UserManagePage')); +import RolesView from '@/pages/roles/RolesView'; // 加载中的占位组件 const LoadingFallback = () => ( @@ -40,6 +42,9 @@ export function AppRouter() { }> } /> + }> + } /> + {/* 添加更多路由 */} diff --git a/src/CellularManagement.WebUI/src/services/roleService.ts b/src/CellularManagement.WebUI/src/services/roleService.ts new file mode 100644 index 0000000..e912602 --- /dev/null +++ b/src/CellularManagement.WebUI/src/services/roleService.ts @@ -0,0 +1,6 @@ +import { httpClient } from '@/lib/http-client'; + +export const getAllRoles = () => httpClient.get('/api/Roles/GetAllRoles'); +export const getRole = (roleId: string) => httpClient.get(`/api/Roles/GetRole/${roleId}`); +export const createRole = (data: { name: string; description?: string }) => httpClient.post('/api/Roles/CreateRole', data); +export const deleteRole = (roleId: string) => httpClient.delete(`/api/Roles/DeleteRole/${roleId}`); \ No newline at end of file