Ver código fonte

refactor: update video media tags structure to use vTag type and adjust related methods

Dave 1 mês atrás
pai
commit
c3e2054412

+ 2 - 2
apps/box-mgnt-api/src/mgnt-backend/feature/provider-video-sync/provider-video-sync.service.ts

@@ -856,12 +856,12 @@ export class ProviderVideoSyncService {
         create: {
           ...record,
           sanitizedSecondTags: record.sanitizedSecondTags ?? [],
-          oSecondTags: record.secondTags ?? [],
+          tags: record.secondTags ?? [],
         },
         update: {
           ...updateData,
           sanitizedSecondTags: (record as any).sanitizedSecondTags ?? [],
-          oSecondTags: (record as any).secondTags ?? [],
+          tags: (record as any).secondTags ?? [],
         },
       });
 

+ 20 - 5
apps/box-mgnt-api/src/mgnt-backend/feature/video-media/video-media.dto.ts

@@ -11,6 +11,7 @@ import {
   Max,
   MaxLength,
   ArrayNotEmpty,
+  ValidateNested,
 } from 'class-validator';
 import { Type } from 'class-transformer';
 import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
@@ -88,6 +89,16 @@ export class VideoMediaListQueryDto extends PageListDto {
   updatedTo?: number;
 }
 
+export class VideoTagItemDto {
+  @ApiProperty({ description: '标签ID', example: '507f1f77bcf86cd799439011' })
+  @IsMongoId()
+  tagId!: string;
+
+  @ApiProperty({ description: '标签名称', example: 'Funny' })
+  @IsString()
+  tagName!: string;
+}
+
 export class UpdateVideoMediaTagsDto {
   @ApiProperty({
     type: String,
@@ -98,15 +109,19 @@ export class UpdateVideoMediaTagsDto {
   id!: string;
 
   @ApiProperty({
-    type: [String],
-    description: '视频标签',
-    example: ['xxx', 'zzz'],
+    type: [VideoTagItemDto],
+    description: '视频标签(tagId + tagName)',
+    example: [
+      { tagId: 'xxxx', tagName: 'Funny' },
+      { tagId: 'vvvv', tagName: 'Meme' },
+    ],
     minItems: 1,
   })
   @IsArray()
   @ArrayNotEmpty()
-  @IsString({ each: true })
-  tags!: string[];
+  @ValidateNested({ each: true })
+  @Type(() => VideoTagItemDto)
+  tags!: VideoTagItemDto[];
 }
 
 export class UpdateVideoMediaStatusDto {

+ 23 - 15
apps/box-mgnt-api/src/mgnt-backend/feature/video-media/video-media.service.ts

@@ -187,15 +187,15 @@ export class VideoMediaService {
         videoTime: row.videoTime,
         size: row.size?.toString?.() ?? '0',
         coverImg: row.coverImg ?? '',
-        categoryIds: row.categoryIds ?? [],
-        tagIds: row.tagIds ?? [],
+        // categoryIds: row.categoryIds ?? [],
+        // tagIds: row.tagIds ?? [],
         listStatus: row.listStatus ?? 0,
         editedAt: Number(row.editedAt ?? 0),
         updatedAt: row.updatedAt ?? null,
         tags: row.tags ?? [],
-        tagsFlat: row.tagsFlat ?? '',
+        // tagsFlat: row.tagsFlat ?? '',
         secondTags: row.secondTags ?? [],
-        sanitizedSecondTags: row.sanitizedSecondTags ?? [],
+        // sanitizedSecondTags: row.sanitizedSecondTags ?? [],
       })),
     };
   }
@@ -314,15 +314,15 @@ export class VideoMediaService {
       country: video.country,
       status: video.status,
       desc: video.desc ?? '',
-      categoryIds: video.categoryIds ?? [],
-      tagIds: video.tagIds ?? [],
+      // categoryIds: video.categoryIds ?? [],
+      // tagIds: video.tagIds ?? [],
       listStatus: video.listStatus ?? 0,
       editedAt: Number(video.editedAt ?? 0),
       updatedAt: video.updatedAt ?? null,
       categoryName: category?.name ?? null,
       // Existing DTO: tags as {id, name}[]
       tags: video.tags ?? [],
-      tagsFlat: video.tagsFlat ?? '',
+      // tagsFlat: video.tagsFlat ?? '',
       secondTags: video.secondTags ?? [],
     };
   }
@@ -332,7 +332,8 @@ export class VideoMediaService {
       where: { id: dto.id },
       select: {
         id: true,
-        oSecondTags: true,
+        secondTags: true,
+        tags: true,
       },
     });
 
@@ -340,18 +341,25 @@ export class VideoMediaService {
       throw new NotFoundException('Video not found');
     }
 
-    const mgntTags = dto.tags; // DTO enforces non-empty string[]
-    const original = video.oSecondTags ?? [];
+    // MGNT sends structured tags now
+    const mgntVTags = Array.from(
+      new Map(
+        dto.tags.map((t) => [t.tagId, { tagId: t.tagId, tagName: t.tagName }]),
+      ).values(),
+    );
+    const mgntTagNames = mgntVTags.map((t) => t.tagName);
 
-    // combine original + mgnt tags, keep order, remove duplicates
-    const mergedSecondTags = Array.from(new Set([...original, ...mgntTags]));
+    const original = video.tags ?? [];
+    const mergedSecondTags = Array.from(
+      new Set([...original, ...mgntTagNames]),
+    );
 
     await this.prisma.videoMedia.update({
       where: { id: dto.id },
       data: {
-        tags: mgntTags,
-        secondTags: mergedSecondTags,
-        editedAt: BigInt(Math.floor(Date.now() / 1000)), // epoch seconds (BigInt)
+        vTags: { set: mgntVTags },
+        tags: { set: mergedSecondTags },
+        editedAt: BigInt(Math.floor(Date.now() / 1000)),
         updatedAt: new Date(),
       },
     });

+ 6 - 1
prisma/mongo/schema/video-media.prisma

@@ -1,3 +1,8 @@
+type vTag {
+  tagId     String
+  tagName   String
+}
+
 model VideoMedia {
   /// Mongo ObjectId stored in `_id`
   id            String    @id @map("_id") @db.ObjectId
@@ -84,7 +89,7 @@ model VideoMedia {
 
   /// Denormalised tag names for fast read (store lowercased or display names)
   tags          String[]  @default([])
-  oSecondTags   String[]  @default([])
+  vTags         vTag[]
   
   /// Lowercased concatenation of tag names, for search
   tagsFlat      String     @default("")