From 788ebcb72b597a706ddc0668065b8453915532a3 Mon Sep 17 00:00:00 2001 From: dengqichen Date: Wed, 8 Jan 2025 15:05:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=A7=E5=A3=B0=E9=81=93=E6=92=92=E6=97=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/dist/scripts/generate-page.js | 762 ++++++++++++++++++ frontend/package.json | 1 + frontend/pnpm-lock.yaml | 33 + frontend/src/components/ui/scroll-area.tsx | 46 ++ frontend/src/components/ui/skeleton.tsx | 15 + .../pages/Deploy/GitManager/List/index.tsx | 363 +++++++++ .../pages/Deploy/GitManager/List/service.ts | 33 + .../src/pages/Deploy/GitManager/List/types.ts | 88 ++ frontend/src/router/index.tsx | 5 + 9 files changed, 1346 insertions(+) create mode 100644 frontend/dist/scripts/generate-page.js create mode 100644 frontend/src/components/ui/scroll-area.tsx create mode 100644 frontend/src/components/ui/skeleton.tsx create mode 100644 frontend/src/pages/Deploy/GitManager/List/index.tsx create mode 100644 frontend/src/pages/Deploy/GitManager/List/service.ts create mode 100644 frontend/src/pages/Deploy/GitManager/List/types.ts diff --git a/frontend/dist/scripts/generate-page.js b/frontend/dist/scripts/generate-page.js new file mode 100644 index 00000000..a174e21d --- /dev/null +++ b/frontend/dist/scripts/generate-page.js @@ -0,0 +1,762 @@ +import { promises as fs } from 'fs'; +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; +import { createInterface } from 'readline'; +// 获取当前文件的目录 +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +// 生成 types.ts +function generateTypes(options) { + const { name } = options; + const typeName = name.charAt(0).toUpperCase() + name.slice(1); + return `import type { BaseResponse, BaseQuery } from '@/types/base'; + +export interface ${typeName}Response extends BaseResponse { + name: string; + description?: string; + enabled: boolean; + sort: number; + // TODO: 添加其他字段 +} + +export interface ${typeName}Query extends BaseQuery { + name?: string; + enabled?: boolean; + // TODO: 添加其他查询字段 +} + +export interface ${typeName}Request { + name: string; + description?: string; + enabled: boolean; + sort: number; + // TODO: 添加其他请求字段 +} +`; +} +// 生成 schema.ts +function generateSchema(options) { + const { name } = options; + const typeName = name.charAt(0).toUpperCase() + name.slice(1); + return `import * as z from "zod"; + +export const searchFormSchema = z.object({ + name: z.string().optional(), + enabled: z.boolean().optional(), +}); + +export const ${typeName.toLowerCase()}FormSchema = z.object({ + name: z.string().min(1, "请输入名称").max(50, "名称不能超过50个字符"), + description: z.string().max(200, "描述不能超过200个字符").optional(), + enabled: z.boolean().default(true), + sort: z.number().min(0).default(0), +}); + +export type SearchFormValues = z.infer; +export type ${typeName}FormValues = z.infer; +`; +} +// 生成 service.ts +function generateService(options) { + const { name, baseUrl } = options; + const typeName = name.charAt(0).toUpperCase() + name.slice(1); + return `import request from '@/utils/request'; +import type { Page } from '@/types/base'; +import type { ${typeName}Response, ${typeName}Query, ${typeName}Request } from './types'; + +const BASE_URL = '${baseUrl}'; + +// 创建 +export const create${typeName} = (data: ${typeName}Request) => + request.post(BASE_URL, data); + +// 更新 +export const update${typeName} = (id: number, data: ${typeName}Request) => + request.put(\`\${BASE_URL}/\${id}\`, data); + +// 删除 +export const delete${typeName} = (id: number) => + request.delete(\`\${BASE_URL}/\${id}\`); + +// 获取详情 +export const get${typeName} = (id: number) => + request.get<${typeName}Response>(\`\${BASE_URL}/\${id}\`); + +// 分页查询列表 +export const get${typeName}Page = (params?: ${typeName}Query) => + request.get>(\`\${BASE_URL}/page\`, { params }); + +// 获取所有列表 +export const get${typeName}List = () => + request.get<${typeName}Response[]>(BASE_URL); + +// 条件查询列表 +export const get${typeName}ListByCondition = (params?: ${typeName}Query) => + request.get<${typeName}Response[]>(\`\${BASE_URL}/list\`, { params }); +`; +} +// 生成 Modal 组件 +function generateModal(options) { + const { name } = options; + const typeName = name.charAt(0).toUpperCase() + name.slice(1); + return `import React, { useEffect } from 'react'; +import type { ${typeName}Response } from '../types'; +import { create${typeName}, update${typeName} } from '../service'; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogFooter, +} from "@/components/ui/dialog"; +import { Button } from "@/components/ui/button"; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { Switch } from "@/components/ui/switch"; +import { useToast } from "@/components/ui/use-toast"; +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { ${typeName.toLowerCase()}FormSchema, type ${typeName}FormValues } from '../schema'; +import { Textarea } from "@/components/ui/textarea"; + +interface ${typeName}ModalProps { + open: boolean; + onCancel: () => void; + onSuccess: () => void; + initialValues?: ${typeName}Response; +} + +const ${typeName}Modal: React.FC<${typeName}ModalProps> = ({ + open, + onCancel, + onSuccess, + initialValues, +}) => { + const { toast } = useToast(); + const isEdit = !!initialValues?.id; + + const form = useForm<${typeName}FormValues>({ + resolver: zodResolver(${typeName.toLowerCase()}FormSchema), + defaultValues: { + name: "", + description: "", + enabled: true, + sort: 0, + }, + }); + + useEffect(() => { + if (initialValues) { + form.reset({ + name: initialValues.name, + description: initialValues.description || "", + enabled: initialValues.enabled, + sort: initialValues.sort, + }); + } + }, [initialValues, form]); + + const handleSubmit = async (values: ${typeName}FormValues) => { + try { + if (isEdit) { + await update${typeName}(initialValues.id, values); + } else { + await create${typeName}(values); + } + toast({ + title: \`\${isEdit ? '更新' : '创建'}成功\`, + duration: 3000, + }); + form.reset(); + onSuccess(); + } catch (error) { + toast({ + variant: "destructive", + title: \`\${isEdit ? '更新' : '创建'}失败\`, + description: error instanceof Error ? error.message : undefined, + duration: 3000, + }); + } + }; + + return ( + !open && onCancel()}> + + + {isEdit ? '编辑' : '新建'} + +
+ + ( + + 名称 + + + + + + )} + /> + + ( + + 描述 + +