video.schema.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import type {
  2. AuditRecordDTO,
  3. AuditRecordVO,
  4. } from '#/request/schema/audit-record';
  5. import { z } from '#/adapter/form';
  6. import { decodeList } from '#/request/schema';
  7. import { decodeAuditRecord } from '#/request/schema/audit-record';
  8. // ---------------------------------------------------------------------------
  9. // 枚举
  10. // ---------------------------------------------------------------------------
  11. export type VideoCategory = 'clinical_skill' | 'clinical_teaching' | 'theory';
  12. export type VideoSortType = 'latest' | 'popular';
  13. export const VIDEO_CATEGORY_OPTIONS = [
  14. { label: '临床技能', value: 'clinical_skill' },
  15. { label: '临床教学', value: 'clinical_teaching' },
  16. { label: '理论讲解', value: 'theory' },
  17. ] as const satisfies ReadonlyArray<{
  18. label: string;
  19. value: VideoCategory;
  20. }>;
  21. export function getVideoCategoryLabel(category?: VideoCategory) {
  22. return (
  23. VIDEO_CATEGORY_OPTIONS.find((item) => item.value === category)?.label ?? ''
  24. );
  25. }
  26. // ---------------------------------------------------------------------------
  27. // DTO
  28. // ---------------------------------------------------------------------------
  29. export interface VideoDTO extends AuditRecordDTO {
  30. id?: number | string;
  31. personalStudioId?: number | string;
  32. videoName?: string;
  33. speakerName?: string;
  34. category?: VideoCategory;
  35. videoUrl?: string;
  36. videoFirstUrl?: string;
  37. duration?: string;
  38. viewCount?: number;
  39. status?: boolean;
  40. }
  41. export interface VideoQueryDTO {
  42. mixture?: string;
  43. personalStudioId?: number | string;
  44. category?: VideoCategory;
  45. sortType?: VideoSortType;
  46. pageNum?: number;
  47. pageSize?: number;
  48. }
  49. // ---------------------------------------------------------------------------
  50. // VO
  51. // ---------------------------------------------------------------------------
  52. export interface VideoVO extends AuditRecordVO {
  53. id?: string;
  54. workroomId: string;
  55. name: string;
  56. speaker?: string;
  57. category: VideoCategory;
  58. videoUrl?: string;
  59. thumbnailUrl?: string;
  60. duration?: string;
  61. viewCount?: number;
  62. status: boolean;
  63. }
  64. export type VideoSubmitVO = VideoVO;
  65. export interface VideoQueryVO {
  66. keyword?: string;
  67. workroomId?: string;
  68. category?: VideoCategory;
  69. sortType?: VideoSortType;
  70. }
  71. // ---------------------------------------------------------------------------
  72. // Schema
  73. // ---------------------------------------------------------------------------
  74. export const VideoVOSchema = z.object({
  75. id: z.string().optional(),
  76. workroomId: z.string().min(1, '工作室不能为空'),
  77. name: z.string().min(1, '请输入视频名称'),
  78. speaker: z.string().optional(),
  79. category: z.enum(['clinical_skill', 'clinical_teaching', 'theory'], {
  80. message: '请选择视频分类',
  81. }),
  82. status: z.boolean(),
  83. });
  84. // ---------------------------------------------------------------------------
  85. // 编解码
  86. // ---------------------------------------------------------------------------
  87. export function decodeVideo(dto: VideoDTO): VideoVO {
  88. return {
  89. ...decodeAuditRecord(dto),
  90. id: dto.id?.toString(),
  91. workroomId: dto.personalStudioId?.toString() ?? '',
  92. name: dto.videoName ?? '',
  93. speaker: dto.speakerName,
  94. category: dto.category ?? 'clinical_skill',
  95. videoUrl: dto.videoUrl,
  96. thumbnailUrl: dto.videoFirstUrl,
  97. duration: dto.duration,
  98. viewCount: dto.viewCount ?? 0,
  99. status: dto.status ?? true,
  100. };
  101. }
  102. export function encodeVideoQuery(query: Partial<VideoQueryVO>): VideoQueryDTO {
  103. return {
  104. mixture: query.keyword,
  105. personalStudioId: query.workroomId,
  106. category: query.category,
  107. sortType: query.sortType,
  108. };
  109. }
  110. export function encodeVideo(vo: VideoSubmitVO): VideoDTO {
  111. return {
  112. id: vo.id,
  113. personalStudioId: vo.workroomId,
  114. videoName: vo.name,
  115. speakerName: vo.speaker,
  116. category: vo.category,
  117. videoUrl: vo.videoUrl,
  118. videoFirstUrl: vo.thumbnailUrl,
  119. duration: vo.duration,
  120. status: vo.status,
  121. };
  122. }
  123. export function decodeVideoList(dto: VideoDTO[]) {
  124. return decodeList(dto, decodeVideo);
  125. }