file.entity.ts 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import { Entity, PrimaryGeneratedColumn, Column, Index, ManyToOne, JoinColumn } from 'typeorm';
  2. import { z } from '@hono/zod-openapi';
  3. import { UserEntity } from '@/server/modules/users/user.entity';
  4. import process from 'node:process';
  5. import { UserSchema } from '../users/user.schema';
  6. @Entity('file')
  7. export class File {
  8. @PrimaryGeneratedColumn({ name: 'id', type: 'int', unsigned: true })
  9. id!: number;
  10. @Column({ name: 'name', type: 'varchar', length: 255 })
  11. name!: string;
  12. @Column({ name: 'type', type: 'varchar', length: 50, nullable: true, comment: '文件类型' })
  13. type!: string | null;
  14. @Column({ name: 'size', type: 'int', unsigned: true, nullable: true, comment: '文件大小,单位字节' })
  15. size!: number | null;
  16. @Column({ name: 'path', type: 'varchar', length: 512, comment: '文件存储路径' })
  17. path!: string;
  18. // 获取完整的文件URL(包含MINIO_HOST前缀)
  19. get fullUrl(): string {
  20. const protocol = process.env.MINIO_USE_SSL !== 'false' ? 'https' : 'http';
  21. const port = process.env.MINIO_PORT ? `:${process.env.MINIO_PORT}` : '';
  22. const host = process.env.MINIO_HOST || 'localhost';
  23. const bucketName = process.env.MINIO_BUCKET_NAME || 'd8dai';
  24. return `${protocol}://${host}${port}/${bucketName}/${this.path}`;
  25. }
  26. @Column({ name: 'description', type: 'text', nullable: true, comment: '文件描述' })
  27. description!: string | null;
  28. @Column({ name: 'upload_user_id', type: 'int', unsigned: true })
  29. uploadUserId!: number;
  30. @ManyToOne(() => UserEntity)
  31. @JoinColumn({ name: 'upload_user_id', referencedColumnName: 'id' })
  32. uploadUser!: UserEntity;
  33. @Column({ name: 'upload_time', type: 'datetime' })
  34. uploadTime!: Date;
  35. @Column({ name: 'last_updated', type: 'datetime', nullable: true, comment: '最后更新时间' })
  36. lastUpdated!: Date | null;
  37. @Column({ name: 'created_at', type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
  38. createdAt!: Date;
  39. @Column({
  40. name: 'updated_at',
  41. type: 'timestamp',
  42. default: () => 'CURRENT_TIMESTAMP',
  43. onUpdate: 'CURRENT_TIMESTAMP'
  44. })
  45. updatedAt!: Date;
  46. }
  47. export const FileSchema = z.object({
  48. id: z.number().int().positive().openapi({
  49. description: '文件ID',
  50. example: 1
  51. }),
  52. name: z.string().max(255).openapi({
  53. description: '文件名称',
  54. example: '项目计划书.pdf'
  55. }),
  56. type: z.string().max(50).nullable().openapi({
  57. description: '文件类型',
  58. example: 'application/pdf'
  59. }),
  60. size: z.number().int().positive().nullable().openapi({
  61. description: '文件大小,单位字节',
  62. example: 102400
  63. }),
  64. path: z.string().max(512).openapi({
  65. description: '文件存储路径',
  66. example: '/uploads/documents/2023/project-plan.pdf'
  67. }),
  68. fullUrl: z.string().url().openapi({
  69. description: '完整文件访问URL',
  70. example: 'https://minio.example.com/d8dai/uploads/documents/2023/project-plan.pdf'
  71. }),
  72. description: z.string().nullable().openapi({
  73. description: '文件描述',
  74. example: '2023年度项目计划书'
  75. }),
  76. uploadUserId: z.number().int().positive().openapi({
  77. description: '上传用户ID',
  78. example: 1
  79. }),
  80. uploadUser: UserSchema,
  81. uploadTime: z.date().openapi({
  82. description: '上传时间',
  83. example: '2023-01-15T10:30:00Z'
  84. }),
  85. lastUpdated: z.date().nullable().openapi({
  86. description: '最后更新时间',
  87. example: '2023-01-16T14:20:00Z'
  88. }),
  89. createdAt: z.date().openapi({
  90. description: '创建时间',
  91. example: '2023-01-15T10:30:00Z'
  92. }),
  93. updatedAt: z.date().openapi({
  94. description: '更新时间',
  95. example: '2023-01-16T14:20:00Z'
  96. })
  97. });
  98. export const CreateFileDto = z.object({
  99. name: z.string().max(255).openapi({
  100. description: '文件名称',
  101. example: '项目计划书.pdf'
  102. }),
  103. type: z.string().max(50).nullable().optional().openapi({
  104. description: '文件类型',
  105. example: 'application/pdf'
  106. }),
  107. size: z.coerce.number().int().positive().nullable().optional().openapi({
  108. description: '文件大小,单位字节',
  109. example: 102400
  110. }),
  111. path: z.string().max(512).openapi({
  112. description: '文件存储路径',
  113. example: '/uploads/documents/2023/project-plan.pdf'
  114. }),
  115. description: z.string().nullable().optional().openapi({
  116. description: '文件描述',
  117. example: '2023年度项目计划书'
  118. }),
  119. lastUpdated: z.coerce.date().nullable().optional().openapi({
  120. description: '最后更新时间',
  121. example: '2023-01-16T14:20:00Z'
  122. })
  123. });
  124. export const UpdateFileDto = z.object({
  125. name: z.string().max(255).optional().openapi({
  126. description: '文件名称',
  127. example: '项目计划书_v2.pdf'
  128. }),
  129. type: z.string().max(50).nullable().optional().openapi({
  130. description: '文件类型',
  131. example: 'application/pdf'
  132. }),
  133. size: z.coerce.number().int().positive().nullable().optional().openapi({
  134. description: '文件大小,单位字节',
  135. example: 153600
  136. }),
  137. path: z.string().max(512).optional().openapi({
  138. description: '文件存储路径',
  139. example: '/uploads/documents/2023/project-plan_v2.pdf'
  140. }),
  141. description: z.string().nullable().optional().openapi({
  142. description: '文件描述',
  143. example: '2023年度项目计划书(修订版)'
  144. }),
  145. uploadUserId: z.number().int().positive().optional().openapi({
  146. description: '上传用户ID',
  147. example: 1
  148. }),
  149. uploadTime: z.coerce.date().optional().openapi({
  150. description: '上传时间',
  151. example: '2023-01-15T10:30:00Z'
  152. }),
  153. lastUpdated: z.coerce.date().nullable().optional().openapi({
  154. description: '最后更新时间',
  155. example: '2023-01-16T14:20:00Z'
  156. })
  157. });
  158. export type FileType = z.infer<typeof FileSchema>