浏览代码

♻️ refactor(files): 优化文件管理页面代码结构

- 统一使用UpdateFileDto作为表单验证schema,移除重复的fileFormSchema定义
- 将pagination中的page字段重命名为current,保持命名一致性
- 更新分页逻辑,使用current代替page处理页码计算
- 调整查询键(queryKey)以匹配新的分页参数命名
- 精简UpdateFileDto,移除不必要的字段(type, size, path等),只保留可编辑的name和description

✨ feat(files): 增强文件表单类型定义

- 引入UpdateFileDto类型,统一前后端文件更新数据结构
- 使用z.infer从UpdateFileDto推断FileFormData类型,提高类型一致性
yourname 4 月之前
父节点
当前提交
1566cb3f3a
共有 2 个文件被更改,包括 18 次插入48 次删除
  1. 14 20
      src/client/admin-shadcn/pages/Files.tsx
  2. 4 28
      src/server/modules/files/file.schema.ts

+ 14 - 20
src/client/admin-shadcn/pages/Files.tsx

@@ -16,27 +16,21 @@ import { fileClient } from '@/client/api';
 import type { InferResponseType, InferRequestType } from 'hono/client';
 import dayjs from 'dayjs';
 import { uploadMinIOWithPolicy } from '@/client/utils/minio';
+import { UpdateFileDto } from '@/server/modules/files/file.schema';
 import * as z from 'zod';
 
 // 定义类型
 type FileItem = InferResponseType<typeof fileClient.$get, 200>['data'][0];
 type FileListResponse = InferResponseType<typeof fileClient.$get, 200>;
 type UpdateFileRequest = InferRequestType<typeof fileClient[':id']['$put']>['json'];
-
-// 表单验证schema
-const fileFormSchema = z.object({
-  name: z.string().min(1, '文件名称不能为空'),
-  description: z.string().optional(),
-});
-
-type FileFormData = z.infer<typeof fileFormSchema>;
+type FileFormData = z.infer<typeof UpdateFileDto>;
 
 export const FilesPage: React.FC = () => {
   const [isModalOpen, setIsModalOpen] = useState(false);
   const [editingFile, setEditingFile] = useState<FileItem | null>(null);
   const [searchText, setSearchText] = useState('');
   const [pagination, setPagination] = useState({
-    page: 1,
+    current: 1,
     pageSize: 10,
     total: 0,
   });
@@ -47,7 +41,7 @@ export const FilesPage: React.FC = () => {
   
   // 表单初始化
   const form = useForm<FileFormData>({
-    resolver: zodResolver(fileFormSchema),
+    resolver: zodResolver(UpdateFileDto),
     defaultValues: {
       name: '',
       description: '',
@@ -88,8 +82,8 @@ export const FilesPage: React.FC = () => {
   };
 
   const { data, isLoading, error } = useQuery({
-    queryKey: ['files', pagination.page, pagination.pageSize, searchText],
-    queryFn: () => fetchFiles({ page: pagination.page, pageSize: pagination.pageSize }),
+    queryKey: ['files', pagination.current, pagination.pageSize, searchText],
+    queryFn: () => fetchFiles({ page: pagination.current, pageSize: pagination.pageSize }),
   });
 
   // 更新文件记录
@@ -207,7 +201,7 @@ export const FilesPage: React.FC = () => {
   };
 
   const handleSearch = () => {
-    setPagination({ ...pagination, page: 1 });
+    setPagination({ ...pagination, current: 1 });
   };
 
   // 格式化文件大小
@@ -366,27 +360,27 @@ export const FilesPage: React.FC = () => {
           {tablePagination.total > 0 && (
             <div className="flex justify-between items-center mt-4">
               <div className="text-sm text-gray-600">
-                显示 {((tablePagination.page - 1) * tablePagination.pageSize + 1)}-
-                {Math.min(tablePagination.page * tablePagination.pageSize, tablePagination.total)} 条,
+                显示 {((tablePagination.current - 1) * tablePagination.pageSize + 1)}-
+                {Math.min(tablePagination.current * tablePagination.pageSize, tablePagination.total)} 条,
                 共 {tablePagination.total} 条
               </div>
               <div className="flex gap-2">
                 <Button
                   variant="outline"
                   size="sm"
-                  disabled={tablePagination.page <= 1}
-                  onClick={() => setPagination({ ...pagination, page: tablePagination.page - 1 })}
+                  disabled={tablePagination.current <= 1}
+                  onClick={() => setPagination({ ...pagination, current: tablePagination.current - 1 })}
                 >
                   上一页
                 </Button>
                 <span className="px-3 py-1 text-sm">
-                  第 {tablePagination.page} 页
+                  第 {tablePagination.current} 页
                 </span>
                 <Button
                   variant="outline"
                   size="sm"
-                  disabled={tablePagination.page >= Math.ceil(tablePagination.total / tablePagination.pageSize)}
-                  onClick={() => setPagination({ ...pagination, page: tablePagination.page + 1 })}
+                  disabled={tablePagination.current >= Math.ceil(tablePagination.total / tablePagination.pageSize)}
+                  onClick={() => setPagination({ ...pagination, current: tablePagination.current + 1 })}
                 >
                   下一页
                 </Button>

+ 4 - 28
src/server/modules/files/file.schema.ts

@@ -81,37 +81,13 @@ export const CreateFileDto = z.object({
 });
 
 export const UpdateFileDto = z.object({
-  name: z.string().max(255).optional().openapi({ 
+  name: z.string().max(255).optional().openapi({
     description: '文件名称',
-    example: '项目计划书_v2.pdf' 
+    example: '项目计划书_v2.pdf'
   }),
-  type: z.string().max(50).nullable().optional().openapi({ 
-    description: '文件类型',
-    example: 'application/pdf' 
-  }),
-  size: z.coerce.number().int().positive().nullable().optional().openapi({ 
-    description: '文件大小,单位字节',
-    example: 153600 
-  }),
-  path: z.string().max(512).optional().openapi({ 
-    description: '文件存储路径',
-    example: '/uploads/documents/2023/project-plan_v2.pdf' 
-  }),
-  description: z.string().nullable().optional().openapi({ 
+  description: z.string().nullable().optional().openapi({
     description: '文件描述',
-    example: '2023年度项目计划书(修订版)' 
-  }),
-  uploadUserId: z.number().int().positive().optional().openapi({
-    description: '上传用户ID',
-    example: 1
-  }),
-  uploadTime: z.coerce.date().optional().openapi({ 
-    description: '上传时间',
-    example: '2023-01-15T10:30:00Z' 
-  }),
-  lastUpdated: z.coerce.date().nullable().optional().openapi({ 
-    description: '最后更新时间',
-    example: '2023-01-16T14:20:00Z' 
+    example: '2023年度项目计划书(修订版)'
   })
 });