121 lines
3.2 KiB
TypeScript
121 lines
3.2 KiB
TypeScript
import type {
|
|
ContentItem,
|
|
ListQuery,
|
|
ListResult,
|
|
SectionKey,
|
|
SinglePage,
|
|
} from "@/types/content";
|
|
import { products } from "@/data/products";
|
|
import { solutions } from "@/data/solutions";
|
|
import { cases } from "@/data/cases";
|
|
import { news } from "@/data/news";
|
|
import { events } from "@/data/events";
|
|
import { singlePages } from "@/data/pages";
|
|
|
|
/**
|
|
* 内容数据访问层
|
|
* 目前读取本地 mock 数据,接入后端 CMS 后只需把下面几个方法
|
|
* 换成 request.get("/cms/...") 即可,调用方无需改动。
|
|
*/
|
|
|
|
const registry: Record<SectionKey, ContentItem[]> = {
|
|
news,
|
|
products,
|
|
solutions,
|
|
cases,
|
|
events,
|
|
};
|
|
|
|
/** 模拟一次异步请求,保证调用方始终按异步处理 */
|
|
const tick = () => new Promise<void>((resolve) => setTimeout(resolve, 0));
|
|
|
|
/** 列表 / 分类 / 搜索(带分页) */
|
|
export async function fetchList(query: ListQuery): Promise<ListResult> {
|
|
await tick();
|
|
|
|
const { section, category, keyword, page = 1, pageSize = 6 } = query;
|
|
let list = [...(registry[section] ?? [])];
|
|
|
|
if (category) {
|
|
list = list.filter((item) => item.category === category);
|
|
}
|
|
|
|
const kw = keyword?.trim().toLowerCase();
|
|
if (kw) {
|
|
list = list.filter((item) =>
|
|
[item.title, item.subtitle, item.summary, ...(item.tags ?? [])]
|
|
.join(" ")
|
|
.toLowerCase()
|
|
.includes(kw)
|
|
);
|
|
}
|
|
|
|
list.sort((a, b) => (b.date ?? "").localeCompare(a.date ?? ""));
|
|
|
|
const total = list.length;
|
|
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
|
const safePage = Math.min(Math.max(1, page), totalPages);
|
|
const start = (safePage - 1) * pageSize;
|
|
|
|
return {
|
|
list: list.slice(start, start + pageSize),
|
|
total,
|
|
page: safePage,
|
|
pageSize,
|
|
totalPages,
|
|
};
|
|
}
|
|
|
|
/** 详情 */
|
|
export async function fetchDetail(
|
|
section: SectionKey,
|
|
slug: string
|
|
): Promise<ContentItem | undefined> {
|
|
await tick();
|
|
return (registry[section] ?? []).find((item) => item.slug === slug);
|
|
}
|
|
|
|
/** 相关推荐:同分类优先,不足时用同栏目其它内容补齐 */
|
|
export async function fetchRelated(
|
|
section: SectionKey,
|
|
slug: string,
|
|
limit = 3
|
|
): Promise<ContentItem[]> {
|
|
await tick();
|
|
|
|
const all = registry[section] ?? [];
|
|
const current = all.find((item) => item.slug === slug);
|
|
if (!current) return all.slice(0, limit);
|
|
|
|
const sameCategory = all.filter(
|
|
(item) => item.slug !== slug && item.category === current.category
|
|
);
|
|
const others = all.filter(
|
|
(item) => item.slug !== slug && item.category !== current.category
|
|
);
|
|
|
|
return [...sameCategory, ...others].slice(0, limit);
|
|
}
|
|
|
|
/** 统计各分类下的内容数量,用于筛选条上的角标 */
|
|
export async function fetchCategoryCounts(
|
|
section: SectionKey
|
|
): Promise<Record<string, number>> {
|
|
await tick();
|
|
|
|
const counts: Record<string, number> = {};
|
|
(registry[section] ?? []).forEach((item) => {
|
|
counts[item.category] = (counts[item.category] ?? 0) + 1;
|
|
});
|
|
counts.__all__ = (registry[section] ?? []).length;
|
|
return counts;
|
|
}
|
|
|
|
/** 单页:key 为去掉前导斜杠的路径,例如 about、support/docs */
|
|
export async function fetchSinglePage(
|
|
key: string
|
|
): Promise<SinglePage | undefined> {
|
|
await tick();
|
|
return singlePages[key];
|
|
}
|