Jelajahi Sumber

📝 docs(agents): 完善通用CRUD页面开发文档

- 重命名"页面结构"为"页面组件结构",更准确反映内容
- 添加页面布局规范,包含标题、搜索和数据表格区域的代码示例
- 增加高级组件集成部分,涵盖分页、关联实体选择器和图片选择器
- 添加复杂字段展示模式,包括关联实体、状态和图片字段的展示方式
- 新增表单字段类型映射表格,规范不同字段类型对应的UI组件
- 添加日期格式化和消息通知规范,统一项目中的日期展示和用户反馈格式
yourname 6 bulan lalu
induk
melakukan
eb00aae3af
1 mengubah file dengan 231 tambahan dan 3 penghapusan
  1. 231 3
      .claude/agents/generic-crud-page.md

+ 231 - 3
.claude/agents/generic-crud-page.md

@@ -89,14 +89,12 @@ const exampleUsage = async () => {
 
 ### 3. 管理页面开发
 
-### 3. 页面开发阶段(基于 shadcn-管理页面开发.md)
-
 #### 文件位置
 - 管理页面:`src/client/admin/pages/[EntityName].tsx`
 - 类型定义:使用后端API自动提取类型
 - 表单验证:直接使用后端Zod Schema
 
-#### 页面结构
+#### 页面组件结构
 ```typescript
 // 1. 类型导入和定义
 type CreateRequest = InferRequestType<typeof yourEntityClient.$post>['json'];
@@ -134,6 +132,236 @@ export const EntityPage = () => {
 };
 ```
 
+#### 页面布局规范
+
+##### 1. 页面标题区域
+```tsx
+<div className="flex justify-between items-center">
+  <h1 className="text-2xl font-bold">页面标题</h1>
+  <Button onClick={handleCreateEntity}>
+    <Plus className="mr-2 h-4 w-4" />
+    创建实体
+  </Button>
+</div>
+```
+
+##### 2. 搜索区域
+```tsx
+<Card>
+  <CardHeader>
+    <CardTitle>列表标题</CardTitle>
+    <CardDescription>列表描述信息</CardDescription>
+  </CardHeader>
+  <CardContent>
+    <div className="mb-4">
+      <form onSubmit={handleSearch} className="flex gap-2">
+        <div className="relative flex-1 max-w-sm">
+          <Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
+          <Input
+            placeholder="搜索提示..."
+            value={searchParams.search}
+            onChange={(e) => setSearchParams(prev => ({ ...prev, search: e.target.value }))}
+            className="pl-8"
+          />
+        </div>
+        <Button type="submit" variant="outline">
+          搜索
+        </Button>
+      </form>
+    </div>
+  </CardContent>
+</Card>
+```
+
+##### 3. 数据表格
+```tsx
+<div className="rounded-md border">
+  <Table>
+    <TableHeader>
+      <TableRow>
+        <TableHead>列标题1</TableHead>
+        <TableHead>列标题2</TableHead>
+        <TableHead className="text-right">操作</TableHead>
+      </TableRow>
+    </TableHeader>
+    <TableBody>
+      {data.map((item) => (
+        <TableRow key={item.id}>
+          <TableCell>{item.field1}</TableCell>
+          <TableCell>{item.field2}</TableCell>
+          <TableCell className="text-right">
+            <div className="flex justify-end gap-2">
+              <Button variant="ghost" size="icon" onClick={() => handleEdit(item)}>
+                <Edit className="h-4 w-4" />
+              </Button>
+              <Button variant="ghost" size="icon" onClick={() => handleDelete(item.id)}>
+                <Trash2 className="h-4 w-4" />
+              </Button>
+            </div>
+          </TableCell>
+        </TableRow>
+      ))}
+    </TableBody>
+  </Table>
+</div>
+
+{data?.data.length === 0 && !isLoading && (
+  <div className="text-center py-8">
+    <p className="text-muted-foreground">暂无数据</p>
+  </div>
+)}
+
+<DataTablePagination
+  currentPage={searchParams.page}
+  pageSize={searchParams.limit}
+  totalCount={data?.pagination.total || 0}
+  onPageChange={(page, limit) => setSearchParams(prev => ({ ...prev, page, limit }))}
+/>
+```
+
+#### 高级组件集成
+
+##### 1. DataTablePagination 分页组件
+```tsx
+import { DataTablePagination } from '@/client/admin/components/DataTablePagination';
+
+<DataTablePagination
+  currentPage={searchParams.page}
+  pageSize={searchParams.limit}
+  totalCount={data?.pagination.total || 0}
+  onPageChange={(page, limit) => setSearchParams(prev => ({ ...prev, page, limit }))}
+/>
+```
+
+##### 2. 关联实体Selector组件
+```tsx
+import AdvertisementTypeSelector from '@/client/admin/components/AdvertisementTypeSelector';
+
+<FormField
+  control={form.control}
+  name="typeId"
+  render={({ field }) => (
+    <FormItem>
+      <FormLabel>广告类型</FormLabel>
+      <FormControl>
+        <AdvertisementTypeSelector
+          value={field.value}
+          onChange={field.onChange}
+          placeholder="请选择广告类型"
+        />
+      </FormControl>
+      <FormMessage />
+    </FormItem>
+  )}
+/>
+```
+
+##### 3. 图片选择器集成
+```tsx
+import ImageSelector from '@/client/admin/components/ImageSelector';
+
+<FormField
+  control={form.control}
+  name="imageFileId"
+  render={({ field }) => (
+    <FormItem>
+      <FormLabel>广告图片</FormLabel>
+      <FormControl>
+        <ImageSelector
+          value={field.value || undefined}
+          onChange={field.onChange}
+          maxSize={2} // MB
+          uploadPath="/advertisements"
+          uploadButtonText="上传广告图片"
+          previewSize="medium"
+          placeholder="选择广告图片"
+          title="选择广告图片"
+          description="上传新图片或从已有图片中选择"
+        />
+      </FormControl>
+      <FormDescription>推荐尺寸:1200x400px,支持jpg、png格式</FormDescription>
+      <FormMessage />
+    </FormItem>
+  )}
+/>
+```
+
+#### 复杂字段展示模式
+
+##### 1. 关联实体字段展示
+```tsx
+<TableCell>
+  {advertisement.advertisementType?.name || '-'}
+</TableCell>
+```
+
+##### 2. 状态字段展示
+```tsx
+<TableCell>
+  <Badge variant={advertisement.status === 1 ? 'default' : 'secondary'}>
+    {advertisement.status === 1 ? '启用' : '禁用'}
+  </Badge>
+</TableCell>
+```
+
+##### 3. 图片字段展示
+```tsx
+<TableCell>
+  {advertisement.imageFile?.fullUrl ? (
+    <img
+      src={advertisement.imageFile.fullUrl}
+      alt={advertisement.title || '图片'}
+      className="w-16 h-10 object-cover rounded"
+      onError={(e) => {
+        e.currentTarget.src = '/placeholder.png';
+      }}
+    />
+  ) : (
+    <span className="text-muted-foreground text-xs">无图片</span>
+  )}
+</TableCell>
+```
+
+#### 表单字段类型映射
+
+| 字段类型 | 组件 | 示例 |
+|----------|------|------|
+| 文本输入 | Input | `<Input placeholder="请输入标题" {...field} />` |
+| 长文本 | Textarea | `<Textarea placeholder="请输入描述" {...field} />` |
+| 选择器 | Select | `<Select value={field.value} onValueChange={field.onChange}>` |
+| 数字输入 | Input | `<Input type="number" {...field} />` |
+| 日期选择 | DatePicker | `<DatePicker selected={field.value} onChange={field.onChange} />` |
+| 开关 | Switch | `<Switch checked={field.value} onCheckedChange={field.onChange} />` |
+| 文件上传 | ImageSelector | `<ImageSelector value={field.value} onChange={field.onChange} />` |
+
+#### 日期格式化规范
+```tsx
+import { format } from 'date-fns';
+
+// 标准日期时间格式:yyyy-MM-dd HH:mm
+<TableCell>
+  {user.createdAt ? format(new Date(user.createdAt), 'yyyy-MM-dd HH:mm') : '-'}
+</TableCell>
+
+// 仅日期格式:yyyy-MM-dd
+<TableCell>
+  {user.birthday ? format(new Date(user.birthday), 'yyyy-MM-dd') : '-'}
+</TableCell>
+```
+
+#### 消息通知规范
+```typescript
+import { toast } from 'sonner';
+
+// 成功通知
+toast.success('操作成功');
+toast.success('用户创建成功');
+
+// 错误通知
+toast.error('操作失败');
+toast.error('创建用户失败,请重试');
+```
+
 #### 核心开发模式
 
 ##### 类型驱动的开发