nomadweb/redmini/scripts/build_data.py
eric 2bcbc303d8 Fix redmini lifestyle/voices/FAQ to use real H5 DOM classes.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-27 13:20:01 -05:00

151 lines
6.4 KiB
Python
Raw 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.

#!/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())