增加应用分类

This commit is contained in:
dengqichen 2025-10-28 17:59:02 +08:00
parent edf4e9f998
commit a1399d6d69
5 changed files with 105 additions and 87 deletions

View File

@ -24,7 +24,7 @@ export const getCategoryById = (id: number) =>
* *
*/ */
export const getEnabledCategories = () => export const getEnabledCategories = () =>
request.get<ApplicationCategoryResponse[]>(`${BASE_URL}/enabled`); request.get<ApplicationCategoryResponse[]>(`${BASE_URL}/list`);
/** /**
* *

View File

@ -20,6 +20,7 @@ export interface ApplicationCategoryResponse {
icon?: string; icon?: string;
sort: number; sort: number;
enabled: boolean; enabled: boolean;
applicationCount?: number;
createBy?: string; createBy?: string;
createTime?: string; createTime?: string;
updateBy?: string; updateBy?: string;

View File

@ -41,6 +41,12 @@ import {ScrollArea} from "@/components/ui/scroll-area";
import {Check, ChevronDown, Search} from "lucide-react"; import {Check, ChevronDown, Search} from "lucide-react";
import {cn} from "@/lib/utils"; import {cn} from "@/lib/utils";
import {Popover, PopoverContent, PopoverTrigger} from "@/components/ui/popover"; import {Popover, PopoverContent, PopoverTrigger} from "@/components/ui/popover";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
interface ApplicationModalProps { interface ApplicationModalProps {
open: boolean; open: boolean;
@ -204,18 +210,43 @@ const ApplicationModal: React.FC<ApplicationModalProps> = ({
return ( return (
<Dialog open={open} onOpenChange={(open) => !open && onCancel()}> <Dialog open={open} onOpenChange={(open) => !open && onCancel()}>
<DialogContent className="max-w-[800px] h-[75vh]"> <DialogContent className="max-w-[800px] max-h-[85vh] flex flex-col">
<DialogHeader className="pb-4"> <DialogHeader>
<DialogTitle>{isEdit ? '编辑' : '新建'}</DialogTitle> <DialogTitle>{isEdit ? '编辑' : '新建'}</DialogTitle>
</DialogHeader> </DialogHeader>
<Form {...form}> <Form {...form}>
<form <form className="flex flex-col flex-1 overflow-hidden">
id="applicationForm" <ScrollArea className="flex-1 px-6">
className="space-y-4 flex flex-col h-full" <div className="space-y-4 pr-4">
>
<ScrollArea className="flex-1 -mx-6">
<div className="px-6 space-y-4">
<div className="grid grid-cols-3 gap-4"> <div className="grid grid-cols-3 gap-4">
<FormField
control={form.control}
name="categoryId"
render={({field}) => (
<FormItem>
<FormLabel></FormLabel>
<Select
onValueChange={(value) => field.onChange(Number(value))}
value={field.value?.toString()}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="请选择应用分类"/>
</SelectTrigger>
</FormControl>
<SelectContent>
{categories.map((category) => (
<SelectItem key={category.id} value={category.id.toString()}>
{category.name}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage/>
</FormItem>
)}
/>
<FormField <FormField
control={form.control} control={form.control}
name="appCode" name="appCode"
@ -247,34 +278,6 @@ const ApplicationModal: React.FC<ApplicationModalProps> = ({
</FormItem> </FormItem>
)} )}
/> />
<FormField
control={form.control}
name="categoryId"
render={({field}) => (
<FormItem>
<FormLabel></FormLabel>
<Select
onValueChange={(value) => field.onChange(Number(value))}
value={field.value?.toString()}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="请选择应用分类"/>
</SelectTrigger>
</FormControl>
<SelectContent>
{categories.map((category) => (
<SelectItem key={category.id} value={category.id.toString()}>
{category.name}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage/>
</FormItem>
)}
/>
</div> </div>
<div className="grid grid-cols-3 gap-4"> <div className="grid grid-cols-3 gap-4">
@ -307,6 +310,13 @@ const ApplicationModal: React.FC<ApplicationModalProps> = ({
/> />
</div> </div>
{/* Git 配置区域(可折叠) */}
<Accordion type="single" collapsible className="border rounded-lg">
<AccordionItem value="git-config" className="border-0">
<AccordionTrigger className="px-4 py-3 hover:no-underline">
<span className="text-sm font-medium">Git </span>
</AccordionTrigger>
<AccordionContent className="px-4 pb-4">
<div className="grid grid-cols-3 gap-4"> <div className="grid grid-cols-3 gap-4">
<FormField <FormField
control={form.control} control={form.control}
@ -454,7 +464,7 @@ const ApplicationModal: React.FC<ApplicationModalProps> = ({
return ( return (
<FormItem> <FormItem>
<FormLabel></FormLabel> <FormLabel></FormLabel>
<Popover open={open} onOpenChange={setOpen}> <Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild> <PopoverTrigger asChild>
<FormControl> <FormControl>
@ -533,6 +543,10 @@ const ApplicationModal: React.FC<ApplicationModalProps> = ({
}} }}
/> />
</div> </div>
</AccordionContent>
</AccordionItem>
</Accordion>
<FormField <FormField
control={form.control} control={form.control}
name="appDesc" name="appDesc"
@ -588,10 +602,9 @@ const ApplicationModal: React.FC<ApplicationModalProps> = ({
)} )}
/> />
<div className="h-4" />
</div> </div>
</ScrollArea> </ScrollArea>
<DialogFooter className="pt-4"> <DialogFooter className="px-6 py-4 border-t mt-0">
<Button type="button" variant="outline" onClick={onCancel}> <Button type="button" variant="outline" onClick={onCancel}>
</Button> </Button>

View File

@ -270,6 +270,7 @@ const CategoryManageDialog: React.FC<CategoryManageDialogProps> = ({
<TableHead className="w-[160px]"></TableHead> <TableHead className="w-[160px]"></TableHead>
<TableHead className="w-[140px]"></TableHead> <TableHead className="w-[140px]"></TableHead>
<TableHead className="w-[60px]"></TableHead> <TableHead className="w-[60px]"></TableHead>
<TableHead className="w-[120px]"></TableHead>
<TableHead className="w-[80px]"></TableHead> <TableHead className="w-[80px]"></TableHead>
<TableHead className="w-[80px]"></TableHead> <TableHead className="w-[80px]"></TableHead>
<TableHead className="min-w-[150px]"></TableHead> <TableHead className="min-w-[150px]"></TableHead>
@ -279,7 +280,7 @@ const CategoryManageDialog: React.FC<CategoryManageDialogProps> = ({
<TableBody> <TableBody>
{loading ? ( {loading ? (
<TableRow> <TableRow>
<TableCell colSpan={7} className="text-center py-8"> <TableCell colSpan={8} className="text-center py-8">
<div className="flex items-center justify-center"> <div className="flex items-center justify-center">
<Loader2 className="h-6 w-6 animate-spin mr-2" /> <Loader2 className="h-6 w-6 animate-spin mr-2" />
<span className="text-sm text-muted-foreground">...</span> <span className="text-sm text-muted-foreground">...</span>
@ -306,6 +307,9 @@ const CategoryManageDialog: React.FC<CategoryManageDialogProps> = ({
<span className="text-muted-foreground text-sm">-</span> <span className="text-muted-foreground text-sm">-</span>
)} )}
</TableCell> </TableCell>
<TableCell className="text-center">
<span className="text-sm font-medium">{record.applicationCount || 0}</span>
</TableCell>
<TableCell className="text-center">{record.sort}</TableCell> <TableCell className="text-center">{record.sort}</TableCell>
<TableCell> <TableCell>
{record.enabled ? ( {record.enabled ? (
@ -341,7 +345,7 @@ const CategoryManageDialog: React.FC<CategoryManageDialogProps> = ({
)) ))
) : ( ) : (
<TableRow> <TableRow>
<TableCell colSpan={7} className="text-center py-12 text-muted-foreground"> <TableCell colSpan={8} className="text-center py-12 text-muted-foreground">
<div className="flex flex-col items-center gap-3"> <div className="flex flex-col items-center gap-3">
<FolderKanban className="h-12 w-12 opacity-20" /> <FolderKanban className="h-12 w-12 opacity-20" />
<p className="text-sm"></p> <p className="text-sm"></p>

View File

@ -201,16 +201,6 @@ const ApplicationList: React.FC = () => {
}; };
const columns: Column[] = [ const columns: Column[] = [
{
accessorKey: 'appCode',
header: '应用编码',
size: 150,
},
{
accessorKey: 'appName',
header: '应用名称',
size: 130,
},
{ {
id: 'category', id: 'category',
header: '应用分类', header: '应用分类',
@ -221,6 +211,16 @@ const ApplicationList: React.FC = () => {
</div> </div>
), ),
}, },
{
accessorKey: 'appCode',
header: '应用编码',
size: 150,
},
{
accessorKey: 'appName',
header: '应用名称',
size: 130,
},
{ {
accessorKey: 'appDesc', accessorKey: 'appDesc',
header: '应用描述', header: '应用描述',