@@ -0,0 +1,104 @@
|
||||
import { pickVideoCardTags } from "@/components/common/card-tags";
|
||||
import { genres, regions, sorts, type Genre, type Region, type ShortDramaItem, type Sort } from "@/components/short-drama/data";
|
||||
import { formatHeat } from "@/components/ranking/data";
|
||||
import type { VideoCategoryListItem, VideoListItem, VideoListResp } from "@/lib/api/types";
|
||||
|
||||
export const VIDEO_PAGE_SIZE = 30;
|
||||
|
||||
export const videoSorts = sorts;
|
||||
export type VideoSort = Sort;
|
||||
|
||||
export function videoSortType(sort: VideoSort): 1 | 2 {
|
||||
return sort === "latest" ? 2 : 1;
|
||||
}
|
||||
|
||||
export function mapVideoListItem(item: VideoListItem): ShortDramaItem | null {
|
||||
if (item.type === 2) {
|
||||
return {
|
||||
kind: "ad",
|
||||
id: `ad-${item.advertiseId || item.id || item.link || "unknown"}`,
|
||||
title: (item.title || "").trim() || "广告",
|
||||
subtitle: "",
|
||||
cover: (item.coverImg || "").trim(),
|
||||
href: (item.link || "").trim() || undefined,
|
||||
};
|
||||
}
|
||||
|
||||
if (!item.id) return null;
|
||||
const slug = (item.slug || "").trim();
|
||||
return {
|
||||
kind: "drama",
|
||||
id: String(item.id),
|
||||
slug: slug || undefined,
|
||||
title: (item.title || "").trim() || "未命名",
|
||||
subtitle: "",
|
||||
tags: pickVideoCardTags(item),
|
||||
heat: formatHeat(item.watchNum),
|
||||
episodes: "",
|
||||
cover: (item.coverImg || "").trim(),
|
||||
};
|
||||
}
|
||||
|
||||
export type VideoListResult = {
|
||||
items: ShortDramaItem[];
|
||||
page: number;
|
||||
pageSize: number;
|
||||
totalCount: number;
|
||||
totalPages: number;
|
||||
sort: VideoSort;
|
||||
categories: VideoCategoryListItem[];
|
||||
categorySlug?: string;
|
||||
};
|
||||
|
||||
export function buildVideoList(
|
||||
data: VideoListResp | null | undefined,
|
||||
sort: VideoSort,
|
||||
fallbackPage = 1,
|
||||
fallbackPageSize = VIDEO_PAGE_SIZE,
|
||||
options?: { categories?: VideoCategoryListItem[]; categorySlug?: string },
|
||||
): VideoListResult {
|
||||
const page = data?.pageNum || fallbackPage;
|
||||
const pageSize = data?.pageSize || fallbackPageSize;
|
||||
const totalCount = data?.totalCount || 0;
|
||||
const items = (data?.list ?? [])
|
||||
.map(mapVideoListItem)
|
||||
.filter((item): item is ShortDramaItem => Boolean(item));
|
||||
|
||||
return {
|
||||
items,
|
||||
page,
|
||||
pageSize,
|
||||
totalCount,
|
||||
totalPages: Math.max(1, Math.ceil(totalCount / pageSize) || 1),
|
||||
sort,
|
||||
categories: options?.categories ?? [],
|
||||
categorySlug: options?.categorySlug,
|
||||
};
|
||||
}
|
||||
|
||||
/** @deprecated 本地 mock,供「更多」等未接接口页面临时使用 */
|
||||
const adSlots = new Set([5, 11, 17, 24, 25]);
|
||||
export function getVideos(genre: Genre, sort: Sort, page: number, region: Region = "全部"): ShortDramaItem[] {
|
||||
const seed = `${genres.indexOf(genre)}-${sorts.indexOf(sort)}-${regions.indexOf(region)}-${page}`;
|
||||
|
||||
return Array.from({ length: VIDEO_PAGE_SIZE }, (_, index): ShortDramaItem => {
|
||||
const id = `video-${seed}-${index}`;
|
||||
const cover = "";
|
||||
|
||||
if (adSlots.has(index)) {
|
||||
return { kind: "ad", id, title: "广告文案", subtitle: "我是副标题", cover };
|
||||
}
|
||||
|
||||
return {
|
||||
kind: "drama",
|
||||
id,
|
||||
title: "有恩必报",
|
||||
subtitle: "权谋交锋爱意藏在局中",
|
||||
tags: [{ name: genre === "全部" ? "标签" : genre }],
|
||||
heat: "25.8万 热度",
|
||||
episodes: "30集",
|
||||
badge: "original",
|
||||
cover,
|
||||
};
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user