's'
This commit is contained in:
146
README.md
146
README.md
@@ -20,8 +20,10 @@ NomadCNA 的目标用户是正在中国或亚洲范围内长期旅居、远程
|
||||
| --- | --- |
|
||||
| 城市探索 | 展示中国数字游民城市数据,包括生活成本、网络、温度、社群密度、安全、文化等指标。 |
|
||||
| 下一站决策 | 根据预算、网络、气候、标签偏好生成城市推荐。 |
|
||||
| 线上/线下活动 | 支持公开、登录成员、VIP、主持人等权限层级;线上和混合活动可进入 MiroTalk 视频房。 |
|
||||
| Web 群聊 | 使用 The Lounge + Ergo IRC Server 提供数字游民 Web 群组聊天,活动参与人可进入群聊。 |
|
||||
| 线上/线下活动 | 支持公开、登录成员、VIP、主持人等权限层级;线上/混合活动进入 **统一活动间**(MiroTalk 视频 + The Lounge 群聊分屏),账户昵称自动带入视频房。 |
|
||||
| Web 群聊 | The Lounge + Ergo IRC;每活动可配置 `loungeChannel`(如 `#nomadcna-20260608`),默认频道 `#nomadcna,#online-events`。 |
|
||||
| 访谈视频 | `/videos` 博主访谈列表,`/videos/[slug]` 单条详情;首页「访谈视频」链到列表页。 |
|
||||
| 社区匹配 | `/dating` 滑动匹配:意图 Tab、城市筛选、互赞、每日额度、高级筛选、撤销滑动。 |
|
||||
| 会员加入与支付 | 支持加入表单、支付订单、支付状态轮询、VIP/会员写入。 |
|
||||
| Digital 子站 | `/digital` 是内容专题站,包含数字游民指南、课程、电子书、资源、工作机会、个人资料等。 |
|
||||
| 媒体与内容 | 支持图片/视频上传、远程媒体代理缓存、内容投稿、博客、电子书、视频等内容页面。 |
|
||||
@@ -58,6 +60,8 @@ NomadCNA 的目标用户是正在中国或亚洲范围内长期旅居、远程
|
||||
│ └── lib/ # API、支付、媒体、活动、PocketBase 等工具
|
||||
├── backend/ # FastAPI 后端
|
||||
├── config/ # 主站和 Digital 子站配置
|
||||
│ └── remote-services.ts # 线上服务地址、Windows 远程开发模式
|
||||
├── scripts/ # dev-tunnel.py、dev-windows.ps1
|
||||
├── i18n/ # 路由和国际化导航封装
|
||||
├── messages/ # zh/en 文案
|
||||
├── public/ # 静态资源
|
||||
@@ -73,9 +77,13 @@ NomadCNA 的目标用户是正在中国或亚洲范围内长期旅居、远程
|
||||
|
||||
- `/zh`、`/en`:首页与城市探索
|
||||
- `/zh/dashboard`:下一站决策仪表盘
|
||||
- `/zh/meetups`:线上/线下活动,含 MiroTalk 视频房和 Web 群聊入口
|
||||
- `/zh/meetups`:线上/线下活动列表与详情弹窗
|
||||
- `/zh/meetups/host`:活动发布页
|
||||
- `/zh/dating`:社区交友/匹配
|
||||
- `/zh/meetups/[id]/live`:**统一活动间**(内嵌 MiroTalk + The Lounge,需权限)
|
||||
- `/zh/videos`:博主访谈视频列表
|
||||
- `/zh/videos/[slug]`:单条访谈详情
|
||||
- `/zh/dating`:社区滑动匹配(意图、城市、互赞、额度)
|
||||
- `/zh/join`:成员加入(城市、寻找意图、资料)
|
||||
- `/zh/discuss`:讨论
|
||||
- `/zh/gigs`:任务赏金
|
||||
- `/zh/tools`:工具箱
|
||||
@@ -154,13 +162,17 @@ FastAPI 入口为 `backend/main.py`,配置读取在 `backend/settings.py`。
|
||||
| `/cnomadcna/*_notify` | 支付网关回调 |
|
||||
| `/api/cities`、`/api/cities/{slug}` | 城市数据 |
|
||||
| `/api/content/*` | 首页内容、内容投稿、内容详情 |
|
||||
| `/api/videos` | 访谈视频列表(`type=video` 的 content_items) |
|
||||
| `/api/notifications/*` | 通知、回执、偏好 |
|
||||
| `/api/recommendations/next-stop` | 下一站推荐 |
|
||||
| `/api/meetups` | 活动列表与活动创建 |
|
||||
| `/api/meetups` | 活动列表与创建 |
|
||||
| `/api/meetups/{id}` | 单个活动详情 |
|
||||
| `/api/meetups/{id}/session` | 活动间会话:权限校验、视频/群聊 URL、社区昵称 |
|
||||
| `/api/matches/*` | 匹配候选、滑动、互赞、额度、撤销、我的资料 |
|
||||
| `/api/discussions` | 讨论列表与创建 |
|
||||
| `/api/gigs` | 任务赏金列表、创建、申请 |
|
||||
| `/api/profiles`、`/api/matches/swipes` | 资料与匹配 |
|
||||
| `/api/feedback` | 用户反馈 |
|
||||
| `/api/profiles` | 资料列表 |
|
||||
| `/api/feedback` | 用户反馈(支持 `?type=report` 预填) |
|
||||
| `/api/stats/*` | 成员地图、概览、城市排行 |
|
||||
| `/api/services`、`/api/services/leads` | 增值服务与线索 |
|
||||
| `/api/ai/assistant` | AI 助手占位接口 |
|
||||
@@ -170,31 +182,68 @@ FastAPI 入口为 `backend/main.py`,配置读取在 `backend/settings.py`。
|
||||
- `backend/pb_client.py`:PocketBase HTTP 客户端
|
||||
- `backend/payment.py`:ZPay / XorPay 支付适配
|
||||
- `backend/minio_storage.py`:MinIO 上传
|
||||
- `backend/meetup_live.py`:活动间 URL 生成、权限判断(MiroTalk / Lounge)
|
||||
- `backend/avatar_assets.py`:与前端同步的头像池(seed 用)
|
||||
- `backend/init_db.py`、`seed_data.py`、`enhanced_seed.py`:初始化与种子数据
|
||||
- `backend/settings.py`:环境变量读取
|
||||
- `backend/settings.py`:环境变量读取(含 `MIROTALK_URL`、`LOUNGE_URL`)
|
||||
|
||||
### 活动、视频与群聊源码
|
||||
### 活动、视频与群聊(深度融合)
|
||||
|
||||
活动相关逻辑主要在:
|
||||
相关文件:
|
||||
|
||||
- `app/[locale]/meetups/page.tsx`
|
||||
- `app/[locale]/meetups/host/page.tsx`
|
||||
- `app/lib/meetups.ts`
|
||||
| 文件 | 作用 |
|
||||
| --- | --- |
|
||||
| `app/[locale]/meetups/page.tsx` | 活动列表、详情弹窗、「进入活动间」入口 |
|
||||
| `app/[locale]/meetups/[id]/live/page.tsx` | 统一活动间页面 |
|
||||
| `app/components/meetups/EventLiveRoom.tsx` | 分屏 UI:视频 iframe + 群聊 iframe |
|
||||
| `app/[locale]/meetups/host/page.tsx` | 发起活动 |
|
||||
| `app/lib/meetups.ts` | MiroTalk/Lounge URL、房间 slug、`loungeChannel`、权限工具 |
|
||||
| `backend/meetup_live.py` | 后端同名逻辑,供 `/api/meetups/{id}/session` 使用 |
|
||||
|
||||
`app/lib/meetups.ts` 负责:
|
||||
|
||||
- MiroTalk 默认地址:`https://mirotalk.nomadro.cn`
|
||||
- MiroTalk 房间名规范化
|
||||
- MiroTalk 入会链接生成
|
||||
- Lounge 默认地址:`https://lounge.nomadro.cn`
|
||||
- Web 群聊服务标签:`The Lounge + Ergo IRC`
|
||||
- MiroTalk 默认地址:`NEXT_PUBLIC_MIROTALK_URL`(生产 `https://mirotalk.nomadro.cn`)
|
||||
- MiroTalk 房间名规范化、`buildMiroTalkJoinUrl(meetup, displayName)`
|
||||
- Lounge 默认地址:`NEXT_PUBLIC_LOUNGE_URL`(生产 `https://lounge.nomadro.cn`)
|
||||
- 活动专属 IRC 频道:`loungeChannel` 字段,或从 `mirotalkRoom` 推导
|
||||
- 群聊 deep link:`buildMeetupChatUrl(meetup)` → `lounge.nomadro.cn/#/chan-#频道`
|
||||
- 活动间路径:`buildMeetupLivePath(id)` → `/meetups/{id}/live`
|
||||
|
||||
线上/混合活动详情页会展示:
|
||||
**账户打通**:`GET /api/meetups/{id}/session` 读取 PocketBase 登录态,校验 `public/members/vip/hosts`,将社区昵称写入 MiroTalk `name=` 参数。
|
||||
|
||||
- MiroTalk P2P 视频入口
|
||||
- 页面内 iframe 打开视频房
|
||||
- The Lounge Web 群聊入口
|
||||
- 信令/中继服务器和群聊入口域名
|
||||
PocketBase `meetups` 集合字段(线上活动相关):
|
||||
|
||||
- `mode`:`offline` / `online` / `hybrid`
|
||||
- `accessLevel`:`public` / `members` / `vip` / `hosts`
|
||||
- `meetingProvider`:如 `mirotalk`
|
||||
- `mirotalkRoom`:视频房间 slug
|
||||
- `loungeChannel`:IRC 频道,如 `#nomadcna-20260608`
|
||||
- `features`:JSON,如 `group_video`、`screen_share`
|
||||
|
||||
### 访谈视频
|
||||
|
||||
- 列表:`app/[locale]/videos/page.tsx`,数据来自 `GET /api/videos`
|
||||
- 详情:`app/[locale]/videos/[slug]/page.tsx`
|
||||
- 首页右侧「访谈视频」卡片链到 `/videos`(非单条 slug)
|
||||
|
||||
### 社区匹配(Dating)
|
||||
|
||||
- 页面:`app/[locale]/dating/page.tsx`
|
||||
- 组件:`app/[locale]/dating/components/`(`IntentTabs`、`CityFilter`、`SwipeStack`、`LikesPanel`、`MatchModal`、`AdvancedFilters`、`SwipeQuota` 等)
|
||||
- 工具:`app/[locale]/dating/utils.ts`、`constants.ts`、`types.ts`
|
||||
- 头像池:`app/data/avatars.ts`(Unsplash 人像,与 `backend/avatar_assets.py` 同步)
|
||||
|
||||
匹配 API(均需登录,部分需 VIP):
|
||||
|
||||
- `GET /api/matches/candidates` — 候选列表(意图、城市、性别筛选)
|
||||
- `POST /api/matches/swipes` — 左滑/右滑/超级赞
|
||||
- `POST /api/matches/swipes/undo` — 撤销上一次滑动
|
||||
- `GET /api/matches/likes`、`/mutual`、`/quota`、`/profile/me`
|
||||
|
||||
### 媒体代理
|
||||
|
||||
- `app/lib/media.ts`:封面 URL 规范化(Unsplash 直连、MinIO 相对路径补全)
|
||||
- `app/api/media/proxy/route.ts`:远程媒体抓取;MinIO 失败时直返图片
|
||||
|
||||
### 配置与国际化
|
||||
|
||||
@@ -205,6 +254,7 @@ FastAPI 入口为 `backend/main.py`,配置读取在 `backend/settings.py`。
|
||||
| `config/footer.config.ts` | 页脚 |
|
||||
| `config/services.config.ts` | 主站支付配置 |
|
||||
| `config/runtime-env.ts` | 运行环境判断 |
|
||||
| `config/remote-services.ts` | 线上域名、MinIO/PocketBase 解析、远程开发模式 |
|
||||
| `config/digital/*` | Digital 子站主题、服务、课程、域名配置 |
|
||||
| `messages/zh.json`、`messages/en.json` | 中英文文案 |
|
||||
| `i18n/routing.ts` | 语言列表与默认语言 |
|
||||
@@ -226,6 +276,41 @@ FastAPI 入口为 `backend/main.py`,配置读取在 `backend/settings.py`。
|
||||
pnpm install
|
||||
```
|
||||
|
||||
### Windows 本地连线上服务
|
||||
|
||||
典型配置见 `.env.example` / `.env.local`:
|
||||
|
||||
1. PocketBase 用公网 `https://pocketbase.nomadro.cn`
|
||||
2. MinIO S3 API 用 SSH 隧道映射到本机 `9100`:
|
||||
|
||||
```powershell
|
||||
python scripts/dev-tunnel.py
|
||||
```
|
||||
|
||||
3. 本地跑 Next.js + FastAPI:
|
||||
|
||||
```powershell
|
||||
pnpm dev
|
||||
# 另开终端
|
||||
backend\.venv\Scripts\uvicorn backend.main:app --host 127.0.0.1 --port 8000 --reload
|
||||
```
|
||||
|
||||
或一键脚本:
|
||||
|
||||
```powershell
|
||||
powershell -ExecutionPolicy Bypass -File scripts/dev-windows.ps1
|
||||
```
|
||||
|
||||
服务地址推导见 `config/remote-services.ts`。
|
||||
|
||||
### 初始化数据库
|
||||
|
||||
```bash
|
||||
python -m backend.init_db
|
||||
```
|
||||
|
||||
会创建/补全 PocketBase 集合字段,并 upsert 城市、活动、内容、资料等种子数据。
|
||||
|
||||
### 前端开发
|
||||
|
||||
```bash
|
||||
@@ -275,6 +360,7 @@ APP_ENV=production NEXT_PUBLIC_APP_ENV=production NODE_ENV=production pnpm build
|
||||
| `NEXT_PUBLIC_SITE_URL` | 站点根地址 |
|
||||
| `NEXT_PUBLIC_SITE_ID` | 站点 ID,用于会员/VIP 隔离 |
|
||||
| `NEXT_PUBLIC_API_BASE_URL` | API 基础地址,生产通常为 `/api` |
|
||||
| `FASTAPI_PROXY_TARGET` | Next.js rewrite 转发 FastAPI 的目标(本地 `http://127.0.0.1:8000`) |
|
||||
| `NEXT_PUBLIC_POCKETBASE_URL` | 浏览器可访问 PocketBase 地址 |
|
||||
| `NEXT_PUBLIC_MIROTALK_URL` | MiroTalk P2P 服务地址 |
|
||||
| `NEXT_PUBLIC_LOUNGE_URL` | The Lounge Web 群聊地址 |
|
||||
@@ -304,6 +390,8 @@ APP_ENV=production NEXT_PUBLIC_APP_ENV=production NODE_ENV=production pnpm build
|
||||
| `MINIO_UPLOAD_PREFIX` | 上传路径前缀 |
|
||||
| `FRONTEND_ORIGINS` | FastAPI CORS 白名单 |
|
||||
| `UPLOAD_DIR` | 后端本地上传目录 |
|
||||
| `MIROTALK_URL` / `LOUNGE_URL` | 后端生成活动间 URL(默认同公网域名) |
|
||||
| `DEV_SSH_HOST` / `DEV_SSH_PASSWORD` | Windows SSH 隧道(仅本地,勿提交) |
|
||||
|
||||
## 生产服务器支持
|
||||
|
||||
@@ -484,7 +572,7 @@ curl -I https://mirotalk.nomadro.cn/join?room=nomadcna-healthcheck
|
||||
- 只监听 `127.0.0.1:9000`
|
||||
- Nginx 通过 `https://lounge.nomadro.cn` 反代
|
||||
- 默认网络锁定到本机 Ergo:`127.0.0.1:6667`
|
||||
- 默认加入频道:`#nomadcna,#online-events`
|
||||
- 默认加入频道:`#nomadcna,#online-events`(可按活动追加,如 `#nomadcna-20260608`)
|
||||
- 文件上传关闭
|
||||
- The Lounge 自身消息持久化关闭,Ergo 保留内存历史
|
||||
|
||||
@@ -578,11 +666,17 @@ curl -I https://ergo.nomadro.cn/
|
||||
|
||||
### 活动视频房如何生成?
|
||||
|
||||
`app/lib/meetups.ts` 会根据活动城市、日期、时间和 ID 生成 MiroTalk room slug。如果活动有自定义 `meetingUrl`,则优先使用自定义链接。
|
||||
`app/lib/meetups.ts` 会根据活动 `mirotalkRoom`、或城市/日期/时间/ID 生成 room slug。登录用户通过 `/api/meetups/{id}/session` 获取带 `name=` 的入会 URL。
|
||||
|
||||
### 如何进入统一活动间?
|
||||
|
||||
活动详情弹窗点 **「进入活动间」** → `/meetups/{id}/live`。页面内分屏嵌入 MiroTalk 与 The Lounge;也可新窗口单独打开。
|
||||
|
||||
### 群聊频道如何进入?
|
||||
|
||||
The Lounge public mode 的默认网络已锁定到 Ergo,并默认加入 `#nomadcna` 和 `#online-events`。活动详情页的“进入群聊”按钮指向 `https://lounge.nomadro.cn`。
|
||||
- 全局:`https://lounge.nomadro.cn`(默认 `#nomadcna`、`#online-events`)
|
||||
- 单活动:`buildMeetupChatUrl(meetup)` → `lounge.nomadro.cn/#/chan-#频道`
|
||||
- PocketBase 活动记录可设 `loungeChannel` 字段
|
||||
|
||||
## 维护命令速查
|
||||
|
||||
|
||||
Reference in New Issue
Block a user