video-media.dto.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // video-media.dto.ts
  2. import {
  3. IsInt,
  4. IsOptional,
  5. IsString,
  6. IsIn,
  7. IsArray,
  8. IsMongoId,
  9. Min,
  10. Max,
  11. MaxLength,
  12. } from 'class-validator';
  13. import { Type } from 'class-transformer';
  14. import { PageListDto } from '@box/common/dto/page-list.dto';
  15. export class VideoMediaListQueryDto extends PageListDto {
  16. /**
  17. * 搜索关键词:匹配标题、文件名等(具体逻辑在 service 里实现)
  18. */
  19. @IsOptional()
  20. @IsString()
  21. @MaxLength(100)
  22. keyword?: string;
  23. /**
  24. * 分类过滤:可选
  25. */
  26. @IsOptional()
  27. @IsMongoId()
  28. categoryId?: string;
  29. /**
  30. * 标签过滤(通常前端只会传一个 tagId)
  31. */
  32. @IsOptional()
  33. @IsMongoId()
  34. tagId?: string;
  35. /**
  36. * 上/下架状态过滤
  37. * 0 = 下架, 1 = 上架
  38. */
  39. @IsOptional()
  40. @Type(() => Number)
  41. @IsInt()
  42. @IsIn([0, 1])
  43. listStatus?: number;
  44. }
  45. export class UpdateVideoMediaManageDto {
  46. @IsOptional()
  47. @IsString()
  48. @MaxLength(200)
  49. title?: string;
  50. /**
  51. * 分类 ID,可为空(取消分类)
  52. */
  53. @IsOptional()
  54. @IsMongoId()
  55. categoryId?: string | null;
  56. /**
  57. * 标签 ID 列表,最多 5 个
  58. */
  59. @IsOptional()
  60. @IsArray()
  61. @IsMongoId({ each: true })
  62. tagIds?: string[];
  63. /**
  64. * 上/下架状态,也可以在这里一起保存(可选)
  65. * 0 = 下架, 1 = 上架
  66. */
  67. @IsOptional()
  68. @Type(() => Number)
  69. @IsInt()
  70. @IsIn([0, 1])
  71. listStatus?: number;
  72. }
  73. export class UpdateVideoMediaStatusDto {
  74. @Type(() => Number)
  75. @IsInt()
  76. @IsIn([0, 1])
  77. listStatus!: number;
  78. }
  79. export class BatchUpdateVideoMediaStatusDto {
  80. @IsArray()
  81. @IsMongoId({ each: true })
  82. ids!: string[];
  83. @Type(() => Number)
  84. @IsInt()
  85. @IsIn([0, 1])
  86. listStatus!: number;
  87. }
  88. export class UpdateVideoMediaCoverResponseDto {
  89. @IsString()
  90. id!: string;
  91. @IsString()
  92. coverImg!: string;
  93. /**
  94. * 新 editedAt 值
  95. */
  96. @IsString()
  97. editedAt!: string;
  98. }
  99. export class VideoMediaListItemDto {
  100. @IsString()
  101. id!: string;
  102. @IsString()
  103. title!: string;
  104. @IsString()
  105. filename!: string;
  106. /**
  107. * 视频时长(秒)
  108. */
  109. @Type(() => Number)
  110. @IsInt()
  111. videoTime!: number;
  112. /**
  113. * 文件大小(业务上 BigInt 存储,DTO 建议用字符串避免精度问题)
  114. */
  115. @IsString()
  116. size!: string;
  117. /**
  118. * 封面 URL / key
  119. */
  120. @IsString()
  121. coverImg!: string;
  122. /**
  123. * 分类 ID,可空
  124. */
  125. @IsOptional()
  126. @IsMongoId()
  127. categoryId?: string | null;
  128. /**
  129. * 当前选中的标签 ID 列表(最多 5 个)
  130. */
  131. @IsArray()
  132. @IsMongoId({ each: true })
  133. tagIds!: string[];
  134. /**
  135. * 上/下架状态 0 = 下架, 1 = 上架
  136. */
  137. @Type(() => Number)
  138. @IsInt()
  139. @IsIn([0, 1])
  140. listStatus!: number;
  141. /**
  142. * 本地编辑时间(BigInt epoch)— 字符串返回
  143. */
  144. @IsString()
  145. editedAt!: string;
  146. }
  147. export class VideoMediaDetailDto {
  148. @IsString()
  149. id!: string;
  150. // --- Provider fields (read-only for mgnt) ---
  151. @IsString()
  152. title!: string;
  153. @IsString()
  154. filename!: string;
  155. @Type(() => Number)
  156. @IsInt()
  157. videoTime!: number;
  158. @IsString()
  159. size!: string; // from BigInt
  160. @IsString()
  161. coverImg!: string;
  162. @IsString()
  163. type!: string;
  164. @Type(() => Number)
  165. @IsInt()
  166. formatType!: number;
  167. @Type(() => Number)
  168. @IsInt()
  169. contentType!: number;
  170. @IsString()
  171. country!: string;
  172. @IsString()
  173. status!: string;
  174. @IsString()
  175. desc!: string;
  176. // --- Local business fields ---
  177. @IsOptional()
  178. @IsMongoId()
  179. categoryId?: string | null;
  180. @IsArray()
  181. @IsMongoId({ each: true })
  182. tagIds!: string[];
  183. @Type(() => Number)
  184. @IsInt()
  185. @IsIn([0, 1])
  186. listStatus!: number;
  187. @IsString()
  188. editedAt!: string;
  189. // --- Optional denormalized information for UI convenience ---
  190. @IsOptional()
  191. @IsString()
  192. categoryName?: string | null;
  193. @IsOptional()
  194. @IsArray()
  195. tags?: { id: string; name: string }[];
  196. }