93 lines
3.0 KiB
TypeScript
93 lines
3.0 KiB
TypeScript
/**
|
||
* 模块配置 - 模块 > 视频教程 > [模块名]
|
||
* 参考 cloudphone/nomadlms 结构
|
||
*/
|
||
|
||
import { CURRICULUM_CONFIG } from "@/app/cloudphone/config/course";
|
||
|
||
export type TopicConfig = {
|
||
id: string;
|
||
icon: string;
|
||
title: string;
|
||
subtitle: string;
|
||
desc: string;
|
||
stats: { value: string; label: string }[];
|
||
/** 使用的 curriculum 模块索引,空则用全部 */
|
||
moduleIndices?: number[];
|
||
/** 外部链接,有则显示「前往了解」而非课程列表 */
|
||
externalUrl?: string;
|
||
payUrl: string;
|
||
};
|
||
|
||
export const TOPIC_CONFIGS: Record<string, TopicConfig> = {
|
||
cloudphone: {
|
||
id: "cloudphone",
|
||
icon: "☁️",
|
||
title: "云手机",
|
||
subtitle: "低成本自建云手机,TikTok/YouTube 运营搭建指南",
|
||
desc: "用开源硬件打造云手机,Redroid、AOSP、ffmpeg、SRS,从零搭建无人直播工作室",
|
||
stats: [
|
||
{ value: "13", label: "节实战课程" },
|
||
{ value: "170+", label: "分钟视频" },
|
||
{ value: "5", label: "大模块" },
|
||
],
|
||
payUrl: "/",
|
||
},
|
||
livestream: {
|
||
id: "livestream",
|
||
icon: "📺",
|
||
title: "无人直播",
|
||
subtitle: "TikTok/YouTube 无人直播,24 小时自动化",
|
||
desc: "ffmpeg 拉流转推、SRS 直播服务器、油猴脚本自动化,实现 24 小时无人值守推流",
|
||
stats: [
|
||
{ value: "7", label: "节核心课程" },
|
||
{ value: "100+", label: "分钟视频" },
|
||
{ value: "2", label: "大模块" },
|
||
],
|
||
moduleIndices: [1, 2],
|
||
payUrl: "/",
|
||
},
|
||
indie: {
|
||
id: "indie",
|
||
icon: "🛠️",
|
||
title: "独立开发",
|
||
subtitle: "从想法到产品,独立开发者全流程指南",
|
||
desc: "即将上线,敬请期待。可先前往数字游民指南了解更多。",
|
||
stats: [
|
||
{ value: "—", label: "课程筹备中" },
|
||
{ value: "—", label: "敬请期待" },
|
||
],
|
||
externalUrl: "https://digital.hackrobot.cn/zh",
|
||
payUrl: "/",
|
||
},
|
||
aiagent: {
|
||
id: "aiagent",
|
||
icon: "🤖",
|
||
title: "AI Agent",
|
||
subtitle: "AIGC 与智能体,Vibe Coding 跨界创造",
|
||
desc: "即将上线,敬请期待。可先前往数字游民指南了解更多。",
|
||
stats: [
|
||
{ value: "—", label: "课程筹备中" },
|
||
{ value: "—", label: "敬请期待" },
|
||
],
|
||
externalUrl: "https://digital.hackrobot.cn/zh",
|
||
payUrl: "/",
|
||
},
|
||
};
|
||
|
||
export function getTopicConfig(topicId: string): TopicConfig | null {
|
||
return TOPIC_CONFIGS[topicId] ?? null;
|
||
}
|
||
|
||
export function getTopicCurriculum(topicId: string) {
|
||
const config = getTopicConfig(topicId);
|
||
if (!config) return null;
|
||
if (config.externalUrl) return { modules: [], hasContent: false };
|
||
const indices = config.moduleIndices ?? CURRICULUM_CONFIG.modules.map((_, i) => i);
|
||
const modules = indices
|
||
.map((i) => ({ module: CURRICULUM_CONFIG.modules[i], originalIndex: i }))
|
||
.filter((x) => x.module)
|
||
.map(({ module: m, originalIndex }) => ({ ...m, originalModuleIndex: originalIndex }));
|
||
return { modules, hasContent: modules.length > 0 };
|
||
}
|