import { RELATED_DISPLAY_COUNT } from "@/components/drama-detail/data"; import { pickVideoCardTags } from "@/components/common/card-tags"; import { formatHeat } from "@/components/ranking/data"; import type { ShortDramaItem } from "@/components/short-drama/data"; import { mapVideoListItem } from "@/components/video/data"; import type { QueryVideoInfoResp, VideoData, VideoDetailInfo, VideoRecommendListResp, } from "@/lib/api/types"; import { resolvePlayURL } from "@/lib/media/playback"; /** 详情页:直接使用接口 videoInfo 字段 */ export type VideoDetail = VideoDetailInfo; /** H5 / 侧栏热门推荐条数 */ export const VIDEO_RECOMMEND_DISPLAY_COUNT = 10; export type VideoPlayView = { detail: VideoDetail; src: string; related: ShortDramaItem[]; }; function mapHotVideoItem(item: VideoData): ShortDramaItem { return { kind: "drama", id: String(item.id), slug: item.slug?.trim() || undefined, title: (item.title || "").trim() || "未命名", subtitle: "", tags: pickVideoCardTags(item), heat: formatHeat(item.watchNum), episodes: "", cover: (item.coverImg || "").trim(), date: item.addedTime || undefined, }; } /** 热门推荐:保留广告位;排除当前视频 */ export function mapVideoRecommendList( data: VideoRecommendListResp | null | undefined, options?: { excludeId?: number | string | null; limit?: number }, ): ShortDramaItem[] { const excludeId = options?.excludeId != null ? Number(options.excludeId) : NaN; const limit = options?.limit ?? VIDEO_RECOMMEND_DISPLAY_COUNT; return (data?.list ?? []) .filter((item) => { if (item.type === 2) return true; if (!item.id) return false; if (Number.isFinite(excludeId) && Number(item.id) === excludeId) return false; return true; }) .map(mapVideoListItem) .filter((item): item is ShortDramaItem => Boolean(item)) .slice(0, limit); } /** 透传接口字段,仅拼播放地址 / 根级点赞收藏态 */ export function mapVideoInfo(data: QueryVideoInfoResp | null | undefined): VideoPlayView | null { const info = data?.videoInfo; if (!info?.id) return null; const media = info.video; const enableH265 = Boolean(data?.config?.enableH265); const path = (enableH265 && media?.h265Url?.trim() ? media.h265Url : media?.url) || media?.h265Url || ""; const src = resolvePlayURL(path); return { detail: { ...info, isLike: Boolean(data?.isLike ?? info.isLike), isFavorite: Boolean(data?.isFavorite ?? info.isFavorite), }, src, related: (data?.hotVideoList ?? []) .filter((item) => Boolean(item.id)) .slice(0, RELATED_DISPLAY_COUNT) .map(mapHotVideoItem), }; } export function formatWatchNum(count?: number | null) { const value = Number(count) || 0; if (value >= 10000) { const wan = value / 10000; const text = wan >= 100 ? String(Math.round(wan)) : wan.toFixed(1).replace(/\.0$/, ""); return `${text}万次播放`; } return `${value}次播放`; } export function formatCount(count?: number | null) { const value = Number(count) || 0; if (value >= 10000) { const wan = value / 10000; const text = wan >= 100 ? String(Math.round(wan)) : wan.toFixed(1).replace(/\.0$/, ""); return `${text}万`; } if (value >= 1000) { const k = value / 1000; return `${k.toFixed(1).replace(/\.0$/, "")}k`; } return String(value); }