/** * 模块配置 - 模块 > 视频教程 > [模块名] * 参考 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 = { 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 }; }