重构前端逻辑

This commit is contained in:
dengqichen 2025-11-10 17:55:05 +08:00
parent c285d224e4
commit d9f084908a
4 changed files with 68 additions and 75 deletions

View File

@ -3,8 +3,9 @@ import type {RoleResponse, RoleRequest, RoleQuery, RoleTagResponse, RoleTagReque
import {Page} from "@/types/base.ts"; import {Page} from "@/types/base.ts";
const BASE_URL = '/api/v1/role'; const BASE_URL = '/api/v1/role';
const ROLE_TAG_BASE_URL = '/api/v1/role-tag';
const ROLE_TAG_BASE_URL = '/api/v1/role-tag' const PERMISSION_BASE_URL = '/api/v1/permission';
const MENU_BASE_URL = '/api/v1/menu';
// 获取角色列表(分页) // 获取角色列表(分页)
export const getRoleList = (params?: RoleQuery) => request.get<Page<RoleResponse>>(`${BASE_URL}/page`, {params}); export const getRoleList = (params?: RoleQuery) => request.get<Page<RoleResponse>>(`${BASE_URL}/page`, {params});
@ -37,7 +38,7 @@ export const getRolePermissions = (roleId: number) => request.get<string[]>(`${B
export const assignPermissions = (roleId: number, permissionIds: Number[]) => request.post(`${BASE_URL}/${roleId}/permissions`, permissionIds); export const assignPermissions = (roleId: number, permissionIds: Number[]) => request.post(`${BASE_URL}/${roleId}/permissions`, permissionIds);
// 获取所有权限列表 // 获取所有权限列表
export const getAllPermissions = () => request.get<Permission[]>('/api/v1/permission/list'); export const getAllPermissions = () => request.get<Permission[]>(`${PERMISSION_BASE_URL}/list`);
// 获取权限树 // 获取权限树
export const getPermissionTree = () => request.get('/api/v1/role/permission-tree'); export const getPermissionTree = () => request.get(`${MENU_BASE_URL}/permission-tree`);

View File

@ -27,7 +27,7 @@ export const resetPassword = (id: number, password: string) =>
// 分配角色 // 分配角色
export const assignRoles = (userId: number, roleIds: number[]) => export const assignRoles = (userId: number, roleIds: number[]) =>
request.post(`${ROLE_BASE_URL}/${userId}/assignRoles`, roleIds); request.post(`${BASE_URL}/${userId}/roles`, roleIds);
// 获取所有角色列表(不分页) // 获取所有角色列表(不分页)
export const getAllRoles = () => export const getAllRoles = () =>

View File

@ -1,10 +1,9 @@
import React from 'react'; import React from 'react';
import { Dialog, DialogPortal, DialogOverlay, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import * as DialogPrimitive from "@radix-ui/react-dialog"; import { Activity, Clock, FileText } from 'lucide-react';
import { X } from "lucide-react"; import { cn } from '@/lib/utils';
import { cn } from "@/lib/utils";
import { WorkflowHistoricalInstance } from '../types'; import { WorkflowHistoricalInstance } from '../types';
import { NodeType } from '../../../Design/nodes/types'; import { NodeType } from '../../../Design/nodes/types';
import FlowGraphTab from './tabs/FlowGraphTab'; import FlowGraphTab from './tabs/FlowGraphTab';
@ -81,52 +80,37 @@ const DetailModal: React.FC<DetailModalProps> = ({ visible, onCancel, instanceDa
return ( return (
<Dialog open={visible} onOpenChange={(open) => !open && onCancel()}> <Dialog open={visible} onOpenChange={(open) => !open && onCancel()}>
<DialogPortal> <DialogContent className="!max-w-7xl w-[90vw] h-[85vh] flex flex-col p-0 overflow-hidden">
<DialogOverlay className="z-[60] backdrop-blur-sm" /> <DialogHeader className="px-6 pt-6 pb-4 border-b flex-shrink-0">
<DialogPrimitive.Content <DialogTitle className="flex items-center justify-between">
className={cn( <div className="flex items-center gap-3">
"fixed left-[50%] top-[50%] z-[60] grid w-full max-w-[90vw]", <span className="text-lg font-semibold"></span>
"translate-x-[-50%] translate-y-[-50%]", {getStatusBadge(instanceData.status)}
"gap-4 border-2 bg-background p-6 shadow-2xl", </div>
"duration-300", <div className="text-sm text-muted-foreground font-normal">
"data-[state=open]:animate-in data-[state=closed]:animate-out", ID: <span className="font-mono">{instanceData.processInstanceId}</span>
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", </div>
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
"data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]",
"data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
"sm:rounded-xl",
"max-h-[90vh] overflow-y-auto"
)}
>
<DialogPrimitive.Close
className="absolute right-6 top-6 rounded-md opacity-70 ring-offset-background transition-all hover:opacity-100 hover:bg-accent hover:scale-110 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground p-1.5"
onClick={onCancel}
>
<X className="h-5 w-5" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
<DialogHeader>
<DialogTitle className="text-2xl font-bold bg-gradient-to-r from-primary to-primary/60 bg-clip-text text-transparent">
</DialogTitle> </DialogTitle>
</DialogHeader> </DialogHeader>
<Tabs defaultValue="graph" className="w-full"> <div className="flex-1 overflow-hidden flex flex-col">
<TabsList className="grid w-full grid-cols-3 h-12"> <Tabs defaultValue="graph" className="flex-1 flex flex-col overflow-hidden">
<TabsTrigger value="graph" className="text-base font-medium"> <TabsList className="grid w-full grid-cols-3 h-12 mx-6 mt-4 rounded-none">
📊 <TabsTrigger value="graph" className="data-[state=active]:bg-background">
<Activity className="h-4 w-4 mr-2" />
</TabsTrigger> </TabsTrigger>
<TabsTrigger value="timeline" className="text-base font-medium"> <TabsTrigger value="timeline" className="data-[state=active]:bg-background">
线 <Clock className="h-4 w-4 mr-2" />
线
</TabsTrigger> </TabsTrigger>
<TabsTrigger value="info" className="text-base font-medium"> <TabsTrigger value="info" className="data-[state=active]:bg-background">
📋 <FileText className="h-4 w-4 mr-2" />
</TabsTrigger> </TabsTrigger>
</TabsList> </TabsList>
{/* 流程图标签页 */} <TabsContent value="graph" className="flex-1 mt-4 mx-6 overflow-auto focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0">
<TabsContent value="graph" className="mt-6">
<FlowGraphTab <FlowGraphTab
instanceData={instanceData} instanceData={instanceData}
getStatusBadge={getStatusBadge} getStatusBadge={getStatusBadge}
@ -134,8 +118,7 @@ const DetailModal: React.FC<DetailModalProps> = ({ visible, onCancel, instanceDa
/> />
</TabsContent> </TabsContent>
{/* 执行时间线标签页 */} <TabsContent value="timeline" className="flex-1 mt-4 mx-6 overflow-auto focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0">
<TabsContent value="timeline" className="mt-6">
<TimelineTab <TimelineTab
instanceData={instanceData} instanceData={instanceData}
getStatusBadge={getStatusBadge} getStatusBadge={getStatusBadge}
@ -143,16 +126,15 @@ const DetailModal: React.FC<DetailModalProps> = ({ visible, onCancel, instanceDa
/> />
</TabsContent> </TabsContent>
{/* 详细信息标签页 */} <TabsContent value="info" className="flex-1 mt-4 mx-6 overflow-auto focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0">
<TabsContent value="info" className="mt-6">
<DetailInfoTab <DetailInfoTab
instanceData={instanceData} instanceData={instanceData}
getStatusBadge={getStatusBadge} getStatusBadge={getStatusBadge}
/> />
</TabsContent> </TabsContent>
</Tabs> </Tabs>
</DialogPrimitive.Content> </div>
</DialogPortal> </DialogContent>
</Dialog> </Dialog>
); );
}; };

View File

@ -1,9 +1,10 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Dialog, DialogContent, DialogHeader, DialogBody, DialogTitle } from '@/components/ui/dialog'; import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Table, TableHeader, TableBody, TableHead, TableRow, TableCell } from '@/components/ui/table'; import { Table, TableHeader, TableBody, TableHead, TableRow, TableCell } from '@/components/ui/table';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { DataTablePagination } from '@/components/ui/pagination'; import { DataTablePagination } from '@/components/ui/pagination';
import { Loader2, History } from 'lucide-react';
import { WorkflowHistoricalInstance } from '../types'; import { WorkflowHistoricalInstance } from '../types';
import { getHistoricalInstances } from '../service'; import { getHistoricalInstances } from '../service';
import DetailModal from './DetailModal'; import DetailModal from './DetailModal';
@ -73,19 +74,27 @@ const HistoryModal: React.FC<HistoryModalProps> = ({ visible, onCancel, workflow
return ( return (
<> <>
<Dialog open={visible} onOpenChange={(open) => !open && onCancel()}> <Dialog open={visible} onOpenChange={(open) => !open && onCancel()}>
<DialogContent className="max-w-6xl"> <DialogContent className="max-w-6xl h-[80vh] flex flex-col p-0 overflow-hidden">
<DialogHeader> <DialogHeader className="px-6 pt-6 pb-4 border-b flex-shrink-0">
<DialogTitle></DialogTitle> <DialogTitle className="flex items-center justify-between">
<div className="flex items-center gap-3">
<History className="h-5 w-5" />
<span className="text-lg font-semibold"></span>
</div>
<div className="text-sm text-muted-foreground font-normal">
{total}
</div>
</DialogTitle>
</DialogHeader> </DialogHeader>
<DialogBody> <div className="flex-1 overflow-auto px-6 py-4">
<div>
{loading ? ( {loading ? (
<div className="flex justify-center items-center py-8"> <div className="flex flex-col items-center justify-center h-full">
<div className="text-muted-foreground">...</div> <Loader2 className="h-8 w-8 animate-spin text-primary mb-2" />
<div className="text-sm text-muted-foreground">...</div>
</div> </div>
) : data.length === 0 ? ( ) : data.length === 0 ? (
<div className="flex justify-center items-center py-8"> <div className="flex flex-col items-center justify-center h-full">
<div className="text-muted-foreground"></div> <div className="text-muted-foreground"></div>
</div> </div>
) : ( ) : (
@ -125,6 +134,7 @@ const HistoryModal: React.FC<HistoryModalProps> = ({ visible, onCancel, workflow
{/* 分页器 */} {/* 分页器 */}
{pageCount > 1 && ( {pageCount > 1 && (
<div className="mt-4">
<DataTablePagination <DataTablePagination
pageIndex={query.pageNum + 1} pageIndex={query.pageNum + 1}
pageSize={query.pageSize} pageSize={query.pageSize}
@ -134,11 +144,11 @@ const HistoryModal: React.FC<HistoryModalProps> = ({ visible, onCancel, workflow
pageNum: page - 1 pageNum: page - 1
}))} }))}
/> />
</div>
)} )}
</> </>
)} )}
</div> </div>
</DialogBody>
</DialogContent> </DialogContent>
</Dialog> </Dialog>