Files
web_hghl_h5/src/components/video-play/data.ts
T
2026-10-26 19:51:59 +07:00

107 lines
3.3 KiB
TypeScript

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);
}