- 支持一对多/多对一关系定义并生成到 Prisma schema - 简化流程:查询关联配置根据关系自动预填 - 修复 Handlebars 模板 HTML 转义导致的乱码问题 - 修复 controller 模板缺少 Prisma 导入的问题 - 新增页面模板 (page.hbs) 生成前端页面 - 添加 FindAllParams/PaginationQueryDto 索引签名修复类型兼容 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
152 lines
4.1 KiB
Handlebars
152 lines
4.1 KiB
Handlebars
'use client';
|
|
|
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
import type { {{pascalCase name}}Response } from '@seclusion/shared';
|
|
import { useEffect } from 'react';
|
|
import { useForm } from 'react-hook-form';
|
|
import { toast } from 'sonner';
|
|
import { z } from 'zod';
|
|
|
|
import { Button } from '@/components/ui/button';
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogFooter,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
} from '@/components/ui/dialog';
|
|
import {
|
|
Form,
|
|
FormControl,
|
|
FormField,
|
|
FormItem,
|
|
FormLabel,
|
|
FormMessage,
|
|
} from '@/components/ui/form';
|
|
import { Input } from '@/components/ui/input';
|
|
{{#if hasTextarea}}
|
|
import { Textarea } from '@/components/ui/textarea';
|
|
{{/if}}
|
|
{{#if hasSelect}}
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from '@/components/ui/select';
|
|
{{/if}}
|
|
{{#if hasSwitch}}
|
|
import { Switch } from '@/components/ui/switch';
|
|
{{/if}}
|
|
import { useUpdate{{pascalCase name}} } from '@/hooks/use{{pascalCase pluralName}}';
|
|
|
|
const edit{{pascalCase name}}Schema = z.object({
|
|
{{#each updateFields}}
|
|
{{name}}: {{{zodValidation this}}}.optional(),
|
|
{{/each}}
|
|
});
|
|
|
|
type Edit{{pascalCase name}}FormValues = z.infer<typeof edit{{pascalCase name}}Schema>;
|
|
|
|
interface {{pascalCase name}}EditDialogProps {
|
|
{{camelCase name}}: {{pascalCase name}}Response | null;
|
|
open: boolean;
|
|
onOpenChange: (open: boolean) => void;
|
|
}
|
|
|
|
export function {{pascalCase name}}EditDialog({
|
|
{{camelCase name}},
|
|
open,
|
|
onOpenChange,
|
|
}: {{pascalCase name}}EditDialogProps) {
|
|
const update{{pascalCase name}} = useUpdate{{pascalCase name}}();
|
|
|
|
const form = useForm<Edit{{pascalCase name}}FormValues>({
|
|
resolver: zodResolver(edit{{pascalCase name}}Schema),
|
|
defaultValues: {
|
|
{{#each updateFields}}
|
|
{{name}}: {{{defaultValue this}}},
|
|
{{/each}}
|
|
},
|
|
});
|
|
|
|
// 当数据变化时重置表单
|
|
useEffect(() => {
|
|
if ({{camelCase name}}) {
|
|
form.reset({
|
|
{{#each updateFields}}
|
|
{{name}}: {{camelCase ../name}}.{{name}}{{#if nullable}} ?? {{{defaultValue this}}}{{/if}},
|
|
{{/each}}
|
|
});
|
|
}
|
|
}, [{{camelCase name}}, form]);
|
|
|
|
const onSubmit = async (values: Edit{{pascalCase name}}FormValues) => {
|
|
if (!{{camelCase name}}) return;
|
|
|
|
try {
|
|
await update{{pascalCase name}}.mutateAsync({
|
|
id: {{camelCase name}}.id,
|
|
data: values,
|
|
});
|
|
toast.success('{{chineseName}}已更新');
|
|
onOpenChange(false);
|
|
} catch (error) {
|
|
toast.error(error instanceof Error ? error.message : '更新失败');
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
<DialogContent className="sm:max-w-[425px]">
|
|
<DialogHeader>
|
|
<DialogTitle>编辑{{chineseName}}</DialogTitle>
|
|
<DialogDescription>修改{{chineseName}}信息</DialogDescription>
|
|
</DialogHeader>
|
|
|
|
<Form {...form}>
|
|
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
|
{{#each updateFields}}
|
|
<FormField
|
|
control={form.control}
|
|
name="{{name}}"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>{{label}}</FormLabel>
|
|
<FormControl>
|
|
{{{formControl this}}}
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
|
|
{{/each}}
|
|
<div className="text-sm text-muted-foreground space-y-1">
|
|
<p>
|
|
<span className="font-medium">ID:</span>{' '}
|
|
<span className="font-mono">{{{camelCase name}}?.id}</span>
|
|
</p>
|
|
</div>
|
|
|
|
<DialogFooter>
|
|
<Button
|
|
type="button"
|
|
variant="outline"
|
|
onClick={() => onOpenChange(false)}
|
|
>
|
|
取消
|
|
</Button>
|
|
<Button type="submit" disabled={update{{pascalCase name}}.isPending}>
|
|
{update{{pascalCase name}}.isPending ? '保存中...' : '保存'}
|
|
</Button>
|
|
</DialogFooter>
|
|
</form>
|
|
</Form>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
}
|