's'
This commit is contained in:
209
config/digital/course.ts
Normal file
209
config/digital/course.ts
Normal file
@@ -0,0 +1,209 @@
|
||||
/**
|
||||
* 课程落地页配置 - 数字游民主题(来自 nomadlms)
|
||||
*/
|
||||
|
||||
export const SITE_CONFIG = {
|
||||
brand: "🌍 数字游民",
|
||||
ctaUrl: "#",
|
||||
footer: "🌍 数字游民 © 2024 | 自由工作,自在生活",
|
||||
} as const;
|
||||
|
||||
export const HERO_CONFIG = {
|
||||
title: "数字游民实战课",
|
||||
subtitle: "从朝九晚五到边旅行边赚钱,开启你的自由人生",
|
||||
stats: [
|
||||
{ value: "21", label: "节实战课程" },
|
||||
{ value: "170+", label: "分钟视频" },
|
||||
{ value: "3", label: "位资深导师" },
|
||||
],
|
||||
} as const;
|
||||
|
||||
export const AUDIENCE_CONFIG = {
|
||||
title: "这门课适合谁?",
|
||||
subtitle: "向往自由,想用技能换时间与地点自由的人",
|
||||
items: [
|
||||
{
|
||||
emoji: "💻",
|
||||
title: "远程打工人",
|
||||
desc: "厌倦通勤,想在家或任何地方高效工作",
|
||||
},
|
||||
{
|
||||
emoji: "✈️",
|
||||
title: "旅行爱好者",
|
||||
desc: "想边旅行边赚钱,不再为假期发愁",
|
||||
},
|
||||
{
|
||||
emoji: "📱",
|
||||
title: "自由职业者",
|
||||
desc: "想建立被动收入,减少接单焦虑",
|
||||
},
|
||||
{
|
||||
emoji: "🌴",
|
||||
title: "生活方式探索者",
|
||||
desc: "想摆脱固定地点,体验不同城市与国家",
|
||||
},
|
||||
],
|
||||
} as const;
|
||||
|
||||
export const BENEFITS_CONFIG = {
|
||||
title: "学完你将获得",
|
||||
subtitle: "5大核心能力,助你成为真正的数字游民",
|
||||
items: [
|
||||
{
|
||||
num: "1",
|
||||
title: "远程工作技能体系",
|
||||
desc: "从技能选择到接单渠道,系统掌握远程变现能力",
|
||||
},
|
||||
{
|
||||
num: "2",
|
||||
title: "被动收入搭建方法",
|
||||
desc: "产品化你的技能,让收入不依赖时间",
|
||||
},
|
||||
{
|
||||
num: "3",
|
||||
title: "全球旅居实操指南",
|
||||
desc: "签证、住宿、网络、保险,一站式搞定",
|
||||
},
|
||||
{
|
||||
num: "4",
|
||||
title: "一人公司运营心法",
|
||||
desc: "从个人到团队,可持续的自由商业模式",
|
||||
},
|
||||
{
|
||||
num: "5",
|
||||
title: "数字游民社群与资源",
|
||||
desc: "加入同频社群,获取持续支持与灵感",
|
||||
},
|
||||
],
|
||||
} as const;
|
||||
|
||||
export const CURRICULUM_CONFIG = {
|
||||
title: "21节实战课程",
|
||||
subtitle: "从入门到进阶,完整成为数字游民",
|
||||
modules: [
|
||||
{
|
||||
emoji: "🚀",
|
||||
title: "基础篇 · 数字游民入门",
|
||||
lessons: [
|
||||
{ name: "01 什么是数字游民?你适合吗?", duration: "11:58" },
|
||||
{ name: "02 从朝九晚五到边旅行边赚钱的路径", duration: "14:32" },
|
||||
],
|
||||
},
|
||||
{
|
||||
emoji: "💼",
|
||||
title: "技能篇 · 远程变现能力",
|
||||
lessons: [
|
||||
{ name: "3.1 最适合远程的5大技能方向", duration: "06:25" },
|
||||
{ name: "3.2 如何打造你的技能组合与作品集", duration: "07:34" },
|
||||
],
|
||||
},
|
||||
{
|
||||
emoji: "💰",
|
||||
title: "收入篇 · 被动收入与副业",
|
||||
lessons: [
|
||||
{ name: "04 从接单到产品的思维转变", duration: "04:16" },
|
||||
{ name: "05 打造你的第一个数字产品", duration: "06:18" },
|
||||
{ name: "06 海外平台接单与变现", duration: "02:30" },
|
||||
{ name: "07 被动收入组合:课程+会员+咨询", duration: "06:25" },
|
||||
{ name: "08 如何定价才能既赚又自由", duration: "03:09" },
|
||||
],
|
||||
},
|
||||
{
|
||||
emoji: "🧠",
|
||||
title: "心态篇 · 自由与自律",
|
||||
lessons: [
|
||||
{ name: "09 数字游民的时间管理心法", duration: "07:49" },
|
||||
{ name: "09-1 独处与社交的平衡", duration: "01:24" },
|
||||
{ name: "10 如何应对家人的不理解", duration: "04:07" },
|
||||
],
|
||||
},
|
||||
{
|
||||
emoji: "⚡",
|
||||
title: "落地篇 · 旅居实操",
|
||||
lessons: [
|
||||
{ name: "11 签证与长期居留规划", duration: "04:12" },
|
||||
{ name: "12 住宿选择:短租、民宿、Co-living", duration: "05:19" },
|
||||
{ name: "13 网络、保险与紧急预案", duration: "04:11" },
|
||||
],
|
||||
},
|
||||
{
|
||||
emoji: "🎯",
|
||||
title: "实战篇 · 真实案例",
|
||||
lessons: [
|
||||
{ name: "14 巴厘岛数字游民社区探访", duration: "12:02" },
|
||||
{ name: "15 曼谷/清迈生活成本与体验", duration: "09:39" },
|
||||
{ name: "16 欧洲数字游民签证攻略", duration: "09:04" },
|
||||
{ name: "17 一人公司如何合法合规运营", duration: "05:12" },
|
||||
],
|
||||
},
|
||||
{
|
||||
emoji: "🏆",
|
||||
title: "进阶篇 · 高阶玩法",
|
||||
lessons: [
|
||||
{ name: "18 从一人到小团队的进化", duration: "11:25" },
|
||||
{ name: "19 建立你的数字游民品牌", duration: "25:57" },
|
||||
{ name: "20 年度旅居计划与预算规划", duration: "12:34" },
|
||||
{ name: "21 长期数字游民的可持续之道", duration: "08:53" },
|
||||
],
|
||||
},
|
||||
],
|
||||
} as const;
|
||||
|
||||
export const INSTRUCTORS_CONFIG = {
|
||||
title: "三位资深导师联合授课",
|
||||
subtitle: "异度世界、大师兄、小美带你开启数字游民之旅",
|
||||
items: [
|
||||
{
|
||||
name: "异度世界",
|
||||
role: "数字游民先行者",
|
||||
desc: "5年旅居经验,走过20+国家",
|
||||
tag: "课程主理",
|
||||
},
|
||||
{
|
||||
name: "大师兄",
|
||||
role: "一人公司实践者",
|
||||
desc: "远程自由职业转型教练",
|
||||
tag: "变现专家",
|
||||
},
|
||||
{
|
||||
name: "小美",
|
||||
role: "生活方式博主",
|
||||
desc: "边旅行边创作的斜杠青年",
|
||||
tag: "旅居达人",
|
||||
},
|
||||
],
|
||||
} as const;
|
||||
|
||||
export const CTA_CONFIG = {
|
||||
title: "准备好开启你的数字游民之旅了吗?",
|
||||
subtitle: "加入我们,跟着异度世界、大师兄、小美一起,从零开始实现自由人生",
|
||||
badges: ["21节实战视频", "永久回看", "社群答疑"],
|
||||
} as const;
|
||||
|
||||
/** FAQ 常见问题 */
|
||||
export const FAQ_CONFIG = {
|
||||
title: "常见问题",
|
||||
items: [
|
||||
{ q: "课程可以永久回看吗?", a: "可以,报名后永久有效,随时回看。" },
|
||||
{ q: "适合零基础吗?", a: "适合。课程从入门到进阶;视频试看暂时关闭,报名后可解锁全部章节。" },
|
||||
{ q: "有社群答疑吗?", a: "有,报名后加入专属社群,导师和同学一起交流。" },
|
||||
{ q: "支持退款吗?", a: "7 天内不满意可申请全额退款。" },
|
||||
],
|
||||
} as const;
|
||||
|
||||
/** 社群入口 */
|
||||
export const COMMUNITY_CONFIG = {
|
||||
enabled: true,
|
||||
wechat: "扫码加入数字游民社群",
|
||||
qrCodeUrl: "/qrcode-community.png",
|
||||
qq: "",
|
||||
link: "",
|
||||
} as const;
|
||||
|
||||
/** 章节底部网盘下载模块 */
|
||||
export const DOWNLOAD_CONFIG = {
|
||||
enabled: true,
|
||||
url: "https://pan.baidu.com/s/example",
|
||||
title: "课程资料下载",
|
||||
buttonText: "前往网盘下载",
|
||||
} as const;
|
||||
48
config/digital/domain.config.ts
Normal file
48
config/digital/domain.config.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* 域名与根域配置 - 特色标识
|
||||
* 更换域名(如 *.hackrobot.cn -> *.nomadro.com)时,只需设置 ROOT_DOMAIN 或各独立变量
|
||||
*
|
||||
* 环境变量:
|
||||
* - ROOT_DOMAIN: 根域名,如 nomadro.com,用于推导 Cookie、API 等默认值
|
||||
* - AUTH_COOKIE_DOMAIN: Cookie 根域,如 .nomadro.com(优先于 ROOT_DOMAIN)
|
||||
* - PAYMENT_API_URL: 支付 API 地址
|
||||
* - NEXT_PUBLIC_POCKETBASE_URL: PocketBase 地址
|
||||
* - NEXT_PUBLIC_SITE_URL: 站点根地址
|
||||
*/
|
||||
|
||||
const isDev = process.env.NODE_ENV === "development";
|
||||
|
||||
/** 根域名,用于推导默认值。如 nomadro.com、hackrobot.cn */
|
||||
export const ROOT_DOMAIN =
|
||||
process.env.ROOT_DOMAIN || process.env.NEXT_PUBLIC_ROOT_DOMAIN || "hackrobot.cn";
|
||||
|
||||
/** 支付 API 默认地址。生产环境固定为 api.${ROOT_DOMAIN},避免 .env 中 127.0.0.1 导致支付失败 */
|
||||
export const DEFAULT_PAYMENT_API_URL = isDev
|
||||
? "http://127.0.0.1:8007"
|
||||
: `https://api.${ROOT_DOMAIN}`;
|
||||
|
||||
/** 生产环境若 PAYMENT_API_URL 指向 localhost,则忽略并使用 api 域名 */
|
||||
export function resolvePaymentApiUrl(): string {
|
||||
const url = process.env.PAYMENT_API_URL || DEFAULT_PAYMENT_API_URL;
|
||||
if (!isDev && /^(https?:\/\/)?(127\.0\.0\.1|localhost)(:\d+)?(\/|$)/i.test(url)) {
|
||||
return `https://api.${ROOT_DOMAIN}`;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
/** PocketBase 默认地址 */
|
||||
export const DEFAULT_POCKETBASE_URL = `https://pocketbase.${ROOT_DOMAIN}`;
|
||||
|
||||
/** 站点根地址默认值 */
|
||||
export const DEFAULT_SITE_URL = isDev
|
||||
? "http://localhost:3001"
|
||||
: `https://${ROOT_DOMAIN}`;
|
||||
|
||||
/** MinIO 端点默认主机 */
|
||||
export const DEFAULT_MINIO_HOST = `minioweb.${ROOT_DOMAIN}`;
|
||||
|
||||
/** meetup(目的地)站链接 */
|
||||
export const MEETUP_URL = `https://meetup.${ROOT_DOMAIN}/`;
|
||||
|
||||
/** vip(异度星球)站链接 */
|
||||
export const VIP_URL = `https://vip.${ROOT_DOMAIN}/`;
|
||||
18
config/digital/index.ts
Normal file
18
config/digital/index.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export {
|
||||
CURRENT_THEME,
|
||||
THEME_IDS,
|
||||
THEME_CONFIGS,
|
||||
TOPIC_IDS,
|
||||
getThemeConfig,
|
||||
type ThemeId,
|
||||
type ThemeConfig,
|
||||
type TopicId,
|
||||
} from "./site.config";
|
||||
|
||||
export {
|
||||
getPocketBaseConfig,
|
||||
getPaymentConfig,
|
||||
getJoinPaymentConfig,
|
||||
getServicesConfig,
|
||||
} from "./services.config";
|
||||
export type { PocketBaseConfig, PaymentConfig, ServicesConfig } from "./services.config";
|
||||
112
config/digital/lessons.ts
Normal file
112
config/digital/lessons.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* 课程章节详情配置 - 数字游民主题(来自 nomadlms)
|
||||
*/
|
||||
|
||||
const SAMPLE_VIDEO = "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4";
|
||||
|
||||
const SAMPLE_MARKDOWN = `# 课程概述
|
||||
|
||||
本小节将带你理解数字游民的核心概念,掌握关键技能。
|
||||
|
||||
## 学习目标
|
||||
|
||||
- 理解数字游民的本质与生活方式
|
||||
- 掌握远程变现的基础路径
|
||||
- 完成个人定位与规划
|
||||
|
||||
## 核心要点
|
||||
|
||||
1. **定义**:数字游民 = 远程工作 + 自由旅行 + 地点独立
|
||||
2. **技能**:选择可远程交付的技能方向
|
||||
3. **心态**:自律与自由是相辅相成的
|
||||
|
||||
## 行动清单
|
||||
|
||||
- [ ] 评估自己的技能是否可远程交付
|
||||
- [ ] 列出3个你想旅居的城市
|
||||
- [ ] 设定6个月内的转型目标
|
||||
|
||||
### 代码示例
|
||||
|
||||
\`\`\`bash
|
||||
# 安装依赖
|
||||
pnpm install
|
||||
|
||||
# 启动开发
|
||||
pnpm dev
|
||||
\`\`\`
|
||||
|
||||
行内代码示例:\`npm run build\` 可生成生产版本。
|
||||
|
||||
## 注意事项
|
||||
|
||||
> 数字游民不是逃避,而是主动选择。建议先有稳定收入再考虑长期旅居。
|
||||
|
||||
| 项目 | 说明 |
|
||||
|------|------|
|
||||
| 收入 | 建议月收入稳定在 1 万以上 |
|
||||
| 技能 | 至少 1 项可远程交付 |
|
||||
| 心态 | 自律与自由平衡 |
|
||||
`;
|
||||
|
||||
export type LessonDetail = {
|
||||
name: string;
|
||||
duration: string;
|
||||
videoUrl: string;
|
||||
markdown: string;
|
||||
};
|
||||
|
||||
/** 扁平化课程数据:moduleIndex-lessonIndex 作为 key */
|
||||
export const LESSONS_MAP: Record<string, LessonDetail> = {
|
||||
"0-0": {
|
||||
name: "01 什么是数字游民?你适合吗?",
|
||||
duration: "11:58",
|
||||
videoUrl: SAMPLE_VIDEO,
|
||||
markdown: SAMPLE_MARKDOWN.replace("本小节", "本节").replace("核心概念", "数字游民的定义与自我评估"),
|
||||
},
|
||||
"0-1": {
|
||||
name: "02 从朝九晚五到边旅行边赚钱的路径",
|
||||
duration: "14:32",
|
||||
videoUrl: SAMPLE_VIDEO,
|
||||
markdown: SAMPLE_MARKDOWN.replace("本小节", "本节").replace("核心概念", "从上班族到数字游民的转型路径"),
|
||||
},
|
||||
"1-0": {
|
||||
name: "3.1 最适合远程的5大技能方向",
|
||||
duration: "06:25",
|
||||
videoUrl: SAMPLE_VIDEO,
|
||||
markdown: SAMPLE_MARKDOWN.replace("本小节", "本节").replace("核心概念", "编程、设计、写作、营销、咨询等远程技能"),
|
||||
},
|
||||
"1-1": {
|
||||
name: "3.2 如何打造你的技能组合与作品集",
|
||||
duration: "07:34",
|
||||
videoUrl: SAMPLE_VIDEO,
|
||||
markdown: SAMPLE_MARKDOWN.replace("本小节", "本节").replace("核心概念", "作品集搭建与个人品牌展示"),
|
||||
},
|
||||
"2-0": { name: "04 从接单到产品的思维转变", duration: "04:16", videoUrl: SAMPLE_VIDEO, markdown: SAMPLE_MARKDOWN },
|
||||
"2-1": { name: "05 打造你的第一个数字产品", duration: "06:18", videoUrl: SAMPLE_VIDEO, markdown: SAMPLE_MARKDOWN },
|
||||
"2-2": { name: "06 海外平台接单与变现", duration: "02:30", videoUrl: SAMPLE_VIDEO, markdown: SAMPLE_MARKDOWN },
|
||||
"2-3": { name: "07 被动收入组合:课程+会员+咨询", duration: "06:25", videoUrl: SAMPLE_VIDEO, markdown: SAMPLE_MARKDOWN },
|
||||
"2-4": { name: "08 如何定价才能既赚又自由", duration: "03:09", videoUrl: SAMPLE_VIDEO, markdown: SAMPLE_MARKDOWN },
|
||||
"3-0": { name: "09 数字游民的时间管理心法", duration: "07:49", videoUrl: SAMPLE_VIDEO, markdown: SAMPLE_MARKDOWN },
|
||||
"3-1": { name: "09-1 独处与社交的平衡", duration: "01:24", videoUrl: SAMPLE_VIDEO, markdown: SAMPLE_MARKDOWN },
|
||||
"3-2": { name: "10 如何应对家人的不理解", duration: "04:07", videoUrl: SAMPLE_VIDEO, markdown: SAMPLE_MARKDOWN },
|
||||
"4-0": { name: "11 签证与长期居留规划", duration: "04:12", videoUrl: SAMPLE_VIDEO, markdown: SAMPLE_MARKDOWN },
|
||||
"4-1": { name: "12 住宿选择:短租、民宿、Co-living", duration: "05:19", videoUrl: SAMPLE_VIDEO, markdown: SAMPLE_MARKDOWN },
|
||||
"4-2": { name: "13 网络、保险与紧急预案", duration: "04:11", videoUrl: SAMPLE_VIDEO, markdown: SAMPLE_MARKDOWN },
|
||||
"5-0": { name: "14 巴厘岛数字游民社区探访", duration: "12:02", videoUrl: SAMPLE_VIDEO, markdown: SAMPLE_MARKDOWN },
|
||||
"5-1": { name: "15 曼谷/清迈生活成本与体验", duration: "09:39", videoUrl: SAMPLE_VIDEO, markdown: SAMPLE_MARKDOWN },
|
||||
"5-2": { name: "16 欧洲数字游民签证攻略", duration: "09:04", videoUrl: SAMPLE_VIDEO, markdown: SAMPLE_MARKDOWN },
|
||||
"5-3": { name: "17 一人公司如何合法合规运营", duration: "05:12", videoUrl: SAMPLE_VIDEO, markdown: SAMPLE_MARKDOWN },
|
||||
"6-0": { name: "18 从一人到小团队的进化", duration: "11:25", videoUrl: SAMPLE_VIDEO, markdown: SAMPLE_MARKDOWN },
|
||||
"6-1": { name: "19 建立你的数字游民品牌", duration: "25:57", videoUrl: SAMPLE_VIDEO, markdown: SAMPLE_MARKDOWN },
|
||||
"6-2": { name: "20 年度旅居计划与预算规划", duration: "12:34", videoUrl: SAMPLE_VIDEO, markdown: SAMPLE_MARKDOWN },
|
||||
"6-3": { name: "21 长期数字游民的可持续之道", duration: "08:53", videoUrl: SAMPLE_VIDEO, markdown: SAMPLE_MARKDOWN },
|
||||
};
|
||||
|
||||
export function getLessonKey(moduleIndex: number, lessonIndex: number): string {
|
||||
return `${moduleIndex}-${lessonIndex}`;
|
||||
}
|
||||
|
||||
export function getLesson(moduleIndex: number, lessonIndex: number): LessonDetail | null {
|
||||
return LESSONS_MAP[getLessonKey(moduleIndex, lessonIndex)] ?? null;
|
||||
}
|
||||
156
config/digital/services.config.ts
Normal file
156
config/digital/services.config.ts
Normal file
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* 服务配置 - PocketBase、支付等第三方服务
|
||||
* 可通过环境变量覆盖,不同主题可配置不同集合/金额
|
||||
* 域名更换:设置 ROOT_DOMAIN(如 nomadro.com)可推导默认 API 地址
|
||||
*/
|
||||
|
||||
import { getThemeConfig } from "./site.config";
|
||||
import {
|
||||
DEFAULT_PAYMENT_API_URL,
|
||||
resolvePaymentApiUrl,
|
||||
DEFAULT_POCKETBASE_URL,
|
||||
DEFAULT_MINIO_HOST,
|
||||
} from "./domain.config";
|
||||
|
||||
export interface PocketBaseConfig {
|
||||
enabled: boolean;
|
||||
/** PocketBase 服务地址 */
|
||||
url: string;
|
||||
/** 用户认证集合 */
|
||||
usersCollection: string;
|
||||
/** 申请/加入表单集合(如 solan、applications) */
|
||||
joinCollection: string;
|
||||
}
|
||||
|
||||
export interface PaymentConfig {
|
||||
enabled: boolean;
|
||||
/** 支付 API 地址(payjsapi) */
|
||||
apiUrl: string;
|
||||
/** 支付提供商:zpay | xorpay */
|
||||
provider: "zpay" | "xorpay";
|
||||
/** 默认金额(分) */
|
||||
defaultAmount: number;
|
||||
/** 默认订单类型 */
|
||||
defaultType: string;
|
||||
/** ZPAY 提交地址 */
|
||||
zpaySubmitUrl: string;
|
||||
}
|
||||
|
||||
export interface MinioConfig {
|
||||
enabled: boolean;
|
||||
/** MinIO 服务端点 */
|
||||
endPoint: string;
|
||||
/** 端口 */
|
||||
port: number;
|
||||
/** 是否使用 SSL */
|
||||
useSSL: boolean;
|
||||
/** 存储桶 */
|
||||
bucket: string;
|
||||
/** Access Key */
|
||||
accessKey: string;
|
||||
/** Secret Key */
|
||||
secretKey: string;
|
||||
/** 区域 */
|
||||
region: string;
|
||||
/** 公开访问 URL(用于生成文件链接) */
|
||||
publicUrl: string;
|
||||
/** 上传路径前缀(如 joins、uploads) */
|
||||
uploadPrefix: string;
|
||||
}
|
||||
|
||||
export interface ServicesConfig {
|
||||
pocketbase: PocketBaseConfig;
|
||||
payment: PaymentConfig;
|
||||
minio: MinioConfig;
|
||||
}
|
||||
|
||||
const isDev = process.env.NODE_ENV === "development";
|
||||
const PAYJSAPI_PORT = process.env.PAYJSAPI_PORT || "8007";
|
||||
|
||||
/** 站点标识,用于 VIP 按站点隔离。digital 专题站(ai.xx/android.xx)各自独立,如 digital_ai、digital_android */
|
||||
export const SITE_ID = process.env.NEXT_PUBLIC_SITE_ID || "digital";
|
||||
|
||||
/** vip 站(vip.hackrobot.cn)的 site_id,其付费 VIP 可解锁所有 digital 专题站 */
|
||||
export const VIP_MASTER_SITE_ID = "vip";
|
||||
|
||||
export function getApiUrlFromRequest(hostHeader: string | null): string | null {
|
||||
if (!hostHeader) return null;
|
||||
if (!isDev) return resolvePaymentApiUrl();
|
||||
const hostname = hostHeader.split(":")[0];
|
||||
return `http://${hostname}:${PAYJSAPI_PORT}`;
|
||||
}
|
||||
|
||||
/** 获取 PocketBase 配置(可传入主题覆盖) */
|
||||
export function getPocketBaseConfig(themeOverride?: { joinCollection?: string }): PocketBaseConfig {
|
||||
const joinCollection =
|
||||
themeOverride?.joinCollection ||
|
||||
process.env.POCKETBASE_JOIN_COLLECTION ||
|
||||
"solan";
|
||||
return {
|
||||
enabled: true,
|
||||
url: process.env.NEXT_PUBLIC_POCKETBASE_URL || process.env.POCKETBASE_URL || DEFAULT_POCKETBASE_URL,
|
||||
usersCollection: "users",
|
||||
joinCollection,
|
||||
};
|
||||
}
|
||||
|
||||
/** 获取支付配置(可传入主题覆盖,如 join 金额/类型) */
|
||||
export function getPaymentConfig(themeOverride?: { amount?: number; type?: string }): PaymentConfig {
|
||||
const base = {
|
||||
enabled: true,
|
||||
apiUrl: resolvePaymentApiUrl(),
|
||||
provider: (process.env.PAYMENT_PROVIDER as "zpay" | "xorpay") || "zpay",
|
||||
defaultAmount: Number(process.env.PAYMENT_DEFAULT_AMOUNT) || 8800,
|
||||
defaultType: process.env.PAYMENT_DEFAULT_TYPE || "meetup",
|
||||
zpaySubmitUrl: process.env.ZPAY_SUBMIT_URL || "https://zpayz.cn/submit.php",
|
||||
};
|
||||
if (themeOverride) {
|
||||
if (themeOverride.amount != null) base.defaultAmount = themeOverride.amount;
|
||||
if (themeOverride.type) base.defaultType = themeOverride.type;
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
/** 获取 MinIO 配置(可传入主题覆盖 bucket/prefix) */
|
||||
export function getMinioConfig(themeOverride?: { bucket?: string; uploadPrefix?: string }): MinioConfig {
|
||||
const endPoint = process.env.MINIO_ENDPOINT || DEFAULT_MINIO_HOST;
|
||||
const port = parseInt(process.env.MINIO_PORT || "9035", 10);
|
||||
const useSSL = process.env.MINIO_USE_SSL === "true";
|
||||
const bucket = themeOverride?.bucket || process.env.MINIO_BUCKET || "hackrobot";
|
||||
const publicUrl =
|
||||
process.env.MINIO_PUBLIC_URL ||
|
||||
`https://${endPoint}/${bucket}`;
|
||||
const uploadPrefix = themeOverride?.uploadPrefix || process.env.MINIO_UPLOAD_PREFIX || "joins";
|
||||
|
||||
return {
|
||||
enabled: true,
|
||||
endPoint,
|
||||
port,
|
||||
useSSL,
|
||||
bucket,
|
||||
accessKey: process.env.MINIO_ACCESS_KEY || "6i56HHfg4zPfYItCZtnp",
|
||||
secretKey: process.env.MINIO_SECRET_KEY || "vDJCqEit3ejH5UmWKAZnvqhziNfbVsoOlBW12G8Q",
|
||||
region: process.env.MINIO_REGION || "china",
|
||||
publicUrl: publicUrl.replace(/\/$/, ""),
|
||||
uploadPrefix,
|
||||
};
|
||||
}
|
||||
|
||||
/** 获取完整服务配置 */
|
||||
export function getServicesConfig(): ServicesConfig {
|
||||
return {
|
||||
pocketbase: getPocketBaseConfig(),
|
||||
payment: getPaymentConfig(),
|
||||
minio: getMinioConfig(),
|
||||
};
|
||||
}
|
||||
|
||||
/** 获取「加入/申请」场景的支付配置(含主题覆盖) */
|
||||
export function getJoinPaymentConfig(): { amount: number; type: string } {
|
||||
const theme = getThemeConfig();
|
||||
const payment = getPaymentConfig();
|
||||
return {
|
||||
amount: theme.services?.join?.amount ?? payment.defaultAmount,
|
||||
type: theme.services?.join?.type ?? payment.defaultType,
|
||||
};
|
||||
}
|
||||
193
config/digital/site.config.ts
Normal file
193
config/digital/site.config.ts
Normal file
@@ -0,0 +1,193 @@
|
||||
/**
|
||||
* 站点模板配置 - 切换主题只需修改 CURRENT_THEME
|
||||
* 克隆新主题:复制 themes/digital-nomad 为 themes/your-theme,修改配置和内容
|
||||
*/
|
||||
|
||||
/** 专题 ID:子域名部署 + 项目复制架构(资源导航中带「专题」标记) */
|
||||
export const TOPIC_IDS = ["indieDev", "aiAgent", "cloudPhone", "unmannedLive"] as const;
|
||||
|
||||
export type TopicId = (typeof TOPIC_IDS)[number];
|
||||
|
||||
export const THEME_IDS = [
|
||||
"digital-nomad",
|
||||
"solo-company",
|
||||
"tiktok-ops",
|
||||
"indie-dev",
|
||||
] as const;
|
||||
|
||||
export type ThemeId = (typeof THEME_IDS)[number];
|
||||
|
||||
export const CURRENT_THEME: ThemeId =
|
||||
(process.env.NEXT_PUBLIC_THEME as ThemeId) || "digital-nomad";
|
||||
|
||||
export interface ThemeConfig {
|
||||
id: ThemeId;
|
||||
name: string;
|
||||
nameEn: string;
|
||||
tagline: string;
|
||||
taglineEn: string;
|
||||
/** SEO 元数据 */
|
||||
meta: {
|
||||
title: string;
|
||||
description: string;
|
||||
};
|
||||
/** 功能开关 */
|
||||
features: {
|
||||
roadmap: boolean;
|
||||
tools: boolean;
|
||||
community: boolean;
|
||||
join: boolean;
|
||||
course: boolean;
|
||||
ebook: boolean;
|
||||
};
|
||||
/** 品牌色 - Tailwind 类名 */
|
||||
colors: {
|
||||
primary: string;
|
||||
accent: string;
|
||||
};
|
||||
/** 服务配置覆盖(可选) */
|
||||
services?: {
|
||||
/** 加入/申请支付 */
|
||||
join?: {
|
||||
amount?: number;
|
||||
type?: string;
|
||||
};
|
||||
/** PocketBase 申请集合名 */
|
||||
pocketbaseJoinCollection?: string;
|
||||
/** MinIO 存储(可选) */
|
||||
minio?: {
|
||||
bucket?: string;
|
||||
uploadPrefix?: string;
|
||||
};
|
||||
/** 电商独立站域名(可选,配置后显示电商卡片) */
|
||||
shopUrl?: string;
|
||||
};
|
||||
/** 关于我们:Linktree 链接(可选) */
|
||||
linktreeUrl?: string;
|
||||
/** 社交平台链接(用于关于页展示) */
|
||||
socialLinks?: Array<{ platform: string; label: string; url: string; group?: "domestic" | "overseas" }>;
|
||||
/** 团队成员(可选) */
|
||||
teamMembers?: Array<{ name: string; role: string; avatar?: string; link?: string }>;
|
||||
}
|
||||
|
||||
export const THEME_CONFIGS: Record<ThemeId, ThemeConfig> = {
|
||||
"digital-nomad": {
|
||||
id: "digital-nomad",
|
||||
name: "数字游民指南",
|
||||
nameEn: "Digital Nomad Guide",
|
||||
tagline: "数字游民资源平台",
|
||||
taglineEn: "Digital nomad resource platform",
|
||||
meta: {
|
||||
title: "数字游民指南 | Digital Nomad Guide",
|
||||
description:
|
||||
"从零开始,7天开启你的数字游民生活。远程工作、地点自由、技能变现 —— 一站式数字游民资源平台。",
|
||||
},
|
||||
features: {
|
||||
roadmap: true,
|
||||
tools: true,
|
||||
community: true,
|
||||
join: true,
|
||||
course: true,
|
||||
ebook: true,
|
||||
},
|
||||
colors: {
|
||||
primary: "sky",
|
||||
accent: "amber",
|
||||
},
|
||||
services: {
|
||||
join: { amount: 8800, type: "meetup" },
|
||||
pocketbaseJoinCollection: "solan",
|
||||
shopUrl: process.env.NEXT_PUBLIC_SHOP_URL || "https://store.hackrobot.cn/", // 独立站域名
|
||||
},
|
||||
linktreeUrl: process.env.NEXT_PUBLIC_LINKTREE_URL || "https://linktr.ee/digitalnomad",
|
||||
socialLinks: [
|
||||
{ platform: "douyin", label: "抖音", url: "https://www.douyin.com", group: "domestic" },
|
||||
{ platform: "wechat-official", label: "微信公众号", url: "https://mp.weixin.qq.com", group: "domestic" },
|
||||
{ platform: "xiaohongshu", label: "小红书", url: "https://www.xiaohongshu.com", group: "domestic" },
|
||||
{ platform: "tiktok", label: "TikTok", url: "https://www.tiktok.com", group: "overseas" },
|
||||
{ platform: "youtube", label: "YouTube 频道", url: "https://www.youtube.com", group: "overseas" },
|
||||
{ platform: "twitter", label: "X", url: "https://x.com", group: "overseas" },
|
||||
],
|
||||
teamMembers: [
|
||||
{ name: "成员 A", role: "发起人", link: "#" },
|
||||
{ name: "成员 B", role: "内容运营", link: "#" },
|
||||
{ name: "成员 C", role: "技术开发", link: "#" },
|
||||
],
|
||||
},
|
||||
"solo-company": {
|
||||
id: "solo-company",
|
||||
name: "一人公司指南",
|
||||
nameEn: "Solo Company Guide",
|
||||
tagline: "一人公司创业与运营指南",
|
||||
taglineEn: "Guide to building and running a solo company",
|
||||
meta: {
|
||||
title: "一人公司指南 | Solo Company Guide",
|
||||
description:
|
||||
"从零到一,打造属于你的一人公司。产品、营销、运营 —— 一人公司全流程指南。",
|
||||
},
|
||||
features: {
|
||||
roadmap: true,
|
||||
tools: true,
|
||||
community: true,
|
||||
join: false,
|
||||
course: false,
|
||||
ebook: true,
|
||||
},
|
||||
colors: {
|
||||
primary: "violet",
|
||||
accent: "emerald",
|
||||
},
|
||||
},
|
||||
"tiktok-ops": {
|
||||
id: "tiktok-ops",
|
||||
name: "TikTok 运营指南",
|
||||
nameEn: "TikTok Operations Guide",
|
||||
tagline: "TikTok 出海运营与变现指南",
|
||||
taglineEn: "TikTok operations and monetization guide",
|
||||
meta: {
|
||||
title: "TikTok 运营指南 | TikTok Operations Guide",
|
||||
description:
|
||||
"TikTok 账号运营、内容创作、广告投放、跨境变现 —— 一站式 TikTok 出海指南。",
|
||||
},
|
||||
features: {
|
||||
roadmap: true,
|
||||
tools: true,
|
||||
community: true,
|
||||
join: false,
|
||||
course: true,
|
||||
ebook: true,
|
||||
},
|
||||
colors: {
|
||||
primary: "pink",
|
||||
accent: "cyan",
|
||||
},
|
||||
},
|
||||
"indie-dev": {
|
||||
id: "indie-dev",
|
||||
name: "独立开发指南",
|
||||
nameEn: "Indie Developer Guide",
|
||||
tagline: "独立开发者产品与变现指南",
|
||||
taglineEn: "Indie developer product and monetization guide",
|
||||
meta: {
|
||||
title: "独立开发指南 | Indie Developer Guide",
|
||||
description:
|
||||
"从想法到产品,独立开发全流程。技术选型、产品设计、上线运营 —— 独立开发者必备指南。",
|
||||
},
|
||||
features: {
|
||||
roadmap: true,
|
||||
tools: true,
|
||||
community: true,
|
||||
join: false,
|
||||
course: false,
|
||||
ebook: true,
|
||||
},
|
||||
colors: {
|
||||
primary: "indigo",
|
||||
accent: "orange",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export function getThemeConfig(): ThemeConfig {
|
||||
return THEME_CONFIGS[CURRENT_THEME];
|
||||
}
|
||||
@@ -17,7 +17,7 @@ export const FOOTER_SECTIONS: FooterSection[] = [
|
||||
titleKey: "about",
|
||||
links: [
|
||||
{ href: "/about", labelKey: "aboutUs" },
|
||||
{ href: "https://digital.hackrobot.cn/", labelKey: "digitalNomadGuide" },
|
||||
{ href: "/digital", labelKey: "digitalNomadGuide" },
|
||||
{ href: "/careers", labelKey: "careers" },
|
||||
{ href: "/press", labelKey: "press" },
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user