151 lines
6.4 KiB
Python
151 lines
6.4 KiB
Python
#!/usr/bin/env python3
|
||
"""Rebuild redmini/src/data.js from backend mock data (offline snapshot)."""
|
||
from __future__ import annotations
|
||
|
||
import json
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
ROOT = Path(__file__).resolve().parents[2]
|
||
BACKEND = ROOT / "backend"
|
||
OUT = ROOT / "redmini" / "src" / "data.js"
|
||
|
||
sys.path.insert(0, str(BACKEND))
|
||
|
||
from app.data import community_data as c # noqa: E402
|
||
from app.data import digital_content as d # noqa: E402
|
||
from app.data import mock_data as m # noqa: E402
|
||
|
||
|
||
def main() -> int:
|
||
meetups = [
|
||
{k: v for k, v in x.items() if k not in ("mirotalkRoom", "loungeChannel", "meetingUrl")}
|
||
for x in c.MEETUPS
|
||
]
|
||
details = getattr(c, "DISCUSSION_DETAILS", {}) or {}
|
||
payload = {
|
||
"brand": "nomadro",
|
||
"tagline": "用一行代码环游世界",
|
||
"offlineNote": "小红书小程序无法联网。本包为官网内容离线镜像,收藏/计划仅保存在本机。完整互动请打开 nomadweb.nomadro.com",
|
||
"site": "https://nomadweb.nomadro.com",
|
||
"stats": {
|
||
"destinations": len(m.DESTINATIONS),
|
||
"visas": len(m.VISAS),
|
||
"meetups": len(meetups),
|
||
"blog": len(m.BLOG_POSTS),
|
||
"faqs": len(m.FAQS),
|
||
"total_nomads": "35.6M",
|
||
"countries": 195,
|
||
"satisfaction": 87,
|
||
"avg_cost": sum(d["cost"] for d in m.DESTINATIONS) // max(1, len(m.DESTINATIONS)) // 100,
|
||
"active_today": 127,
|
||
},
|
||
"ticker": m.TICKER_MESSAGES,
|
||
"rings": {
|
||
"explore": [
|
||
{"id": "destinations", "emoji": "🌴", "title": "目的地", "desc": "发现下一座城市"},
|
||
{"id": "visas", "emoji": "📋", "title": "签证指南", "desc": "远程友好签证"},
|
||
{"id": "matcher", "emoji": "🎯", "title": "智能匹配", "desc": "按预算气候排序"},
|
||
{"id": "compare", "emoji": "⚖️", "title": "城市对比", "desc": "并排看成本网速"},
|
||
],
|
||
"connect": [
|
||
{"id": "meetups", "emoji": "🎉", "title": "游民活动", "desc": "同城与线上"},
|
||
{"id": "community", "emoji": "💬", "title": "社区讨论", "desc": "签证住宿经验"},
|
||
{"id": "voices", "emoji": "🗣️", "title": "游民心声", "desc": "真实旅居评价"},
|
||
],
|
||
"grow": [
|
||
{"id": "digital", "emoji": "🎓", "title": "游民学院", "desc": "远程工作课程"},
|
||
{"id": "blog", "emoji": "📝", "title": "博客", "desc": "指南与攻略"},
|
||
{"id": "tools", "emoji": "🧰", "title": "工具箱", "desc": "费用估算等"},
|
||
{"id": "faq", "emoji": "❓", "title": "常见问题", "desc": "启动资金与保险"},
|
||
],
|
||
},
|
||
"lifestyle": {
|
||
"tag": "💻 NOMAD LIFE",
|
||
"title": "数字游民的一天",
|
||
"subtitle": "自由不等于散漫,高效工作才能尽情探索 — 点击卡片查看详情",
|
||
"ctaDay": "七天落地指南",
|
||
"ctaMeetups": "去参加活动",
|
||
"items": [
|
||
{
|
||
"key": "morning",
|
||
"time": "🌅 07:00",
|
||
"icon": "🧘",
|
||
"title": "晨间仪式",
|
||
"desc": "瑜伽、冥想或海边跑步,用身心唤醒开启新的一天",
|
||
"tip": "推荐:清迈河边晨跑、巴厘岛海滩瑜伽",
|
||
},
|
||
{
|
||
"key": "work",
|
||
"time": "☕ 09:00",
|
||
"icon": "💻",
|
||
"title": "深度工作",
|
||
"desc": "在 Co-working Space 或咖啡馆专注 4 小时,完成核心任务",
|
||
"tip": "推荐:Punspace 清迈、Outsite 里斯本",
|
||
},
|
||
{
|
||
"key": "explore",
|
||
"time": "🍜 13:00",
|
||
"icon": "🍽️",
|
||
"title": "本地探索",
|
||
"desc": "品尝地道美食,与当地人交流,感受文化碰撞",
|
||
"tip": "推荐:清迈夜市、巴塞罗那 Tapas 之旅",
|
||
},
|
||
{
|
||
"key": "collab",
|
||
"time": "🌇 17:00",
|
||
"icon": "📞",
|
||
"title": "跨时区协作",
|
||
"desc": "与全球团队视频会议,灵活安排跨时区沟通",
|
||
"tip": "工具:Calendly 排时区、World Time Buddy",
|
||
},
|
||
{
|
||
"key": "social",
|
||
"time": "🌙 20:00",
|
||
"icon": "🎉",
|
||
"title": "社群社交",
|
||
"desc": "参加 Nomad Meetup,结识来自世界各地的同行者",
|
||
"tip": "平台:nomadro 活动、同城社群",
|
||
},
|
||
],
|
||
},
|
||
"homeCommunity": {
|
||
"tag": "🤝 COMMUNITY",
|
||
"title": "游民心声",
|
||
"subtitle": "来自全球数字游民的真实故事",
|
||
},
|
||
"planChecklist": [
|
||
{"id": "visa", "label": "确认签证/停留天数"},
|
||
{"id": "flight", "label": "预订机票"},
|
||
{"id": "housing", "label": "首周短租/酒店"},
|
||
{"id": "sim", "label": "当地 SIM / eSIM"},
|
||
{"id": "cowork", "label": "踩点联合办公"},
|
||
{"id": "insurance", "label": "国际医疗保险"},
|
||
{"id": "budget", "label": "写下月预算"},
|
||
{"id": "meetup", "label": "报名一场同城活动"},
|
||
],
|
||
"destinations": m.DESTINATIONS,
|
||
"visas": m.VISAS,
|
||
"faqs": m.FAQS,
|
||
"testimonials": m.TESTIMONIALS,
|
||
"tools": m.TOOLS,
|
||
"blog": m.BLOG_POSTS,
|
||
"blogContent": m.BLOG_CONTENT,
|
||
"meetups": meetups,
|
||
"discussions": c.DISCUSSIONS,
|
||
"discussionDetails": details if isinstance(details, dict) else {},
|
||
"course": d.COURSE_MODULES,
|
||
"lessons": d.LESSONS,
|
||
"jobs": (d.JOBS[:8] if getattr(d, "JOBS", None) else []),
|
||
}
|
||
OUT.write_text(
|
||
"window.NOMADRO_DATA = " + json.dumps(payload, ensure_ascii=False, default=str) + ";\n",
|
||
encoding="utf-8",
|
||
)
|
||
print(f"wrote {OUT} ({OUT.stat().st_size} bytes)")
|
||
return 0
|
||
|
||
|
||
if __name__ == "__main__":
|
||
raise SystemExit(main())
|