feat: 新增签到墙、摇一摇等功能及开发环境配置

新功能:
- 签到墙页面 (CheckinWallView) 及后端接口
- 摇一摇互动页面 (ShakeView) 及服务
- 头像服务 (avatar.service)
- 微信公众号静默授权登录增强

开发环境:
- 新增 dev-tunnel skill 用于本地调试
- docker-compose.dev.yml 开发环境配置
- 客户端 .env.development 配置文件

其他改进:
- VoteView 投票页面功能增强
- AdminControl 管理控制台更新
- 连接状态管理优化
- 新增马蹄声音效

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
empty
2026-02-04 17:25:56 +08:00
parent c1b4b09e40
commit 48d61a1e15
38 changed files with 2020 additions and 27 deletions

View File

@@ -0,0 +1,38 @@
{
email let5sne@gmail.com
}
2026.cptp.let5see.xyz {
# WeChat verification file
handle /A6e75lM1ge.txt {
respond "3a5d2d7f410fbcbc32e3c222b2cf28bf"
}
# Screen client → local dev server via tunnel
handle /screen* {
reverse_proxy localhost:5174
}
# API proxy → local backend via tunnel
handle /api/* {
header Cache-Control "no-store, no-cache, must-revalidate"
reverse_proxy localhost:3001
}
# WebSocket proxy → local backend via tunnel
handle /socket.io/* {
reverse_proxy localhost:3001
}
# Avatars proxy → local backend via tunnel
handle /avatars/* {
reverse_proxy localhost:3001
}
# Mobile client → local dev server via tunnel
handle {
reverse_proxy localhost:5173
}
encode gzip
}

View File

@@ -0,0 +1,48 @@
{
email let5sne@gmail.com
}
2026.cptp.let5see.xyz {
# WeChat verification file
handle /A6e75lM1ge.txt {
respond "3a5d2d7f410fbcbc32e3c222b2cf28bf"
}
# Screen client
handle /screen* {
root * /root/company-celebration/packages/client-screen/dist
uri strip_prefix /screen
try_files {path} /index.html
file_server
header Cache-Control "no-cache, no-store, must-revalidate"
@screenassets path_regexp assets \/assets\/.*
header @screenassets Cache-Control "public, max-age=31536000, immutable"
}
# API proxy
handle /api/* {
header Cache-Control "no-store, no-cache, must-revalidate"
reverse_proxy localhost:3000
}
# WebSocket proxy
handle /socket.io/* {
reverse_proxy localhost:3000
}
# Mobile client (default)
handle {
root * /root/company-celebration/packages/client-mobile/dist
try_files {path} /index.html
file_server
header Cache-Control "no-cache, no-store, must-revalidate"
@mobileassets path_regexp assets \/assets\/.*
header @mobileassets Cache-Control "public, max-age=31536000, immutable"
}
encode gzip
}

View File

@@ -0,0 +1,228 @@
# dev-tunnel - 本地开发隧道
通过 SSH 反向隧道将本地服务暴露到生产服务器,实现完整的本地开发调试(前端+后端),同时使用生产域名和微信授权。
## 使用场景
- 本地调试需要微信授权回调
- 本地调试需要使用生产域名
- 需要同时调试前端和后端
- 本地没有公网 IP
## 命令
```
/dev-tunnel start # 启动本地调试模式
/dev-tunnel stop # 恢复生产环境
/dev-tunnel status # 查看当前状态
```
## 架构说明
```
生产环境:
/api/*, /socket.io/* → localhost:3000 → PM2(gala-server)
/screen* → 静态文件 (client-screen/dist)
其他 → 静态文件 (client-mobile/dist)
调试模式:
/api/*, /socket.io/* → localhost:3001 → 隧道 → 本地:3000 (后端)
/screen* → localhost:5174 → 隧道 → 本地:5174 (大屏 dev)
其他 → localhost:5173 → 隧道 → 本地:5173 (移动端 dev)
```
## 隧道端口映射
| 服务 | 服务器端口 | 本地端口 |
|------|-----------|---------|
| 后端 API | 3001 | 3000 |
| 移动端前端 | 5173 | 5173 |
| 大屏端前端 | 5174 | 5174 |
## 操作步骤
### start - 启动调试模式
1. **服务器**: 停止 PM2 后端服务
2. **服务器**: 切换 Caddy 为调试模式配置
3. **本地**: 切换 MOBILE_CLIENT_URL 为生产域名(自动执行)
4. **本地**: 建立 SSH 隧道(自动执行)
5. **本地**: 启动后端和前端 dev server手动执行
### stop - 恢复生产环境
1. **本地**: 终止 SSH 隧道进程(自动执行)
2. **本地**: 恢复 MOBILE_CLIENT_URL 为本地地址(自动执行)
3. **服务器**: 恢复 Caddy 生产环境配置
4. **服务器**: 重启 PM2 后端服务
## 具体命令
### 启动调试模式
```bash
# 1. 停止服务器后端
ssh vote "pm2 stop gala-server"
# 2. 切换 Caddy 为调试模式配置
# 注意:需要先将 Caddyfile.debug 上传到服务器,或直接替换内容
ssh vote "cat > /etc/caddy/Caddyfile << 'EOF'
{
email let5sne@gmail.com
}
2026.cptp.let5see.xyz {
handle /A6e75lM1ge.txt {
respond \"3a5d2d7f410fbcbc32e3c222b2cf28bf\"
}
handle /screen* {
reverse_proxy localhost:5174
}
handle /api/* {
header Cache-Control \"no-store, no-cache, must-revalidate\"
reverse_proxy localhost:3001
}
handle /socket.io/* {
reverse_proxy localhost:3001
}
handle /avatars/* {
reverse_proxy localhost:3001
}
handle {
reverse_proxy localhost:5173
}
encode gzip
}
EOF"
# 3. 重载 Caddy
ssh vote "caddy reload --config /etc/caddy/Caddyfile"
# 4. 切换 MOBILE_CLIENT_URL 为生产域名
sed -i '' 's|MOBILE_CLIENT_URL=http://localhost:5173|MOBILE_CLIENT_URL=https://2026.cptp.let5see.xyz|g' packages/server/.env
# 5. 切换大屏端 VITE_MOBILE_URL 为生产域名
sed -i '' 's|VITE_MOBILE_URL=http://localhost:5173|VITE_MOBILE_URL=https://2026.cptp.let5see.xyz|g' packages/client-screen/.env.development
# 6. 切换移动端 VITE_SOCKET_URL/VITE_API_URL 为生产域名
sed -i '' 's|VITE_SOCKET_URL=http://localhost:3000|VITE_SOCKET_URL=https://2026.cptp.let5see.xyz|g' packages/client-mobile/.env.development
sed -i '' 's|VITE_API_URL=http://localhost:3000|VITE_API_URL=https://2026.cptp.let5see.xyz|g' packages/client-mobile/.env.development
# 7. 建立 SSH 隧道(自动后台运行)
ssh -R 3001:localhost:3000 -R 5173:localhost:5173 -R 5174:localhost:5174 vote -N -o ServerAliveInterval=30
# 6. 本地启动服务3个终端手动执行
# 终端1: 后端
pnpm --filter @gala/server dev
# 终端2: 移动端前端
pnpm --filter @gala/client-mobile dev --host
# 终端3: 大屏端前端
pnpm --filter @gala/client-screen dev --host
```
### 恢复生产环境
```bash
# 1. 终止本地 SSH 隧道进程
pkill -f "ssh -R 3001:localhost:3000"
# 2. 恢复 MOBILE_CLIENT_URL 为本地地址
sed -i '' 's|MOBILE_CLIENT_URL=https://2026.cptp.let5see.xyz|MOBILE_CLIENT_URL=http://localhost:5173|g' packages/server/.env
# 3. 恢复大屏端 VITE_MOBILE_URL 为本地地址
sed -i '' 's|VITE_MOBILE_URL=https://2026.cptp.let5see.xyz|VITE_MOBILE_URL=http://localhost:5173|g' packages/client-screen/.env.development
# 4. 恢复移动端 VITE_SOCKET_URL/VITE_API_URL 为本地地址
sed -i '' 's|VITE_SOCKET_URL=https://2026.cptp.let5see.xyz|VITE_SOCKET_URL=http://localhost:3000|g' packages/client-mobile/.env.development
sed -i '' 's|VITE_API_URL=https://2026.cptp.let5see.xyz|VITE_API_URL=http://localhost:3000|g' packages/client-mobile/.env.development
# 5. 恢复 Caddy 生产环境配置
ssh vote "cat > /etc/caddy/Caddyfile << 'EOF'
{
email let5sne@gmail.com
}
2026.cptp.let5see.xyz {
handle /A6e75lM1ge.txt {
respond \"3a5d2d7f410fbcbc32e3c222b2cf28bf\"
}
handle /screen* {
root * /root/company-celebration/packages/client-screen/dist
uri strip_prefix /screen
try_files {path} /index.html
file_server
header Cache-Control \"no-cache, no-store, must-revalidate\"
@screenassets path_regexp assets \\/assets\\/.*
header @screenassets Cache-Control \"public, max-age=31536000, immutable\"
}
handle /api/* {
header Cache-Control \"no-store, no-cache, must-revalidate\"
reverse_proxy localhost:3000
}
handle /socket.io/* {
reverse_proxy localhost:3000
}
handle {
root * /root/company-celebration/packages/client-mobile/dist
try_files {path} /index.html
file_server
header Cache-Control \"no-cache, no-store, must-revalidate\"
@mobileassets path_regexp assets \\/assets\\/.*
header @mobileassets Cache-Control \"public, max-age=31536000, immutable\"
}
encode gzip
}
EOF"
# 3. 重载 Caddy
ssh vote "caddy reload --config /etc/caddy/Caddyfile"
# 4. 重启服务器后端
ssh vote "pm2 restart gala-server"
```
## 前端 dev server 配置
### 必需配置
两个前端项目的 `vite.config.ts` 需要包含以下配置:
**client-mobile** (端口 5173):
```ts
server: {
host: '0.0.0.0',
port: 5173,
allowedHosts: ['2026.cptp.let5see.xyz'],
}
```
**client-screen** (端口 5174):
```ts
server: {
host: '0.0.0.0',
port: 5174,
allowedHosts: ['2026.cptp.let5see.xyz'],
}
```
### 配置说明
| 配置项 | 说明 |
|--------|------|
| `host: '0.0.0.0'` | 允许外部网络访问 |
| `allowedHosts` | 允许通过生产域名访问,否则 Vite 会拒绝请求 |
| `base: '/screen/'` | 大屏端需要配置,支持 `/screen` 路径前缀 |
## 注意事项
- SSH 隧道断开后,生产环境将不可用,务必及时恢复
- 调试完成后**必须执行 stop** 恢复生产环境
- 隧道命令需要保持终端运行,关闭终端会断开隧道
- 本地需要同时运行 4 个终端(后端 + 2个前端 + 隧道)
## 文件说明
- `Caddyfile.production` - 生产环境 Caddy 配置模板
- `Caddyfile.debug` - 调试模式 Caddy 配置模板