Files
2026-03-13 21:38:04 -05:00

93 lines
3.0 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 模块配置 - 模块 > 视频教程 > [模块名]
* 参考 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 };
}