From 4927420266536abd41b9820cfbc9ead745c9dd7d Mon Sep 17 00:00:00 2001 From: taiyi Date: Thu, 18 Dec 2025 13:28:29 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AC=AC=E4=B8=89=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 2 +- QUICKSTART.md | 130 --------- backend/.env | 58 +--- backend/app/core/config.py | 57 ++-- backend/app/core/database.py | 33 ++- backend/app/routers/game.py | 5 + backend/app/services/game_service.py | 360 ++++++++++++++---------- baoxiang.sql | 356 ----------------------- frontend/.env | 8 +- frontend/dist/assets/index-B4_1kpoc.css | 1 - frontend/dist/assets/index-DUKe-Ir9.js | 94 ------- frontend/dist/index.html | 4 +- frontend/src/pages/HomePage.tsx | 35 +-- frontend/src/services/websocket.ts | 78 +++-- frontend/tsconfig.json | 4 +- frontend/vite.config.ts | 1 + init_mysql.sql | 199 ------------- package-lock.json | 6 - requirements-dev.txt | 6 - 19 files changed, 331 insertions(+), 1106 deletions(-) delete mode 100644 QUICKSTART.md delete mode 100644 baoxiang.sql delete mode 100644 frontend/dist/assets/index-B4_1kpoc.css delete mode 100644 frontend/dist/assets/index-DUKe-Ir9.js delete mode 100644 init_mysql.sql delete mode 100644 package-lock.json delete mode 100644 requirements-dev.txt diff --git a/.env b/.env index e189bf0..695876e 100644 --- a/.env +++ b/.env @@ -12,7 +12,7 @@ DB_POOL_SIZE=20 DB_MAX_OVERFLOW=30 DB_POOL_TIMEOUT=30 -DB_POOL_RECYCLE=3600 +DB_POOL_RECYCLE=1800 # 覆盖默认配置 DATABASE_URL=mysql+pymysql://root:taiyi1224@localhost:3306/baoxiang diff --git a/QUICKSTART.md b/QUICKSTART.md deleted file mode 100644 index 45f2aad..0000000 --- a/QUICKSTART.md +++ /dev/null @@ -1,130 +0,0 @@ -# 🚀 快速启动指南 - -## 一键启动(推荐) - -使用 Docker Compose 一键启动所有服务: - -```bash -# 启动所有服务(MySQL、Redis、后端、前端) -docker-compose up -d - -# 查看服务状态 -docker-compose ps - -# 查看日志 -docker-compose logs -f backend -``` - -启动后访问: -- **前端界面**: http://localhost:3000 -- **后端 API**: http://localhost:8000 -- **API 文档**: http://localhost:8000/docs - ---- - -## 分别启动 - -### 1. 后端服务 - -```bash -# 进入后端目录 -cd backend - -# 安装依赖 -pip install -r requirements.txt - -# 启动服务 -python run.py -``` - -### 2. 前端服务 - -```bash -# 进入前端目录 -cd frontend - -# 安装依赖 -npm install - -# 启动开发服务器 -npm run dev -``` - ---- - -## 📋 系统要求 - -- **Docker**: 20.10+ -- **Docker Compose**: 2.0+ -- **Python**: 3.10+ -- **Node.js**: 16+ - ---- - -## 🔧 配置说明 - -### 环境变量 - -复制环境变量示例文件: -```bash -cp .env.example .env -``` - -主要配置项: -- `DATABASE_URL`: MySQL 连接地址 -- `SECRET_KEY`: JWT 密钥 -- `REDIS_HOST`: Redis 主机地址 - -### MySQL 连接信息 - -通过 Docker 启动时: -``` -主机: localhost -端口: 3306 -数据库: treasure_box_game -用户名: root -密码: treasure_box_2024 -``` - ---- - -## 🐛 常见问题 - -### Q: Docker 启动失败? -A: 检查端口占用情况: -```bash -# Windows -netstat -ano | findstr :3306 -# Linux/Mac -lsof -i :3306 -``` - -### Q: 数据库连接失败? -A: 确保 MySQL 容器已启动并健康: -```bash -docker-compose ps -docker-compose logs mysql -``` - -### Q: 前端无法连接后端? -A: 检查 Vite 代理配置和后端 CORS 设置 - ---- - -## 📚 更多文档 - -- **完整迁移指南**: `MYSQL_迁移指南.md` -- **项目完成报告**: `项目完成报告.md` -- **前端开发文档**: `frontend/README.md` -- **后端 API 文档**: http://localhost:8000/docs - ---- - -## 🎯 下一步 - -1. 访问 http://localhost:3000 注册用户 -2. 体验完整的竞猜流程 -3. 尝试创建宝箱(需要 streamer 权限) -4. 查看 API 文档了解所有接口 - -**祝您使用愉快!** 🎉 diff --git a/backend/.env b/backend/.env index 08e5d94..dd46dc2 100644 --- a/backend/.env +++ b/backend/.env @@ -1,57 +1,17 @@ -# ======================================== -# 数据库配置 (MySQL) -# ======================================== -# MySQL连接格式: mysql+pymysql://username:password@host:port/database_name -DATABASE_URL=mysql+pymysql://root:taiyi1224@localhost:3306/baoxiang +# 这是一个示例.env文件,用于说明环境变量的格式 +# 在生产环境中,请使用环境变量而不是这个文件 -# SQLite开发配置 (可选) -# SQLite连接格式: sqlite:///./database.db -# DATABASE_URL=sqlite:///./treasure_box_game.db - -# 数据库连接池配置 +# 数据库配置 +DB_DATABASE_URL=mysql+pymysql://root:taiyi1224@199.68.217.236:3306/baoxiang DB_POOL_SIZE=20 -DB_MAX_OVERFLOW=30 -DB_POOL_TIMEOUT=30 -DB_POOL_RECYCLE=3600 -# ======================================== -# JWT配置 -# ======================================== +# 安全配置 SECRET_KEY=qwer123 -ALGORITHM=HS256 -ACCESS_TOKEN_EXPIRE_MINUTES=10080 -# ======================================== # Redis配置 -# ======================================== -REDIS_HOST=localhost +REDIS_HOST=199.68.217.236 REDIS_PORT=6379 -REDIS_DB=0 -REDIS_PASSWORD= - -# ======================================== -# 游戏配置 -# ======================================== -NEW_USER_REWARD=100000 -DAILY_ALLOWANCE=5000 -ALLOWANCE_THRESHOLD=1000 - -# ======================================== -# 抽水配置 -# ======================================== -HOUSE_EDGE=0.10 -STREAMER_SHARE=0.05 -PLATFORM_SHARE=0.05 - -# ======================================== -# MySQL Docker配置说明 -# ======================================== -# 如果使用docker-compose中的MySQL服务,连接地址为: -# DATABASE_URL=mysql+pymysql://root:treasure_box_2024@mysql:3306/treasure_box_game -# -# MySQL容器配置: -# - 用户名: root -# - 密码: treasure_box_2024 -# - 数据库: treasure_box_game -# - 端口: 3306 +# 服务器配置 +HOST=0.0.0.0 +PORT=8000 diff --git a/backend/app/core/config.py b/backend/app/core/config.py index c771513..14494c6 100644 --- a/backend/app/core/config.py +++ b/backend/app/core/config.py @@ -6,65 +6,64 @@ from pydantic_settings import BaseSettings from pydantic import ConfigDict from typing import Optional, List from functools import lru_cache +import os class ServerSettings(BaseSettings): """服务器配置""" + model_config = ConfigDict(env_prefix="SERVER_", env_file="D:\work\code\python\demo\demo07\backend\.env") + HOST: str = "0.0.0.0" PORT: int = 8000 WORKERS: int = 1 LOG_LEVEL: str = "info" - class Config: - env_prefix = "SERVER_" - class DatabaseSettings(BaseSettings): """数据库配置""" + model_config = ConfigDict(env_prefix="DB_", env_file="D:\work\code\python\demo\demo07\backend\.env") + # MySQL连接格式: mysql+pymysql://username:password@host:port/database_name?charset=utf8mb4 DATABASE_URL: str = "mysql+pymysql://root:taiyi1224@localhost:3306/baoxiang?charset=utf8mb4" # SQLite开发配置 (可选) # SQLite连接格式: sqlite:///./database.db # DATABASE_URL: str = "sqlite:///./treasure_box_game.db" - + # 数据库连接池配置 DB_POOL_SIZE: int = 20 DB_MAX_OVERFLOW: int = 30 DB_POOL_TIMEOUT: int = 30 DB_POOL_RECYCLE: int = 3600 - - class Config: - env_prefix = "DB_" class SecuritySettings(BaseSettings): """安全配置""" + model_config = ConfigDict(env_prefix="SECURITY_", env_file="D:\work\code\python\demo\demo07\backend\.env") + SECRET_KEY: str = "your-secret-key-change-in-production" ALGORITHM: str = "HS256" ACCESS_TOKEN_EXPIRE_MINUTES: int = 10080 # 7天 PASSWORD_MAX_LENGTH: int = 72 # 密码哈希最大长度 WS_CLOSE_CODE: int = 4001 # WebSocket关闭码 - class Config: - env_prefix = "SECURITY_" - class RedisSettings(BaseSettings): """Redis配置""" + model_config = ConfigDict(env_prefix="REDIS_", env_file="D:\work\code\python\demo\demo07\backend\.env") + REDIS_HOST: str = "localhost" REDIS_PORT: int = 6379 REDIS_DB: int = 0 REDIS_PASSWORD: Optional[str] = None REDIS_TIMEOUT: int = 5 - class Config: - env_prefix = "REDIS_" - class CORSSettings(BaseSettings): """CORS跨域配置""" - ALLOW_ORIGINS: str = "http://localhost:3000,http://127.0.0.1:3000,http://localhost:3001,http://127.0.0.1:3001,*" + model_config = ConfigDict(env_prefix="CORS_", env_file="D:\work\code\python\demo\demo07\backend\.env") + + ALLOW_ORIGINS: str = "http://localhost:3000,http://127.0.0.1:3000,http://localhost:3001,http://127.0.0.1:3001,http://bx.youxidaren.cn,https://bx.youxidaren.cn,http://199.68.217.236:3000,http://199.68.217.236:3001,http://199.68.217.236:8000,*" ALLOW_CREDENTIALS: bool = True ALLOW_METHODS: str = "GET,POST,PUT,DELETE,PATCH,OPTIONS" ALLOW_HEADERS: str = "Authorization,Content-Type,Accept,X-Requested-With" @@ -81,12 +80,11 @@ class CORSSettings(BaseSettings): """解析允许的头部列表""" return [header.strip() for header in self.ALLOW_HEADERS.split(",")] - class Config: - env_prefix = "CORS_" - class PaginationSettings(BaseSettings): """分页配置""" + model_config = ConfigDict(env_prefix="PAGINATION_", env_file="D:\work\code\python\demo\demo07\backend\.env") + DEFAULT_PAGE_SIZE: int = 20 MAX_PAGE_SIZE: int = 100 ADMIN_PAGE_SIZE: int = 20 @@ -95,12 +93,11 @@ class PaginationSettings(BaseSettings): USER_LIST_LIMIT: int = 100 STREAMER_LIST_LIMIT: int = 100 - class Config: - env_prefix = "PAGINATION_" - class GameSettings(BaseSettings): """游戏配置""" + model_config = ConfigDict(env_prefix="GAME_", env_file="D:\work\code\python\demo\demo07\backend\.env") + # 经济配置 NEW_USER_REWARD: int = 100000 # 新用户注册奖励(分) DAILY_ALLOWANCE: int = 5000 # 每日低保(分) @@ -120,22 +117,20 @@ class GameSettings(BaseSettings): MAX_COMMISSION_RATE: float = 100.0 # 最大主播抽成(%) DEFAULT_COMMISSION_RATE: float = 5.0 # 默认主播抽成(%) - class Config: - env_prefix = "GAME_" - class WebSocketSettings(BaseSettings): """WebSocket配置""" + model_config = ConfigDict(env_prefix="WS_", env_file="D:\work\code\python\demo\demo07\backend\.env") + BROADCAST_INTERVAL: int = 200 # 广播间隔(毫秒) HEARTBEAT_INTERVAL: int = 30 # 心跳间隔(秒) CONNECTION_TIMEOUT: int = 60 # 连接超时(秒) - class Config: - env_prefix = "WS_" - class AdminSettings(BaseSettings): """管理员配置""" + model_config = ConfigDict(env_prefix="ADMIN_", env_file="D:\work\code\python\demo\demo07\backend\.env") + DEFAULT_ADMIN_PASSWORD: str = "admin123" DEFAULT_STREAMER_PASSWORD: str = "streamer123" DEFAULT_USER_PASSWORD: str = "user123" @@ -143,26 +138,22 @@ class AdminSettings(BaseSettings): DEFAULT_STREAMER_BALANCE: int = 500000 # 默认主播余额(分) DEFAULT_USER_BALANCE: int = 200000 # 默认用户余额(分) - class Config: - env_prefix = "ADMIN_" - class AnnouncementSettings(BaseSettings): """公告配置""" + model_config = ConfigDict(env_prefix="ANNOUNCEMENT_", env_file="D:\work\code\python\demo\demo07\backend\.env") + DEFAULT_PRIORITY: int = 0 MAX_PRIORITY: int = 100 HIGH_PRIORITY: int = 100 - class Config: - env_prefix = "ANNOUNCEMENT_" - class Settings(BaseSettings): """ 根配置类 - 组合所有子配置 """ model_config = ConfigDict( - env_file=".env", + env_file="./.env", extra='ignore' # 忽略.env文件中未定义的变量 ) diff --git a/backend/app/core/database.py b/backend/app/core/database.py index 11ea0d3..38ba94e 100644 --- a/backend/app/core/database.py +++ b/backend/app/core/database.py @@ -27,10 +27,18 @@ else: max_overflow=db_settings.DB_MAX_OVERFLOW, pool_timeout=db_settings.DB_POOL_TIMEOUT, pool_recycle=db_settings.DB_POOL_RECYCLE, + pool_pre_ping=True, # 每次使用连接前检测是否有效,防止使用已断开的连接 echo=False, future=True, # 设置连接时使用的字符集 - connect_args={"charset": "utf8mb4", "collation": "utf8mb4_unicode_ci"} + connect_args={ + "charset": "utf8mb4", + "collation": "utf8mb4_unicode_ci", + # 添加连接超时设置 + "connect_timeout": 60, + "read_timeout": 60, + "write_timeout": 60 + } ) # 如果是MySQL,启用严格模式 @@ -60,8 +68,29 @@ def get_db(): db = SessionLocal() try: yield db + except Exception as e: + # 如果发生异常,先回滚未提交的事务 + try: + if db.is_active: + db.rollback() + except Exception: + pass + raise e finally: - db.close() + # 安全地关闭数据库连接 + try: + # 检查会话状态 + if db.is_active: + db.close() + else: + # 如果会话已经不活跃,尝试无效化连接 + try: + db.close() + except Exception: + pass + except Exception: + # 忽略关闭时的错误,避免掩盖原始异常 + pass def create_tables(): diff --git a/backend/app/routers/game.py b/backend/app/routers/game.py index e18ee30..f526fd4 100644 --- a/backend/app/routers/game.py +++ b/backend/app/routers/game.py @@ -26,6 +26,7 @@ def create_chest( """ 创建宝箱(仅主播) """ + print(f"[DEBUG] Creating chest: user={current_user.id}, role={current_user.role}, data={chest_data}") try: chest = GameService.create_chest(db, current_user, chest_data) @@ -66,6 +67,10 @@ def create_chest( created_at=chest.created_at ) except ValueError as e: + print(f"[DEBUG] Create chest ValueError: {e}") + raise HTTPException(status_code=400, detail=str(e)) + except Exception as e: + print(f"[DEBUG] Create chest Exception: {type(e).__name__}: {e}") raise HTTPException(status_code=400, detail=str(e)) diff --git a/backend/app/services/game_service.py b/backend/app/services/game_service.py index abfcf0f..751fa72 100644 --- a/backend/app/services/game_service.py +++ b/backend/app/services/game_service.py @@ -330,13 +330,17 @@ class GameService: return True except Exception as e: - db.rollback() + # 确保在异常时正确回滚 + try: + db.rollback() + except Exception: + pass raise e @staticmethod def _settle_winner(db: Session, chest: Chest, winner: str) -> None: """ - 结算获胜方 + 结算获胜方 - 简化版本,避免数据库连接问题 """ # 获取所有下注 bets = db.query(Bet).filter( @@ -355,130 +359,173 @@ class GameService: platform_share = ConfigManager.get_platform_share(db) streamer_income = int(total_pool * streamer_share) platform_income = int(total_pool * platform_share) - distributable = total_pool - streamer_income - platform_income + + # 准备结算数据 + settlement_data = { + 'streamer_income': streamer_income, + 'platform_income': platform_income, + 'settlement_results': [], + 'admin_user_info': None, + 'streamer_user_info': None + } # 主播分润 streamer = db.query(User).filter(User.id == chest.streamer_id).first() - if streamer: + if streamer and streamer_income > 0: + old_balance = streamer.balance streamer.balance += streamer_income - db.commit() + settlement_data['streamer_user_info'] = { + 'user_id': streamer.id, + 'old_balance': old_balance, + 'new_balance': streamer.balance, + 'amount': streamer_income + } - from ..services.user_service import UserService - UserService.create_transaction( - db=db, - user_id=streamer.id, - transaction_type="抽水分润", - amount=streamer_income, - balance_after=streamer.balance, - related_id=chest.id, - description=f"宝箱《{chest.title}》抽水分润" - ) + # 平台抽水 - 获取管理员信息但不更新 + admin_user = None + if platform_income > 0: + try: + admin_user = db.query(User).filter(User.role == "admin").first() + if admin_user: + old_balance = admin_user.balance + admin_user.balance += platform_income + settlement_data['admin_user_info'] = { + 'user_id': admin_user.id, + 'old_balance': old_balance, + 'new_balance': admin_user.balance, + 'amount': platform_income + } + except Exception as e: + print(f"获取管理员用户失败: {str(e)}") + admin_user = None - # 平台抽水 - 直接到管理员账户 - try: - admin_user = UserService.get_admin_user(db) - if admin_user and platform_income > 0: - # 记录转账前的余额 - old_balance = admin_user.balance - admin_user.balance += platform_income - db.commit() - - try: - UserService.create_transaction( - db=db, - user_id=admin_user.id, - transaction_type="平台抽水", - amount=platform_income, - balance_after=admin_user.balance, - related_id=chest.id, - description=f"宝箱《{chest.title}》平台抽水收益" - ) - except Exception as e: - print(f"创建平台抽水交易记录失败: {str(e)}") - # 即使交易记录创建失败,也不应回滚余额变更 - # 可以在这里添加告警通知或其他补偿措施 - - # 通知管理员余额更新 - import asyncio - try: - # 尝试获取当前事件循环 - loop = asyncio.get_running_loop() - # 局部导入避免循环导入 - from ..routers.websocket import notify_user_balance_update - loop.create_task(notify_user_balance_update(admin_user.id, admin_user.balance)) - except RuntimeError: - # 如果没有运行中的事件循环,则在新线程中处理 - import threading - def run_async(): - async def _run(): - # 局部导入避免循环导入 - from ..routers.websocket import notify_user_balance_update - await notify_user_balance_update(admin_user.id, admin_user.balance) - asyncio.run(_run()) - thread = threading.Thread(target=run_async, daemon=True) - thread.start() - - print(f"平台抽水转账成功: {platform_income} 分至管理员账户 {admin_user.id}") - except Exception as e: - # 如果转账失败,记录错误并回滚 - db.rollback() - print(f"平台抽水转账失败: {str(e)}") - # 可以在这里添加更详细的错误处理逻辑,比如发送告警通知 - - # 计算赔率 - 修改为只对获胜方抽水 + # 计算赔率 - 正确的赔率计算 winner_pool = chest.pool_a if winner == "A" else chest.pool_b loser_pool = chest.pool_b if winner == "A" else chest.pool_a if winner_pool > 0: - # 赔率计算改为:(获胜方奖池 + 失败方奖池 * 0.9) / 获胜方奖池 - odds = (winner_pool + loser_pool * 0.9) / winner_pool + # 赔率计算:失败方奖池的90%按比例分配给获胜方用户 + odds = 1 + (loser_pool * 0.9 / winner_pool) # 结算给获胜方 for bet in bets: if bet.option == winner: - payout = int(bet.amount * odds) - bet.payout = payout - bet.status = "WON" - # 给用户加钱 user = db.query(User).filter(User.id == bet.user_id).first() if user: - user.balance += payout - db.commit() - - # 通知用户余额更新 - import asyncio - try: - # 尝试获取当前事件循环 - loop = asyncio.get_running_loop() - # 局部导入避免循环导入 - from ..routers.websocket import notify_user_balance_update - loop.create_task(notify_user_balance_update(user.id, user.balance)) - except RuntimeError: - # 如果没有运行中的事件循环,则在新线程中处理 - import threading - def run_async(): - async def _run(): - # 局部导入避免循环导入 - from ..routers.websocket import notify_user_balance_update - await notify_user_balance_update(user.id, user.balance) - asyncio.run(_run()) - thread = threading.Thread(target=run_async, daemon=True) - thread.start() + # 计算奖金 + payout = int(bet.amount * odds) + bet.payout = payout + bet.status = "WON" - # 记录交易 - UserService.create_transaction( - db=db, - user_id=user.id, - transaction_type="获胜", - amount=payout, - balance_after=user.balance, - related_id=chest.id, - description=f"宝箱《{chest.title}》获胜奖金" - ) + # 更新用户余额 + old_balance = user.balance + user.balance += payout + settlement_data['settlement_results'].append({ + 'bet_id': bet.id, + 'user_id': user.id, + 'old_balance': old_balance, + 'new_balance': user.balance, + 'payout': payout, + 'success': True + }) + else: + bet.status = "WON" + bet.payout = 0 + settlement_data['settlement_results'].append({ + 'bet_id': bet.id, + 'user_id': bet.user_id, + 'error': '用户不存在', + 'success': False + }) else: bet.status = "LOST" - db.commit() + # 一次性提交所有变更 + db.commit() + + # 创建交易记录和发送通知(在提交后进行) + from ..services.user_service import UserService + + # 主播交易记录 + if settlement_data['streamer_user_info']: + try: + info = settlement_data['streamer_user_info'] + UserService.create_transaction( + db=db, + user_id=info['user_id'], + transaction_type="抽水分润", + amount=info['amount'], + balance_after=info['new_balance'], + related_id=chest.id, + description=f"宝箱《{chest.title}》抽水分润" + ) + # 发送通知 + GameService._send_balance_notification(info['user_id'], info['new_balance']) + except Exception as e: + print(f"创建主播分润交易记录失败: {str(e)}") + + # 管理员交易记录 + if settlement_data['admin_user_info']: + try: + info = settlement_data['admin_user_info'] + UserService.create_transaction( + db=db, + user_id=info['user_id'], + transaction_type="平台抽水", + amount=info['amount'], + balance_after=info['new_balance'], + related_id=chest.id, + description=f"宝箱《{chest.title}》平台抽水收益" + ) + # 发送通知 + GameService._send_balance_notification(info['user_id'], info['new_balance']) + except Exception as e: + print(f"创建平台抽水交易记录失败: {str(e)}") + + # 用户交易记录 + for result in settlement_data['settlement_results']: + if result['success']: + try: + UserService.create_transaction( + db=db, + user_id=result['user_id'], + transaction_type="获胜", + amount=result['payout'], + balance_after=result['new_balance'], + related_id=chest.id, + description=f"宝箱《{chest.title}》获胜奖金" + ) + # 发送通知 + GameService._send_balance_notification(result['user_id'], result['new_balance']) + except Exception as e: + print(f"创建用户获胜交易记录失败 - 用户ID: {result['user_id']}, 错误: {str(e)}") + + @staticmethod + def _send_balance_notification(user_id: int, new_balance: int) -> None: + """ + 发送余额更新通知 + """ + try: + import asyncio + try: + # 尝试获取当前事件循环 + loop = asyncio.get_running_loop() + # 局部导入避免循环导入 + from ..routers.websocket import notify_user_balance_update + loop.create_task(notify_user_balance_update(user_id, new_balance)) + except RuntimeError: + # 如果没有运行中的事件循环,则在新线程中处理 + import threading + def run_async(): + async def _run(): + # 局部导入避免循环导入 + from ..routers.websocket import notify_user_balance_update + await notify_user_balance_update(user_id, new_balance) + asyncio.run(_run()) + thread = threading.Thread(target=run_async, daemon=True) + thread.start() + except Exception as e: + print(f"发送余额通知失败 - 用户ID: {user_id}, 错误: {str(e)}") @staticmethod def _refund_chest(db: Session, chest: Chest) -> None: @@ -490,55 +537,78 @@ class GameService: Bet.status == "PENDING" ).all() + refund_results = [] for bet in bets: - # 退款给用户 - user = db.query(User).filter(User.id == bet.user_id).first() - if user: - user.balance += bet.amount - db.commit() - - # 通知用户余额更新 - import asyncio - try: - # 尝试获取当前事件循环 - loop = asyncio.get_running_loop() - # 局部导入避免循环导入 - from ..routers.websocket import notify_user_balance_update - loop.create_task(notify_user_balance_update(user.id, user.balance)) - except RuntimeError: - # 如果没有运行中的事件循环,则在新线程中处理 - import threading - def run_async(): - async def _run(): - # 局部导入避免循环导入 - from ..routers.websocket import notify_user_balance_update - await notify_user_balance_update(user.id, user.balance) - asyncio.run(_run()) - thread = threading.Thread(target=run_async, daemon=True) - thread.start() - - # 记录交易 - from ..services.user_service import UserService - UserService.create_transaction( - db=db, - user_id=user.id, - transaction_type="退款", - amount=bet.amount, - balance_after=user.balance, - related_id=chest.id, - description=f"宝箱《{chest.title}》流局退款" - ) - - bet.status = "REFUNDED" + try: + # 退款给用户 + user = db.query(User).filter(User.id == bet.user_id).first() + if user: + old_balance = user.balance + user.balance += bet.amount + bet.status = "REFUNDED" + refund_results.append({ + 'bet_id': bet.id, + 'user_id': user.id, + 'old_balance': old_balance, + 'new_balance': user.balance, + 'refund_amount': bet.amount, + 'success': True + }) + else: + bet.status = "REFUNDED" + refund_results.append({ + 'bet_id': bet.id, + 'user_id': bet.user_id, + 'error': '用户不存在', + 'success': False + }) + except Exception as e: + # 记录错误但不中断其他用户的退款 + print(f"退款失败 - 下注ID: {bet.id}, 错误: {str(e)}") + bet.status = "REFUNDED" + refund_results.append({ + 'bet_id': bet.id, + 'user_id': bet.user_id, + 'error': str(e), + 'success': False + }) # 重置奖池 chest.pool_a = 0 chest.pool_b = 0 + + # 一次性提交所有变更 db.commit() # 更新缓存 update_pool_cache(chest.id, 0, 0) + # 创建交易记录和发送通知(在提交后进行) + for result in refund_results: + if result['success']: + user_id = result['user_id'] + refund_amount = result['refund_amount'] + new_balance = result['new_balance'] + + # 发送通知 + GameService._send_balance_notification(user_id, new_balance) + + # 记录交易 + try: + from ..services.user_service import UserService + UserService.create_transaction( + db=db, + user_id=user_id, + transaction_type="退款", + amount=refund_amount, + balance_after=new_balance, + related_id=chest.id, + description=f"宝箱《{chest.title}》流局退款" + ) + except Exception as e: + print(f"创建交易记录失败 - 用户ID: {user_id}, 错误: {str(e)}") + # 即使交易记录创建失败,也不回滚余额(因为已经提交) + @staticmethod def get_chest_bets(db: Session, chest_id: int) -> List[Bet]: """ diff --git a/baoxiang.sql b/baoxiang.sql deleted file mode 100644 index da4907b..0000000 --- a/baoxiang.sql +++ /dev/null @@ -1,356 +0,0 @@ -/* - Navicat Premium Dump SQL - - Source Server : 本地 - Source Server Type : MySQL - Source Server Version : 80406 (8.4.6) - Source Host : localhost:3306 - Source Schema : baoxiang - - Target Server Type : MySQL - Target Server Version : 80406 (8.4.6) - File Encoding : 65001 - - Date: 15/12/2025 17:44:49 -*/ - -SET NAMES utf8mb4; -SET FOREIGN_KEY_CHECKS = 0; - --- ---------------------------- --- Table structure for announcements --- ---------------------------- -DROP TABLE IF EXISTS `announcements`; -CREATE TABLE `announcements` ( - `id` int NOT NULL AUTO_INCREMENT, - `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '公告标题', - `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '公告内容', - `type` enum('INFO','WARNING','PRIZE') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '公告类型', - `is_pinned` tinyint(1) NULL DEFAULT NULL COMMENT '是否置顶', - `priority` int NULL DEFAULT NULL COMMENT '优先级(数字越大优先级越高)', - `starts_at` datetime NULL DEFAULT NULL COMMENT '生效时间', - `expires_at` datetime NULL DEFAULT NULL COMMENT '过期时间', - `created_at` datetime NULL DEFAULT (now()) COMMENT '创建时间', - `updated_at` datetime NULL DEFAULT (now()) COMMENT '更新时间', - PRIMARY KEY (`id`) USING BTREE, - INDEX `ix_announcements_id`(`id` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; - --- ---------------------------- --- Records of announcements --- ---------------------------- -INSERT INTO `announcements` VALUES (1, 'c', 'a', 'WARNING', 1, 0, NULL, NULL, '2025-12-13 08:16:37', '2025-12-13 08:16:37'); -INSERT INTO `announcements` VALUES (3, 'dfa', 'sfasd', 'WARNING', 1, 0, NULL, NULL, '2025-12-14 03:16:04', '2025-12-14 03:16:04'); - --- ---------------------------- --- Table structure for bets --- ---------------------------- -DROP TABLE IF EXISTS `bets`; -CREATE TABLE `bets` ( - `id` int NOT NULL AUTO_INCREMENT, - `user_id` int NOT NULL COMMENT '用户ID', - `chest_id` int NOT NULL COMMENT '宝箱ID', - `option` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '下注选项', - `amount` bigint NOT NULL COMMENT '下注金额(分)', - `payout` bigint NULL DEFAULT NULL COMMENT '获奖金额(分)', - `status` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '状态', - `created_at` datetime NULL DEFAULT (now()) COMMENT '创建时间', - PRIMARY KEY (`id`) USING BTREE, - INDEX `ix_bets_chest_id`(`chest_id` ASC) USING BTREE, - INDEX `ix_bets_id`(`id` ASC) USING BTREE, - INDEX `ix_bets_user_id`(`user_id` ASC) USING BTREE, - CONSTRAINT `bets_ibfk_1` FOREIGN KEY (`chest_id`) REFERENCES `chests` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT -) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; - --- ---------------------------- --- Records of bets --- ---------------------------- -INSERT INTO `bets` VALUES (1, 7, 3, 'A', 500, 0, 'PENDING', '2025-12-14 04:35:46'); -INSERT INTO `bets` VALUES (2, 9, 3, 'A', 2300, 0, 'PENDING', '2025-12-14 04:39:06'); -INSERT INTO `bets` VALUES (3, 9, 3, 'B', 2500, 0, 'PENDING', '2025-12-14 04:44:04'); -INSERT INTO `bets` VALUES (4, 9, 4, 'A', 200, 180, 'WON', '2025-12-14 05:15:13'); -INSERT INTO `bets` VALUES (5, 9, 6, 'A', 3000, 0, 'LOST', '2025-12-14 05:23:54'); -INSERT INTO `bets` VALUES (6, 9, 6, 'B', 1000, 3600, 'WON', '2025-12-14 05:23:58'); -INSERT INTO `bets` VALUES (7, 10, 3, 'A', 1100, 0, 'PENDING', '2025-12-14 05:26:08'); -INSERT INTO `bets` VALUES (8, 9, 9, 'A', 100, 0, 'PENDING', '2025-12-14 06:43:42'); -INSERT INTO `bets` VALUES (9, 9, 10, 'A', 500, 0, 'LOST', '2025-12-14 10:16:39'); -INSERT INTO `bets` VALUES (10, 9, 10, 'B', 1000, 1350, 'WON', '2025-12-14 10:17:11'); -INSERT INTO `bets` VALUES (11, 9, 11, 'A', 1000, 0, 'PENDING', '2025-12-14 10:19:24'); -INSERT INTO `bets` VALUES (12, 9, 12, 'A', 500, 450, 'WON', '2025-12-14 10:39:53'); -INSERT INTO `bets` VALUES (13, 9, 13, 'B', 500, 450, 'WON', '2025-12-14 10:56:23'); -INSERT INTO `bets` VALUES (14, 9, 14, 'A', 10911, 18700, 'WON', '2025-12-14 11:03:29'); -INSERT INTO `bets` VALUES (15, 9, 14, 'B', 9865, 0, 'LOST', '2025-12-14 11:03:38'); -INSERT INTO `bets` VALUES (16, 9, 17, 'A', 100, 0, 'PENDING', '2025-12-14 11:23:25'); - --- ---------------------------- --- Table structure for chests --- ---------------------------- -DROP TABLE IF EXISTS `chests`; -CREATE TABLE `chests` ( - `id` int NOT NULL AUTO_INCREMENT, - `streamer_id` int NOT NULL COMMENT '主播ID', - `title` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '宝箱标题', - `option_a` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '选项A', - `option_b` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '选项B', - `status` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '宝箱状态', - `pool_a` bigint NULL DEFAULT NULL COMMENT 'A边奖池(分)', - `pool_b` bigint NULL DEFAULT NULL COMMENT 'B边奖池(分)', - `total_bets` int NULL DEFAULT NULL COMMENT '总下注次数', - `countdown_seconds` int NULL DEFAULT NULL COMMENT '倒计时(秒)', - `locked_at` datetime NULL DEFAULT NULL COMMENT '封盘时间', - `settled_at` datetime NULL DEFAULT NULL COMMENT '结算时间', - `result` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '结算结果', - `created_at` datetime NULL DEFAULT (now()) COMMENT '创建时间', - PRIMARY KEY (`id`) USING BTREE, - INDEX `ix_chests_streamer_id`(`streamer_id` ASC) USING BTREE, - INDEX `ix_chests_id`(`id` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 22 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; - --- ---------------------------- --- Records of chests --- ---------------------------- -INSERT INTO `chests` VALUES (3, 7, 'sdaf', 'asdf', 'adf', 'BETTING', 3900, 2500, 11, 298, NULL, NULL, NULL, '2025-12-14 04:32:51'); -INSERT INTO `chests` VALUES (4, 10, 'ad', '1', '2', 'FINISHED', 200, 0, 2, 300, '2025-12-14 13:15:24', '2025-12-14 13:36:59', 'A', '2025-12-14 05:13:40'); -INSERT INTO `chests` VALUES (5, 10, '123', '1', '1', 'FINISHED', 0, 0, 0, 300, '2025-12-14 13:22:59', '2025-12-14 13:36:54', 'A', '2025-12-14 05:22:55'); -INSERT INTO `chests` VALUES (6, 10, '123', '1', '1', 'FINISHED', 3000, 1000, 5, 300, '2025-12-14 13:24:45', '2025-12-14 13:36:43', 'B', '2025-12-14 05:23:30'); -INSERT INTO `chests` VALUES (7, 10, '`12', '1', '2', 'FINISHED', 0, 0, 0, 300, '2025-12-14 14:38:28', '2025-12-14 14:38:32', 'B', '2025-12-14 06:37:37'); -INSERT INTO `chests` VALUES (8, 10, '123', '1', '12', 'FINISHED', 0, 0, 0, 60, '2025-12-14 14:42:30', '2025-12-14 14:42:35', 'B', '2025-12-14 06:38:40'); -INSERT INTO `chests` VALUES (9, 10, '123', '1', '12', 'FINISHED', 100, 0, 1, 60, '2025-12-14 18:15:45', '2025-12-14 18:15:50', 'B', '2025-12-14 06:42:51'); -INSERT INTO `chests` VALUES (10, 10, '123', '1', '12', 'FINISHED', 500, 1000, 2, 60, '2025-12-14 18:17:59', '2025-12-14 18:18:03', 'B', '2025-12-14 10:16:20'); -INSERT INTO `chests` VALUES (11, 10, '123', '123', '111', 'FINISHED', 1000, 0, 1, 60, '2025-12-14 18:39:21', '2025-12-14 18:39:25', 'B', '2025-12-14 10:18:11'); -INSERT INTO `chests` VALUES (12, 10, '123', '123', '12311', 'FINISHED', 500, 0, 1, 300, '2025-12-14 18:44:05', '2025-12-14 18:44:11', 'A', '2025-12-14 10:39:32'); -INSERT INTO `chests` VALUES (13, 10, '123', '1', '12', 'FINISHED', 0, 500, 1, 300, '2025-12-14 19:02:28', '2025-12-14 19:02:32', 'B', '2025-12-14 10:44:38'); -INSERT INTO `chests` VALUES (14, 10, '123', '11', '22', 'FINISHED', 10911, 9865, 2, 300, '2025-12-14 19:04:26', '2025-12-14 19:04:31', 'A', '2025-12-14 11:03:12'); -INSERT INTO `chests` VALUES (15, 10, '123', '11', '12', 'FINISHED', 0, 0, 0, 300, '2025-12-14 19:14:02', '2025-12-14 19:14:06', 'B', '2025-12-14 11:09:53'); -INSERT INTO `chests` VALUES (16, 10, '123', '123', '111', 'FINISHED', 0, 0, 0, 3600, '2025-12-14 19:22:41', '2025-12-14 19:22:44', 'B', '2025-12-14 11:14:21'); -INSERT INTO `chests` VALUES (17, 10, '123', '11', '22', 'FINISHED', 100, 0, 1, 300, '2025-12-14 19:31:50', '2025-12-14 19:31:54', 'B', '2025-12-14 11:23:14'); -INSERT INTO `chests` VALUES (18, 10, '请问', '11', '22', 'FINISHED', 0, 0, 0, 3000, '2025-12-14 19:56:18', '2025-12-14 19:56:22', 'A', '2025-12-14 11:32:03'); -INSERT INTO `chests` VALUES (19, 10, '123', '12', '1211', 'FINISHED', 0, 0, 0, 300, '2025-12-14 19:59:04', '2025-12-14 19:59:08', 'REFUND', '2025-12-14 11:56:27'); -INSERT INTO `chests` VALUES (20, 12, '测试宝箱 19:57:28', '选项A', '选项B', 'BETTING', 0, 0, 0, 60, NULL, NULL, NULL, '2025-12-14 11:57:30'); -INSERT INTO `chests` VALUES (21, 10, '1123', '11', '22', 'FINISHED', 0, 0, 0, 300, '2025-12-15 12:28:43', '2025-12-15 12:28:54', 'REFUND', '2025-12-15 04:28:25'); - --- ---------------------------- --- Table structure for streamer_profiles --- ---------------------------- -DROP TABLE IF EXISTS `streamer_profiles`; -CREATE TABLE `streamer_profiles` ( - `id` int NOT NULL AUTO_INCREMENT, - `user_id` int NOT NULL COMMENT '用户ID', - `display_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '主播展示名称', - `avatar_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '主播头像', - `bio` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '主播简介', - `commission_rate` decimal(5, 2) NULL DEFAULT NULL COMMENT '主播抽成比例(%)', - `max_active_chests` int NULL DEFAULT NULL COMMENT '最大活跃宝箱数', - `total_chests` int NULL DEFAULT NULL COMMENT '历史宝箱总数', - `total_winnings` decimal(15, 2) NULL DEFAULT NULL COMMENT '历史获奖总额(分)', - `status` enum('ACTIVE','SUSPENDED','BANNED') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '主播状态', - `created_at` datetime NULL DEFAULT (now()) COMMENT '创建时间', - `updated_at` datetime NULL DEFAULT (now()) COMMENT '更新时间', - PRIMARY KEY (`id`) USING BTREE, - UNIQUE INDEX `user_id`(`user_id` ASC) USING BTREE, - INDEX `ix_streamer_profiles_id`(`id` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; - --- ---------------------------- --- Records of streamer_profiles --- ---------------------------- -INSERT INTO `streamer_profiles` VALUES (1, 9, 'test1', NULL, NULL, 5.00, 10, 0, 0.00, 'ACTIVE', '2025-12-14 03:30:38', '2025-12-14 03:30:38'); -INSERT INTO `streamer_profiles` VALUES (2, 7, 'zhubo', NULL, NULL, 5.00, 10, 0, 0.00, 'ACTIVE', '2025-12-14 04:32:10', '2025-12-14 04:32:10'); -INSERT INTO `streamer_profiles` VALUES (3, 10, 'zhubo12', NULL, NULL, 5.00, 10, 0, 0.00, 'ACTIVE', '2025-12-14 05:13:20', '2025-12-14 05:13:20'); - --- ---------------------------- --- Table structure for system_configs --- ---------------------------- -DROP TABLE IF EXISTS `system_configs`; -CREATE TABLE `system_configs` ( - `id` int NOT NULL AUTO_INCREMENT, - `config_key` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '配置键', - `config_value` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '配置值', - `config_type` enum('STRING','NUMBER','BOOLEAN','JSON') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '配置类型', - `category` enum('GAME_ECONOMY','GAME_LOGIC','SYSTEM_OPERATIONS','UI_DISPLAY') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '配置分类', - `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '配置描述', - `is_editable` tinyint(1) NULL DEFAULT NULL COMMENT '是否可编辑', - `is_public` tinyint(1) NULL DEFAULT NULL COMMENT '是否对前端公开', - `display_order` int NULL DEFAULT NULL COMMENT '显示顺序', - `created_at` datetime NULL DEFAULT (now()) COMMENT '创建时间', - `updated_at` datetime NULL DEFAULT (now()) COMMENT '更新时间', - PRIMARY KEY (`id`) USING BTREE, - UNIQUE INDEX `ix_system_configs_config_key`(`config_key` ASC) USING BTREE, - INDEX `ix_system_configs_id`(`id` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 23 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; - --- ---------------------------- --- Records of system_configs --- ---------------------------- -INSERT INTO `system_configs` VALUES (1, 'GAME_NEW_USER_REWARD', '1', 'NUMBER', 'GAME_ECONOMY', '新用户注册奖励(分)', 1, 0, 1, '2025-12-14 02:44:50', '2025-12-14 05:32:52'); -INSERT INTO `system_configs` VALUES (2, 'GAME_DAILY_ALLOWANCE', '50', 'NUMBER', 'GAME_ECONOMY', '每日低保(分)', 1, 0, 2, '2025-12-14 02:44:50', '2025-12-14 04:12:58'); -INSERT INTO `system_configs` VALUES (3, 'GAME_ALLOWANCE_THRESHOLD', '10', 'NUMBER', 'GAME_ECONOMY', '低保门槛(分)', 1, 0, 3, '2025-12-14 02:44:50', '2025-12-14 05:33:00'); -INSERT INTO `system_configs` VALUES (4, 'GAME_HOUSE_EDGE', '0.10', 'NUMBER', 'GAME_ECONOMY', '总抽水比例', 1, 0, 4, '2025-12-14 02:44:50', '2025-12-14 02:44:50'); -INSERT INTO `system_configs` VALUES (5, 'GAME_STREAMER_SHARE', '0.05', 'NUMBER', 'GAME_ECONOMY', '主播分润比例', 1, 0, 5, '2025-12-14 02:44:50', '2025-12-14 02:44:50'); -INSERT INTO `system_configs` VALUES (6, 'GAME_PLATFORM_SHARE', '0.05', 'NUMBER', 'GAME_ECONOMY', '平台分润比例', 1, 0, 6, '2025-12-14 02:44:50', '2025-12-14 02:44:50'); -INSERT INTO `system_configs` VALUES (7, 'GAME_DAILY_CHECKIN_REWARD', '10', 'NUMBER', 'GAME_ECONOMY', '每日签到奖励(分)', 1, 0, 7, '2025-12-14 02:44:50', '2025-12-14 05:33:07'); -INSERT INTO `system_configs` VALUES (8, 'GAME_DEFAULT_COUNTDOWN', '300', 'NUMBER', 'GAME_LOGIC', '默认倒计时(秒)', 1, 0, 1, '2025-12-14 02:44:50', '2025-12-14 02:44:50'); -INSERT INTO `system_configs` VALUES (9, 'GAME_MIN_COUNTDOWN', '10', 'NUMBER', 'GAME_LOGIC', '最小倒计时(秒)', 1, 0, 2, '2025-12-14 02:44:50', '2025-12-14 02:44:50'); -INSERT INTO `system_configs` VALUES (10, 'GAME_MAX_COUNTDOWN', '3600', 'NUMBER', 'GAME_LOGIC', '最大倒计时(秒)', 1, 0, 3, '2025-12-14 02:44:50', '2025-12-14 02:44:50'); -INSERT INTO `system_configs` VALUES (11, 'GAME_DEFAULT_MAX_ACTIVE_CHESTS', '10', 'NUMBER', 'GAME_LOGIC', '默认最大活跃宝箱数', 1, 0, 4, '2025-12-14 02:44:50', '2025-12-14 02:44:50'); -INSERT INTO `system_configs` VALUES (12, 'GAME_MIN_COMMISSION_RATE', '0.0', 'NUMBER', 'GAME_LOGIC', '最小主播抽成(%)', 1, 0, 5, '2025-12-14 02:44:50', '2025-12-14 02:44:50'); -INSERT INTO `system_configs` VALUES (13, 'GAME_MAX_COMMISSION_RATE', '100.0', 'NUMBER', 'GAME_LOGIC', '最大主播抽成(%)', 1, 0, 6, '2025-12-14 02:44:50', '2025-12-14 02:44:50'); -INSERT INTO `system_configs` VALUES (14, 'GAME_DEFAULT_COMMISSION_RATE', '5.0', 'NUMBER', 'GAME_LOGIC', '默认主播抽成(%)', 1, 0, 7, '2025-12-14 02:44:50', '2025-12-14 02:44:50'); -INSERT INTO `system_configs` VALUES (15, 'PAGINATION_DEFAULT_PAGE_SIZE', '10', 'NUMBER', 'SYSTEM_OPERATIONS', '默认分页大小', 1, 0, 1, '2025-12-14 02:44:50', '2025-12-14 05:33:24'); -INSERT INTO `system_configs` VALUES (16, 'PAGINATION_ADMIN_PAGE_SIZE', '10', 'NUMBER', 'SYSTEM_OPERATIONS', '管理员页面分页大小', 1, 0, 2, '2025-12-14 02:44:50', '2025-12-14 05:33:28'); -INSERT INTO `system_configs` VALUES (17, 'PAGINATION_ANNOUNCEMENT_PAGE_SIZE', '10', 'NUMBER', 'SYSTEM_OPERATIONS', '公告页面分页大小', 1, 0, 3, '2025-12-14 02:44:50', '2025-12-14 02:44:50'); -INSERT INTO `system_configs` VALUES (18, 'WS_BROADCAST_INTERVAL', '200', 'NUMBER', 'SYSTEM_OPERATIONS', 'WebSocket广播间隔(毫秒)', 1, 0, 4, '2025-12-14 02:44:50', '2025-12-14 02:44:50'); -INSERT INTO `system_configs` VALUES (19, 'WS_HEARTBEAT_INTERVAL', '30', 'NUMBER', 'SYSTEM_OPERATIONS', 'WebSocket心跳间隔(秒)', 1, 0, 5, '2025-12-14 02:44:50', '2025-12-14 02:44:50'); -INSERT INTO `system_configs` VALUES (20, 'WS_CONNECTION_TIMEOUT', '60', 'NUMBER', 'SYSTEM_OPERATIONS', 'WebSocket连接超时(秒)', 1, 0, 6, '2025-12-14 02:44:50', '2025-12-14 02:44:50'); -INSERT INTO `system_configs` VALUES (21, 'ANNOUNCEMENT_DEFAULT_PRIORITY', '0', 'NUMBER', 'UI_DISPLAY', '公告默认优先级', 1, 0, 1, '2025-12-14 02:44:50', '2025-12-14 02:44:50'); -INSERT INTO `system_configs` VALUES (22, 'ANNOUNCEMENT_MAX_PRIORITY', '100', 'NUMBER', 'UI_DISPLAY', '公告最大优先级', 1, 0, 2, '2025-12-14 02:44:50', '2025-12-14 02:44:50'); - --- ---------------------------- --- Table structure for transactions --- ---------------------------- -DROP TABLE IF EXISTS `transactions`; -CREATE TABLE `transactions` ( - `id` int NOT NULL AUTO_INCREMENT, - `user_id` int NOT NULL COMMENT '用户ID', - `type` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '交易类型', - `amount` bigint NOT NULL COMMENT '金额(分)', - `balance_after` bigint NOT NULL COMMENT '交易后余额', - `related_id` int NULL DEFAULT NULL COMMENT '关联ID', - `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '描述', - `created_at` datetime NULL DEFAULT (now()) COMMENT '创建时间', - PRIMARY KEY (`id`) USING BTREE, - INDEX `ix_transactions_id`(`id` ASC) USING BTREE, - INDEX `ix_transactions_user_id`(`user_id` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 64 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; - --- ---------------------------- --- Records of transactions --- ---------------------------- -INSERT INTO `transactions` VALUES (1, 5, '低保', 5000, 5000, NULL, '每日低保', '2025-12-13 07:14:26'); -INSERT INTO `transactions` VALUES (2, 6, '注册奖励', 100000, 0, NULL, '新用户注册奖励', '2025-12-13 07:39:19'); -INSERT INTO `transactions` VALUES (3, 6, '低保', 5000, 5000, NULL, '每日低保', '2025-12-13 07:39:23'); -INSERT INTO `transactions` VALUES (4, 7, '注册奖励', 100000, 0, NULL, '新用户注册奖励', '2025-12-13 07:46:22'); -INSERT INTO `transactions` VALUES (5, 7, '低保', 5000, 5000, NULL, '每日低保', '2025-12-13 07:46:38'); -INSERT INTO `transactions` VALUES (6, 8, '注册奖励', 100000, 0, NULL, '新用户注册奖励', '2025-12-13 09:03:37'); -INSERT INTO `transactions` VALUES (7, 8, '低保', 5000, 5000, NULL, '每日低保', '2025-12-13 09:07:49'); -INSERT INTO `transactions` VALUES (8, 9, '注册奖励', 100000, 0, NULL, '新用户注册奖励', '2025-12-13 09:22:26'); -INSERT INTO `transactions` VALUES (9, 9, '低保', 5000, 5000, NULL, '每日低保', '2025-12-13 09:28:01'); -INSERT INTO `transactions` VALUES (10, 5, '管理员调整', -22211, -17211, NULL, '管理员调整 (操作人: admin)', '2025-12-14 02:42:50'); -INSERT INTO `transactions` VALUES (11, 9, '管理员调整', 22, 5022, NULL, '管理员调整 (操作人: admin)', '2025-12-14 03:24:27'); -INSERT INTO `transactions` VALUES (12, 7, '下注', -500, 4500, 3, '下注sdaf(A边)', '2025-12-14 04:35:46'); -INSERT INTO `transactions` VALUES (13, 9, '下注', -1000, 4022, 3, '下注sdaf(A边)', '2025-12-14 04:39:06'); -INSERT INTO `transactions` VALUES (14, 9, '下注', -1000, 3022, 3, '下注sdaf(B边)', '2025-12-14 04:44:04'); -INSERT INTO `transactions` VALUES (15, 9, '下注', -1000, 2022, 3, '追加下注sdaf(B边)', '2025-12-14 04:44:10'); -INSERT INTO `transactions` VALUES (16, 9, '下注', -500, 1522, 3, '追加下注sdaf(B边)', '2025-12-14 04:44:18'); -INSERT INTO `transactions` VALUES (17, 9, '下注', -1000, 522, 3, '追加下注sdaf(A边)', '2025-12-14 04:46:23'); -INSERT INTO `transactions` VALUES (18, 9, '下注', -100, 422, 3, '追加下注sdaf(A边)', '2025-12-14 04:46:28'); -INSERT INTO `transactions` VALUES (19, 10, '注册奖励', 100000, 0, NULL, '新用户注册奖励', '2025-12-14 05:12:53'); -INSERT INTO `transactions` VALUES (20, 9, '下注', -100, 322, 4, '下注ad(A边)', '2025-12-14 05:15:13'); -INSERT INTO `transactions` VALUES (21, 9, '下注', -100, 222, 4, '追加下注ad(A边)', '2025-12-14 05:15:19'); -INSERT INTO `transactions` VALUES (22, 5, '低保', 5000, -12211, NULL, '每日低保', '2025-12-14 05:17:33'); -INSERT INTO `transactions` VALUES (23, 9, '管理员调整', 111111, 111333, NULL, '管理员调整 (操作人: admin)', '2025-12-14 05:18:01'); -INSERT INTO `transactions` VALUES (24, 5, '管理员调整', 111111, 98900, NULL, '省分公司个 (操作人: admin)', '2025-12-14 05:18:06'); -INSERT INTO `transactions` VALUES (25, 5, '管理员调整', 111, 99011, NULL, '管理员调整 (操作人: admin)', '2025-12-14 05:18:25'); -INSERT INTO `transactions` VALUES (26, 5, '管理员调整', 3452342, 3551353, NULL, '管理员调整 (操作人: admin)', '2025-12-14 05:18:48'); -INSERT INTO `transactions` VALUES (27, 9, '下注', -500, 110833, 6, '下注123(A边)', '2025-12-14 05:23:54'); -INSERT INTO `transactions` VALUES (28, 9, '下注', -1000, 109833, 6, '下注123(B边)', '2025-12-14 05:23:58'); -INSERT INTO `transactions` VALUES (29, 9, '下注', -500, 109333, 6, '追加下注123(A边)', '2025-12-14 05:24:04'); -INSERT INTO `transactions` VALUES (30, 9, '下注', -1000, 108333, 6, '追加下注123(A边)', '2025-12-14 05:24:13'); -INSERT INTO `transactions` VALUES (31, 9, '下注', -1000, 107333, 6, '追加下注123(A边)', '2025-12-14 05:24:27'); -INSERT INTO `transactions` VALUES (32, 10, '低保', 5000, 5000, NULL, '每日低保', '2025-12-14 05:25:12'); -INSERT INTO `transactions` VALUES (33, 10, '下注', -100, 4900, 3, '下注sdaf(A边)', '2025-12-14 05:26:08'); -INSERT INTO `transactions` VALUES (34, 10, '抽水分润', 200, 5100, 6, '宝箱《123》抽水分润', '2025-12-14 05:36:42'); -INSERT INTO `transactions` VALUES (35, 9, '获胜', 3600, 110933, 6, '宝箱《123》获胜奖金', '2025-12-14 05:36:42'); -INSERT INTO `transactions` VALUES (36, 10, '抽水分润', 10, 5110, 4, '宝箱《ad》抽水分润', '2025-12-14 05:36:59'); -INSERT INTO `transactions` VALUES (37, 9, '获胜', 180, 111113, 4, '宝箱《ad》获胜奖金', '2025-12-14 05:36:59'); -INSERT INTO `transactions` VALUES (38, 7, '管理员调整', 111, 4611, NULL, '管理员调整 (操作人: admin)', '2025-12-14 05:59:43'); -INSERT INTO `transactions` VALUES (39, 5, '管理员调整', -10000, 3541353, NULL, '管理员调整 (操作人: admin)', '2025-12-14 05:59:53'); -INSERT INTO `transactions` VALUES (40, 5, '管理员调整', -3540000, 1353, NULL, '管理员调整 (操作人: admin)', '2025-12-14 06:00:13'); -INSERT INTO `transactions` VALUES (41, 9, '下注', -100, 111013, 3, '追加下注sdaf(A边)', '2025-12-14 06:11:27'); -INSERT INTO `transactions` VALUES (42, 9, '下注', -100, 110913, 3, '追加下注sdaf(A边)', '2025-12-14 06:11:33'); -INSERT INTO `transactions` VALUES (43, 5, '管理员调整', 1111, 2464, NULL, '管理员调整 (操作人: admin)', '2025-12-14 06:12:33'); -INSERT INTO `transactions` VALUES (44, 9, '下注', -100, 110813, 9, '下注123(A边)', '2025-12-14 06:43:42'); -INSERT INTO `transactions` VALUES (45, 10, '抽水分润', 5, 5115, 9, '宝箱《123》抽水分润', '2025-12-14 10:15:49'); -INSERT INTO `transactions` VALUES (46, 10, '下注', -1000, 4115, 3, '追加下注sdaf(A边)', '2025-12-14 10:16:07'); -INSERT INTO `transactions` VALUES (47, 9, '下注', -500, 110313, 10, '下注123(A边)', '2025-12-14 10:16:39'); -INSERT INTO `transactions` VALUES (48, 9, '下注', -1000, 109313, 10, '下注123(B边)', '2025-12-14 10:17:11'); -INSERT INTO `transactions` VALUES (49, 10, '抽水分润', 75, 4190, 10, '宝箱《123》抽水分润', '2025-12-14 10:18:02'); -INSERT INTO `transactions` VALUES (50, 9, '获胜', 1350, 110663, 10, '宝箱《123》获胜奖金', '2025-12-14 10:18:02'); -INSERT INTO `transactions` VALUES (51, 9, '下注', -1000, 109663, 11, '下注123(A边)', '2025-12-14 10:19:24'); -INSERT INTO `transactions` VALUES (52, 10, '抽水分润', 50, 4240, 11, '宝箱《123》抽水分润', '2025-12-14 10:39:25'); -INSERT INTO `transactions` VALUES (53, 9, '下注', -500, 109163, 12, '下注123(A边)', '2025-12-14 10:39:53'); -INSERT INTO `transactions` VALUES (54, 10, '抽水分润', 25, 4265, 12, '宝箱《123》抽水分润', '2025-12-14 10:44:08'); -INSERT INTO `transactions` VALUES (55, 9, '下注', -500, 109113, 13, '下注123(B边)', '2025-12-14 10:56:23'); -INSERT INTO `transactions` VALUES (56, 10, '抽水分润', 25, 4290, 13, '宝箱《123》抽水分润', '2025-12-14 11:02:31'); -INSERT INTO `transactions` VALUES (57, 9, '获胜', 450, 109563, 13, '宝箱《123》获胜奖金', '2025-12-14 11:02:31'); -INSERT INTO `transactions` VALUES (58, 9, '下注', -10911, 98652, 14, '下注123(A边)', '2025-12-14 11:03:29'); -INSERT INTO `transactions` VALUES (59, 9, '下注', -9865, 88787, 14, '下注123(B边)', '2025-12-14 11:03:38'); -INSERT INTO `transactions` VALUES (60, 10, '抽水分润', 1038, 5328, 14, '宝箱《123》抽水分润', '2025-12-14 11:04:30'); -INSERT INTO `transactions` VALUES (61, 9, '获胜', 18700, 107487, 14, '宝箱《123》获胜奖金', '2025-12-14 11:04:30'); -INSERT INTO `transactions` VALUES (62, 9, '下注', -100, 107387, 17, '下注123(A边)', '2025-12-14 11:23:26'); -INSERT INTO `transactions` VALUES (63, 10, '抽水分润', 5, 5333, 17, '宝箱《123》抽水分润', '2025-12-14 11:31:54'); - --- ---------------------------- --- Table structure for user_operation_logs --- ---------------------------- -DROP TABLE IF EXISTS `user_operation_logs`; -CREATE TABLE `user_operation_logs` ( - `id` int NOT NULL AUTO_INCREMENT, - `user_id` int NOT NULL COMMENT '操作用户ID', - `operator_id` int NULL DEFAULT NULL COMMENT '操作人ID(管理员)', - `operation_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '操作类型', - `operation_details` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '操作详情(JSON格式)', - `ip_address` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT 'IP地址', - `created_at` datetime NULL DEFAULT (now()) COMMENT '创建时间', - PRIMARY KEY (`id`) USING BTREE, - INDEX `ix_user_operation_logs_id`(`id` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; - --- ---------------------------- --- Records of user_operation_logs --- ---------------------------- - --- ---------------------------- --- Table structure for users --- ---------------------------- -DROP TABLE IF EXISTS `users`; -CREATE TABLE `users` ( - `id` int NOT NULL AUTO_INCREMENT, - `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户名', - `email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '邮箱', - `hashed_password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '哈希密码', - `role` enum('USER','STREAMER','ADMIN') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户角色', - `nickname` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '用户昵称', - `avatar_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '头像URL', - `phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '手机号', - `status` enum('ACTIVE','DISABLED','BANNED') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '用户状态', - `balance` bigint NULL DEFAULT NULL COMMENT '余额(分)', - `version` int NULL DEFAULT NULL COMMENT '乐观锁版本号', - `last_login_at` datetime NULL DEFAULT NULL COMMENT '最后登录时间', - `login_count` int NULL DEFAULT NULL COMMENT '登录次数', - `created_at` datetime NULL DEFAULT (now()) COMMENT '创建时间', - `updated_at` datetime NULL DEFAULT (now()) COMMENT '更新时间', - `is_active` tinyint NULL DEFAULT NULL COMMENT '是否激活(1:是 0:否)', - PRIMARY KEY (`id`) USING BTREE, - UNIQUE INDEX `ix_users_email`(`email` ASC) USING BTREE, - UNIQUE INDEX `ix_users_username`(`username` ASC) USING BTREE, - INDEX `ix_users_id`(`id` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; - --- ---------------------------- --- Records of users --- ---------------------------- -INSERT INTO `users` VALUES (1, 'testuser', 'test@example.com', '$scrypt$ln=16,r=8,p=1$sdYa4zzHuHduLQWAsLZWSg$jUu5IbiK+htBbLOt/qBP6WR5zQRMMPwbhVDx6aP/dKw', 'USER', NULL, NULL, NULL, 'ACTIVE', 0, 0, NULL, 0, '2025-12-13 03:07:55', '2025-12-14 02:03:21', 1); -INSERT INTO `users` VALUES (2, 'testuser123', 'test123@example.com', '$scrypt$ln=16,r=8,p=1$Zux9b21NiTFGqNXamzOG0A$4gQGVyGfobpB87bjk44+dwhX5b/tj7x8YTxGT83aFHg', 'USER', NULL, NULL, NULL, 'ACTIVE', 0, 0, NULL, 0, '2025-12-13 03:07:55', '2025-12-13 03:07:55', 1); -INSERT INTO `users` VALUES (3, 'test', 'test@test.com', '$scrypt$ln=16,r=8,p=1$VMoZ41zL2ZsTYoxx7v0/Bw$yQOZIticgjRM7s4MTVXV44wgYgehsrxAoki27ot2fAc', 'USER', NULL, NULL, NULL, 'ACTIVE', 0, 0, NULL, 0, '2025-12-13 03:07:55', '2025-12-13 03:07:55', 1); -INSERT INTO `users` VALUES (5, 'admin', 'amdin@ad.c', '$scrypt$ln=16,r=8,p=1$AaDU+l9rjTGGsLYWIsS4tw$EyZmBBLjJifJSiBWexovADnvvR2hRq8NMSZIBePBzfs', 'ADMIN', NULL, NULL, NULL, 'ACTIVE', 2464, 7, NULL, 0, '2025-12-13 03:10:35', '2025-12-14 06:12:33', 1); -INSERT INTO `users` VALUES (6, 'user1', 'user@qq.com', '$scrypt$ln=16,r=8,p=1$xzhHiHGu1dq7lzIGQAiBMA$/IMDnslsTmQSNclXcX1z6z8/6RX9mUdgDIJU9PZaOV4', 'USER', NULL, NULL, NULL, 'ACTIVE', 5000, 0, NULL, 0, '2025-12-13 07:39:19', '2025-12-13 07:39:23', 1); -INSERT INTO `users` VALUES (7, 'zhubo', 'zhobo@zhuobo.com', '$scrypt$ln=16,r=8,p=1$dk5pzbnXOgfAmJOylrK21g$QhgDI2BJdlRDSkAIc6TMsuU10IP97arhwraxw0MKZWk', 'STREAMER', NULL, NULL, NULL, 'ACTIVE', 4611, 2, NULL, 0, '2025-12-13 07:46:22', '2025-12-14 05:59:43', 1); -INSERT INTO `users` VALUES (8, 'zhubo1', 'zhuobo12@q.q', '$scrypt$ln=16,r=8,p=1$uxeCcK5VqrV2DuEcQwiBsA$OwN51jBQIbyGhCnJfWTeWcOQy3FIa3qnljkCuokWMjo', 'USER', NULL, NULL, NULL, 'ACTIVE', 5000, 0, NULL, 0, '2025-12-13 09:03:37', '2025-12-14 02:03:48', 1); -INSERT INTO `users` VALUES (9, 'test1', 'te11st@test.com', '$scrypt$ln=16,r=8,p=1$RYgRIiRkTIlxLmWMkfKekw$e0bQSZ8aoelJq0X3A+x8xRXHVDiDGZ8Y+evhnNs48mM', 'USER', NULL, NULL, NULL, 'ACTIVE', 107387, 26, NULL, 0, '2025-12-13 09:22:26', '2025-12-14 11:23:25', 1); -INSERT INTO `users` VALUES (10, 'zhubo12', 'zhu@q.oc', '$scrypt$ln=16,r=8,p=1$x3hPyflfKwXAOAfA2Fvr/Q$mstdmf0PWLrdrbrWGYDXZHdO79CdTmJqPg7/Dt38vLg', 'STREAMER', NULL, NULL, NULL, 'ACTIVE', 5333, 2, NULL, 0, '2025-12-14 05:12:53', '2025-12-14 11:31:54', 1); -INSERT INTO `users` VALUES (11, 'streamer1', 'streamer1@example.com', '$scrypt$ln=16,r=8,p=1$KkVo7T0nZAyhNIYQIqR0Lg$iqN2qdCYPzgfhLiLDhgCAuTKzF0Nr1+1alm3/zVL0IU', 'STREAMER', NULL, NULL, NULL, 'ACTIVE', 0, 0, NULL, 0, '2025-12-14 11:27:41', '2025-12-14 11:27:41', 1); -INSERT INTO `users` VALUES (12, 'streamer', 'streamer@example.com', '$scrypt$ln=16,r=8,p=1$BWAsRYixVqqV8t7b27v3ng$8O+rQCKRJtTE56I2oYyRR8Zjl6tu/JPa4XgiFDdKayY', 'STREAMER', '测试主播', NULL, NULL, 'ACTIVE', 500000, 0, NULL, 0, '2025-12-14 11:57:11', '2025-12-14 11:57:11', 1); -INSERT INTO `users` VALUES (13, 'user', 'user@example.com', '$scrypt$ln=16,r=8,p=1$UGpNqZWy1ppzjjEmROi9tw$d9aGNBDqO0fyGnSttv1NpMs7Ra0uovlAsT/cF5FDxlU', 'USER', '测试用户', NULL, NULL, 'ACTIVE', 200000, 0, NULL, 0, '2025-12-14 11:57:11', '2025-12-14 11:57:11', 1); - -SET FOREIGN_KEY_CHECKS = 1; diff --git a/frontend/.env b/frontend/.env index bce67d2..e03aed1 100644 --- a/frontend/.env +++ b/frontend/.env @@ -5,11 +5,11 @@ VITE_APP_TITLE=宝箱竞猜系统 VITE_FRONTEND_PORT=3000 # 后端配置 -VITE_BACKEND_URL=http://localhost:8000 -VITE_BACKEND_WS_URL=ws://localhost:8000 +VITE_BACKEND_URL=http://127.0.0.1:8000 +VITE_BACKEND_WS_URL=ws://127.0.0.1:8000 # API配置 -VITE_API_BASE_URL=http://localhost:8000 +VITE_API_BASE_URL=http://127.0.0.1:8000 # WebSocket配置 -VITE_WEBSOCKET_BASE_URL=ws://localhost:8000 \ No newline at end of file +VITE_WEBSOCKET_BASE_URL=ws://127.0.0.1:8000 \ No newline at end of file diff --git a/frontend/dist/assets/index-B4_1kpoc.css b/frontend/dist/assets/index-B4_1kpoc.css deleted file mode 100644 index bd67d27..0000000 --- a/frontend/dist/assets/index-B4_1kpoc.css +++ /dev/null @@ -1 +0,0 @@ -.admin-panel{max-width:1600px;margin:0 auto;padding:2rem;background:var(--bg-color);min-height:calc(100vh - 120px)}.panel-header{background:linear-gradient(135deg,var(--bg-secondary) 0%,var(--bg-tertiary) 100%);padding:2rem;border-radius:1.5rem;box-shadow:0 8px 20px #0000004d,0 2px 6px #0003;margin-bottom:2rem;border:1px solid rgba(99,102,241,.2);position:relative;overflow:hidden}.panel-header:before{content:"";position:absolute;top:0;left:0;right:0;height:4px;background:linear-gradient(90deg,var(--primary-color),var(--secondary-color))}.panel-header h1{font-size:2.5rem;font-weight:800;margin-bottom:1.5rem;background:linear-gradient(135deg,var(--primary-color),var(--secondary-color));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;letter-spacing:1px}.tabs{display:flex;gap:.75rem;flex-wrap:wrap;padding-top:1rem;border-top:1px solid rgba(99,102,241,.2)}.tab{padding:1rem 1.75rem;background:var(--bg-tertiary);border:2px solid transparent;border-radius:.75rem;color:var(--text-secondary);font-weight:600;font-size:1rem;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1);position:relative;overflow:hidden}.tab:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.1),transparent);transition:left .5s}.tab:hover:before{left:100%}.tab:hover{background:var(--primary-color);color:#fff;transform:translateY(-2px);box-shadow:0 8px 16px #6366f166;border-color:var(--primary-color)}.tab.active{background:linear-gradient(135deg,var(--primary-color),var(--secondary-color));color:#fff;border-color:var(--primary-color);box-shadow:0 8px 20px #6366f180,0 0 0 1px #ffffff1a inset;transform:translateY(-2px)}.dashboard-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:1.5rem;margin-bottom:2rem}.dashboard-grid .card{background:linear-gradient(135deg,var(--bg-secondary) 0%,var(--bg-tertiary) 100%);padding:2rem;border-radius:1.25rem;box-shadow:0 8px 20px #0000004d,0 4px 8px #0003;border:1px solid rgba(99,102,241,.15);transition:all .3s cubic-bezier(.4,0,.2,1);position:relative;overflow:hidden}.dashboard-grid .card:before{content:"";position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,var(--primary-color),var(--secondary-color))}.dashboard-grid .card:hover{transform:translateY(-5px);box-shadow:0 12px 28px #6366f166,0 6px 12px #0000004d;border-color:var(--primary-color)}.dashboard-grid .card h3{color:var(--text-secondary);font-size:1rem;font-weight:600;margin-bottom:1rem;text-transform:uppercase;letter-spacing:.5px}.dashboard-grid .card .stat-value{font-size:2.5rem;font-weight:800;background:linear-gradient(135deg,var(--primary-color),var(--secondary-color));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;margin-bottom:.5rem}.dashboard-grid .card p{color:var(--text-secondary);font-size:.9rem;margin:0}.filters{display:flex;gap:1rem;margin-bottom:1.5rem;padding:1.5rem;background:var(--bg-tertiary);border-radius:1rem;border:1px solid var(--border-color);flex-wrap:wrap}.filters input,.filters select{padding:.75rem 1rem;background:var(--bg-secondary);border:2px solid var(--border-color);border-radius:.5rem;color:var(--text-primary);font-size:.95rem;transition:all .3s;min-width:180px}.filters input:focus,.filters select:focus{outline:none;border-color:var(--primary-color);box-shadow:0 0 0 3px #6366f11a}.filters .btn{padding:.75rem 1.5rem;white-space:nowrap}.table-container{background:var(--bg-secondary);border-radius:1rem;overflow:hidden;box-shadow:0 4px 12px #0003,0 2px 4px #0000001a;border:1px solid var(--border-color)}.table{width:100%;border-collapse:collapse}.table thead{background:linear-gradient(135deg,var(--primary-color),var(--secondary-color))}.table thead th{padding:1.25rem 1rem;text-align:left;font-weight:700;color:#fff;font-size:.95rem;text-transform:uppercase;letter-spacing:.5px;border:none}.table tbody tr{border-bottom:1px solid var(--border-color);transition:all .2s}.table tbody tr:hover{background:#6366f10d}.table tbody tr:last-child{border-bottom:none}.table tbody td{padding:1.25rem 1rem;color:var(--text-primary);vertical-align:middle}.badge{padding:.4rem .9rem;border-radius:2rem;font-size:.85rem;font-weight:600;display:inline-block;border:1px solid transparent;transition:all .3s}.badge-success{background:#10b98126;color:var(--success-color);border-color:var(--success-color)}.badge-error{background:#ef444426;color:var(--danger-color);border-color:var(--danger-color)}.badge-warning{background:#f59e0b26;color:var(--warning-color);border-color:var(--warning-color)}.badge-info{background:#6366f126;color:var(--primary-color);border-color:var(--primary-color)}.btn{padding:.65rem 1.25rem;border:none;border-radius:.6rem;font-weight:600;font-size:.95rem;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1);display:inline-flex;align-items:center;gap:.5rem;position:relative;overflow:hidden}.btn:before{content:"";position:absolute;top:50%;left:50%;width:0;height:0;background:#fff3;border-radius:50%;transform:translate(-50%,-50%);transition:width .6s,height .6s}.btn:active:before{width:300px;height:300px}.btn-primary{background:linear-gradient(135deg,var(--primary-color),var(--primary-dark));color:#fff;box-shadow:0 4px 12px #6366f14d}.btn-primary:hover{background:linear-gradient(135deg,var(--primary-dark),var(--primary-color));transform:translateY(-2px);box-shadow:0 6px 16px #6366f180}.btn-secondary{background:var(--bg-tertiary);color:var(--text-primary);border:2px solid var(--border-color)}.btn-secondary:hover{background:var(--border-color);border-color:var(--primary-color);color:var(--primary-color);transform:translateY(-2px)}.btn-success{background:linear-gradient(135deg,var(--success-color),#059669);color:#fff;box-shadow:0 4px 12px #10b9814d}.btn-success:hover{background:linear-gradient(135deg,#059669,var(--success-color));transform:translateY(-2px);box-shadow:0 6px 16px #10b98180}.btn-danger{background:linear-gradient(135deg,var(--danger-color),#dc2626);color:#fff;box-shadow:0 4px 12px #ef44444d}.btn-danger:hover{background:linear-gradient(135deg,#dc2626,var(--danger-color));transform:translateY(-2px);box-shadow:0 6px 16px #ef444480}.config-edit-mode{display:flex;gap:.5rem;align-items:center}.config-edit-mode input{padding:.5rem .75rem;background:var(--bg-tertiary);border:2px solid var(--primary-color);border-radius:.5rem;color:var(--text-primary);font-size:.95rem;width:200px;transition:all .3s}.config-edit-mode input:focus{outline:none;box-shadow:0 0 0 3px #6366f133;border-color:var(--secondary-color)}.form-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:1.5rem;margin-top:2rem;padding:2rem;background:var(--bg-tertiary);border-radius:1rem;border:1px solid var(--border-color)}.form-group{display:flex;flex-direction:column;gap:.5rem}.form-group.full-width{grid-column:1 / -1}.form-label{font-weight:600;color:var(--text-primary);font-size:.95rem;margin-bottom:.25rem}.form-input,.form-select,.form-textarea{padding:.75rem 1rem;background:var(--bg-secondary);border:2px solid var(--border-color);border-radius:.6rem;color:var(--text-primary);font-size:.95rem;transition:all .3s}.form-input:focus,.form-select:focus,.form-textarea:focus{outline:none;border-color:var(--primary-color);box-shadow:0 0 0 3px #6366f11a;background:var(--bg-color)}.form-textarea{min-height:120px;resize:vertical}.stats-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:1.5rem;margin:1.5rem 0}.stat-card{background:linear-gradient(135deg,var(--bg-tertiary) 0%,var(--bg-secondary) 100%);padding:1.5rem;border-radius:1rem;text-align:center;border:1px solid var(--border-color);transition:all .3s}.stat-card:hover{transform:translateY(-3px);border-color:var(--primary-color);box-shadow:0 6px 16px #6366f133}.stat-card h4{color:var(--text-secondary);font-size:.9rem;font-weight:600;margin-bottom:.75rem;text-transform:uppercase;letter-spacing:.5px}.stat-card .stat-value{font-size:2rem;font-weight:800;color:var(--text-primary)}.modal-overlay{background:#000000bf;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.modal{background:linear-gradient(135deg,var(--bg-secondary) 0%,var(--bg-tertiary) 100%);border-radius:1.5rem;padding:2.5rem;border:1px solid rgba(99,102,241,.3);box-shadow:0 25px 50px #00000080,0 0 0 1px #ffffff0d inset}.modal h2{background:linear-gradient(135deg,var(--primary-color),var(--secondary-color));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;font-weight:800;margin-bottom:1.5rem}.empty-state{text-align:center;padding:4rem 2rem;background:var(--bg-secondary);border-radius:1.5rem;border:2px dashed var(--border-color);margin:2rem 0}.empty-state-icon{font-size:4rem;margin-bottom:1.5rem;opacity:.5}.empty-state h3{color:var(--text-primary);font-size:1.5rem;margin-bottom:.5rem;font-weight:700}@media (max-width: 1200px){.admin-panel{padding:1.5rem}.dashboard-grid{grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}}@media (max-width: 768px){.admin-panel{padding:1rem}.panel-header{padding:1.5rem}.panel-header h1{font-size:2rem}.tabs{flex-direction:column}.tab{width:100%}.dashboard-grid{grid-template-columns:1fr}.filters{flex-direction:column}.filters input,.filters select{width:100%;min-width:100%}.table-container{overflow-x:auto}.table{min-width:800px}.form-grid{grid-template-columns:1fr;padding:1.5rem}.stats-grid{grid-template-columns:repeat(2,1fr)}.modal{padding:2rem 1.5rem;margin:1rem}}@media (max-width: 480px){.stats-grid{grid-template-columns:1fr}.btn{width:100%;justify-content:center}.config-edit-mode{flex-direction:column;align-items:stretch}.config-edit-mode input{width:100%}}@keyframes fadeIn{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}.admin-panel>*{animation:fadeIn .5s ease-out}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:var(--bg-tertiary);border-radius:5px}::-webkit-scrollbar-thumb{background:linear-gradient(135deg,var(--primary-color),var(--secondary-color));border-radius:5px}::-webkit-scrollbar-thumb:hover{background:linear-gradient(135deg,var(--secondary-color),var(--primary-color))}*{margin:0;padding:0;box-sizing:border-box}:root{--primary-color: #6366f1;--primary-dark: #4f46e5;--secondary-color: #8b5cf6;--success-color: #10b981;--danger-color: #ef4444;--warning-color: #f59e0b;--bg-color: #0f172a;--bg-secondary: #1e293b;--bg-tertiary: #334155;--text-primary: #f1f5f9;--text-secondary: #cbd5e1;--border-color: #475569;--shadow: 0 4px 6px -1px rgba(0, 0, 0, .3)}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:var(--bg-color);color:var(--text-primary)}.app{min-height:100vh;display:flex;flex-direction:column}.main-content{flex:1;padding:2rem;max-width:1400px;margin:0 auto;width:100%}.btn{padding:.75rem 1.5rem;border:none;border-radius:.5rem;font-size:1rem;font-weight:500;cursor:pointer;transition:all .2s;text-decoration:none;display:inline-block;text-align:center}.btn-primary{background:var(--primary-color);color:#fff}.btn-primary:hover{background:var(--primary-dark);transform:translateY(-1px);box-shadow:var(--shadow)}.btn-secondary{background:var(--bg-tertiary);color:var(--text-primary)}.btn-secondary:hover{background:var(--border-color)}.btn-success{background:var(--success-color);color:#fff}.btn-danger{background:var(--danger-color);color:#fff}.btn:disabled{opacity:.5;cursor:not-allowed}.form-group{margin-bottom:1.5rem}.form-label{display:block;margin-bottom:.5rem;color:var(--text-secondary);font-weight:500}.form-input{width:100%;padding:.75rem;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:.5rem;color:var(--text-primary);font-size:1rem}.form-input:focus{outline:none;border-color:var(--primary-color);box-shadow:0 0 0 3px #6366f11a}.card{background:var(--bg-secondary);border-radius:1rem;padding:1.5rem;box-shadow:var(--shadow);border:1px solid var(--border-color)}.card-header{margin-bottom:1rem;padding-bottom:1rem;border-bottom:1px solid var(--border-color)}.card-title{font-size:1.5rem;font-weight:600;color:var(--text-primary)}.grid{display:grid;gap:1.5rem}.grid-2{grid-template-columns:repeat(auto-fill,minmax(300px,1fr))}.grid-3{grid-template-columns:repeat(auto-fill,minmax(250px,1fr))}.text-center{text-align:center}.text-success{color:var(--success-color)}.text-danger{color:var(--danger-color)}.text-warning{color:var(--warning-color)}.mb-1{margin-bottom:.5rem}.small{font-size:.875rem}.mb-2{margin-bottom:1rem}.mt-1{margin-top:.5rem}.mt-2{margin-top:1rem}.mt-3{margin-top:1.5rem}.status-locked{color:#ff9800;font-weight:700}.btn-settle{background:linear-gradient(45deg,#4caf50,#8bc34a);border:none;padding:10px 20px;font-size:16px;animation:pulse 2s infinite}@keyframes pulse{0%{transform:scale(1)}50%{transform:scale(1.05)}to{transform:scale(1)}}.actions-settle{display:flex;flex-direction:column;align-items:center;gap:8px}.settle-hint{font-size:12px;color:#999;text-align:center}.locked-notice{background-color:#fff3cd;border:1px solid #ffeeba;border-radius:.375rem;padding:.5rem;margin-top:.5rem;display:flex;align-items:center;animation:pulse 2s infinite}.locked-notice-icon{font-size:1.2rem;margin-right:.5rem;color:#856404}.locked-notice-text{font-weight:500;color:#856404}.radio-group{display:flex;flex-direction:column;gap:12px}.radio-label{display:flex;align-items:center;cursor:pointer;padding:12px;border-radius:8px;background:var(--bg-tertiary);transition:all .2s}.radio-label:hover{background:var(--border-color)}.radio-label input[type=radio]{margin-right:12px;width:18px;height:18px;cursor:pointer}.radio-text{font-size:1rem;color:var(--text-primary)}.loading{display:inline-block;width:40px;height:40px;border:4px solid var(--bg-tertiary);border-radius:50%;border-top-color:var(--primary-color);animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.header{background:var(--bg-secondary);border-bottom:1px solid var(--border-color);padding:1rem 0;position:sticky;top:0;z-index:100;box-shadow:0 2px 4px #0000001a}.header-container{max-width:1400px;margin:0 auto;padding:0 2rem;display:flex;justify-content:space-between;align-items:center}.logo{text-decoration:none}.logo h1{font-size:1.5rem;color:var(--primary-color);margin:0}.nav{display:flex;align-items:center;gap:1.5rem}.nav-link{color:var(--text-secondary);text-decoration:none;font-weight:500;transition:color .2s;padding:8px 16px;border-radius:4px}.nav-link:hover{color:var(--text-primary);background:var(--bg-tertiary)}.nav-link.active{color:var(--primary-color);background:#6366f11a}.user-balance{color:var(--warning-color);font-weight:600}.user-menu{display:flex;align-items:center;gap:1rem}.user-name{color:var(--text-primary);font-weight:500}.loading-container{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem}.loading-text{margin-top:1rem;color:var(--text-secondary)}.chest-card-link{text-decoration:none;color:inherit;display:block;transition:transform .3s ease,box-shadow .3s ease;height:100%}.chest-card-link:hover{transform:translateY(-5px);box-shadow:0 10px 20px #0000004d}.chest-card{cursor:pointer;transition:all .3s ease;height:100%;display:flex;flex-direction:column}.chest-card:hover{border-color:var(--primary-color);box-shadow:0 6px 16px #6366f14d}.chest-card-header{display:flex;justify-content:space-between;align-items:start;margin-bottom:1rem}.chest-title{font-size:1.3rem;font-weight:700;color:var(--text-primary);margin:0;flex:1}.status{padding:.3rem .8rem;border-radius:1rem;font-size:.9rem;font-weight:600;background:var(--bg-tertiary);white-space:nowrap}.chest-options{display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-bottom:1.2rem;flex:1}.option{padding:1.2rem;background:var(--bg-tertiary);border-radius:.7rem;display:flex;flex-direction:column;gap:.6rem;transition:all .2s}.option:hover{background:var(--primary-color);transform:scale(1.02)}.option-label{font-size:.8rem;color:var(--text-secondary);font-weight:500}.option-text{font-size:1.1rem;font-weight:700;color:var(--text-primary)}.option-amount{font-size:1rem;color:var(--warning-color);font-weight:600}.chest-footer{display:flex;justify-content:space-between;align-items:center;padding-top:1.2rem;border-top:1px solid var(--border-color);margin-top:auto}.total-pool{color:var(--text-secondary);font-weight:500}.total-pool strong{color:var(--warning-color);font-weight:700}.bet-count{font-size:.9rem;color:var(--text-secondary);font-weight:500}.countdown{margin-top:1.2rem;padding:.9rem;background:linear-gradient(135deg,var(--primary-color),var(--secondary-color));border-radius:.7rem;text-align:center;color:#fff;font-weight:700;font-size:1.1rem;animation:pulse 1.5s infinite;box-shadow:0 4px 10px #6366f166}@keyframes pulse{0%,to{transform:scale(1);box-shadow:0 4px 10px #6366f166}50%{transform:scale(1.03);box-shadow:0 6px 15px #6366f199}}@keyframes highlight{0%{transform:scale(1);box-shadow:0 0 #4caf50b3}50%{transform:scale(1.05);box-shadow:0 0 0 10px #4caf504d}to{transform:scale(1);box-shadow:0 0 0 20px #4caf5000}}.highlight{animation:highlight .5s ease-in-out}.home-page{max-width:1400px;margin:0 auto;padding:1rem}.page-header{text-align:center;margin-bottom:2rem;padding:1rem}.page-title{font-size:2.2rem;font-weight:800;margin-bottom:.5rem;background:linear-gradient(135deg,var(--primary-color),var(--secondary-color));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;letter-spacing:1px}.page-subtitle{font-size:1.1rem;color:var(--text-secondary);max-width:600px;margin:0 auto}.chests-grid{margin-top:1.5rem;display:grid;grid-template-columns:repeat(auto-fill,minmax(350px,1fr));gap:1.5rem}@media (max-width: 768px){.chests-grid{grid-template-columns:1fr}}.empty-state{text-align:center;padding:3rem 1rem;background:var(--bg-secondary);border-radius:1rem;margin:1rem}.empty-icon{font-size:3.5rem;margin-bottom:1rem}.empty-state h3{font-size:1.4rem;margin-bottom:.5rem;color:var(--text-primary)}.empty-state p{color:var(--text-secondary);font-size:1rem}.chest-page{max-width:1000px;margin:0 auto;padding:1rem}.back-btn{margin-bottom:1.5rem;padding:.8rem 1.5rem;font-size:1rem;display:inline-flex;align-items:center;gap:.5rem}.chest-detail{margin-top:1rem}.chest-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:2rem;padding-bottom:1rem;border-bottom:2px solid var(--border-color)}.chest-title{font-size:2.2rem;font-weight:800;margin:0;color:var(--text-primary);background:linear-gradient(135deg,var(--primary-color),var(--secondary-color));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.status-badge{padding:.6rem 1.2rem;border-radius:1.5rem;background:var(--bg-tertiary);color:var(--text-primary);font-size:1rem;font-weight:600;box-shadow:0 2px 5px #0003}.chest-info{display:grid;grid-template-columns:1fr 1fr;gap:1.5rem;margin-bottom:2rem;padding:1.5rem;background:var(--bg-tertiary);border-radius:1rem;box-shadow:0 4px 6px #0000001a}@media (max-width: 768px){.chest-info{grid-template-columns:1fr}}.info-item{display:flex;flex-direction:column;gap:.5rem}.info-label{color:var(--text-secondary);font-weight:600;font-size:.9rem}.info-value{color:var(--text-primary);font-weight:700;font-size:1.2rem}.pool-info{display:grid;grid-template-columns:1fr auto 1fr;gap:2rem;margin-bottom:2rem;align-items:stretch}@media (max-width: 768px){.pool-info{grid-template-columns:1fr;gap:1rem}.vs{display:none}}.pool-item{text-align:center;padding:2rem;background:var(--bg-secondary);border-radius:1.5rem;box-shadow:0 6px 12px #0003;display:flex;flex-direction:column;justify-content:center;transition:transform .3s ease}.pool-item:hover{transform:translateY(-5px)}.pool-header{font-size:1.2rem;color:var(--text-secondary);margin-bottom:1rem;font-weight:600}.pool-amount{font-size:1.8rem;font-weight:800;color:var(--warning-color);margin-bottom:1rem}.pool-odds{font-size:1.2rem;color:var(--text-primary);font-weight:700}.vs{font-size:2.5rem;font-weight:800;color:var(--primary-color);display:flex;align-items:center;justify-content:center}.total-pool{text-align:center;padding:1.8rem;background:linear-gradient(135deg,var(--primary-color),var(--secondary-color));border-radius:1rem;font-size:1.4rem;margin-bottom:2rem;color:#fff;font-weight:700;box-shadow:0 6px 15px #6366f166}.total-pool strong{color:#fff;font-weight:800}.bet-section{margin-top:2rem;padding:2rem;background:var(--bg-tertiary);border-radius:1.5rem;box-shadow:0 6px 12px #0000001a}.bet-section h3{margin-bottom:1.5rem;color:var(--text-primary);font-size:1.5rem;text-align:center;font-weight:700}.bet-options{display:grid;grid-template-columns:1fr 1fr;gap:1.5rem;margin-bottom:2rem}@media (max-width: 768px){.bet-options{grid-template-columns:1fr}}.option-btn{padding:1.8rem;background:var(--bg-secondary);border:3px solid var(--border-color);border-radius:1rem;color:var(--text-primary);font-size:1.3rem;font-weight:700;cursor:pointer;transition:all .3s ease;text-align:center;box-shadow:0 4px 8px #0003}.option-btn:hover:not(:disabled){border-color:var(--primary-color);background:linear-gradient(135deg,var(--primary-color),var(--secondary-color));color:#fff;transform:translateY(-3px);box-shadow:0 6px 12px #6366f166}.option-btn.selected{border-color:var(--primary-color);background:linear-gradient(135deg,var(--primary-color),var(--secondary-color));color:#fff;transform:translateY(-3px);box-shadow:0 6px 12px #6366f166}.option-btn:disabled{opacity:.6;cursor:not-allowed;transform:none}.bet-input-group{margin-bottom:2rem}.form-label{font-size:1.1rem;font-weight:600;margin-bottom:.8rem}.form-input{padding:1.2rem;font-size:1.1rem;border-width:2px;border-radius:.8rem}.quick-amounts{display:flex;gap:.8rem;margin-top:1rem;flex-wrap:wrap}.quick-amounts button{padding:.8rem 1.5rem;background:var(--bg-secondary);border:2px solid var(--border-color);border-radius:.5rem;color:var(--text-primary);cursor:pointer;transition:all .3s ease;font-weight:600;flex:1;min-width:80px}.quick-amounts button:hover{background:var(--primary-color);color:#fff;transform:translateY(-2px);box-shadow:0 4px 8px #6366f14d}.btn-large{padding:1.2rem 2.5rem;font-size:1.3rem;font-weight:700;border-radius:1rem;width:100%;margin-top:1rem}.bet-closed{text-align:center;padding:3rem;background:var(--bg-tertiary);border-radius:1rem;color:var(--text-secondary);font-size:1.3rem;margin-top:2rem;font-weight:600}.bets-list{display:flex;flex-direction:column;gap:1rem}.bet-item{display:flex;justify-content:space-between;align-items:center;padding:1.2rem;background:var(--bg-tertiary);border-radius:.8rem;box-shadow:0 2px 5px #0000001a;transition:all .2s}.bet-item:hover{background:var(--bg-secondary);transform:translate(5px)}.bet-option{font-weight:700;color:var(--text-primary);font-size:1.1rem}.bet-amount{color:var(--warning-color);font-weight:700;font-size:1.1rem}.bet-status{font-size:1rem;color:var(--text-secondary);font-weight:500}.streamer-console{max-width:1200px;margin:0 auto}.console-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:2rem}.chests-list{display:flex;flex-direction:column;gap:1rem}.chest-item{display:flex;justify-content:space-between;align-items:center;padding:1.5rem;background:var(--bg-tertiary);border-radius:.5rem;transition:all .2s}.chest-item:hover{background:var(--bg-secondary)}.chest-item.finished{opacity:.7}.chest-item h3{margin:0 0 .5rem;color:var(--text-primary)}.chest-item p{margin:0;color:var(--text-secondary)}.chest-stats{display:flex;gap:1.5rem;margin-top:.5rem;font-size:.875rem;color:var(--text-secondary)}.chest-actions{display:flex;gap:.5rem}.user-profile{max-width:1200px;margin:0 auto;padding:1rem}.profile-header{display:flex;justify-content:space-between;align-items:center;background:var(--bg-secondary);padding:2rem;border-radius:1rem;box-shadow:0 4px 12px #0000001a;margin-bottom:2rem}@media (max-width: 768px){.profile-header{flex-direction:column;gap:1.5rem;text-align:center}}.profile-info{display:flex;gap:2rem;align-items:center}@media (max-width: 768px){.profile-info{flex-direction:column;gap:1rem}}.profile-avatar{width:100px;height:100px;border-radius:50%;background:linear-gradient(135deg,var(--primary-color),var(--secondary-color));display:flex;align-items:center;justify-content:center;font-size:2.5rem;font-weight:800;color:#fff;box-shadow:0 6px 15px #6366f166}.profile-details h2{margin:0 0 .5rem;color:var(--text-primary);font-size:1.8rem;font-weight:700}.profile-details .text-secondary{color:var(--text-secondary);font-size:1.1rem;margin-bottom:1rem}.user-stats{display:flex;gap:2.5rem;margin-top:.5rem}@media (max-width: 768px){.user-stats{justify-content:center}}.stat-item{color:var(--text-secondary);font-size:1rem;font-weight:500}.stat-item strong{color:var(--text-primary);font-weight:700;font-size:1.2rem}.text-warning{color:var(--warning-color);font-weight:800}.profile-actions{display:flex;align-items:center}@media (max-width: 768px){.profile-actions{width:100%}.profile-actions .btn{flex:1}}.transactions-list{display:flex;flex-direction:column;gap:1rem;max-height:600px;overflow-y:auto;padding-right:.5rem}.transactions-list::-webkit-scrollbar{width:6px}.transactions-list::-webkit-scrollbar-track{background:var(--bg-tertiary);border-radius:3px}.transactions-list::-webkit-scrollbar-thumb{background:var(--primary-color);border-radius:3px}.transaction-item{display:flex;justify-content:space-between;align-items:center;padding:1.2rem;background:var(--bg-tertiary);border-radius:.8rem;box-shadow:0 2px 5px #0000001a;transition:all .3s ease}.transaction-item:hover{background:var(--bg-secondary);transform:translate(5px);box-shadow:0 4px 8px #6366f133}.transaction-info{display:flex;flex-direction:column;gap:.3rem}.transaction-type{font-weight:700;color:var(--text-primary);font-size:1.1rem}.transaction-desc{font-size:.9rem;color:var(--text-secondary)}.transaction-details{display:flex;flex-direction:column;align-items:flex-end;gap:.3rem}.transaction-amount{font-weight:800;font-size:1.1rem}.transaction-amount.text-success{color:var(--success-color)}.transaction-amount.text-danger{color:var(--danger-color)}.transaction-balance{font-size:.9rem;color:var(--text-secondary);font-weight:500}.ranking-list{display:flex;flex-direction:column;gap:.8rem}.ranking-item{display:flex;align-items:center;gap:1.2rem;padding:1.2rem;background:var(--bg-tertiary);border-radius:.8rem;transition:all .3s ease;box-shadow:0 2px 5px #0000001a}.ranking-item:hover{background:var(--bg-secondary);transform:translateY(-2px);box-shadow:0 4px 8px #6366f133}.ranking-item.current-user{background:linear-gradient(135deg,var(--primary-color),var(--secondary-color));color:#fff;font-weight:700}.ranking-position{width:36px;height:36px;border-radius:50%;background:var(--bg-secondary);display:flex;align-items:center;justify-content:center;font-weight:800;color:var(--primary-color);font-size:1.1rem;box-shadow:0 2px 5px #0003}.ranking-item.current-user .ranking-position{background:#fff3;color:#fff}.ranking-username{flex:1;font-weight:600;font-size:1.1rem}.ranking-balance{font-weight:800;color:var(--warning-color);font-size:1.1rem}.ranking-item.current-user .ranking-balance{color:#fff}.grid-2{grid-template-columns:repeat(auto-fit,minmax(350px,1fr))}@media (max-width: 768px){.grid-2{grid-template-columns:1fr}}.admin-panel{max-width:1400px;margin:0 auto;padding:1rem}.panel-header{margin-bottom:2rem;background:var(--bg-secondary);padding:1.5rem;border-radius:1rem;box-shadow:0 4px 12px #0000001a}.page-title{font-size:2rem;font-weight:800;margin-bottom:1rem;background:linear-gradient(135deg,var(--primary-color),var(--secondary-color));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.tabs{display:flex;gap:.5rem;border-bottom:2px solid var(--border-color);padding-bottom:.5rem}.tab{padding:.8rem 1.5rem;background:var(--bg-tertiary);border:none;border-radius:.5rem;color:var(--text-primary);font-weight:600;cursor:pointer;transition:all .3s ease}.tab:hover,.tab.active{background:var(--primary-color);color:#fff}.users-table,.streamers-table,.configs-table{width:100%}@media (max-width: 768px){.tabs{flex-direction:column}.tab{width:100%}}.table-header,.table-row{display:grid;grid-template-columns:60px 1fr 2fr 100px 150px 120px;gap:1rem;padding:1.2rem;align-items:center;border-radius:.8rem;transition:all .3s ease}@media (max-width: 768px){.table-header,.table-row{grid-template-columns:50px 1fr 1fr 80px 100px 100px;font-size:.875rem;padding:1rem}}.table-header{background:linear-gradient(135deg,var(--primary-color),var(--secondary-color));color:#fff;font-weight:700;box-shadow:0 4px 8px #6366f14d}.table-row{background:var(--bg-secondary);margin-top:.5rem;box-shadow:0 2px 5px #0000001a}.table-row:hover{background:var(--bg-tertiary);transform:translate(5px);box-shadow:0 4px 8px #6366f133}.chests-table{width:100%;margin-top:1rem}.chests-table .table-header,.chests-table .table-row{grid-template-columns:60px 1fr 1fr 1fr 100px 120px 120px}@media (max-width: 768px){.chests-table .table-header,.chests-table .table-row{grid-template-columns:50px 1fr 1fr 1fr 80px 100px 100px;font-size:.8rem}}.mt-4{margin-top:2rem}.mb-3{margin-bottom:1.5rem}.mb-3 h4{font-size:1.3rem;font-weight:700;color:var(--text-primary);margin-bottom:.8rem;padding-bottom:.5rem;border-bottom:1px solid var(--border-color)}.announcement-bar{background:var(--bg-secondary);border-radius:8px;padding:16px 24px;margin-bottom:24px;border-left:4px solid var(--primary-color);display:flex;align-items:center;gap:16px}.announcement-icon{font-size:24px}.announcement-content{flex:1}.announcement-content h4{margin-bottom:4px;color:var(--text-primary)}.announcement-content p{color:var(--text-secondary);font-size:14px}.streamers-section{background:var(--bg-secondary);border-radius:8px;padding:24px;margin-bottom:24px}.section-title{font-size:20px;margin-bottom:16px;padding-bottom:12px;border-bottom:2px solid var(--border-color);color:var(--text-primary)}.streamers-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:16px}.streamer-card{border:1px solid var(--border-color);border-radius:8px;padding:16px;transition:all .3s;cursor:pointer;background:var(--bg-tertiary)}.streamer-card:hover{border-color:var(--primary-color);box-shadow:0 2px 8px #6366f133}.streamer-info{display:flex;align-items:center;gap:12px;margin-bottom:12px}.streamer-avatar{width:48px;height:48px;border-radius:50%;background:linear-gradient(135deg,var(--primary-color) 0%,var(--secondary-color) 100%);display:flex;align-items:center;justify-content:center;color:#fff;font-size:20px;font-weight:700}.streamer-details h4{margin-bottom:4px;color:var(--text-primary)}.streamer-status{font-size:12px;color:var(--success-color)}.streamer-stats{display:flex;justify-content:space-between;font-size:14px;color:var(--text-secondary)}.profile-container{display:grid;grid-template-columns:1fr 2fr;gap:24px}@media (max-width: 768px){.profile-container{grid-template-columns:1fr}}.profile-card{background:var(--bg-secondary);border-radius:8px;padding:24px}.user-avatar-large{width:80px;height:80px;border-radius:50%;background:linear-gradient(135deg,var(--primary-color) 0%,var(--secondary-color) 100%);display:flex;align-items:center;justify-content:center;color:#fff;font-size:32px;font-weight:700;margin:0 auto 16px}.user-name-large{text-align:center;font-size:18px;font-weight:700;margin-bottom:8px;color:var(--text-primary)}.user-role-text{text-align:center;color:var(--text-secondary);margin-bottom:16px}.balance-card{background:linear-gradient(135deg,var(--primary-color) 0%,var(--secondary-color) 100%);color:#fff;padding:16px;border-radius:8px;margin-bottom:16px}.balance-label{font-size:14px;opacity:.9;margin-bottom:8px}.balance-value-large{font-size:32px;font-weight:700}.quick-actions{display:grid;grid-template-columns:1fr 1fr;gap:8px}.action-btn{padding:12px;border:1px solid var(--border-color);background:var(--bg-tertiary);border-radius:4px;cursor:pointer;transition:all .3s;text-align:center;color:var(--text-primary)}.action-btn:hover{border-color:var(--primary-color);color:var(--primary-color)}.allowance-card{background:linear-gradient(135deg,#667eea,#764ba2);border-radius:12px;padding:20px;color:#fff;box-shadow:0 4px 15px #0003;margin-bottom:24px;text-align:center}.allowance-header{display:flex;align-items:center;justify-content:center;gap:12px;margin-bottom:16px}.allowance-icon{font-size:28px}.allowance-title{font-size:20px;font-weight:700}.allowance-countdown{margin:16px 0}.countdown-label{font-size:16px;margin-bottom:8px;opacity:.9}.countdown-time{font-size:24px;font-weight:700;font-family:Courier New,monospace}.allowance-claim-btn{background:#fff3;border:2px solid white;color:#fff;padding:12px 24px;border-radius:8px;font-size:18px;font-weight:700;cursor:pointer;transition:all .3s ease;width:100%;margin:16px 0}.allowance-claim-btn:hover:not(:disabled){background:#ffffff4d;transform:translateY(-2px)}.allowance-claim-btn:disabled{opacity:.7;cursor:not-allowed}.allowance-note{font-size:14px;opacity:.8;margin-top:16px}.action-btn-icon{font-size:24px;margin-bottom:8px}.stats-grid-enhanced{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-bottom:24px}@media (max-width: 768px){.stats-grid-enhanced{grid-template-columns:1fr}}.stat-card-enhanced{background:var(--bg-secondary);padding:16px;border-radius:8px;text-align:center}.stat-label-enhanced{font-size:14px;color:var(--text-secondary);margin-bottom:8px}.stat-value-enhanced{font-size:24px;font-weight:700;color:var(--text-primary)}.transactions-section{background:var(--bg-secondary);border-radius:8px;padding:24px;margin-bottom:24px}.transaction-list-enhanced{margin-top:16px}.transaction-item-enhanced{display:flex;justify-content:space-between;align-items:center;padding:12px 0;border-bottom:1px solid var(--border-color)}.transaction-item-enhanced:last-child{border-bottom:none}.transaction-info-enhanced h5{margin-bottom:4px;color:var(--text-primary)}.transaction-info-enhanced p{font-size:14px;color:var(--text-secondary)}.transaction-amount-enhanced{font-size:16px;font-weight:700}.amount-positive{color:var(--success-color)}.amount-negative{color:var(--danger-color)}.admin-container{display:flex;min-height:calc(100vh - 80px)}.admin-sidebar{width:240px;background:#001529;color:#fff;padding:24px;position:fixed;height:calc(100vh - 80px);overflow-y:auto}.admin-sidebar h2{font-size:20px;margin-bottom:24px;padding-bottom:16px;border-bottom:1px solid rgba(255,255,255,.1)}.admin-nav-item{padding:12px 16px;margin-bottom:8px;cursor:pointer;border-radius:6px;transition:all .3s;color:#ffffffd9}.admin-nav-item:hover,.admin-nav-item.active{background:var(--primary-color)}.admin-main{flex:1;margin-left:240px;padding:24px;background:var(--bg-color)}.admin-header{background:var(--bg-secondary);padding:16px 24px;margin-bottom:24px;border-radius:8px;display:flex;justify-content:space-between;align-items:center}.admin-content{background:var(--bg-secondary);padding:24px;border-radius:8px}.admin-stats-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:24px}@media (max-width: 1024px){.admin-stats-grid{grid-template-columns:repeat(2,1fr)}}@media (max-width: 768px){.admin-stats-grid{grid-template-columns:1fr}.admin-sidebar{display:none}.admin-main{margin-left:0}}.admin-stat-card{padding:20px;border-radius:8px;color:#fff}.admin-stat-card.blue{background:linear-gradient(135deg,#667eea,#764ba2)}.admin-stat-card.green{background:linear-gradient(135deg,#f093fb,#f5576c)}.admin-stat-card.orange{background:linear-gradient(135deg,#4facfe,#00f2fe)}.admin-stat-card.purple{background:linear-gradient(135deg,#43e97b,#38f9d7)}.admin-stat-card h3{font-size:14px;opacity:.9;margin-bottom:8px}.admin-stat-card .value{font-size:28px;font-weight:700}.search-bar{display:flex;gap:8px;margin-bottom:16px;flex-wrap:wrap}.search-bar input,.search-bar select{padding:8px 12px;border:1px solid var(--border-color);border-radius:4px;background:var(--bg-tertiary);color:var(--text-primary)}.search-bar input{flex:1;min-width:200px}.search-bar select{min-width:120px}.data-table{width:100%;border-collapse:collapse}.data-table th,.data-table td{padding:12px;text-align:left;border-bottom:1px solid var(--border-color)}.data-table th{background:var(--bg-tertiary);font-weight:600;color:var(--text-primary)}.data-table tr:hover{background:var(--bg-tertiary)}.badge{padding:4px 8px;border-radius:4px;font-size:12px;font-weight:500}.badge-success{background:#10b98133;color:var(--success-color);border:1px solid var(--success-color)}.badge-error{background:#ef444433;color:var(--danger-color);border:1px solid var(--danger-color)}.badge-warning{background:#f59e0b33;color:var(--warning-color);border:1px solid var(--warning-color)}.badge-info{background:#6366f133;color:var(--primary-color);border:1px solid var(--primary-color)}.pagination{display:flex;gap:8px;justify-content:center;margin-top:16px}.pagination button{padding:6px 12px;border:1px solid var(--border-color);background:var(--bg-tertiary);cursor:pointer;border-radius:4px;color:var(--text-primary);transition:all .3s}.pagination button:hover{border-color:var(--primary-color);color:var(--primary-color)}.pagination button.active{background:var(--primary-color);color:#fff;border-color:var(--primary-color)}.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:24px}@media (max-width: 768px){.form-grid{grid-template-columns:1fr}}.form-section h4{margin-bottom:16px;color:var(--text-primary)}.mobile-nav-toggle{display:none;background:var(--primary-color);color:#fff;border:none;padding:10px 16px;border-radius:4px;cursor:pointer;margin-bottom:16px}@media (max-width: 768px){.mobile-nav-toggle{display:block}.admin-sidebar.show{display:block;position:fixed;z-index:1000;left:0;top:80px;width:100%;height:auto;max-height:calc(100vh - 80px)}}.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:#000000b3;display:flex;align-items:center;justify-content:center;z-index:1000}.modal{background:var(--bg-secondary);border-radius:1rem;padding:2rem;max-width:500px;width:90%;max-height:90vh;overflow-y:auto;box-shadow:0 10px 25px #00000080;border:1px solid var(--border-color);animation:modalFadeIn .3s ease-out}@keyframes modalFadeIn{0%{opacity:0;transform:translateY(-20px)}to{opacity:1;transform:translateY(0)}}.modal h2{margin:0 0 1rem;color:var(--text-primary);font-size:1.5rem;font-weight:700}.modal-chest-title{font-size:1.125rem;font-weight:600;color:var(--text-primary);margin:0 0 .5rem}.radio-group{display:flex;flex-direction:column;gap:.75rem}.radio-group label{display:flex;align-items:center;gap:.5rem;cursor:pointer;padding:.75rem;background:var(--bg-tertiary);border-radius:.5rem;transition:all .2s}.radio-group label:hover{background:var(--border-color);transform:translate(3px)}.modal-user-info{background:var(--bg-tertiary);padding:1rem;border-radius:.5rem;margin-bottom:1.5rem;box-shadow:0 2px 5px #0000001a}.modal-user-info p{margin:.5rem 0;color:var(--text-secondary)}.modal-actions{display:flex;gap:1rem;margin-top:1.5rem}.modal-actions button{flex:1;padding:.8rem;font-weight:600;border-radius:.5rem}.close-btn{position:absolute;top:1rem;right:1rem;background:none;border:none;color:var(--text-secondary);font-size:1.5rem;cursor:pointer;width:40px;height:40px;display:flex;align-items:center;justify-content:center;border-radius:50%;transition:all .2s}.close-btn:hover{background:var(--bg-tertiary);color:var(--text-primary)}.error-page{text-align:center;padding:4rem 2rem;max-width:600px;margin:0 auto}.error-page h2{font-size:2rem;margin-bottom:1.5rem;color:var(--text-primary)}.error-page p{color:var(--text-secondary);font-size:1.1rem;margin-bottom:2rem}@media (max-width: 768px){.main-content{padding:1rem}.grid-2,.grid-3{grid-template-columns:1fr}.header-container{flex-direction:column;gap:1rem}.nav{flex-wrap:wrap;justify-content:center}.chest-options,.pool-info{grid-template-columns:1fr}.vs{display:none}.bet-options{grid-template-columns:1fr}.console-header{flex-direction:column;gap:1rem;align-items:stretch}.chest-item{flex-direction:column;align-items:stretch;gap:1rem}.chest-actions{justify-content:stretch}.chest-actions button{flex:1}.profile-header{flex-direction:column;align-items:stretch;gap:1rem}.profile-info{flex-direction:column;text-align:center}.table-header,.table-row{grid-template-columns:50px 1fr 1fr 80px 100px 100px;font-size:.875rem}.modal{padding:1.5rem 1rem;margin:0 1rem}.modal-actions{flex-direction:column}}.locked-chests-alert{margin-bottom:1.5rem}.alert{padding:1rem;border-radius:.5rem;display:flex;align-items:center}.alert-warning{background-color:#fff3cd;border:1px solid #ffeeba;color:#856404}.alert-icon{font-size:1.5rem;margin-right:1rem}.alert-content h3{margin:0 0 .5rem;font-size:1.2rem}.alert-content p{margin:0 0 1rem}.btn-sm{padding:.5rem 1rem;font-size:.875rem} diff --git a/frontend/dist/assets/index-DUKe-Ir9.js b/frontend/dist/assets/index-DUKe-Ir9.js deleted file mode 100644 index 0486a8d..0000000 --- a/frontend/dist/assets/index-DUKe-Ir9.js +++ /dev/null @@ -1,94 +0,0 @@ -var Xh=Object.defineProperty;var Yh=(e,t,n)=>t in e?Xh(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Hi=(e,t,n)=>Yh(e,typeof t!="symbol"?t+"":t,n);function Gh(e,t){for(var n=0;nr[s]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))r(s);new MutationObserver(s=>{for(const i of s)if(i.type==="childList")for(const o of i.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&r(o)}).observe(document,{childList:!0,subtree:!0});function n(s){const i={};return s.integrity&&(i.integrity=s.integrity),s.referrerPolicy&&(i.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?i.credentials="include":s.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function r(s){if(s.ep)return;s.ep=!0;const i=n(s);fetch(s.href,i)}})();function Zh(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var Bc={exports:{}},vi={},Dc={exports:{}},M={};/** - * @license React - * react.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var Xr=Symbol.for("react.element"),ep=Symbol.for("react.portal"),tp=Symbol.for("react.fragment"),np=Symbol.for("react.strict_mode"),rp=Symbol.for("react.profiler"),sp=Symbol.for("react.provider"),ip=Symbol.for("react.context"),op=Symbol.for("react.forward_ref"),lp=Symbol.for("react.suspense"),ap=Symbol.for("react.memo"),up=Symbol.for("react.lazy"),Ja=Symbol.iterator;function cp(e){return e===null||typeof e!="object"?null:(e=Ja&&e[Ja]||e["@@iterator"],typeof e=="function"?e:null)}var Fc={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Ic=Object.assign,Uc={};function Xn(e,t,n){this.props=e,this.context=t,this.refs=Uc,this.updater=n||Fc}Xn.prototype.isReactComponent={};Xn.prototype.setState=function(e,t){if(typeof e!="object"&&typeof e!="function"&&e!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")};Xn.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")};function zc(){}zc.prototype=Xn.prototype;function Dl(e,t,n){this.props=e,this.context=t,this.refs=Uc,this.updater=n||Fc}var Fl=Dl.prototype=new zc;Fl.constructor=Dl;Ic(Fl,Xn.prototype);Fl.isPureReactComponent=!0;var Xa=Array.isArray,Mc=Object.prototype.hasOwnProperty,Il={current:null},$c={key:!0,ref:!0,__self:!0,__source:!0};function Vc(e,t,n){var r,s={},i=null,o=null;if(t!=null)for(r in t.ref!==void 0&&(o=t.ref),t.key!==void 0&&(i=""+t.key),t)Mc.call(t,r)&&!$c.hasOwnProperty(r)&&(s[r]=t[r]);var a=arguments.length-2;if(a===1)s.children=n;else if(1>>1,U=k[D];if(0>>1;Ds(Ue,L))Ces(et,Ue)?(k[D]=et,k[Ce]=L,D=Ce):(k[D]=Ue,k[Se]=L,D=Se);else if(Ces(et,L))k[D]=et,k[Ce]=L,D=Ce;else break e}}return _}function s(k,_){var L=k.sortIndex-_.sortIndex;return L!==0?L:k.id-_.id}if(typeof performance=="object"&&typeof performance.now=="function"){var i=performance;e.unstable_now=function(){return i.now()}}else{var o=Date,a=o.now();e.unstable_now=function(){return o.now()-a}}var u=[],c=[],d=1,f=null,g=3,S=!1,y=!1,v=!1,w=typeof setTimeout=="function"?setTimeout:null,p=typeof clearTimeout=="function"?clearTimeout:null,h=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function m(k){for(var _=n(c);_!==null;){if(_.callback===null)r(c);else if(_.startTime<=k)r(c),_.sortIndex=_.expirationTime,t(u,_);else break;_=n(c)}}function N(k){if(v=!1,m(k),!y)if(n(u)!==null)y=!0,W(C);else{var _=n(c);_!==null&&he(N,_.startTime-k)}}function C(k,_){y=!1,v&&(v=!1,p(O),O=-1),S=!0;var L=g;try{for(m(_),f=n(u);f!==null&&(!(f.expirationTime>_)||k&&!Y());){var D=f.callback;if(typeof D=="function"){f.callback=null,g=f.priorityLevel;var U=D(f.expirationTime<=_);_=e.unstable_now(),typeof U=="function"?f.callback=U:f===n(u)&&r(u),m(_)}else r(u);f=n(u)}if(f!==null)var ge=!0;else{var Se=n(c);Se!==null&&he(N,Se.startTime-_),ge=!1}return ge}finally{f=null,g=L,S=!1}}var P=!1,T=null,O=-1,I=5,b=-1;function Y(){return!(e.unstable_now()-bk||125D?(k.sortIndex=L,t(c,k),n(u)===null&&k===n(c)&&(v?(p(O),O=-1):v=!0,he(N,L-D))):(k.sortIndex=U,t(u,k),y||S||(y=!0,W(C))),k},e.unstable_shouldYield=Y,e.unstable_wrapCallback=function(k){var _=g;return function(){var L=g;g=_;try{return k.apply(this,arguments)}finally{g=L}}}})(Jc);Qc.exports=Jc;var Np=Qc.exports;/** - * @license React - * react-dom.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var Ep=x,He=Np;function R(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Po=Object.prototype.hasOwnProperty,kp=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,Ga={},Za={};function _p(e){return Po.call(Za,e)?!0:Po.call(Ga,e)?!1:kp.test(e)?Za[e]=!0:(Ga[e]=!0,!1)}function jp(e,t,n,r){if(n!==null&&n.type===0)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return r?!1:n!==null?!n.acceptsBooleans:(e=e.toLowerCase().slice(0,5),e!=="data-"&&e!=="aria-");default:return!1}}function Cp(e,t,n,r){if(t===null||typeof t>"u"||jp(e,t,n,r))return!0;if(r)return!1;if(n!==null)switch(n.type){case 3:return!t;case 4:return t===!1;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}function Oe(e,t,n,r,s,i,o){this.acceptsBooleans=t===2||t===3||t===4,this.attributeName=r,this.attributeNamespace=s,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=i,this.removeEmptyString=o}var we={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(e){we[e]=new Oe(e,0,!1,e,null,!1,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(e){var t=e[0];we[t]=new Oe(t,1,!1,e[1],null,!1,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(e){we[e]=new Oe(e,2,!1,e.toLowerCase(),null,!1,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(e){we[e]=new Oe(e,2,!1,e,null,!1,!1)});"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(e){we[e]=new Oe(e,3,!1,e.toLowerCase(),null,!1,!1)});["checked","multiple","muted","selected"].forEach(function(e){we[e]=new Oe(e,3,!0,e,null,!1,!1)});["capture","download"].forEach(function(e){we[e]=new Oe(e,4,!1,e,null,!1,!1)});["cols","rows","size","span"].forEach(function(e){we[e]=new Oe(e,6,!1,e,null,!1,!1)});["rowSpan","start"].forEach(function(e){we[e]=new Oe(e,5,!1,e.toLowerCase(),null,!1,!1)});var zl=/[\-:]([a-z])/g;function Ml(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var t=e.replace(zl,Ml);we[t]=new Oe(t,1,!1,e,null,!1,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var t=e.replace(zl,Ml);we[t]=new Oe(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)});["xml:base","xml:lang","xml:space"].forEach(function(e){var t=e.replace(zl,Ml);we[t]=new Oe(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)});["tabIndex","crossOrigin"].forEach(function(e){we[e]=new Oe(e,1,!1,e.toLowerCase(),null,!1,!1)});we.xlinkHref=new Oe("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1);["src","href","action","formAction"].forEach(function(e){we[e]=new Oe(e,1,!1,e.toLowerCase(),null,!0,!0)});function $l(e,t,n,r){var s=we.hasOwnProperty(t)?we[t]:null;(s!==null?s.type!==0:r||!(2a||s[o]!==i[a]){var u=` -`+s[o].replace(" at new "," at ");return e.displayName&&u.includes("")&&(u=u.replace("",e.displayName)),u}while(1<=o&&0<=a);break}}}finally{Ki=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?gr(e):""}function Rp(e){switch(e.tag){case 5:return gr(e.type);case 16:return gr("Lazy");case 13:return gr("Suspense");case 19:return gr("SuspenseList");case 0:case 2:case 15:return e=Qi(e.type,!1),e;case 11:return e=Qi(e.type.render,!1),e;case 1:return e=Qi(e.type,!0),e;default:return""}}function bo(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case _n:return"Fragment";case kn:return"Portal";case Oo:return"Profiler";case Vl:return"StrictMode";case Ao:return"Suspense";case Lo:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case Gc:return(e.displayName||"Context")+".Consumer";case Yc:return(e._context.displayName||"Context")+".Provider";case Hl:var t=e.render;return e=e.displayName,e||(e=t.displayName||t.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case Wl:return t=e.displayName||null,t!==null?t:bo(e.type)||"Memo";case At:t=e._payload,e=e._init;try{return bo(e(t))}catch{}}return null}function Tp(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=t.render,e=e.displayName||e.name||"",t.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return bo(t);case 8:return t===Vl?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof t=="function")return t.displayName||t.name||null;if(typeof t=="string")return t}return null}function Xt(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function ed(e){var t=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(t==="checkbox"||t==="radio")}function Pp(e){var t=ed(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&typeof n<"u"&&typeof n.get=="function"&&typeof n.set=="function"){var s=n.get,i=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return s.call(this)},set:function(o){r=""+o,i.call(this,o)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(o){r=""+o},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}function as(e){e._valueTracker||(e._valueTracker=Pp(e))}function td(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=ed(e)?e.checked?"true":"false":e.value),e=r,e!==n?(t.setValue(e),!0):!1}function qs(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}function Bo(e,t){var n=t.checked;return ne({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:n??e._wrapperState.initialChecked})}function tu(e,t){var n=t.defaultValue==null?"":t.defaultValue,r=t.checked!=null?t.checked:t.defaultChecked;n=Xt(t.value!=null?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:t.type==="checkbox"||t.type==="radio"?t.checked!=null:t.value!=null}}function nd(e,t){t=t.checked,t!=null&&$l(e,"checked",t,!1)}function Do(e,t){nd(e,t);var n=Xt(t.value),r=t.type;if(n!=null)r==="number"?(n===0&&e.value===""||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if(r==="submit"||r==="reset"){e.removeAttribute("value");return}t.hasOwnProperty("value")?Fo(e,t.type,n):t.hasOwnProperty("defaultValue")&&Fo(e,t.type,Xt(t.defaultValue)),t.checked==null&&t.defaultChecked!=null&&(e.defaultChecked=!!t.defaultChecked)}function nu(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!(r!=="submit"&&r!=="reset"||t.value!==void 0&&t.value!==null))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}n=e.name,n!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,n!==""&&(e.name=n)}function Fo(e,t,n){(t!=="number"||qs(e.ownerDocument)!==e)&&(n==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}var yr=Array.isArray;function Dn(e,t,n,r){if(e=e.options,t){t={};for(var s=0;s"+t.valueOf().toString()+"",t=us.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}});function Ar(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&n.nodeType===3){n.nodeValue=t;return}}e.textContent=t}var Nr={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},Op=["Webkit","ms","Moz","O"];Object.keys(Nr).forEach(function(e){Op.forEach(function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),Nr[t]=Nr[e]})});function od(e,t,n){return t==null||typeof t=="boolean"||t===""?"":n||typeof t!="number"||t===0||Nr.hasOwnProperty(e)&&Nr[e]?(""+t).trim():t+"px"}function ld(e,t){e=e.style;for(var n in t)if(t.hasOwnProperty(n)){var r=n.indexOf("--")===0,s=od(n,t[n],r);n==="float"&&(n="cssFloat"),r?e.setProperty(n,s):e[n]=s}}var Ap=ne({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function zo(e,t){if(t){if(Ap[e]&&(t.children!=null||t.dangerouslySetInnerHTML!=null))throw Error(R(137,e));if(t.dangerouslySetInnerHTML!=null){if(t.children!=null)throw Error(R(60));if(typeof t.dangerouslySetInnerHTML!="object"||!("__html"in t.dangerouslySetInnerHTML))throw Error(R(61))}if(t.style!=null&&typeof t.style!="object")throw Error(R(62))}}function Mo(e,t){if(e.indexOf("-")===-1)return typeof t.is=="string";switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var $o=null;function ql(e){return e=e.target||e.srcElement||window,e.correspondingUseElement&&(e=e.correspondingUseElement),e.nodeType===3?e.parentNode:e}var Vo=null,Fn=null,In=null;function iu(e){if(e=Zr(e)){if(typeof Vo!="function")throw Error(R(280));var t=e.stateNode;t&&(t=Ei(t),Vo(e.stateNode,e.type,t))}}function ad(e){Fn?In?In.push(e):In=[e]:Fn=e}function ud(){if(Fn){var e=Fn,t=In;if(In=Fn=null,iu(e),t)for(e=0;e>>=0,e===0?32:31-(Vp(e)/Hp|0)|0}var cs=64,ds=4194304;function vr(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return e&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function Xs(e,t){var n=e.pendingLanes;if(n===0)return 0;var r=0,s=e.suspendedLanes,i=e.pingedLanes,o=n&268435455;if(o!==0){var a=o&~s;a!==0?r=vr(a):(i&=o,i!==0&&(r=vr(i)))}else o=n&~s,o!==0?r=vr(o):i!==0&&(r=vr(i));if(r===0)return 0;if(t!==0&&t!==r&&!(t&s)&&(s=r&-r,i=t&-t,s>=i||s===16&&(i&4194240)!==0))return t;if(r&4&&(r|=n&16),t=e.entangledLanes,t!==0)for(e=e.entanglements,t&=r;0n;n++)t.push(e);return t}function Yr(e,t,n){e.pendingLanes|=t,t!==536870912&&(e.suspendedLanes=0,e.pingedLanes=0),e=e.eventTimes,t=31-lt(t),e[t]=n}function Qp(e,t){var n=e.pendingLanes&~t;e.pendingLanes=t,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=t,e.mutableReadLanes&=t,e.entangledLanes&=t,t=e.entanglements;var r=e.eventTimes;for(e=e.expirationTimes;0=kr),pu=" ",mu=!1;function Td(e,t){switch(e){case"keyup":return Nm.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Pd(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var jn=!1;function km(e,t){switch(e){case"compositionend":return Pd(t);case"keypress":return t.which!==32?null:(mu=!0,pu);case"textInput":return e=t.data,e===pu&&mu?null:e;default:return null}}function _m(e,t){if(jn)return e==="compositionend"||!ea&&Td(e,t)?(e=Cd(),Ps=Yl=Dt=null,jn=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}e:{for(;n;){if(n.nextSibling){n=n.nextSibling;break e}n=n.parentNode}n=void 0}n=wu(n)}}function bd(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?bd(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Bd(){for(var e=window,t=qs();t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href=="string"}catch{n=!1}if(n)e=t.contentWindow;else break;t=qs(e.document)}return t}function ta(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}function bm(e){var t=Bd(),n=e.focusedElem,r=e.selectionRange;if(t!==n&&n&&n.ownerDocument&&bd(n.ownerDocument.documentElement,n)){if(r!==null&&ta(n)){if(t=r.start,e=r.end,e===void 0&&(e=t),"selectionStart"in n)n.selectionStart=t,n.selectionEnd=Math.min(e,n.value.length);else if(e=(t=n.ownerDocument||document)&&t.defaultView||window,e.getSelection){e=e.getSelection();var s=n.textContent.length,i=Math.min(r.start,s);r=r.end===void 0?i:Math.min(r.end,s),!e.extend&&i>r&&(s=r,r=i,i=s),s=xu(n,i);var o=xu(n,r);s&&o&&(e.rangeCount!==1||e.anchorNode!==s.node||e.anchorOffset!==s.offset||e.focusNode!==o.node||e.focusOffset!==o.offset)&&(t=t.createRange(),t.setStart(s.node,s.offset),e.removeAllRanges(),i>r?(e.addRange(t),e.extend(o.node,o.offset)):(t.setEnd(o.node,o.offset),e.addRange(t)))}}for(t=[],e=n;e=e.parentNode;)e.nodeType===1&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for(typeof n.focus=="function"&&n.focus(),n=0;n=document.documentMode,Cn=null,Jo=null,jr=null,Xo=!1;function Su(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Xo||Cn==null||Cn!==qs(r)||(r=Cn,"selectionStart"in r&&ta(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),jr&&Ir(jr,r)||(jr=r,r=Zs(Jo,"onSelect"),0Pn||(e.current=nl[Pn],nl[Pn]=null,Pn--)}function Q(e,t){Pn++,nl[Pn]=e.current,e.current=t}var Yt={},je=Zt(Yt),be=Zt(!1),mn=Yt;function Vn(e,t){var n=e.type.contextTypes;if(!n)return Yt;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var s={},i;for(i in n)s[i]=t[i];return r&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=s),s}function Be(e){return e=e.childContextTypes,e!=null}function ti(){X(be),X(je)}function Ru(e,t,n){if(je.current!==Yt)throw Error(R(168));Q(je,t),Q(be,n)}function Hd(e,t,n){var r=e.stateNode;if(t=t.childContextTypes,typeof r.getChildContext!="function")return n;r=r.getChildContext();for(var s in r)if(!(s in t))throw Error(R(108,Tp(e)||"Unknown",s));return ne({},n,r)}function ni(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||Yt,mn=je.current,Q(je,e),Q(be,be.current),!0}function Tu(e,t,n){var r=e.stateNode;if(!r)throw Error(R(169));n?(e=Hd(e,t,mn),r.__reactInternalMemoizedMergedChildContext=e,X(be),X(je),Q(je,e)):X(be),Q(be,n)}var St=null,ki=!1,ao=!1;function Wd(e){St===null?St=[e]:St.push(e)}function qm(e){ki=!0,Wd(e)}function en(){if(!ao&&St!==null){ao=!0;var e=0,t=K;try{var n=St;for(K=1;e>=o,s-=o,Nt=1<<32-lt(t)+s|n<O?(I=T,T=null):I=T.sibling;var b=g(p,T,m[O],N);if(b===null){T===null&&(T=I);break}e&&T&&b.alternate===null&&t(p,T),h=i(b,h,O),P===null?C=b:P.sibling=b,P=b,T=I}if(O===m.length)return n(p,T),G&&on(p,O),C;if(T===null){for(;OO?(I=T,T=null):I=T.sibling;var Y=g(p,T,b.value,N);if(Y===null){T===null&&(T=I);break}e&&T&&Y.alternate===null&&t(p,T),h=i(Y,h,O),P===null?C=Y:P.sibling=Y,P=Y,T=I}if(b.done)return n(p,T),G&&on(p,O),C;if(T===null){for(;!b.done;O++,b=m.next())b=f(p,b.value,N),b!==null&&(h=i(b,h,O),P===null?C=b:P.sibling=b,P=b);return G&&on(p,O),C}for(T=r(p,T);!b.done;O++,b=m.next())b=S(T,p,O,b.value,N),b!==null&&(e&&b.alternate!==null&&T.delete(b.key===null?O:b.key),h=i(b,h,O),P===null?C=b:P.sibling=b,P=b);return e&&T.forEach(function(le){return t(p,le)}),G&&on(p,O),C}function w(p,h,m,N){if(typeof m=="object"&&m!==null&&m.type===_n&&m.key===null&&(m=m.props.children),typeof m=="object"&&m!==null){switch(m.$$typeof){case ls:e:{for(var C=m.key,P=h;P!==null;){if(P.key===C){if(C=m.type,C===_n){if(P.tag===7){n(p,P.sibling),h=s(P,m.props.children),h.return=p,p=h;break e}}else if(P.elementType===C||typeof C=="object"&&C!==null&&C.$$typeof===At&&Au(C)===P.type){n(p,P.sibling),h=s(P,m.props),h.ref=cr(p,P,m),h.return=p,p=h;break e}n(p,P);break}else t(p,P);P=P.sibling}m.type===_n?(h=hn(m.props.children,p.mode,N,m.key),h.return=p,p=h):(N=Is(m.type,m.key,m.props,null,p.mode,N),N.ref=cr(p,h,m),N.return=p,p=N)}return o(p);case kn:e:{for(P=m.key;h!==null;){if(h.key===P)if(h.tag===4&&h.stateNode.containerInfo===m.containerInfo&&h.stateNode.implementation===m.implementation){n(p,h.sibling),h=s(h,m.children||[]),h.return=p,p=h;break e}else{n(p,h);break}else t(p,h);h=h.sibling}h=yo(m,p.mode,N),h.return=p,p=h}return o(p);case At:return P=m._init,w(p,h,P(m._payload),N)}if(yr(m))return y(p,h,m,N);if(ir(m))return v(p,h,m,N);vs(p,m)}return typeof m=="string"&&m!==""||typeof m=="number"?(m=""+m,h!==null&&h.tag===6?(n(p,h.sibling),h=s(h,m),h.return=p,p=h):(n(p,h),h=go(m,p.mode,N),h.return=p,p=h),o(p)):n(p,h)}return w}var Wn=Jd(!0),Xd=Jd(!1),ii=Zt(null),oi=null,Ln=null,ia=null;function oa(){ia=Ln=oi=null}function la(e){var t=ii.current;X(ii),e._currentValue=t}function il(e,t,n){for(;e!==null;){var r=e.alternate;if((e.childLanes&t)!==t?(e.childLanes|=t,r!==null&&(r.childLanes|=t)):r!==null&&(r.childLanes&t)!==t&&(r.childLanes|=t),e===n)break;e=e.return}}function zn(e,t){oi=e,ia=Ln=null,e=e.dependencies,e!==null&&e.firstContext!==null&&(e.lanes&t&&(Le=!0),e.firstContext=null)}function Ge(e){var t=e._currentValue;if(ia!==e)if(e={context:e,memoizedValue:t,next:null},Ln===null){if(oi===null)throw Error(R(308));Ln=e,oi.dependencies={lanes:0,firstContext:e}}else Ln=Ln.next=e;return t}var un=null;function aa(e){un===null?un=[e]:un.push(e)}function Yd(e,t,n,r){var s=t.interleaved;return s===null?(n.next=n,aa(t)):(n.next=s.next,s.next=n),t.interleaved=n,Ct(e,r)}function Ct(e,t){e.lanes|=t;var n=e.alternate;for(n!==null&&(n.lanes|=t),n=e,e=e.return;e!==null;)e.childLanes|=t,n=e.alternate,n!==null&&(n.childLanes|=t),n=e,e=e.return;return n.tag===3?n.stateNode:null}var Lt=!1;function ua(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function Gd(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function kt(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function Ht(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,H&2){var s=r.pending;return s===null?t.next=t:(t.next=s.next,s.next=t),r.pending=t,Ct(e,n)}return s=r.interleaved,s===null?(t.next=t,aa(r)):(t.next=s.next,s.next=t),r.interleaved=t,Ct(e,n)}function As(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,(n&4194240)!==0)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,Ql(e,n)}}function Lu(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var s=null,i=null;if(n=n.firstBaseUpdate,n!==null){do{var o={eventTime:n.eventTime,lane:n.lane,tag:n.tag,payload:n.payload,callback:n.callback,next:null};i===null?s=i=o:i=i.next=o,n=n.next}while(n!==null);i===null?s=i=t:i=i.next=t}else s=i=t;n={baseState:r.baseState,firstBaseUpdate:s,lastBaseUpdate:i,shared:r.shared,effects:r.effects},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}function li(e,t,n,r){var s=e.updateQueue;Lt=!1;var i=s.firstBaseUpdate,o=s.lastBaseUpdate,a=s.shared.pending;if(a!==null){s.shared.pending=null;var u=a,c=u.next;u.next=null,o===null?i=c:o.next=c,o=u;var d=e.alternate;d!==null&&(d=d.updateQueue,a=d.lastBaseUpdate,a!==o&&(a===null?d.firstBaseUpdate=c:a.next=c,d.lastBaseUpdate=u))}if(i!==null){var f=s.baseState;o=0,d=c=u=null,a=i;do{var g=a.lane,S=a.eventTime;if((r&g)===g){d!==null&&(d=d.next={eventTime:S,lane:0,tag:a.tag,payload:a.payload,callback:a.callback,next:null});e:{var y=e,v=a;switch(g=t,S=n,v.tag){case 1:if(y=v.payload,typeof y=="function"){f=y.call(S,f,g);break e}f=y;break e;case 3:y.flags=y.flags&-65537|128;case 0:if(y=v.payload,g=typeof y=="function"?y.call(S,f,g):y,g==null)break e;f=ne({},f,g);break e;case 2:Lt=!0}}a.callback!==null&&a.lane!==0&&(e.flags|=64,g=s.effects,g===null?s.effects=[a]:g.push(a))}else S={eventTime:S,lane:g,tag:a.tag,payload:a.payload,callback:a.callback,next:null},d===null?(c=d=S,u=f):d=d.next=S,o|=g;if(a=a.next,a===null){if(a=s.shared.pending,a===null)break;g=a,a=g.next,g.next=null,s.lastBaseUpdate=g,s.shared.pending=null}}while(!0);if(d===null&&(u=f),s.baseState=u,s.firstBaseUpdate=c,s.lastBaseUpdate=d,t=s.shared.interleaved,t!==null){s=t;do o|=s.lane,s=s.next;while(s!==t)}else i===null&&(s.shared.lanes=0);vn|=o,e.lanes=o,e.memoizedState=f}}function bu(e,t,n){if(e=t.effects,t.effects=null,e!==null)for(t=0;tn?n:4,e(!0);var r=co.transition;co.transition={};try{e(!1),t()}finally{K=n,co.transition=r}}function gf(){return Ze().memoizedState}function Xm(e,t,n){var r=qt(e);if(n={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null},yf(e))vf(t,n);else if(n=Yd(e,t,n,r),n!==null){var s=Te();at(n,e,r,s),wf(n,t,r)}}function Ym(e,t,n){var r=qt(e),s={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null};if(yf(e))vf(t,s);else{var i=e.alternate;if(e.lanes===0&&(i===null||i.lanes===0)&&(i=t.lastRenderedReducer,i!==null))try{var o=t.lastRenderedState,a=i(o,n);if(s.hasEagerState=!0,s.eagerState=a,ut(a,o)){var u=t.interleaved;u===null?(s.next=s,aa(t)):(s.next=u.next,u.next=s),t.interleaved=s;return}}catch{}finally{}n=Yd(e,t,s,r),n!==null&&(s=Te(),at(n,e,r,s),wf(n,t,r))}}function yf(e){var t=e.alternate;return e===te||t!==null&&t===te}function vf(e,t){Cr=ui=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function wf(e,t,n){if(n&4194240){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,Ql(e,n)}}var ci={readContext:Ge,useCallback:Ne,useContext:Ne,useEffect:Ne,useImperativeHandle:Ne,useInsertionEffect:Ne,useLayoutEffect:Ne,useMemo:Ne,useReducer:Ne,useRef:Ne,useState:Ne,useDebugValue:Ne,useDeferredValue:Ne,useTransition:Ne,useMutableSource:Ne,useSyncExternalStore:Ne,useId:Ne,unstable_isNewReconciler:!1},Gm={readContext:Ge,useCallback:function(e,t){return ht().memoizedState=[e,t===void 0?null:t],e},useContext:Ge,useEffect:Du,useImperativeHandle:function(e,t,n){return n=n!=null?n.concat([e]):null,bs(4194308,4,df.bind(null,t,e),n)},useLayoutEffect:function(e,t){return bs(4194308,4,e,t)},useInsertionEffect:function(e,t){return bs(4,2,e,t)},useMemo:function(e,t){var n=ht();return t=t===void 0?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=ht();return t=n!==void 0?n(t):t,r.memoizedState=r.baseState=t,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:t},r.queue=e,e=e.dispatch=Xm.bind(null,te,e),[r.memoizedState,e]},useRef:function(e){var t=ht();return e={current:e},t.memoizedState=e},useState:Bu,useDebugValue:ya,useDeferredValue:function(e){return ht().memoizedState=e},useTransition:function(){var e=Bu(!1),t=e[0];return e=Jm.bind(null,e[1]),ht().memoizedState=e,[t,e]},useMutableSource:function(){},useSyncExternalStore:function(e,t,n){var r=te,s=ht();if(G){if(n===void 0)throw Error(R(407));n=n()}else{if(n=t(),me===null)throw Error(R(349));yn&30||nf(r,t,n)}s.memoizedState=n;var i={value:n,getSnapshot:t};return s.queue=i,Du(sf.bind(null,r,i,e),[e]),r.flags|=2048,qr(9,rf.bind(null,r,i,n,t),void 0,null),n},useId:function(){var e=ht(),t=me.identifierPrefix;if(G){var n=Et,r=Nt;n=(r&~(1<<32-lt(r)-1)).toString(32)+n,t=":"+t+"R"+n,n=Hr++,0<\/script>",e=e.removeChild(e.firstChild)):typeof r.is=="string"?e=o.createElement(n,{is:r.is}):(e=o.createElement(n),n==="select"&&(o=e,r.multiple?o.multiple=!0:r.size&&(o.size=r.size))):e=o.createElementNS(e,n),e[pt]=t,e[Mr]=r,Tf(e,t,!1,!1),t.stateNode=e;e:{switch(o=Mo(n,r),n){case"dialog":J("cancel",e),J("close",e),s=r;break;case"iframe":case"object":case"embed":J("load",e),s=r;break;case"video":case"audio":for(s=0;sQn&&(t.flags|=128,r=!0,dr(i,!1),t.lanes=4194304)}else{if(!r)if(e=ai(o),e!==null){if(t.flags|=128,r=!0,n=e.updateQueue,n!==null&&(t.updateQueue=n,t.flags|=4),dr(i,!0),i.tail===null&&i.tailMode==="hidden"&&!o.alternate&&!G)return Ee(t),null}else 2*se()-i.renderingStartTime>Qn&&n!==1073741824&&(t.flags|=128,r=!0,dr(i,!1),t.lanes=4194304);i.isBackwards?(o.sibling=t.child,t.child=o):(n=i.last,n!==null?n.sibling=o:t.child=o,i.last=o)}return i.tail!==null?(t=i.tail,i.rendering=t,i.tail=t.sibling,i.renderingStartTime=se(),t.sibling=null,n=ee.current,Q(ee,r?n&1|2:n&1),t):(Ee(t),null);case 22:case 23:return Ea(),r=t.memoizedState!==null,e!==null&&e.memoizedState!==null!==r&&(t.flags|=8192),r&&t.mode&1?ze&1073741824&&(Ee(t),t.subtreeFlags&6&&(t.flags|=8192)):Ee(t),null;case 24:return null;case 25:return null}throw Error(R(156,t.tag))}function og(e,t){switch(ra(t),t.tag){case 1:return Be(t.type)&&ti(),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return qn(),X(be),X(je),fa(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 5:return da(t),null;case 13:if(X(ee),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(R(340));Hn()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return X(ee),null;case 4:return qn(),null;case 10:return la(t.type._context),null;case 22:case 23:return Ea(),null;case 24:return null;default:return null}}var xs=!1,ke=!1,lg=typeof WeakSet=="function"?WeakSet:Set,A=null;function bn(e,t){var n=e.ref;if(n!==null)if(typeof n=="function")try{n(null)}catch(r){re(e,t,r)}else n.current=null}function pl(e,t,n){try{n()}catch(r){re(e,t,r)}}var Ku=!1;function ag(e,t){if(Yo=Ys,e=Bd(),ta(e)){if("selectionStart"in e)var n={start:e.selectionStart,end:e.selectionEnd};else e:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var s=r.anchorOffset,i=r.focusNode;r=r.focusOffset;try{n.nodeType,i.nodeType}catch{n=null;break e}var o=0,a=-1,u=-1,c=0,d=0,f=e,g=null;t:for(;;){for(var S;f!==n||s!==0&&f.nodeType!==3||(a=o+s),f!==i||r!==0&&f.nodeType!==3||(u=o+r),f.nodeType===3&&(o+=f.nodeValue.length),(S=f.firstChild)!==null;)g=f,f=S;for(;;){if(f===e)break t;if(g===n&&++c===s&&(a=o),g===i&&++d===r&&(u=o),(S=f.nextSibling)!==null)break;f=g,g=f.parentNode}f=S}n=a===-1||u===-1?null:{start:a,end:u}}else n=null}n=n||{start:0,end:0}}else n=null;for(Go={focusedElem:e,selectionRange:n},Ys=!1,A=t;A!==null;)if(t=A,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,A=e;else for(;A!==null;){t=A;try{var y=t.alternate;if(t.flags&1024)switch(t.tag){case 0:case 11:case 15:break;case 1:if(y!==null){var v=y.memoizedProps,w=y.memoizedState,p=t.stateNode,h=p.getSnapshotBeforeUpdate(t.elementType===t.type?v:nt(t.type,v),w);p.__reactInternalSnapshotBeforeUpdate=h}break;case 3:var m=t.stateNode.containerInfo;m.nodeType===1?m.textContent="":m.nodeType===9&&m.documentElement&&m.removeChild(m.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(R(163))}}catch(N){re(t,t.return,N)}if(e=t.sibling,e!==null){e.return=t.return,A=e;break}A=t.return}return y=Ku,Ku=!1,y}function Rr(e,t,n){var r=t.updateQueue;if(r=r!==null?r.lastEffect:null,r!==null){var s=r=r.next;do{if((s.tag&e)===e){var i=s.destroy;s.destroy=void 0,i!==void 0&&pl(t,n,i)}s=s.next}while(s!==r)}}function Ci(e,t){if(t=t.updateQueue,t=t!==null?t.lastEffect:null,t!==null){var n=t=t.next;do{if((n.tag&e)===e){var r=n.create;n.destroy=r()}n=n.next}while(n!==t)}}function ml(e){var t=e.ref;if(t!==null){var n=e.stateNode;switch(e.tag){case 5:e=n;break;default:e=n}typeof t=="function"?t(e):t.current=e}}function Af(e){var t=e.alternate;t!==null&&(e.alternate=null,Af(t)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(t=e.stateNode,t!==null&&(delete t[pt],delete t[Mr],delete t[tl],delete t[Hm],delete t[Wm])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function Lf(e){return e.tag===5||e.tag===3||e.tag===4}function Qu(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||Lf(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function gl(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.nodeType===8?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(n.nodeType===8?(t=n.parentNode,t.insertBefore(e,n)):(t=n,t.appendChild(e)),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=ei));else if(r!==4&&(e=e.child,e!==null))for(gl(e,t,n),e=e.sibling;e!==null;)gl(e,t,n),e=e.sibling}function yl(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(e=e.child,e!==null))for(yl(e,t,n),e=e.sibling;e!==null;)yl(e,t,n),e=e.sibling}var ye=null,st=!1;function Ot(e,t,n){for(n=n.child;n!==null;)bf(e,t,n),n=n.sibling}function bf(e,t,n){if(mt&&typeof mt.onCommitFiberUnmount=="function")try{mt.onCommitFiberUnmount(wi,n)}catch{}switch(n.tag){case 5:ke||bn(n,t);case 6:var r=ye,s=st;ye=null,Ot(e,t,n),ye=r,st=s,ye!==null&&(st?(e=ye,n=n.stateNode,e.nodeType===8?e.parentNode.removeChild(n):e.removeChild(n)):ye.removeChild(n.stateNode));break;case 18:ye!==null&&(st?(e=ye,n=n.stateNode,e.nodeType===8?lo(e.parentNode,n):e.nodeType===1&&lo(e,n),Dr(e)):lo(ye,n.stateNode));break;case 4:r=ye,s=st,ye=n.stateNode.containerInfo,st=!0,Ot(e,t,n),ye=r,st=s;break;case 0:case 11:case 14:case 15:if(!ke&&(r=n.updateQueue,r!==null&&(r=r.lastEffect,r!==null))){s=r=r.next;do{var i=s,o=i.destroy;i=i.tag,o!==void 0&&(i&2||i&4)&&pl(n,t,o),s=s.next}while(s!==r)}Ot(e,t,n);break;case 1:if(!ke&&(bn(n,t),r=n.stateNode,typeof r.componentWillUnmount=="function"))try{r.props=n.memoizedProps,r.state=n.memoizedState,r.componentWillUnmount()}catch(a){re(n,t,a)}Ot(e,t,n);break;case 21:Ot(e,t,n);break;case 22:n.mode&1?(ke=(r=ke)||n.memoizedState!==null,Ot(e,t,n),ke=r):Ot(e,t,n);break;default:Ot(e,t,n)}}function Ju(e){var t=e.updateQueue;if(t!==null){e.updateQueue=null;var n=e.stateNode;n===null&&(n=e.stateNode=new lg),t.forEach(function(r){var s=yg.bind(null,e,r);n.has(r)||(n.add(r),r.then(s,s))})}}function tt(e,t){var n=t.deletions;if(n!==null)for(var r=0;rs&&(s=o),r&=~i}if(r=s,r=se()-r,r=(120>r?120:480>r?480:1080>r?1080:1920>r?1920:3e3>r?3e3:4320>r?4320:1960*cg(r/1960))-r,10e?16:e,Ft===null)var r=!1;else{if(e=Ft,Ft=null,hi=0,H&6)throw Error(R(331));var s=H;for(H|=4,A=e.current;A!==null;){var i=A,o=i.child;if(A.flags&16){var a=i.deletions;if(a!==null){for(var u=0;use()-Sa?fn(e,0):xa|=n),De(e,t)}function $f(e,t){t===0&&(e.mode&1?(t=ds,ds<<=1,!(ds&130023424)&&(ds=4194304)):t=1);var n=Te();e=Ct(e,t),e!==null&&(Yr(e,t,n),De(e,n))}function gg(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),$f(e,n)}function yg(e,t){var n=0;switch(e.tag){case 13:var r=e.stateNode,s=e.memoizedState;s!==null&&(n=s.retryLane);break;case 19:r=e.stateNode;break;default:throw Error(R(314))}r!==null&&r.delete(t),$f(e,n)}var Vf;Vf=function(e,t,n){if(e!==null)if(e.memoizedProps!==t.pendingProps||be.current)Le=!0;else{if(!(e.lanes&n)&&!(t.flags&128))return Le=!1,sg(e,t,n);Le=!!(e.flags&131072)}else Le=!1,G&&t.flags&1048576&&qd(t,si,t.index);switch(t.lanes=0,t.tag){case 2:var r=t.type;Bs(e,t),e=t.pendingProps;var s=Vn(t,je.current);zn(t,n),s=pa(null,t,r,e,s,n);var i=ma();return t.flags|=1,typeof s=="object"&&s!==null&&typeof s.render=="function"&&s.$$typeof===void 0?(t.tag=1,t.memoizedState=null,t.updateQueue=null,Be(r)?(i=!0,ni(t)):i=!1,t.memoizedState=s.state!==null&&s.state!==void 0?s.state:null,ua(t),s.updater=ji,t.stateNode=s,s._reactInternals=t,ll(t,r,e,n),t=cl(null,t,r,!0,i,n)):(t.tag=0,G&&i&&na(t),Re(null,t,s,n),t=t.child),t;case 16:r=t.elementType;e:{switch(Bs(e,t),e=t.pendingProps,s=r._init,r=s(r._payload),t.type=r,s=t.tag=wg(r),e=nt(r,e),s){case 0:t=ul(null,t,r,e,n);break e;case 1:t=Hu(null,t,r,e,n);break e;case 11:t=$u(null,t,r,e,n);break e;case 14:t=Vu(null,t,r,nt(r.type,e),n);break e}throw Error(R(306,r,""))}return t;case 0:return r=t.type,s=t.pendingProps,s=t.elementType===r?s:nt(r,s),ul(e,t,r,s,n);case 1:return r=t.type,s=t.pendingProps,s=t.elementType===r?s:nt(r,s),Hu(e,t,r,s,n);case 3:e:{if(jf(t),e===null)throw Error(R(387));r=t.pendingProps,i=t.memoizedState,s=i.element,Gd(e,t),li(t,r,null,n);var o=t.memoizedState;if(r=o.element,i.isDehydrated)if(i={element:r,isDehydrated:!1,cache:o.cache,pendingSuspenseBoundaries:o.pendingSuspenseBoundaries,transitions:o.transitions},t.updateQueue.baseState=i,t.memoizedState=i,t.flags&256){s=Kn(Error(R(423)),t),t=Wu(e,t,r,n,s);break e}else if(r!==s){s=Kn(Error(R(424)),t),t=Wu(e,t,r,n,s);break e}else for($e=Vt(t.stateNode.containerInfo.firstChild),Ve=t,G=!0,ot=null,n=Xd(t,null,r,n),t.child=n;n;)n.flags=n.flags&-3|4096,n=n.sibling;else{if(Hn(),r===s){t=Rt(e,t,n);break e}Re(e,t,r,n)}t=t.child}return t;case 5:return Zd(t),e===null&&sl(t),r=t.type,s=t.pendingProps,i=e!==null?e.memoizedProps:null,o=s.children,Zo(r,s)?o=null:i!==null&&Zo(r,i)&&(t.flags|=32),_f(e,t),Re(e,t,o,n),t.child;case 6:return e===null&&sl(t),null;case 13:return Cf(e,t,n);case 4:return ca(t,t.stateNode.containerInfo),r=t.pendingProps,e===null?t.child=Wn(t,null,r,n):Re(e,t,r,n),t.child;case 11:return r=t.type,s=t.pendingProps,s=t.elementType===r?s:nt(r,s),$u(e,t,r,s,n);case 7:return Re(e,t,t.pendingProps,n),t.child;case 8:return Re(e,t,t.pendingProps.children,n),t.child;case 12:return Re(e,t,t.pendingProps.children,n),t.child;case 10:e:{if(r=t.type._context,s=t.pendingProps,i=t.memoizedProps,o=s.value,Q(ii,r._currentValue),r._currentValue=o,i!==null)if(ut(i.value,o)){if(i.children===s.children&&!be.current){t=Rt(e,t,n);break e}}else for(i=t.child,i!==null&&(i.return=t);i!==null;){var a=i.dependencies;if(a!==null){o=i.child;for(var u=a.firstContext;u!==null;){if(u.context===r){if(i.tag===1){u=kt(-1,n&-n),u.tag=2;var c=i.updateQueue;if(c!==null){c=c.shared;var d=c.pending;d===null?u.next=u:(u.next=d.next,d.next=u),c.pending=u}}i.lanes|=n,u=i.alternate,u!==null&&(u.lanes|=n),il(i.return,n,t),a.lanes|=n;break}u=u.next}}else if(i.tag===10)o=i.type===t.type?null:i.child;else if(i.tag===18){if(o=i.return,o===null)throw Error(R(341));o.lanes|=n,a=o.alternate,a!==null&&(a.lanes|=n),il(o,n,t),o=i.sibling}else o=i.child;if(o!==null)o.return=i;else for(o=i;o!==null;){if(o===t){o=null;break}if(i=o.sibling,i!==null){i.return=o.return,o=i;break}o=o.return}i=o}Re(e,t,s.children,n),t=t.child}return t;case 9:return s=t.type,r=t.pendingProps.children,zn(t,n),s=Ge(s),r=r(s),t.flags|=1,Re(e,t,r,n),t.child;case 14:return r=t.type,s=nt(r,t.pendingProps),s=nt(r.type,s),Vu(e,t,r,s,n);case 15:return Ef(e,t,t.type,t.pendingProps,n);case 17:return r=t.type,s=t.pendingProps,s=t.elementType===r?s:nt(r,s),Bs(e,t),t.tag=1,Be(r)?(e=!0,ni(t)):e=!1,zn(t,n),xf(t,r,s),ll(t,r,s,n),cl(null,t,r,!0,e,n);case 19:return Rf(e,t,n);case 22:return kf(e,t,n)}throw Error(R(156,t.tag))};function Hf(e,t){return gd(e,t)}function vg(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Xe(e,t,n,r){return new vg(e,t,n,r)}function _a(e){return e=e.prototype,!(!e||!e.isReactComponent)}function wg(e){if(typeof e=="function")return _a(e)?1:0;if(e!=null){if(e=e.$$typeof,e===Hl)return 11;if(e===Wl)return 14}return 2}function Kt(e,t){var n=e.alternate;return n===null?(n=Xe(e.tag,t,e.key,e.mode),n.elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.subtreeFlags=0,n.deletions=null),n.flags=e.flags&14680064,n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=t===null?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function Is(e,t,n,r,s,i){var o=2;if(r=e,typeof e=="function")_a(e)&&(o=1);else if(typeof e=="string")o=5;else e:switch(e){case _n:return hn(n.children,s,i,t);case Vl:o=8,s|=8;break;case Oo:return e=Xe(12,n,t,s|2),e.elementType=Oo,e.lanes=i,e;case Ao:return e=Xe(13,n,t,s),e.elementType=Ao,e.lanes=i,e;case Lo:return e=Xe(19,n,t,s),e.elementType=Lo,e.lanes=i,e;case Zc:return Ti(n,s,i,t);default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case Yc:o=10;break e;case Gc:o=9;break e;case Hl:o=11;break e;case Wl:o=14;break e;case At:o=16,r=null;break e}throw Error(R(130,e==null?e:typeof e,""))}return t=Xe(o,n,t,s),t.elementType=e,t.type=r,t.lanes=i,t}function hn(e,t,n,r){return e=Xe(7,e,r,t),e.lanes=n,e}function Ti(e,t,n,r){return e=Xe(22,e,r,t),e.elementType=Zc,e.lanes=n,e.stateNode={isHidden:!1},e}function go(e,t,n){return e=Xe(6,e,null,t),e.lanes=n,e}function yo(e,t,n){return t=Xe(4,e.children!==null?e.children:[],e.key,t),t.lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function xg(e,t,n,r,s){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=Xi(0),this.expirationTimes=Xi(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=Xi(0),this.identifierPrefix=r,this.onRecoverableError=s,this.mutableSourceEagerHydrationData=null}function ja(e,t,n,r,s,i,o,a,u){return e=new xg(e,t,n,a,u),t===1?(t=1,i===!0&&(t|=8)):t=0,i=Xe(3,null,null,t),e.current=i,i.stateNode=e,i.memoizedState={element:r,isDehydrated:n,cache:null,transitions:null,pendingSuspenseBoundaries:null},ua(i),e}function Sg(e,t,n){var r=3"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(Qf)}catch(e){console.error(e)}}Qf(),Kc.exports=We;var jg=Kc.exports,rc=jg;To.createRoot=rc.createRoot,To.hydrateRoot=rc.hydrateRoot;/** - * @remix-run/router v1.23.1 - * - * Copyright (c) Remix Software Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE.md file in the root directory of this source tree. - * - * @license MIT - */function Qr(){return Qr=Object.assign?Object.assign.bind():function(e){for(var t=1;t"u")throw new Error(t)}function Pa(e,t){if(!e){typeof console<"u"&&console.warn(t);try{throw new Error(t)}catch{}}}function Rg(){return Math.random().toString(36).substr(2,8)}function ic(e,t){return{usr:e.state,key:e.key,idx:t}}function Nl(e,t,n,r){return n===void 0&&(n=null),Qr({pathname:typeof e=="string"?e:e.pathname,search:"",hash:""},typeof t=="string"?Zn(t):t,{state:n,key:t&&t.key||r||Rg()})}function gi(e){let{pathname:t="/",search:n="",hash:r=""}=e;return n&&n!=="?"&&(t+=n.charAt(0)==="?"?n:"?"+n),r&&r!=="#"&&(t+=r.charAt(0)==="#"?r:"#"+r),t}function Zn(e){let t={};if(e){let n=e.indexOf("#");n>=0&&(t.hash=e.substr(n),e=e.substr(0,n));let r=e.indexOf("?");r>=0&&(t.search=e.substr(r),e=e.substr(0,r)),e&&(t.pathname=e)}return t}function Tg(e,t,n,r){r===void 0&&(r={});let{window:s=document.defaultView,v5Compat:i=!1}=r,o=s.history,a=It.Pop,u=null,c=d();c==null&&(c=0,o.replaceState(Qr({},o.state,{idx:c}),""));function d(){return(o.state||{idx:null}).idx}function f(){a=It.Pop;let w=d(),p=w==null?null:w-c;c=w,u&&u({action:a,location:v.location,delta:p})}function g(w,p){a=It.Push;let h=Nl(v.location,w,p);c=d()+1;let m=ic(h,c),N=v.createHref(h);try{o.pushState(m,"",N)}catch(C){if(C instanceof DOMException&&C.name==="DataCloneError")throw C;s.location.assign(N)}i&&u&&u({action:a,location:v.location,delta:1})}function S(w,p){a=It.Replace;let h=Nl(v.location,w,p);c=d();let m=ic(h,c),N=v.createHref(h);o.replaceState(m,"",N),i&&u&&u({action:a,location:v.location,delta:0})}function y(w){let p=s.location.origin!=="null"?s.location.origin:s.location.href,h=typeof w=="string"?w:gi(w);return h=h.replace(/ $/,"%20"),ie(p,"No window.location.(origin|href) available to create URL for href: "+h),new URL(h,p)}let v={get action(){return a},get location(){return e(s,o)},listen(w){if(u)throw new Error("A history only accepts one active listener");return s.addEventListener(sc,f),u=w,()=>{s.removeEventListener(sc,f),u=null}},createHref(w){return t(s,w)},createURL:y,encodeLocation(w){let p=y(w);return{pathname:p.pathname,search:p.search,hash:p.hash}},push:g,replace:S,go(w){return o.go(w)}};return v}var oc;(function(e){e.data="data",e.deferred="deferred",e.redirect="redirect",e.error="error"})(oc||(oc={}));function Pg(e,t,n){return n===void 0&&(n="/"),Og(e,t,n)}function Og(e,t,n,r){let s=typeof t=="string"?Zn(t):t,i=Oa(s.pathname||"/",n);if(i==null)return null;let o=Jf(e);Ag(o);let a=null;for(let u=0;a==null&&u{let u={relativePath:a===void 0?i.path||"":a,caseSensitive:i.caseSensitive===!0,childrenIndex:o,route:i};u.relativePath.startsWith("/")&&(ie(u.relativePath.startsWith(r),'Absolute route path "'+u.relativePath+'" nested under path '+('"'+r+'" is not valid. An absolute child route path ')+"must start with the combined path of all its parent routes."),u.relativePath=u.relativePath.slice(r.length));let c=Qt([r,u.relativePath]),d=n.concat(u);i.children&&i.children.length>0&&(ie(i.index!==!0,"Index routes must not have child routes. Please remove "+('all child routes from route path "'+c+'".')),Jf(i.children,t,d,c)),!(i.path==null&&!i.index)&&t.push({path:c,score:Ug(c,i.index),routesMeta:d})};return e.forEach((i,o)=>{var a;if(i.path===""||!((a=i.path)!=null&&a.includes("?")))s(i,o);else for(let u of Xf(i.path))s(i,o,u)}),t}function Xf(e){let t=e.split("/");if(t.length===0)return[];let[n,...r]=t,s=n.endsWith("?"),i=n.replace(/\?$/,"");if(r.length===0)return s?[i,""]:[i];let o=Xf(r.join("/")),a=[];return a.push(...o.map(u=>u===""?i:[i,u].join("/"))),s&&a.push(...o),a.map(u=>e.startsWith("/")&&u===""?"/":u)}function Ag(e){e.sort((t,n)=>t.score!==n.score?n.score-t.score:zg(t.routesMeta.map(r=>r.childrenIndex),n.routesMeta.map(r=>r.childrenIndex)))}const Lg=/^:[\w-]+$/,bg=3,Bg=2,Dg=1,Fg=10,Ig=-2,lc=e=>e==="*";function Ug(e,t){let n=e.split("/"),r=n.length;return n.some(lc)&&(r+=Ig),t&&(r+=Bg),n.filter(s=>!lc(s)).reduce((s,i)=>s+(Lg.test(i)?bg:i===""?Dg:Fg),r)}function zg(e,t){return e.length===t.length&&e.slice(0,-1).every((r,s)=>r===t[s])?e[e.length-1]-t[t.length-1]:0}function Mg(e,t,n){let{routesMeta:r}=e,s={},i="/",o=[];for(let a=0;a{let{paramName:g,isOptional:S}=d;if(g==="*"){let v=a[f]||"";o=i.slice(0,i.length-v.length).replace(/(.)\/+$/,"$1")}const y=a[f];return S&&!y?c[g]=void 0:c[g]=(y||"").replace(/%2F/g,"/"),c},{}),pathname:i,pathnameBase:o,pattern:e}}function Vg(e,t,n){t===void 0&&(t=!1),n===void 0&&(n=!0),Pa(e==="*"||!e.endsWith("*")||e.endsWith("/*"),'Route path "'+e+'" will be treated as if it were '+('"'+e.replace(/\*$/,"/*")+'" because the `*` character must ')+"always follow a `/` in the pattern. To get rid of this warning, "+('please change the route path to "'+e.replace(/\*$/,"/*")+'".'));let r=[],s="^"+e.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(o,a,u)=>(r.push({paramName:a,isOptional:u!=null}),u?"/?([^\\/]+)?":"/([^\\/]+)"));return e.endsWith("*")?(r.push({paramName:"*"}),s+=e==="*"||e==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):n?s+="\\/*$":e!==""&&e!=="/"&&(s+="(?:(?=\\/|$))"),[new RegExp(s,t?void 0:"i"),r]}function Hg(e){try{return e.split("/").map(t=>decodeURIComponent(t).replace(/\//g,"%2F")).join("/")}catch(t){return Pa(!1,'The URL path "'+e+'" could not be decoded because it is is a malformed URL segment. This is probably due to a bad percent '+("encoding ("+t+").")),e}}function Oa(e,t){if(t==="/")return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith("/")?t.length-1:t.length,r=e.charAt(n);return r&&r!=="/"?null:e.slice(n)||"/"}const Wg=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,qg=e=>Wg.test(e);function Kg(e,t){t===void 0&&(t="/");let{pathname:n,search:r="",hash:s=""}=typeof e=="string"?Zn(e):e,i;if(n)if(qg(n))i=n;else{if(n.includes("//")){let o=n;n=n.replace(/\/\/+/g,"/"),Pa(!1,"Pathnames cannot have embedded double slashes - normalizing "+(o+" -> "+n))}n.startsWith("/")?i=ac(n.substring(1),"/"):i=ac(n,t)}else i=t;return{pathname:i,search:Xg(r),hash:Yg(s)}}function ac(e,t){let n=t.replace(/\/+$/,"").split("/");return e.split("/").forEach(s=>{s===".."?n.length>1&&n.pop():s!=="."&&n.push(s)}),n.length>1?n.join("/"):"/"}function vo(e,t,n,r){return"Cannot include a '"+e+"' character in a manually specified "+("`to."+t+"` field ["+JSON.stringify(r)+"]. Please separate it out to the ")+("`to."+n+"` field. Alternatively you may provide the full path as ")+'a string in and the router will parse it for you.'}function Qg(e){return e.filter((t,n)=>n===0||t.route.path&&t.route.path.length>0)}function Aa(e,t){let n=Qg(e);return t?n.map((r,s)=>s===n.length-1?r.pathname:r.pathnameBase):n.map(r=>r.pathnameBase)}function La(e,t,n,r){r===void 0&&(r=!1);let s;typeof e=="string"?s=Zn(e):(s=Qr({},e),ie(!s.pathname||!s.pathname.includes("?"),vo("?","pathname","search",s)),ie(!s.pathname||!s.pathname.includes("#"),vo("#","pathname","hash",s)),ie(!s.search||!s.search.includes("#"),vo("#","search","hash",s)));let i=e===""||s.pathname==="",o=i?"/":s.pathname,a;if(o==null)a=n;else{let f=t.length-1;if(!r&&o.startsWith("..")){let g=o.split("/");for(;g[0]==="..";)g.shift(),f-=1;s.pathname=g.join("/")}a=f>=0?t[f]:"/"}let u=Kg(s,a),c=o&&o!=="/"&&o.endsWith("/"),d=(i||o===".")&&n.endsWith("/");return!u.pathname.endsWith("/")&&(c||d)&&(u.pathname+="/"),u}const Qt=e=>e.join("/").replace(/\/\/+/g,"/"),Jg=e=>e.replace(/\/+$/,"").replace(/^\/*/,"/"),Xg=e=>!e||e==="?"?"":e.startsWith("?")?e:"?"+e,Yg=e=>!e||e==="#"?"":e.startsWith("#")?e:"#"+e;function Gg(e){return e!=null&&typeof e.status=="number"&&typeof e.statusText=="string"&&typeof e.internal=="boolean"&&"data"in e}const Yf=["post","put","patch","delete"];new Set(Yf);const Zg=["get",...Yf];new Set(Zg);/** - * React Router v6.30.2 - * - * Copyright (c) Remix Software Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE.md file in the root directory of this source tree. - * - * @license MIT - */function Jr(){return Jr=Object.assign?Object.assign.bind():function(e){for(var t=1;t{a.current=!0}),x.useCallback(function(c,d){if(d===void 0&&(d={}),!a.current)return;if(typeof c=="number"){r.go(c);return}let f=La(c,JSON.parse(o),i,d.relative==="path");e==null&&t!=="/"&&(f.pathname=f.pathname==="/"?t:Qt([t,f.pathname])),(d.replace?r.replace:r.push)(f,d.state,d)},[t,r,o,i,e])}function ry(){let{matches:e}=x.useContext(Pt),t=e[e.length-1];return t?t.params:{}}function eh(e,t){let{relative:n}=t===void 0?{}:t,{future:r}=x.useContext(tn),{matches:s}=x.useContext(Pt),{pathname:i}=tr(),o=JSON.stringify(Aa(s,r.v7_relativeSplatPath));return x.useMemo(()=>La(e,JSON.parse(o),i,n==="path"),[e,o,i,n])}function sy(e,t){return iy(e,t)}function iy(e,t,n,r){er()||ie(!1);let{navigator:s}=x.useContext(tn),{matches:i}=x.useContext(Pt),o=i[i.length-1],a=o?o.params:{};o&&o.pathname;let u=o?o.pathnameBase:"/";o&&o.route;let c=tr(),d;if(t){var f;let w=typeof t=="string"?Zn(t):t;u==="/"||(f=w.pathname)!=null&&f.startsWith(u)||ie(!1),d=w}else d=c;let g=d.pathname||"/",S=g;if(u!=="/"){let w=u.replace(/^\//,"").split("/");S="/"+g.replace(/^\//,"").split("/").slice(w.length).join("/")}let y=Pg(e,{pathname:S}),v=cy(y&&y.map(w=>Object.assign({},w,{params:Object.assign({},a,w.params),pathname:Qt([u,s.encodeLocation?s.encodeLocation(w.pathname).pathname:w.pathname]),pathnameBase:w.pathnameBase==="/"?u:Qt([u,s.encodeLocation?s.encodeLocation(w.pathnameBase).pathname:w.pathnameBase])})),i,n,r);return t&&v?x.createElement(bi.Provider,{value:{location:Jr({pathname:"/",search:"",hash:"",state:null,key:"default"},d),navigationType:It.Pop}},v):v}function oy(){let e=py(),t=Gg(e)?e.status+" "+e.statusText:e instanceof Error?e.message:JSON.stringify(e),n=e instanceof Error?e.stack:null,s={padding:"0.5rem",backgroundColor:"rgba(200,200,200, 0.5)"};return x.createElement(x.Fragment,null,x.createElement("h2",null,"Unexpected Application Error!"),x.createElement("h3",{style:{fontStyle:"italic"}},t),n?x.createElement("pre",{style:s},n):null,null)}const ly=x.createElement(oy,null);class ay extends x.Component{constructor(t){super(t),this.state={location:t.location,revalidation:t.revalidation,error:t.error}}static getDerivedStateFromError(t){return{error:t}}static getDerivedStateFromProps(t,n){return n.location!==t.location||n.revalidation!=="idle"&&t.revalidation==="idle"?{error:t.error,location:t.location,revalidation:t.revalidation}:{error:t.error!==void 0?t.error:n.error,location:n.location,revalidation:t.revalidation||n.revalidation}}componentDidCatch(t,n){console.error("React Router caught the following error during render",t,n)}render(){return this.state.error!==void 0?x.createElement(Pt.Provider,{value:this.props.routeContext},x.createElement(Gf.Provider,{value:this.state.error,children:this.props.component})):this.props.children}}function uy(e){let{routeContext:t,match:n,children:r}=e,s=x.useContext(ba);return s&&s.static&&s.staticContext&&(n.route.errorElement||n.route.ErrorBoundary)&&(s.staticContext._deepestRenderedBoundaryId=n.route.id),x.createElement(Pt.Provider,{value:t},r)}function cy(e,t,n,r){var s;if(t===void 0&&(t=[]),n===void 0&&(n=null),r===void 0&&(r=null),e==null){var i;if(!n)return null;if(n.errors)e=n.matches;else if((i=r)!=null&&i.v7_partialHydration&&t.length===0&&!n.initialized&&n.matches.length>0)e=n.matches;else return null}let o=e,a=(s=n)==null?void 0:s.errors;if(a!=null){let d=o.findIndex(f=>f.route.id&&(a==null?void 0:a[f.route.id])!==void 0);d>=0||ie(!1),o=o.slice(0,Math.min(o.length,d+1))}let u=!1,c=-1;if(n&&r&&r.v7_partialHydration)for(let d=0;d=0?o=o.slice(0,c+1):o=[o[0]];break}}}return o.reduceRight((d,f,g)=>{let S,y=!1,v=null,w=null;n&&(S=a&&f.route.id?a[f.route.id]:void 0,v=f.route.errorElement||ly,u&&(c<0&&g===0?(gy("route-fallback"),y=!0,w=null):c===g&&(y=!0,w=f.route.hydrateFallbackElement||null)));let p=t.concat(o.slice(0,g+1)),h=()=>{let m;return S?m=v:y?m=w:f.route.Component?m=x.createElement(f.route.Component,null):f.route.element?m=f.route.element:m=d,x.createElement(uy,{match:f,routeContext:{outlet:d,matches:p,isDataRoute:n!=null},children:m})};return n&&(f.route.ErrorBoundary||f.route.errorElement||g===0)?x.createElement(ay,{location:n.location,revalidation:n.revalidation,component:v,error:S,children:h(),routeContext:{outlet:null,matches:p,isDataRoute:!0}}):h()},null)}var th=function(e){return e.UseBlocker="useBlocker",e.UseRevalidator="useRevalidator",e.UseNavigateStable="useNavigate",e}(th||{}),nh=function(e){return e.UseBlocker="useBlocker",e.UseLoaderData="useLoaderData",e.UseActionData="useActionData",e.UseRouteError="useRouteError",e.UseNavigation="useNavigation",e.UseRouteLoaderData="useRouteLoaderData",e.UseMatches="useMatches",e.UseRevalidator="useRevalidator",e.UseNavigateStable="useNavigate",e.UseRouteId="useRouteId",e}(nh||{});function dy(e){let t=x.useContext(ba);return t||ie(!1),t}function fy(e){let t=x.useContext(ey);return t||ie(!1),t}function hy(e){let t=x.useContext(Pt);return t||ie(!1),t}function rh(e){let t=hy(),n=t.matches[t.matches.length-1];return n.route.id||ie(!1),n.route.id}function py(){var e;let t=x.useContext(Gf),n=fy(),r=rh();return t!==void 0?t:(e=n.errors)==null?void 0:e[r]}function my(){let{router:e}=dy(th.UseNavigateStable),t=rh(nh.UseNavigateStable),n=x.useRef(!1);return Zf(()=>{n.current=!0}),x.useCallback(function(s,i){i===void 0&&(i={}),n.current&&(typeof s=="number"?e.navigate(s):e.navigate(s,Jr({fromRouteId:t},i)))},[e,t])}const uc={};function gy(e,t,n){uc[e]||(uc[e]=!0)}function yy(e,t){e==null||e.v7_startTransition,e==null||e.v7_relativeSplatPath}function El(e){let{to:t,replace:n,state:r,relative:s}=e;er()||ie(!1);let{future:i,static:o}=x.useContext(tn),{matches:a}=x.useContext(Pt),{pathname:u}=tr(),c=nn(),d=La(t,Aa(a,i.v7_relativeSplatPath),u,s==="path"),f=JSON.stringify(d);return x.useEffect(()=>c(JSON.parse(f),{replace:n,state:r,relative:s}),[c,f,s,n,r]),null}function wt(e){ie(!1)}function vy(e){let{basename:t="/",children:n=null,location:r,navigationType:s=It.Pop,navigator:i,static:o=!1,future:a}=e;er()&&ie(!1);let u=t.replace(/^\/*/,"/"),c=x.useMemo(()=>({basename:u,navigator:i,static:o,future:Jr({v7_relativeSplatPath:!1},a)}),[u,a,i,o]);typeof r=="string"&&(r=Zn(r));let{pathname:d="/",search:f="",hash:g="",state:S=null,key:y="default"}=r,v=x.useMemo(()=>{let w=Oa(d,u);return w==null?null:{location:{pathname:w,search:f,hash:g,state:S,key:y},navigationType:s}},[u,d,f,g,S,y,s]);return v==null?null:x.createElement(tn.Provider,{value:c},x.createElement(bi.Provider,{children:n,value:v}))}function wy(e){let{children:t,location:n}=e;return sy(kl(t),n)}new Promise(()=>{});function kl(e,t){t===void 0&&(t=[]);let n=[];return x.Children.forEach(e,(r,s)=>{if(!x.isValidElement(r))return;let i=[...t,s];if(r.type===x.Fragment){n.push.apply(n,kl(r.props.children,i));return}r.type!==wt&&ie(!1),!r.props.index||!r.props.children||ie(!1);let o={id:r.props.id||i.join("-"),caseSensitive:r.props.caseSensitive,element:r.props.element,Component:r.props.Component,index:r.props.index,path:r.props.path,loader:r.props.loader,action:r.props.action,errorElement:r.props.errorElement,ErrorBoundary:r.props.ErrorBoundary,hasErrorBoundary:r.props.ErrorBoundary!=null||r.props.errorElement!=null,shouldRevalidate:r.props.shouldRevalidate,handle:r.props.handle,lazy:r.props.lazy};r.props.children&&(o.children=kl(r.props.children,i)),n.push(o)}),n}/** - * React Router DOM v6.30.2 - * - * Copyright (c) Remix Software Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE.md file in the root directory of this source tree. - * - * @license MIT - */function _l(){return _l=Object.assign?Object.assign.bind():function(e){for(var t=1;t=0)&&(n[s]=e[s]);return n}function Sy(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function Ny(e,t){return e.button===0&&(!t||t==="_self")&&!Sy(e)}const Ey=["onClick","relative","reloadDocument","replace","state","target","to","preventScrollReset","viewTransition"],ky="6";try{window.__reactRouterVersion=ky}catch{}const _y="startTransition",cc=mp[_y];function jy(e){let{basename:t,children:n,future:r,window:s}=e,i=x.useRef();i.current==null&&(i.current=Cg({window:s,v5Compat:!0}));let o=i.current,[a,u]=x.useState({action:o.action,location:o.location}),{v7_startTransition:c}=r||{},d=x.useCallback(f=>{c&&cc?cc(()=>u(f)):u(f)},[u,c]);return x.useLayoutEffect(()=>o.listen(d),[o,d]),x.useEffect(()=>yy(r),[r]),x.createElement(vy,{basename:t,children:n,location:a.location,navigationType:a.action,navigator:o,future:r})}const Cy=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u",Ry=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,rt=x.forwardRef(function(t,n){let{onClick:r,relative:s,reloadDocument:i,replace:o,state:a,target:u,to:c,preventScrollReset:d,viewTransition:f}=t,g=xy(t,Ey),{basename:S}=x.useContext(tn),y,v=!1;if(typeof c=="string"&&Ry.test(c)&&(y=c,Cy))try{let m=new URL(window.location.href),N=c.startsWith("//")?new URL(m.protocol+c):new URL(c),C=Oa(N.pathname,S);N.origin===m.origin&&C!=null?c=C+N.search+N.hash:v=!0}catch{}let w=ty(c,{relative:s}),p=Ty(c,{replace:o,state:a,target:u,preventScrollReset:d,relative:s,viewTransition:f});function h(m){r&&r(m),m.defaultPrevented||p(m)}return x.createElement("a",_l({},g,{href:y||w,onClick:v||i?r:h,ref:n,target:u}))});var dc;(function(e){e.UseScrollRestoration="useScrollRestoration",e.UseSubmit="useSubmit",e.UseSubmitFetcher="useSubmitFetcher",e.UseFetcher="useFetcher",e.useViewTransitionState="useViewTransitionState"})(dc||(dc={}));var fc;(function(e){e.UseFetcher="useFetcher",e.UseFetchers="useFetchers",e.UseScrollRestoration="useScrollRestoration"})(fc||(fc={}));function Ty(e,t){let{target:n,replace:r,state:s,preventScrollReset:i,relative:o,viewTransition:a}=t===void 0?{}:t,u=nn(),c=tr(),d=eh(e,{relative:o});return x.useCallback(f=>{if(Ny(f,n)){f.preventDefault();let g=r!==void 0?r:gi(c)===gi(d);u(e,{replace:g,state:s,preventScrollReset:i,relative:o,viewTransition:a})}},[c,u,d,r,s,n,e,i,o,a])}function sh(e,t){return function(){return e.apply(t,arguments)}}const{toString:Py}=Object.prototype,{getPrototypeOf:Ba}=Object,{iterator:Bi,toStringTag:ih}=Symbol,Di=(e=>t=>{const n=Py.call(t);return e[n]||(e[n]=n.slice(8,-1).toLowerCase())})(Object.create(null)),ct=e=>(e=e.toLowerCase(),t=>Di(t)===e),Fi=e=>t=>typeof t===e,{isArray:nr}=Array,Jn=Fi("undefined");function ts(e){return e!==null&&!Jn(e)&&e.constructor!==null&&!Jn(e.constructor)&&Fe(e.constructor.isBuffer)&&e.constructor.isBuffer(e)}const oh=ct("ArrayBuffer");function Oy(e){let t;return typeof ArrayBuffer<"u"&&ArrayBuffer.isView?t=ArrayBuffer.isView(e):t=e&&e.buffer&&oh(e.buffer),t}const Ay=Fi("string"),Fe=Fi("function"),lh=Fi("number"),ns=e=>e!==null&&typeof e=="object",Ly=e=>e===!0||e===!1,Us=e=>{if(Di(e)!=="object")return!1;const t=Ba(e);return(t===null||t===Object.prototype||Object.getPrototypeOf(t)===null)&&!(ih in e)&&!(Bi in e)},by=e=>{if(!ns(e)||ts(e))return!1;try{return Object.keys(e).length===0&&Object.getPrototypeOf(e)===Object.prototype}catch{return!1}},By=ct("Date"),Dy=ct("File"),Fy=ct("Blob"),Iy=ct("FileList"),Uy=e=>ns(e)&&Fe(e.pipe),zy=e=>{let t;return e&&(typeof FormData=="function"&&e instanceof FormData||Fe(e.append)&&((t=Di(e))==="formdata"||t==="object"&&Fe(e.toString)&&e.toString()==="[object FormData]"))},My=ct("URLSearchParams"),[$y,Vy,Hy,Wy]=["ReadableStream","Request","Response","Headers"].map(ct),qy=e=>e.trim?e.trim():e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"");function rs(e,t,{allOwnKeys:n=!1}={}){if(e===null||typeof e>"u")return;let r,s;if(typeof e!="object"&&(e=[e]),nr(e))for(r=0,s=e.length;r0;)if(s=n[r],t===s.toLowerCase())return s;return null}const dn=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global,uh=e=>!Jn(e)&&e!==dn;function jl(){const{caseless:e,skipUndefined:t}=uh(this)&&this||{},n={},r=(s,i)=>{const o=e&&ah(n,i)||i;Us(n[o])&&Us(s)?n[o]=jl(n[o],s):Us(s)?n[o]=jl({},s):nr(s)?n[o]=s.slice():(!t||!Jn(s))&&(n[o]=s)};for(let s=0,i=arguments.length;s(rs(t,(s,i)=>{n&&Fe(s)?e[i]=sh(s,n):e[i]=s},{allOwnKeys:r}),e),Qy=e=>(e.charCodeAt(0)===65279&&(e=e.slice(1)),e),Jy=(e,t,n,r)=>{e.prototype=Object.create(t.prototype,r),e.prototype.constructor=e,Object.defineProperty(e,"super",{value:t.prototype}),n&&Object.assign(e.prototype,n)},Xy=(e,t,n,r)=>{let s,i,o;const a={};if(t=t||{},e==null)return t;do{for(s=Object.getOwnPropertyNames(e),i=s.length;i-- >0;)o=s[i],(!r||r(o,e,t))&&!a[o]&&(t[o]=e[o],a[o]=!0);e=n!==!1&&Ba(e)}while(e&&(!n||n(e,t))&&e!==Object.prototype);return t},Yy=(e,t,n)=>{e=String(e),(n===void 0||n>e.length)&&(n=e.length),n-=t.length;const r=e.indexOf(t,n);return r!==-1&&r===n},Gy=e=>{if(!e)return null;if(nr(e))return e;let t=e.length;if(!lh(t))return null;const n=new Array(t);for(;t-- >0;)n[t]=e[t];return n},Zy=(e=>t=>e&&t instanceof e)(typeof Uint8Array<"u"&&Ba(Uint8Array)),ev=(e,t)=>{const r=(e&&e[Bi]).call(e);let s;for(;(s=r.next())&&!s.done;){const i=s.value;t.call(e,i[0],i[1])}},tv=(e,t)=>{let n;const r=[];for(;(n=e.exec(t))!==null;)r.push(n);return r},nv=ct("HTMLFormElement"),rv=e=>e.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,function(n,r,s){return r.toUpperCase()+s}),hc=(({hasOwnProperty:e})=>(t,n)=>e.call(t,n))(Object.prototype),sv=ct("RegExp"),ch=(e,t)=>{const n=Object.getOwnPropertyDescriptors(e),r={};rs(n,(s,i)=>{let o;(o=t(s,i,e))!==!1&&(r[i]=o||s)}),Object.defineProperties(e,r)},iv=e=>{ch(e,(t,n)=>{if(Fe(e)&&["arguments","caller","callee"].indexOf(n)!==-1)return!1;const r=e[n];if(Fe(r)){if(t.enumerable=!1,"writable"in t){t.writable=!1;return}t.set||(t.set=()=>{throw Error("Can not rewrite read-only method '"+n+"'")})}})},ov=(e,t)=>{const n={},r=s=>{s.forEach(i=>{n[i]=!0})};return nr(e)?r(e):r(String(e).split(t)),n},lv=()=>{},av=(e,t)=>e!=null&&Number.isFinite(e=+e)?e:t;function uv(e){return!!(e&&Fe(e.append)&&e[ih]==="FormData"&&e[Bi])}const cv=e=>{const t=new Array(10),n=(r,s)=>{if(ns(r)){if(t.indexOf(r)>=0)return;if(ts(r))return r;if(!("toJSON"in r)){t[s]=r;const i=nr(r)?[]:{};return rs(r,(o,a)=>{const u=n(o,s+1);!Jn(u)&&(i[a]=u)}),t[s]=void 0,i}}return r};return n(e,0)},dv=ct("AsyncFunction"),fv=e=>e&&(ns(e)||Fe(e))&&Fe(e.then)&&Fe(e.catch),dh=((e,t)=>e?setImmediate:t?((n,r)=>(dn.addEventListener("message",({source:s,data:i})=>{s===dn&&i===n&&r.length&&r.shift()()},!1),s=>{r.push(s),dn.postMessage(n,"*")}))(`axios@${Math.random()}`,[]):n=>setTimeout(n))(typeof setImmediate=="function",Fe(dn.postMessage)),hv=typeof queueMicrotask<"u"?queueMicrotask.bind(dn):typeof process<"u"&&process.nextTick||dh,pv=e=>e!=null&&Fe(e[Bi]),E={isArray:nr,isArrayBuffer:oh,isBuffer:ts,isFormData:zy,isArrayBufferView:Oy,isString:Ay,isNumber:lh,isBoolean:Ly,isObject:ns,isPlainObject:Us,isEmptyObject:by,isReadableStream:$y,isRequest:Vy,isResponse:Hy,isHeaders:Wy,isUndefined:Jn,isDate:By,isFile:Dy,isBlob:Fy,isRegExp:sv,isFunction:Fe,isStream:Uy,isURLSearchParams:My,isTypedArray:Zy,isFileList:Iy,forEach:rs,merge:jl,extend:Ky,trim:qy,stripBOM:Qy,inherits:Jy,toFlatObject:Xy,kindOf:Di,kindOfTest:ct,endsWith:Yy,toArray:Gy,forEachEntry:ev,matchAll:tv,isHTMLForm:nv,hasOwnProperty:hc,hasOwnProp:hc,reduceDescriptors:ch,freezeMethods:iv,toObjectSet:ov,toCamelCase:rv,noop:lv,toFiniteNumber:av,findKey:ah,global:dn,isContextDefined:uh,isSpecCompliantForm:uv,toJSONObject:cv,isAsyncFn:dv,isThenable:fv,setImmediate:dh,asap:hv,isIterable:pv};function z(e,t,n,r,s){Error.call(this),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=new Error().stack,this.message=e,this.name="AxiosError",t&&(this.code=t),n&&(this.config=n),r&&(this.request=r),s&&(this.response=s,this.status=s.status?s.status:null)}E.inherits(z,Error,{toJSON:function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:E.toJSONObject(this.config),code:this.code,status:this.status}}});const fh=z.prototype,hh={};["ERR_BAD_OPTION_VALUE","ERR_BAD_OPTION","ECONNABORTED","ETIMEDOUT","ERR_NETWORK","ERR_FR_TOO_MANY_REDIRECTS","ERR_DEPRECATED","ERR_BAD_RESPONSE","ERR_BAD_REQUEST","ERR_CANCELED","ERR_NOT_SUPPORT","ERR_INVALID_URL"].forEach(e=>{hh[e]={value:e}});Object.defineProperties(z,hh);Object.defineProperty(fh,"isAxiosError",{value:!0});z.from=(e,t,n,r,s,i)=>{const o=Object.create(fh);E.toFlatObject(e,o,function(d){return d!==Error.prototype},c=>c!=="isAxiosError");const a=e&&e.message?e.message:"Error",u=t==null&&e?e.code:t;return z.call(o,a,u,n,r,s),e&&o.cause==null&&Object.defineProperty(o,"cause",{value:e,configurable:!0}),o.name=e&&e.name||"Error",i&&Object.assign(o,i),o};const mv=null;function Cl(e){return E.isPlainObject(e)||E.isArray(e)}function ph(e){return E.endsWith(e,"[]")?e.slice(0,-2):e}function pc(e,t,n){return e?e.concat(t).map(function(s,i){return s=ph(s),!n&&i?"["+s+"]":s}).join(n?".":""):t}function gv(e){return E.isArray(e)&&!e.some(Cl)}const yv=E.toFlatObject(E,{},null,function(t){return/^is[A-Z]/.test(t)});function Ii(e,t,n){if(!E.isObject(e))throw new TypeError("target must be an object");t=t||new FormData,n=E.toFlatObject(n,{metaTokens:!0,dots:!1,indexes:!1},!1,function(v,w){return!E.isUndefined(w[v])});const r=n.metaTokens,s=n.visitor||d,i=n.dots,o=n.indexes,u=(n.Blob||typeof Blob<"u"&&Blob)&&E.isSpecCompliantForm(t);if(!E.isFunction(s))throw new TypeError("visitor must be a function");function c(y){if(y===null)return"";if(E.isDate(y))return y.toISOString();if(E.isBoolean(y))return y.toString();if(!u&&E.isBlob(y))throw new z("Blob is not supported. Use a Buffer instead.");return E.isArrayBuffer(y)||E.isTypedArray(y)?u&&typeof Blob=="function"?new Blob([y]):Buffer.from(y):y}function d(y,v,w){let p=y;if(y&&!w&&typeof y=="object"){if(E.endsWith(v,"{}"))v=r?v:v.slice(0,-2),y=JSON.stringify(y);else if(E.isArray(y)&&gv(y)||(E.isFileList(y)||E.endsWith(v,"[]"))&&(p=E.toArray(y)))return v=ph(v),p.forEach(function(m,N){!(E.isUndefined(m)||m===null)&&t.append(o===!0?pc([v],N,i):o===null?v:v+"[]",c(m))}),!1}return Cl(y)?!0:(t.append(pc(w,v,i),c(y)),!1)}const f=[],g=Object.assign(yv,{defaultVisitor:d,convertValue:c,isVisitable:Cl});function S(y,v){if(!E.isUndefined(y)){if(f.indexOf(y)!==-1)throw Error("Circular reference detected in "+v.join("."));f.push(y),E.forEach(y,function(p,h){(!(E.isUndefined(p)||p===null)&&s.call(t,p,E.isString(h)?h.trim():h,v,g))===!0&&S(p,v?v.concat(h):[h])}),f.pop()}}if(!E.isObject(e))throw new TypeError("data must be an object");return S(e),t}function mc(e){const t={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+","%00":"\0"};return encodeURIComponent(e).replace(/[!'()~]|%20|%00/g,function(r){return t[r]})}function Da(e,t){this._pairs=[],e&&Ii(e,this,t)}const mh=Da.prototype;mh.append=function(t,n){this._pairs.push([t,n])};mh.toString=function(t){const n=t?function(r){return t.call(this,r,mc)}:mc;return this._pairs.map(function(s){return n(s[0])+"="+n(s[1])},"").join("&")};function vv(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+")}function gh(e,t,n){if(!t)return e;const r=n&&n.encode||vv;E.isFunction(n)&&(n={serialize:n});const s=n&&n.serialize;let i;if(s?i=s(t,n):i=E.isURLSearchParams(t)?t.toString():new Da(t,n).toString(r),i){const o=e.indexOf("#");o!==-1&&(e=e.slice(0,o)),e+=(e.indexOf("?")===-1?"?":"&")+i}return e}class gc{constructor(){this.handlers=[]}use(t,n,r){return this.handlers.push({fulfilled:t,rejected:n,synchronous:r?r.synchronous:!1,runWhen:r?r.runWhen:null}),this.handlers.length-1}eject(t){this.handlers[t]&&(this.handlers[t]=null)}clear(){this.handlers&&(this.handlers=[])}forEach(t){E.forEach(this.handlers,function(r){r!==null&&t(r)})}}const yh={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},wv=typeof URLSearchParams<"u"?URLSearchParams:Da,xv=typeof FormData<"u"?FormData:null,Sv=typeof Blob<"u"?Blob:null,Nv={isBrowser:!0,classes:{URLSearchParams:wv,FormData:xv,Blob:Sv},protocols:["http","https","file","blob","url","data"]},Fa=typeof window<"u"&&typeof document<"u",Rl=typeof navigator=="object"&&navigator||void 0,Ev=Fa&&(!Rl||["ReactNative","NativeScript","NS"].indexOf(Rl.product)<0),kv=typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope&&typeof self.importScripts=="function",_v=Fa&&window.location.href||"http://localhost",jv=Object.freeze(Object.defineProperty({__proto__:null,hasBrowserEnv:Fa,hasStandardBrowserEnv:Ev,hasStandardBrowserWebWorkerEnv:kv,navigator:Rl,origin:_v},Symbol.toStringTag,{value:"Module"})),_e={...jv,...Nv};function Cv(e,t){return Ii(e,new _e.classes.URLSearchParams,{visitor:function(n,r,s,i){return _e.isNode&&E.isBuffer(n)?(this.append(r,n.toString("base64")),!1):i.defaultVisitor.apply(this,arguments)},...t})}function Rv(e){return E.matchAll(/\w+|\[(\w*)]/g,e).map(t=>t[0]==="[]"?"":t[1]||t[0])}function Tv(e){const t={},n=Object.keys(e);let r;const s=n.length;let i;for(r=0;r=n.length;return o=!o&&E.isArray(s)?s.length:o,u?(E.hasOwnProp(s,o)?s[o]=[s[o],r]:s[o]=r,!a):((!s[o]||!E.isObject(s[o]))&&(s[o]=[]),t(n,r,s[o],i)&&E.isArray(s[o])&&(s[o]=Tv(s[o])),!a)}if(E.isFormData(e)&&E.isFunction(e.entries)){const n={};return E.forEachEntry(e,(r,s)=>{t(Rv(r),s,n,0)}),n}return null}function Pv(e,t,n){if(E.isString(e))try{return(t||JSON.parse)(e),E.trim(e)}catch(r){if(r.name!=="SyntaxError")throw r}return(n||JSON.stringify)(e)}const ss={transitional:yh,adapter:["xhr","http","fetch"],transformRequest:[function(t,n){const r=n.getContentType()||"",s=r.indexOf("application/json")>-1,i=E.isObject(t);if(i&&E.isHTMLForm(t)&&(t=new FormData(t)),E.isFormData(t))return s?JSON.stringify(vh(t)):t;if(E.isArrayBuffer(t)||E.isBuffer(t)||E.isStream(t)||E.isFile(t)||E.isBlob(t)||E.isReadableStream(t))return t;if(E.isArrayBufferView(t))return t.buffer;if(E.isURLSearchParams(t))return n.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),t.toString();let a;if(i){if(r.indexOf("application/x-www-form-urlencoded")>-1)return Cv(t,this.formSerializer).toString();if((a=E.isFileList(t))||r.indexOf("multipart/form-data")>-1){const u=this.env&&this.env.FormData;return Ii(a?{"files[]":t}:t,u&&new u,this.formSerializer)}}return i||s?(n.setContentType("application/json",!1),Pv(t)):t}],transformResponse:[function(t){const n=this.transitional||ss.transitional,r=n&&n.forcedJSONParsing,s=this.responseType==="json";if(E.isResponse(t)||E.isReadableStream(t))return t;if(t&&E.isString(t)&&(r&&!this.responseType||s)){const o=!(n&&n.silentJSONParsing)&&s;try{return JSON.parse(t,this.parseReviver)}catch(a){if(o)throw a.name==="SyntaxError"?z.from(a,z.ERR_BAD_RESPONSE,this,null,this.response):a}}return t}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:_e.classes.FormData,Blob:_e.classes.Blob},validateStatus:function(t){return t>=200&&t<300},headers:{common:{Accept:"application/json, text/plain, */*","Content-Type":void 0}}};E.forEach(["delete","get","head","post","put","patch"],e=>{ss.headers[e]={}});const Ov=E.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]),Av=e=>{const t={};let n,r,s;return e&&e.split(` -`).forEach(function(o){s=o.indexOf(":"),n=o.substring(0,s).trim().toLowerCase(),r=o.substring(s+1).trim(),!(!n||t[n]&&Ov[n])&&(n==="set-cookie"?t[n]?t[n].push(r):t[n]=[r]:t[n]=t[n]?t[n]+", "+r:r)}),t},yc=Symbol("internals");function hr(e){return e&&String(e).trim().toLowerCase()}function zs(e){return e===!1||e==null?e:E.isArray(e)?e.map(zs):String(e)}function Lv(e){const t=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let r;for(;r=n.exec(e);)t[r[1]]=r[2];return t}const bv=e=>/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(e.trim());function wo(e,t,n,r,s){if(E.isFunction(r))return r.call(this,t,n);if(s&&(t=n),!!E.isString(t)){if(E.isString(r))return t.indexOf(r)!==-1;if(E.isRegExp(r))return r.test(t)}}function Bv(e){return e.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(t,n,r)=>n.toUpperCase()+r)}function Dv(e,t){const n=E.toCamelCase(" "+t);["get","set","has"].forEach(r=>{Object.defineProperty(e,r+n,{value:function(s,i,o){return this[r].call(this,t,s,i,o)},configurable:!0})})}let Ie=class{constructor(t){t&&this.set(t)}set(t,n,r){const s=this;function i(a,u,c){const d=hr(u);if(!d)throw new Error("header name must be a non-empty string");const f=E.findKey(s,d);(!f||s[f]===void 0||c===!0||c===void 0&&s[f]!==!1)&&(s[f||u]=zs(a))}const o=(a,u)=>E.forEach(a,(c,d)=>i(c,d,u));if(E.isPlainObject(t)||t instanceof this.constructor)o(t,n);else if(E.isString(t)&&(t=t.trim())&&!bv(t))o(Av(t),n);else if(E.isObject(t)&&E.isIterable(t)){let a={},u,c;for(const d of t){if(!E.isArray(d))throw TypeError("Object iterator must return a key-value pair");a[c=d[0]]=(u=a[c])?E.isArray(u)?[...u,d[1]]:[u,d[1]]:d[1]}o(a,n)}else t!=null&&i(n,t,r);return this}get(t,n){if(t=hr(t),t){const r=E.findKey(this,t);if(r){const s=this[r];if(!n)return s;if(n===!0)return Lv(s);if(E.isFunction(n))return n.call(this,s,r);if(E.isRegExp(n))return n.exec(s);throw new TypeError("parser must be boolean|regexp|function")}}}has(t,n){if(t=hr(t),t){const r=E.findKey(this,t);return!!(r&&this[r]!==void 0&&(!n||wo(this,this[r],r,n)))}return!1}delete(t,n){const r=this;let s=!1;function i(o){if(o=hr(o),o){const a=E.findKey(r,o);a&&(!n||wo(r,r[a],a,n))&&(delete r[a],s=!0)}}return E.isArray(t)?t.forEach(i):i(t),s}clear(t){const n=Object.keys(this);let r=n.length,s=!1;for(;r--;){const i=n[r];(!t||wo(this,this[i],i,t,!0))&&(delete this[i],s=!0)}return s}normalize(t){const n=this,r={};return E.forEach(this,(s,i)=>{const o=E.findKey(r,i);if(o){n[o]=zs(s),delete n[i];return}const a=t?Bv(i):String(i).trim();a!==i&&delete n[i],n[a]=zs(s),r[a]=!0}),this}concat(...t){return this.constructor.concat(this,...t)}toJSON(t){const n=Object.create(null);return E.forEach(this,(r,s)=>{r!=null&&r!==!1&&(n[s]=t&&E.isArray(r)?r.join(", "):r)}),n}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map(([t,n])=>t+": "+n).join(` -`)}getSetCookie(){return this.get("set-cookie")||[]}get[Symbol.toStringTag](){return"AxiosHeaders"}static from(t){return t instanceof this?t:new this(t)}static concat(t,...n){const r=new this(t);return n.forEach(s=>r.set(s)),r}static accessor(t){const r=(this[yc]=this[yc]={accessors:{}}).accessors,s=this.prototype;function i(o){const a=hr(o);r[a]||(Dv(s,o),r[a]=!0)}return E.isArray(t)?t.forEach(i):i(t),this}};Ie.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]);E.reduceDescriptors(Ie.prototype,({value:e},t)=>{let n=t[0].toUpperCase()+t.slice(1);return{get:()=>e,set(r){this[n]=r}}});E.freezeMethods(Ie);function xo(e,t){const n=this||ss,r=t||n,s=Ie.from(r.headers);let i=r.data;return E.forEach(e,function(a){i=a.call(n,i,s.normalize(),t?t.status:void 0)}),s.normalize(),i}function wh(e){return!!(e&&e.__CANCEL__)}function rr(e,t,n){z.call(this,e??"canceled",z.ERR_CANCELED,t,n),this.name="CanceledError"}E.inherits(rr,z,{__CANCEL__:!0});function xh(e,t,n){const r=n.config.validateStatus;!n.status||!r||r(n.status)?e(n):t(new z("Request failed with status code "+n.status,[z.ERR_BAD_REQUEST,z.ERR_BAD_RESPONSE][Math.floor(n.status/100)-4],n.config,n.request,n))}function Fv(e){const t=/^([-+\w]{1,25})(:?\/\/|:)/.exec(e);return t&&t[1]||""}function Iv(e,t){e=e||10;const n=new Array(e),r=new Array(e);let s=0,i=0,o;return t=t!==void 0?t:1e3,function(u){const c=Date.now(),d=r[i];o||(o=c),n[s]=u,r[s]=c;let f=i,g=0;for(;f!==s;)g+=n[f++],f=f%e;if(s=(s+1)%e,s===i&&(i=(i+1)%e),c-o{n=d,s=null,i&&(clearTimeout(i),i=null),e(...c)};return[(...c)=>{const d=Date.now(),f=d-n;f>=r?o(c,d):(s=c,i||(i=setTimeout(()=>{i=null,o(s)},r-f)))},()=>s&&o(s)]}const yi=(e,t,n=3)=>{let r=0;const s=Iv(50,250);return Uv(i=>{const o=i.loaded,a=i.lengthComputable?i.total:void 0,u=o-r,c=s(u),d=o<=a;r=o;const f={loaded:o,total:a,progress:a?o/a:void 0,bytes:u,rate:c||void 0,estimated:c&&a&&d?(a-o)/c:void 0,event:i,lengthComputable:a!=null,[t?"download":"upload"]:!0};e(f)},n)},vc=(e,t)=>{const n=e!=null;return[r=>t[0]({lengthComputable:n,total:e,loaded:r}),t[1]]},wc=e=>(...t)=>E.asap(()=>e(...t)),zv=_e.hasStandardBrowserEnv?((e,t)=>n=>(n=new URL(n,_e.origin),e.protocol===n.protocol&&e.host===n.host&&(t||e.port===n.port)))(new URL(_e.origin),_e.navigator&&/(msie|trident)/i.test(_e.navigator.userAgent)):()=>!0,Mv=_e.hasStandardBrowserEnv?{write(e,t,n,r,s,i,o){if(typeof document>"u")return;const a=[`${e}=${encodeURIComponent(t)}`];E.isNumber(n)&&a.push(`expires=${new Date(n).toUTCString()}`),E.isString(r)&&a.push(`path=${r}`),E.isString(s)&&a.push(`domain=${s}`),i===!0&&a.push("secure"),E.isString(o)&&a.push(`SameSite=${o}`),document.cookie=a.join("; ")},read(e){if(typeof document>"u")return null;const t=document.cookie.match(new RegExp("(?:^|; )"+e+"=([^;]*)"));return t?decodeURIComponent(t[1]):null},remove(e){this.write(e,"",Date.now()-864e5,"/")}}:{write(){},read(){return null},remove(){}};function $v(e){return/^([a-z][a-z\d+\-.]*:)?\/\//i.test(e)}function Vv(e,t){return t?e.replace(/\/?\/$/,"")+"/"+t.replace(/^\/+/,""):e}function Sh(e,t,n){let r=!$v(t);return e&&(r||n==!1)?Vv(e,t):t}const xc=e=>e instanceof Ie?{...e}:e;function xn(e,t){t=t||{};const n={};function r(c,d,f,g){return E.isPlainObject(c)&&E.isPlainObject(d)?E.merge.call({caseless:g},c,d):E.isPlainObject(d)?E.merge({},d):E.isArray(d)?d.slice():d}function s(c,d,f,g){if(E.isUndefined(d)){if(!E.isUndefined(c))return r(void 0,c,f,g)}else return r(c,d,f,g)}function i(c,d){if(!E.isUndefined(d))return r(void 0,d)}function o(c,d){if(E.isUndefined(d)){if(!E.isUndefined(c))return r(void 0,c)}else return r(void 0,d)}function a(c,d,f){if(f in t)return r(c,d);if(f in e)return r(void 0,c)}const u={url:i,method:i,data:i,baseURL:o,transformRequest:o,transformResponse:o,paramsSerializer:o,timeout:o,timeoutMessage:o,withCredentials:o,withXSRFToken:o,adapter:o,responseType:o,xsrfCookieName:o,xsrfHeaderName:o,onUploadProgress:o,onDownloadProgress:o,decompress:o,maxContentLength:o,maxBodyLength:o,beforeRedirect:o,transport:o,httpAgent:o,httpsAgent:o,cancelToken:o,socketPath:o,responseEncoding:o,validateStatus:a,headers:(c,d,f)=>s(xc(c),xc(d),f,!0)};return E.forEach(Object.keys({...e,...t}),function(d){const f=u[d]||s,g=f(e[d],t[d],d);E.isUndefined(g)&&f!==a||(n[d]=g)}),n}const Nh=e=>{const t=xn({},e);let{data:n,withXSRFToken:r,xsrfHeaderName:s,xsrfCookieName:i,headers:o,auth:a}=t;if(t.headers=o=Ie.from(o),t.url=gh(Sh(t.baseURL,t.url,t.allowAbsoluteUrls),e.params,e.paramsSerializer),a&&o.set("Authorization","Basic "+btoa((a.username||"")+":"+(a.password?unescape(encodeURIComponent(a.password)):""))),E.isFormData(n)){if(_e.hasStandardBrowserEnv||_e.hasStandardBrowserWebWorkerEnv)o.setContentType(void 0);else if(E.isFunction(n.getHeaders)){const u=n.getHeaders(),c=["content-type","content-length"];Object.entries(u).forEach(([d,f])=>{c.includes(d.toLowerCase())&&o.set(d,f)})}}if(_e.hasStandardBrowserEnv&&(r&&E.isFunction(r)&&(r=r(t)),r||r!==!1&&zv(t.url))){const u=s&&i&&Mv.read(i);u&&o.set(s,u)}return t},Hv=typeof XMLHttpRequest<"u",Wv=Hv&&function(e){return new Promise(function(n,r){const s=Nh(e);let i=s.data;const o=Ie.from(s.headers).normalize();let{responseType:a,onUploadProgress:u,onDownloadProgress:c}=s,d,f,g,S,y;function v(){S&&S(),y&&y(),s.cancelToken&&s.cancelToken.unsubscribe(d),s.signal&&s.signal.removeEventListener("abort",d)}let w=new XMLHttpRequest;w.open(s.method.toUpperCase(),s.url,!0),w.timeout=s.timeout;function p(){if(!w)return;const m=Ie.from("getAllResponseHeaders"in w&&w.getAllResponseHeaders()),C={data:!a||a==="text"||a==="json"?w.responseText:w.response,status:w.status,statusText:w.statusText,headers:m,config:e,request:w};xh(function(T){n(T),v()},function(T){r(T),v()},C),w=null}"onloadend"in w?w.onloadend=p:w.onreadystatechange=function(){!w||w.readyState!==4||w.status===0&&!(w.responseURL&&w.responseURL.indexOf("file:")===0)||setTimeout(p)},w.onabort=function(){w&&(r(new z("Request aborted",z.ECONNABORTED,e,w)),w=null)},w.onerror=function(N){const C=N&&N.message?N.message:"Network Error",P=new z(C,z.ERR_NETWORK,e,w);P.event=N||null,r(P),w=null},w.ontimeout=function(){let N=s.timeout?"timeout of "+s.timeout+"ms exceeded":"timeout exceeded";const C=s.transitional||yh;s.timeoutErrorMessage&&(N=s.timeoutErrorMessage),r(new z(N,C.clarifyTimeoutError?z.ETIMEDOUT:z.ECONNABORTED,e,w)),w=null},i===void 0&&o.setContentType(null),"setRequestHeader"in w&&E.forEach(o.toJSON(),function(N,C){w.setRequestHeader(C,N)}),E.isUndefined(s.withCredentials)||(w.withCredentials=!!s.withCredentials),a&&a!=="json"&&(w.responseType=s.responseType),c&&([g,y]=yi(c,!0),w.addEventListener("progress",g)),u&&w.upload&&([f,S]=yi(u),w.upload.addEventListener("progress",f),w.upload.addEventListener("loadend",S)),(s.cancelToken||s.signal)&&(d=m=>{w&&(r(!m||m.type?new rr(null,e,w):m),w.abort(),w=null)},s.cancelToken&&s.cancelToken.subscribe(d),s.signal&&(s.signal.aborted?d():s.signal.addEventListener("abort",d)));const h=Fv(s.url);if(h&&_e.protocols.indexOf(h)===-1){r(new z("Unsupported protocol "+h+":",z.ERR_BAD_REQUEST,e));return}w.send(i||null)})},qv=(e,t)=>{const{length:n}=e=e?e.filter(Boolean):[];if(t||n){let r=new AbortController,s;const i=function(c){if(!s){s=!0,a();const d=c instanceof Error?c:this.reason;r.abort(d instanceof z?d:new rr(d instanceof Error?d.message:d))}};let o=t&&setTimeout(()=>{o=null,i(new z(`timeout ${t} of ms exceeded`,z.ETIMEDOUT))},t);const a=()=>{e&&(o&&clearTimeout(o),o=null,e.forEach(c=>{c.unsubscribe?c.unsubscribe(i):c.removeEventListener("abort",i)}),e=null)};e.forEach(c=>c.addEventListener("abort",i));const{signal:u}=r;return u.unsubscribe=()=>E.asap(a),u}},Kv=function*(e,t){let n=e.byteLength;if(n{const s=Qv(e,t);let i=0,o,a=u=>{o||(o=!0,r&&r(u))};return new ReadableStream({async pull(u){try{const{done:c,value:d}=await s.next();if(c){a(),u.close();return}let f=d.byteLength;if(n){let g=i+=f;n(g)}u.enqueue(new Uint8Array(d))}catch(c){throw a(c),c}},cancel(u){return a(u),s.return()}},{highWaterMark:2})},Nc=64*1024,{isFunction:Es}=E,Xv=(({Request:e,Response:t})=>({Request:e,Response:t}))(E.global),{ReadableStream:Ec,TextEncoder:kc}=E.global,_c=(e,...t)=>{try{return!!e(...t)}catch{return!1}},Yv=e=>{e=E.merge.call({skipUndefined:!0},Xv,e);const{fetch:t,Request:n,Response:r}=e,s=t?Es(t):typeof fetch=="function",i=Es(n),o=Es(r);if(!s)return!1;const a=s&&Es(Ec),u=s&&(typeof kc=="function"?(y=>v=>y.encode(v))(new kc):async y=>new Uint8Array(await new n(y).arrayBuffer())),c=i&&a&&_c(()=>{let y=!1;const v=new n(_e.origin,{body:new Ec,method:"POST",get duplex(){return y=!0,"half"}}).headers.has("Content-Type");return y&&!v}),d=o&&a&&_c(()=>E.isReadableStream(new r("").body)),f={stream:d&&(y=>y.body)};s&&["text","arrayBuffer","blob","formData","stream"].forEach(y=>{!f[y]&&(f[y]=(v,w)=>{let p=v&&v[y];if(p)return p.call(v);throw new z(`Response type '${y}' is not supported`,z.ERR_NOT_SUPPORT,w)})});const g=async y=>{if(y==null)return 0;if(E.isBlob(y))return y.size;if(E.isSpecCompliantForm(y))return(await new n(_e.origin,{method:"POST",body:y}).arrayBuffer()).byteLength;if(E.isArrayBufferView(y)||E.isArrayBuffer(y))return y.byteLength;if(E.isURLSearchParams(y)&&(y=y+""),E.isString(y))return(await u(y)).byteLength},S=async(y,v)=>{const w=E.toFiniteNumber(y.getContentLength());return w??g(v)};return async y=>{let{url:v,method:w,data:p,signal:h,cancelToken:m,timeout:N,onDownloadProgress:C,onUploadProgress:P,responseType:T,headers:O,withCredentials:I="same-origin",fetchOptions:b}=Nh(y),Y=t||fetch;T=T?(T+"").toLowerCase():"text";let le=qv([h,m&&m.toAbortSignal()],N),F=null;const V=le&&le.unsubscribe&&(()=>{le.unsubscribe()});let xe;try{if(P&&c&&w!=="get"&&w!=="head"&&(xe=await S(O,p))!==0){let D=new n(v,{method:"POST",body:p,duplex:"half"}),U;if(E.isFormData(p)&&(U=D.headers.get("content-type"))&&O.setContentType(U),D.body){const[ge,Se]=vc(xe,yi(wc(P)));p=Sc(D.body,Nc,ge,Se)}}E.isString(I)||(I=I?"include":"omit");const W=i&&"credentials"in n.prototype,he={...b,signal:le,method:w.toUpperCase(),headers:O.normalize().toJSON(),body:p,duplex:"half",credentials:W?I:void 0};F=i&&new n(v,he);let k=await(i?Y(F,b):Y(v,he));const _=d&&(T==="stream"||T==="response");if(d&&(C||_&&V)){const D={};["status","statusText","headers"].forEach(Ue=>{D[Ue]=k[Ue]});const U=E.toFiniteNumber(k.headers.get("content-length")),[ge,Se]=C&&vc(U,yi(wc(C),!0))||[];k=new r(Sc(k.body,Nc,ge,()=>{Se&&Se(),V&&V()}),D)}T=T||"text";let L=await f[E.findKey(f,T)||"text"](k,y);return!_&&V&&V(),await new Promise((D,U)=>{xh(D,U,{data:L,headers:Ie.from(k.headers),status:k.status,statusText:k.statusText,config:y,request:F})})}catch(W){throw V&&V(),W&&W.name==="TypeError"&&/Load failed|fetch/i.test(W.message)?Object.assign(new z("Network Error",z.ERR_NETWORK,y,F),{cause:W.cause||W}):z.from(W,W&&W.code,y,F)}}},Gv=new Map,Eh=e=>{let t=e&&e.env||{};const{fetch:n,Request:r,Response:s}=t,i=[r,s,n];let o=i.length,a=o,u,c,d=Gv;for(;a--;)u=i[a],c=d.get(u),c===void 0&&d.set(u,c=a?new Map:Yv(t)),d=c;return c};Eh();const Ia={http:mv,xhr:Wv,fetch:{get:Eh}};E.forEach(Ia,(e,t)=>{if(e){try{Object.defineProperty(e,"name",{value:t})}catch{}Object.defineProperty(e,"adapterName",{value:t})}});const jc=e=>`- ${e}`,Zv=e=>E.isFunction(e)||e===null||e===!1;function e0(e,t){e=E.isArray(e)?e:[e];const{length:n}=e;let r,s;const i={};for(let o=0;o`adapter ${u} `+(c===!1?"is not supported by the environment":"is not available in the build"));let a=n?o.length>1?`since : -`+o.map(jc).join(` -`):" "+jc(o[0]):"as no adapter specified";throw new z("There is no suitable adapter to dispatch the request "+a,"ERR_NOT_SUPPORT")}return s}const kh={getAdapter:e0,adapters:Ia};function So(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw new rr(null,e)}function Cc(e){return So(e),e.headers=Ie.from(e.headers),e.data=xo.call(e,e.transformRequest),["post","put","patch"].indexOf(e.method)!==-1&&e.headers.setContentType("application/x-www-form-urlencoded",!1),kh.getAdapter(e.adapter||ss.adapter,e)(e).then(function(r){return So(e),r.data=xo.call(e,e.transformResponse,r),r.headers=Ie.from(r.headers),r},function(r){return wh(r)||(So(e),r&&r.response&&(r.response.data=xo.call(e,e.transformResponse,r.response),r.response.headers=Ie.from(r.response.headers))),Promise.reject(r)})}const _h="1.13.2",Ui={};["object","boolean","number","function","string","symbol"].forEach((e,t)=>{Ui[e]=function(r){return typeof r===e||"a"+(t<1?"n ":" ")+e}});const Rc={};Ui.transitional=function(t,n,r){function s(i,o){return"[Axios v"+_h+"] Transitional option '"+i+"'"+o+(r?". "+r:"")}return(i,o,a)=>{if(t===!1)throw new z(s(o," has been removed"+(n?" in "+n:"")),z.ERR_DEPRECATED);return n&&!Rc[o]&&(Rc[o]=!0,console.warn(s(o," has been deprecated since v"+n+" and will be removed in the near future"))),t?t(i,o,a):!0}};Ui.spelling=function(t){return(n,r)=>(console.warn(`${r} is likely a misspelling of ${t}`),!0)};function t0(e,t,n){if(typeof e!="object")throw new z("options must be an object",z.ERR_BAD_OPTION_VALUE);const r=Object.keys(e);let s=r.length;for(;s-- >0;){const i=r[s],o=t[i];if(o){const a=e[i],u=a===void 0||o(a,i,e);if(u!==!0)throw new z("option "+i+" must be "+u,z.ERR_BAD_OPTION_VALUE);continue}if(n!==!0)throw new z("Unknown option "+i,z.ERR_BAD_OPTION)}}const Ms={assertOptions:t0,validators:Ui},ft=Ms.validators;let pn=class{constructor(t){this.defaults=t||{},this.interceptors={request:new gc,response:new gc}}async request(t,n){try{return await this._request(t,n)}catch(r){if(r instanceof Error){let s={};Error.captureStackTrace?Error.captureStackTrace(s):s=new Error;const i=s.stack?s.stack.replace(/^.+\n/,""):"";try{r.stack?i&&!String(r.stack).endsWith(i.replace(/^.+\n.+\n/,""))&&(r.stack+=` -`+i):r.stack=i}catch{}}throw r}}_request(t,n){typeof t=="string"?(n=n||{},n.url=t):n=t||{},n=xn(this.defaults,n);const{transitional:r,paramsSerializer:s,headers:i}=n;r!==void 0&&Ms.assertOptions(r,{silentJSONParsing:ft.transitional(ft.boolean),forcedJSONParsing:ft.transitional(ft.boolean),clarifyTimeoutError:ft.transitional(ft.boolean)},!1),s!=null&&(E.isFunction(s)?n.paramsSerializer={serialize:s}:Ms.assertOptions(s,{encode:ft.function,serialize:ft.function},!0)),n.allowAbsoluteUrls!==void 0||(this.defaults.allowAbsoluteUrls!==void 0?n.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:n.allowAbsoluteUrls=!0),Ms.assertOptions(n,{baseUrl:ft.spelling("baseURL"),withXsrfToken:ft.spelling("withXSRFToken")},!0),n.method=(n.method||this.defaults.method||"get").toLowerCase();let o=i&&E.merge(i.common,i[n.method]);i&&E.forEach(["delete","get","head","post","put","patch","common"],y=>{delete i[y]}),n.headers=Ie.concat(o,i);const a=[];let u=!0;this.interceptors.request.forEach(function(v){typeof v.runWhen=="function"&&v.runWhen(n)===!1||(u=u&&v.synchronous,a.unshift(v.fulfilled,v.rejected))});const c=[];this.interceptors.response.forEach(function(v){c.push(v.fulfilled,v.rejected)});let d,f=0,g;if(!u){const y=[Cc.bind(this),void 0];for(y.unshift(...a),y.push(...c),g=y.length,d=Promise.resolve(n);f{if(!r._listeners)return;let i=r._listeners.length;for(;i-- >0;)r._listeners[i](s);r._listeners=null}),this.promise.then=s=>{let i;const o=new Promise(a=>{r.subscribe(a),i=a}).then(s);return o.cancel=function(){r.unsubscribe(i)},o},t(function(i,o,a){r.reason||(r.reason=new rr(i,o,a),n(r.reason))})}throwIfRequested(){if(this.reason)throw this.reason}subscribe(t){if(this.reason){t(this.reason);return}this._listeners?this._listeners.push(t):this._listeners=[t]}unsubscribe(t){if(!this._listeners)return;const n=this._listeners.indexOf(t);n!==-1&&this._listeners.splice(n,1)}toAbortSignal(){const t=new AbortController,n=r=>{t.abort(r)};return this.subscribe(n),t.signal.unsubscribe=()=>this.unsubscribe(n),t.signal}static source(){let t;return{token:new jh(function(s){t=s}),cancel:t}}};function r0(e){return function(n){return e.apply(null,n)}}function s0(e){return E.isObject(e)&&e.isAxiosError===!0}const Tl={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511,WebServerIsDown:521,ConnectionTimedOut:522,OriginIsUnreachable:523,TimeoutOccurred:524,SslHandshakeFailed:525,InvalidSslCertificate:526};Object.entries(Tl).forEach(([e,t])=>{Tl[t]=e});function Ch(e){const t=new pn(e),n=sh(pn.prototype.request,t);return E.extend(n,pn.prototype,t,{allOwnKeys:!0}),E.extend(n,t,null,{allOwnKeys:!0}),n.create=function(s){return Ch(xn(e,s))},n}const oe=Ch(ss);oe.Axios=pn;oe.CanceledError=rr;oe.CancelToken=n0;oe.isCancel=wh;oe.VERSION=_h;oe.toFormData=Ii;oe.AxiosError=z;oe.Cancel=oe.CanceledError;oe.all=function(t){return Promise.all(t)};oe.spread=r0;oe.isAxiosError=s0;oe.mergeConfig=xn;oe.AxiosHeaders=Ie;oe.formToJSON=e=>vh(E.isHTMLForm(e)?new FormData(e):e);oe.getAdapter=kh.getAdapter;oe.HttpStatusCode=Tl;oe.default=oe;const{Axios:yw,AxiosError:vw,CanceledError:ww,isCancel:xw,CancelToken:Sw,VERSION:Nw,all:Ew,Cancel:kw,isAxiosError:_w,spread:jw,toFormData:Cw,AxiosHeaders:Rw,HttpStatusCode:Tw,formToJSON:Pw,getAdapter:Ow,mergeConfig:Aw}=oe,i0="http://localhost:8000",B=oe.create({baseURL:i0,timeout:1e4,headers:{"Content-Type":"application/json"}});B.interceptors.request.use(e=>{const t=localStorage.getItem("token");return t&&(e.headers.Authorization=`Bearer ${t}`),e});B.interceptors.response.use(e=>e,e=>{var t;return((t=e.response)==null?void 0:t.status)===401&&(localStorage.removeItem("token"),localStorage.removeItem("user"),window.location.href="/login"),Promise.reject(e)});const No={register:async(e,t,n)=>{try{return(await B.post("/api/auth/register",{username:e,email:t,password:n})).data}catch(r){throw r}},login:async(e,t)=>{const n=new FormData;n.append("username",e),n.append("password",t);const r=await B.post("/api/auth/login",n,{headers:{"Content-Type":"application/x-www-form-urlencoded"}});return localStorage.setItem("token",r.data.access_token),localStorage.setItem("user",JSON.stringify(r.data.user)),r.data},getMe:async()=>(await B.get("/api/auth/me")).data},pr={getMe:async()=>(await B.get("/api/users/me")).data,getMyTransactions:async(e=50)=>(await B.get("/api/users/me/transactions",{params:{limit:e}})).data,claimAllowance:async()=>(await B.post("/api/users/me/allowance")).data,getAllowanceInfo:async()=>(await B.get("/api/users/me/allowance-info")).data,getRichRanking:async(e=10)=>(await B.get("/api/users/ranking/rich",{params:{limit:e}})).data,getUsers:async(e=0,t=100)=>(await B.get("/api/users/",{params:{skip:e,limit:t}})).data,updateUser:async(e,t)=>(await B.patch(`/api/users/${e}`,t)).data,adjustBalance:async(e,t,n)=>(await B.post(`/api/users/${e}/adjust-balance`,null,{params:{amount:t,description:n}})).data,changePassword:async(e,t)=>(await B.post("/api/users/me/change-password",{current_password:e,new_password:t})).data},Ut={createChest:async e=>(await B.post("/api/chests",e)).data,getChests:async(e,t=!1)=>(await B.get("/api/chests",{params:e?{streamer_id:e,include_history:t}:{}})).data,getChest:async e=>(await B.get(`/api/chests/${e}`)).data,placeBet:async e=>(await B.post("/api/bet",e)).data,lockChest:async e=>(await B.post(`/api/chests/${e}/lock`,{})).data,settleChest:async(e,t)=>(await B.post(`/api/chests/${e}/settle`,t)).data,getChestBets:async e=>(await B.get(`/api/chests/${e}/bets`)).data},o0={getStreamers:async(e=0,t=100)=>(await B.get("/api/streamers",{params:{skip:e,limit:t}})).data,getStreamerChests:async(e,t=0,n=100)=>(await B.get(`/api/streamers/${e}/chests`,{params:{skip:t,limit:n}})).data,getStreamerBets:async(e,t=0,n=100)=>(await B.get(`/api/streamers/${e}/bets`,{params:{skip:t,limit:n}})).data},Eo={getUsers:async(e={})=>(await B.get("/api/admin/users",{params:e})).data,getUserDetail:async e=>(await B.get(`/api/admin/users/${e}`)).data,updateUser:async(e,t)=>(await B.put(`/api/admin/users/${e}`,t)).data,setUserRole:async(e,t)=>(await B.put(`/api/admin/users/${e}/set-role`,{role:t})).data,adjustBalance:async(e,t,n)=>(await B.post(`/api/admin/users/${e}/adjust-balance`,{amount:t,description:n})).data,batchAction:async(e,t,n)=>(await B.post("/api/admin/users/batch-action",{action:e,user_ids:t,reason:n})).data,getUserTransactions:async(e,t=1,n=20)=>(await B.get(`/api/admin/users/${e}/transactions`,{params:{page:t,size:n}})).data},Tc={getStreamers:async(e={})=>(await B.get("/api/admin/streamers",{params:e})).data,getStreamerDetail:async e=>(await B.get(`/api/admin/streamers/${e}`)).data,updateStreamer:async(e,t)=>(await B.put(`/api/admin/streamers/${e}`,t)).data,getStreamerStatistics:async e=>(await B.get(`/api/admin/streamers/${e}/stats`)).data,getStreamerChests:async(e,t=1,n=20,r)=>(await B.get(`/api/admin/streamers/${e}/chests`,{params:{page:t,size:n,status:r}})).data},ks={getConfigs:async()=>(await B.get("/api/admin/system/configs")).data,createConfig:async e=>(await B.post("/api/admin/system/configs",e)).data,updateConfig:async(e,t)=>(await B.put(`/api/admin/system/configs/${e}`,t)).data,deleteConfig:async e=>{await B.delete(`/api/admin/system/configs/${e}`)},batchUpdateConfigs:async e=>(await B.put("/api/admin/system/configs/batch",{configs:e})).data,getConfigGroups:async()=>(await B.get("/api/system/configs/groups")).data},ko={getAnnouncements:async(e={})=>(await B.get("/api/admin/announcements",{params:e})).data,createAnnouncement:async e=>(await B.post("/api/admin/announcements",e)).data,updateAnnouncement:async(e,t)=>(await B.put(`/api/admin/announcements/${e}`,t)).data,deleteAnnouncement:async e=>(await B.delete(`/api/admin/announcements/${e}`)).data},l0={getAnnouncements:async(e=1,t=10)=>(await B.get("/api/announcements",{params:{page:e,size:t}})).data,getActiveAnnouncements:async(e=5)=>(await B.get("/api/announcements/active",{params:{limit:e}})).data},vt=Object.create(null);vt.open="0";vt.close="1";vt.ping="2";vt.pong="3";vt.message="4";vt.upgrade="5";vt.noop="6";const $s=Object.create(null);Object.keys(vt).forEach(e=>{$s[vt[e]]=e});const Pl={type:"error",data:"parser error"},Rh=typeof Blob=="function"||typeof Blob<"u"&&Object.prototype.toString.call(Blob)==="[object BlobConstructor]",Th=typeof ArrayBuffer=="function",Ph=e=>typeof ArrayBuffer.isView=="function"?ArrayBuffer.isView(e):e&&e.buffer instanceof ArrayBuffer,Ua=({type:e,data:t},n,r)=>Rh&&t instanceof Blob?n?r(t):Pc(t,r):Th&&(t instanceof ArrayBuffer||Ph(t))?n?r(t):Pc(new Blob([t]),r):r(vt[e]+(t||"")),Pc=(e,t)=>{const n=new FileReader;return n.onload=function(){const r=n.result.split(",")[1];t("b"+(r||""))},n.readAsDataURL(e)};function Oc(e){return e instanceof Uint8Array?e:e instanceof ArrayBuffer?new Uint8Array(e):new Uint8Array(e.buffer,e.byteOffset,e.byteLength)}let _o;function a0(e,t){if(Rh&&e.data instanceof Blob)return e.data.arrayBuffer().then(Oc).then(t);if(Th&&(e.data instanceof ArrayBuffer||Ph(e.data)))return t(Oc(e.data));Ua(e,!1,n=>{_o||(_o=new TextEncoder),t(_o.encode(n))})}const Ac="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",xr=typeof Uint8Array>"u"?[]:new Uint8Array(256);for(let e=0;e{let t=e.length*.75,n=e.length,r,s=0,i,o,a,u;e[e.length-1]==="="&&(t--,e[e.length-2]==="="&&t--);const c=new ArrayBuffer(t),d=new Uint8Array(c);for(r=0;r>4,d[s++]=(o&15)<<4|a>>2,d[s++]=(a&3)<<6|u&63;return c},c0=typeof ArrayBuffer=="function",za=(e,t)=>{if(typeof e!="string")return{type:"message",data:Oh(e,t)};const n=e.charAt(0);return n==="b"?{type:"message",data:d0(e.substring(1),t)}:$s[n]?e.length>1?{type:$s[n],data:e.substring(1)}:{type:$s[n]}:Pl},d0=(e,t)=>{if(c0){const n=u0(e);return Oh(n,t)}else return{base64:!0,data:e}},Oh=(e,t)=>{switch(t){case"blob":return e instanceof Blob?e:new Blob([e]);case"arraybuffer":default:return e instanceof ArrayBuffer?e:e.buffer}},Ah="",f0=(e,t)=>{const n=e.length,r=new Array(n);let s=0;e.forEach((i,o)=>{Ua(i,!1,a=>{r[o]=a,++s===n&&t(r.join(Ah))})})},h0=(e,t)=>{const n=e.split(Ah),r=[];for(let s=0;s{const r=n.length;let s;if(r<126)s=new Uint8Array(1),new DataView(s.buffer).setUint8(0,r);else if(r<65536){s=new Uint8Array(3);const i=new DataView(s.buffer);i.setUint8(0,126),i.setUint16(1,r)}else{s=new Uint8Array(9);const i=new DataView(s.buffer);i.setUint8(0,127),i.setBigUint64(1,BigInt(r))}e.data&&typeof e.data!="string"&&(s[0]|=128),t.enqueue(s),t.enqueue(n)})}})}let jo;function _s(e){return e.reduce((t,n)=>t+n.length,0)}function js(e,t){if(e[0].length===t)return e.shift();const n=new Uint8Array(t);let r=0;for(let s=0;sMath.pow(2,21)-1){a.enqueue(Pl);break}s=d*Math.pow(2,32)+c.getUint32(4),r=3}else{if(_s(n)e){a.enqueue(Pl);break}}}})}const Lh=4;function ce(e){if(e)return g0(e)}function g0(e){for(var t in ce.prototype)e[t]=ce.prototype[t];return e}ce.prototype.on=ce.prototype.addEventListener=function(e,t){return this._callbacks=this._callbacks||{},(this._callbacks["$"+e]=this._callbacks["$"+e]||[]).push(t),this};ce.prototype.once=function(e,t){function n(){this.off(e,n),t.apply(this,arguments)}return n.fn=t,this.on(e,n),this};ce.prototype.off=ce.prototype.removeListener=ce.prototype.removeAllListeners=ce.prototype.removeEventListener=function(e,t){if(this._callbacks=this._callbacks||{},arguments.length==0)return this._callbacks={},this;var n=this._callbacks["$"+e];if(!n)return this;if(arguments.length==1)return delete this._callbacks["$"+e],this;for(var r,s=0;sPromise.resolve().then(t):(t,n)=>n(t,0),Je=typeof self<"u"?self:typeof window<"u"?window:Function("return this")(),y0="arraybuffer";function bh(e,...t){return t.reduce((n,r)=>(e.hasOwnProperty(r)&&(n[r]=e[r]),n),{})}const v0=Je.setTimeout,w0=Je.clearTimeout;function Mi(e,t){t.useNativeTimers?(e.setTimeoutFn=v0.bind(Je),e.clearTimeoutFn=w0.bind(Je)):(e.setTimeoutFn=Je.setTimeout.bind(Je),e.clearTimeoutFn=Je.clearTimeout.bind(Je))}const x0=1.33;function S0(e){return typeof e=="string"?N0(e):Math.ceil((e.byteLength||e.size)*x0)}function N0(e){let t=0,n=0;for(let r=0,s=e.length;r=57344?n+=3:(r++,n+=4);return n}function Bh(){return Date.now().toString(36).substring(3)+Math.random().toString(36).substring(2,5)}function E0(e){let t="";for(let n in e)e.hasOwnProperty(n)&&(t.length&&(t+="&"),t+=encodeURIComponent(n)+"="+encodeURIComponent(e[n]));return t}function k0(e){let t={},n=e.split("&");for(let r=0,s=n.length;r{this.readyState="paused",t()};if(this._polling||!this.writable){let r=0;this._polling&&(r++,this.once("pollComplete",function(){--r||n()})),this.writable||(r++,this.once("drain",function(){--r||n()}))}else n()}_poll(){this._polling=!0,this.doPoll(),this.emitReserved("poll")}onData(t){const n=r=>{if(this.readyState==="opening"&&r.type==="open"&&this.onOpen(),r.type==="close")return this.onClose({description:"transport closed by the server"}),!1;this.onPacket(r)};h0(t,this.socket.binaryType).forEach(n),this.readyState!=="closed"&&(this._polling=!1,this.emitReserved("pollComplete"),this.readyState==="open"&&this._poll())}doClose(){const t=()=>{this.write([{type:"close"}])};this.readyState==="open"?t():this.once("open",t)}write(t){this.writable=!1,f0(t,n=>{this.doWrite(n,()=>{this.writable=!0,this.emitReserved("drain")})})}uri(){const t=this.opts.secure?"https":"http",n=this.query||{};return this.opts.timestampRequests!==!1&&(n[this.opts.timestampParam]=Bh()),!this.supportsBinary&&!n.sid&&(n.b64=1),this.createUri(t,n)}}let Dh=!1;try{Dh=typeof XMLHttpRequest<"u"&&"withCredentials"in new XMLHttpRequest}catch{}const C0=Dh;function R0(){}class T0 extends j0{constructor(t){if(super(t),typeof location<"u"){const n=location.protocol==="https:";let r=location.port;r||(r=n?"443":"80"),this.xd=typeof location<"u"&&t.hostname!==location.hostname||r!==t.port}}doWrite(t,n){const r=this.request({method:"POST",data:t});r.on("success",n),r.on("error",(s,i)=>{this.onError("xhr post error",s,i)})}doPoll(){const t=this.request();t.on("data",this.onData.bind(this)),t.on("error",(n,r)=>{this.onError("xhr poll error",n,r)}),this.pollXhr=t}}class yt extends ce{constructor(t,n,r){super(),this.createRequest=t,Mi(this,r),this._opts=r,this._method=r.method||"GET",this._uri=n,this._data=r.data!==void 0?r.data:null,this._create()}_create(){var t;const n=bh(this._opts,"agent","pfx","key","passphrase","cert","ca","ciphers","rejectUnauthorized","autoUnref");n.xdomain=!!this._opts.xd;const r=this._xhr=this.createRequest(n);try{r.open(this._method,this._uri,!0);try{if(this._opts.extraHeaders){r.setDisableHeaderCheck&&r.setDisableHeaderCheck(!0);for(let s in this._opts.extraHeaders)this._opts.extraHeaders.hasOwnProperty(s)&&r.setRequestHeader(s,this._opts.extraHeaders[s])}}catch{}if(this._method==="POST")try{r.setRequestHeader("Content-type","text/plain;charset=UTF-8")}catch{}try{r.setRequestHeader("Accept","*/*")}catch{}(t=this._opts.cookieJar)===null||t===void 0||t.addCookies(r),"withCredentials"in r&&(r.withCredentials=this._opts.withCredentials),this._opts.requestTimeout&&(r.timeout=this._opts.requestTimeout),r.onreadystatechange=()=>{var s;r.readyState===3&&((s=this._opts.cookieJar)===null||s===void 0||s.parseCookies(r.getResponseHeader("set-cookie"))),r.readyState===4&&(r.status===200||r.status===1223?this._onLoad():this.setTimeoutFn(()=>{this._onError(typeof r.status=="number"?r.status:0)},0))},r.send(this._data)}catch(s){this.setTimeoutFn(()=>{this._onError(s)},0);return}typeof document<"u"&&(this._index=yt.requestsCount++,yt.requests[this._index]=this)}_onError(t){this.emitReserved("error",t,this._xhr),this._cleanup(!0)}_cleanup(t){if(!(typeof this._xhr>"u"||this._xhr===null)){if(this._xhr.onreadystatechange=R0,t)try{this._xhr.abort()}catch{}typeof document<"u"&&delete yt.requests[this._index],this._xhr=null}}_onLoad(){const t=this._xhr.responseText;t!==null&&(this.emitReserved("data",t),this.emitReserved("success"),this._cleanup())}abort(){this._cleanup()}}yt.requestsCount=0;yt.requests={};if(typeof document<"u"){if(typeof attachEvent=="function")attachEvent("onunload",Lc);else if(typeof addEventListener=="function"){const e="onpagehide"in Je?"pagehide":"unload";addEventListener(e,Lc,!1)}}function Lc(){for(let e in yt.requests)yt.requests.hasOwnProperty(e)&&yt.requests[e].abort()}const P0=function(){const e=Fh({xdomain:!1});return e&&e.responseType!==null}();class O0 extends T0{constructor(t){super(t);const n=t&&t.forceBase64;this.supportsBinary=P0&&!n}request(t={}){return Object.assign(t,{xd:this.xd},this.opts),new yt(Fh,this.uri(),t)}}function Fh(e){const t=e.xdomain;try{if(typeof XMLHttpRequest<"u"&&(!t||C0))return new XMLHttpRequest}catch{}if(!t)try{return new Je[["Active"].concat("Object").join("X")]("Microsoft.XMLHTTP")}catch{}}const Ih=typeof navigator<"u"&&typeof navigator.product=="string"&&navigator.product.toLowerCase()==="reactnative";class A0 extends Ma{get name(){return"websocket"}doOpen(){const t=this.uri(),n=this.opts.protocols,r=Ih?{}:bh(this.opts,"agent","perMessageDeflate","pfx","key","passphrase","cert","ca","ciphers","rejectUnauthorized","localAddress","protocolVersion","origin","maxPayload","family","checkServerIdentity");this.opts.extraHeaders&&(r.headers=this.opts.extraHeaders);try{this.ws=this.createSocket(t,n,r)}catch(s){return this.emitReserved("error",s)}this.ws.binaryType=this.socket.binaryType,this.addEventListeners()}addEventListeners(){this.ws.onopen=()=>{this.opts.autoUnref&&this.ws._socket.unref(),this.onOpen()},this.ws.onclose=t=>this.onClose({description:"websocket connection closed",context:t}),this.ws.onmessage=t=>this.onData(t.data),this.ws.onerror=t=>this.onError("websocket error",t)}write(t){this.writable=!1;for(let n=0;n{try{this.doWrite(r,i)}catch{}s&&zi(()=>{this.writable=!0,this.emitReserved("drain")},this.setTimeoutFn)})}}doClose(){typeof this.ws<"u"&&(this.ws.onerror=()=>{},this.ws.close(),this.ws=null)}uri(){const t=this.opts.secure?"wss":"ws",n=this.query||{};return this.opts.timestampRequests&&(n[this.opts.timestampParam]=Bh()),this.supportsBinary||(n.b64=1),this.createUri(t,n)}}const Co=Je.WebSocket||Je.MozWebSocket;class L0 extends A0{createSocket(t,n,r){return Ih?new Co(t,n,r):n?new Co(t,n):new Co(t)}doWrite(t,n){this.ws.send(n)}}class b0 extends Ma{get name(){return"webtransport"}doOpen(){try{this._transport=new WebTransport(this.createUri("https"),this.opts.transportOptions[this.name])}catch(t){return this.emitReserved("error",t)}this._transport.closed.then(()=>{this.onClose()}).catch(t=>{this.onError("webtransport error",t)}),this._transport.ready.then(()=>{this._transport.createBidirectionalStream().then(t=>{const n=m0(Number.MAX_SAFE_INTEGER,this.socket.binaryType),r=t.readable.pipeThrough(n).getReader(),s=p0();s.readable.pipeTo(t.writable),this._writer=s.writable.getWriter();const i=()=>{r.read().then(({done:a,value:u})=>{a||(this.onPacket(u),i())}).catch(a=>{})};i();const o={type:"open"};this.query.sid&&(o.data=`{"sid":"${this.query.sid}"}`),this._writer.write(o).then(()=>this.onOpen())})})}write(t){this.writable=!1;for(let n=0;n{s&&zi(()=>{this.writable=!0,this.emitReserved("drain")},this.setTimeoutFn)})}}doClose(){var t;(t=this._transport)===null||t===void 0||t.close()}}const B0={websocket:L0,webtransport:b0,polling:O0},D0=/^(?:(?![^:@\/?#]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/,F0=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"];function Ol(e){if(e.length>8e3)throw"URI too long";const t=e,n=e.indexOf("["),r=e.indexOf("]");n!=-1&&r!=-1&&(e=e.substring(0,n)+e.substring(n,r).replace(/:/g,";")+e.substring(r,e.length));let s=D0.exec(e||""),i={},o=14;for(;o--;)i[F0[o]]=s[o]||"";return n!=-1&&r!=-1&&(i.source=t,i.host=i.host.substring(1,i.host.length-1).replace(/;/g,":"),i.authority=i.authority.replace("[","").replace("]","").replace(/;/g,":"),i.ipv6uri=!0),i.pathNames=I0(i,i.path),i.queryKey=U0(i,i.query),i}function I0(e,t){const n=/\/{2,9}/g,r=t.replace(n,"/").split("/");return(t.slice(0,1)=="/"||t.length===0)&&r.splice(0,1),t.slice(-1)=="/"&&r.splice(r.length-1,1),r}function U0(e,t){const n={};return t.replace(/(?:^|&)([^&=]*)=?([^&]*)/g,function(r,s,i){s&&(n[s]=i)}),n}const Al=typeof addEventListener=="function"&&typeof removeEventListener=="function",Vs=[];Al&&addEventListener("offline",()=>{Vs.forEach(e=>e())},!1);class Jt extends ce{constructor(t,n){if(super(),this.binaryType=y0,this.writeBuffer=[],this._prevBufferLen=0,this._pingInterval=-1,this._pingTimeout=-1,this._maxPayload=-1,this._pingTimeoutTime=1/0,t&&typeof t=="object"&&(n=t,t=null),t){const r=Ol(t);n.hostname=r.host,n.secure=r.protocol==="https"||r.protocol==="wss",n.port=r.port,r.query&&(n.query=r.query)}else n.host&&(n.hostname=Ol(n.host).host);Mi(this,n),this.secure=n.secure!=null?n.secure:typeof location<"u"&&location.protocol==="https:",n.hostname&&!n.port&&(n.port=this.secure?"443":"80"),this.hostname=n.hostname||(typeof location<"u"?location.hostname:"localhost"),this.port=n.port||(typeof location<"u"&&location.port?location.port:this.secure?"443":"80"),this.transports=[],this._transportsByName={},n.transports.forEach(r=>{const s=r.prototype.name;this.transports.push(s),this._transportsByName[s]=r}),this.opts=Object.assign({path:"/engine.io",agent:!1,withCredentials:!1,upgrade:!0,timestampParam:"t",rememberUpgrade:!1,addTrailingSlash:!0,rejectUnauthorized:!0,perMessageDeflate:{threshold:1024},transportOptions:{},closeOnBeforeunload:!1},n),this.opts.path=this.opts.path.replace(/\/$/,"")+(this.opts.addTrailingSlash?"/":""),typeof this.opts.query=="string"&&(this.opts.query=k0(this.opts.query)),Al&&(this.opts.closeOnBeforeunload&&(this._beforeunloadEventListener=()=>{this.transport&&(this.transport.removeAllListeners(),this.transport.close())},addEventListener("beforeunload",this._beforeunloadEventListener,!1)),this.hostname!=="localhost"&&(this._offlineEventListener=()=>{this._onClose("transport close",{description:"network connection lost"})},Vs.push(this._offlineEventListener))),this.opts.withCredentials&&(this._cookieJar=void 0),this._open()}createTransport(t){const n=Object.assign({},this.opts.query);n.EIO=Lh,n.transport=t,this.id&&(n.sid=this.id);const r=Object.assign({},this.opts,{query:n,socket:this,hostname:this.hostname,secure:this.secure,port:this.port},this.opts.transportOptions[t]);return new this._transportsByName[t](r)}_open(){if(this.transports.length===0){this.setTimeoutFn(()=>{this.emitReserved("error","No transports available")},0);return}const t=this.opts.rememberUpgrade&&Jt.priorWebsocketSuccess&&this.transports.indexOf("websocket")!==-1?"websocket":this.transports[0];this.readyState="opening";const n=this.createTransport(t);n.open(),this.setTransport(n)}setTransport(t){this.transport&&this.transport.removeAllListeners(),this.transport=t,t.on("drain",this._onDrain.bind(this)).on("packet",this._onPacket.bind(this)).on("error",this._onError.bind(this)).on("close",n=>this._onClose("transport close",n))}onOpen(){this.readyState="open",Jt.priorWebsocketSuccess=this.transport.name==="websocket",this.emitReserved("open"),this.flush()}_onPacket(t){if(this.readyState==="opening"||this.readyState==="open"||this.readyState==="closing")switch(this.emitReserved("packet",t),this.emitReserved("heartbeat"),t.type){case"open":this.onHandshake(JSON.parse(t.data));break;case"ping":this._sendPacket("pong"),this.emitReserved("ping"),this.emitReserved("pong"),this._resetPingTimeout();break;case"error":const n=new Error("server error");n.code=t.data,this._onError(n);break;case"message":this.emitReserved("data",t.data),this.emitReserved("message",t.data);break}}onHandshake(t){this.emitReserved("handshake",t),this.id=t.sid,this.transport.query.sid=t.sid,this._pingInterval=t.pingInterval,this._pingTimeout=t.pingTimeout,this._maxPayload=t.maxPayload,this.onOpen(),this.readyState!=="closed"&&this._resetPingTimeout()}_resetPingTimeout(){this.clearTimeoutFn(this._pingTimeoutTimer);const t=this._pingInterval+this._pingTimeout;this._pingTimeoutTime=Date.now()+t,this._pingTimeoutTimer=this.setTimeoutFn(()=>{this._onClose("ping timeout")},t),this.opts.autoUnref&&this._pingTimeoutTimer.unref()}_onDrain(){this.writeBuffer.splice(0,this._prevBufferLen),this._prevBufferLen=0,this.writeBuffer.length===0?this.emitReserved("drain"):this.flush()}flush(){if(this.readyState!=="closed"&&this.transport.writable&&!this.upgrading&&this.writeBuffer.length){const t=this._getWritablePackets();this.transport.send(t),this._prevBufferLen=t.length,this.emitReserved("flush")}}_getWritablePackets(){if(!(this._maxPayload&&this.transport.name==="polling"&&this.writeBuffer.length>1))return this.writeBuffer;let n=1;for(let r=0;r0&&n>this._maxPayload)return this.writeBuffer.slice(0,r);n+=2}return this.writeBuffer}_hasPingExpired(){if(!this._pingTimeoutTime)return!0;const t=Date.now()>this._pingTimeoutTime;return t&&(this._pingTimeoutTime=0,zi(()=>{this._onClose("ping timeout")},this.setTimeoutFn)),t}write(t,n,r){return this._sendPacket("message",t,n,r),this}send(t,n,r){return this._sendPacket("message",t,n,r),this}_sendPacket(t,n,r,s){if(typeof n=="function"&&(s=n,n=void 0),typeof r=="function"&&(s=r,r=null),this.readyState==="closing"||this.readyState==="closed")return;r=r||{},r.compress=r.compress!==!1;const i={type:t,data:n,options:r};this.emitReserved("packetCreate",i),this.writeBuffer.push(i),s&&this.once("flush",s),this.flush()}close(){const t=()=>{this._onClose("forced close"),this.transport.close()},n=()=>{this.off("upgrade",n),this.off("upgradeError",n),t()},r=()=>{this.once("upgrade",n),this.once("upgradeError",n)};return(this.readyState==="opening"||this.readyState==="open")&&(this.readyState="closing",this.writeBuffer.length?this.once("drain",()=>{this.upgrading?r():t()}):this.upgrading?r():t()),this}_onError(t){if(Jt.priorWebsocketSuccess=!1,this.opts.tryAllTransports&&this.transports.length>1&&this.readyState==="opening")return this.transports.shift(),this._open();this.emitReserved("error",t),this._onClose("transport error",t)}_onClose(t,n){if(this.readyState==="opening"||this.readyState==="open"||this.readyState==="closing"){if(this.clearTimeoutFn(this._pingTimeoutTimer),this.transport.removeAllListeners("close"),this.transport.close(),this.transport.removeAllListeners(),Al&&(this._beforeunloadEventListener&&removeEventListener("beforeunload",this._beforeunloadEventListener,!1),this._offlineEventListener)){const r=Vs.indexOf(this._offlineEventListener);r!==-1&&Vs.splice(r,1)}this.readyState="closed",this.id=null,this.emitReserved("close",t,n),this.writeBuffer=[],this._prevBufferLen=0}}}Jt.protocol=Lh;class z0 extends Jt{constructor(){super(...arguments),this._upgrades=[]}onOpen(){if(super.onOpen(),this.readyState==="open"&&this.opts.upgrade)for(let t=0;t{r||(n.send([{type:"ping",data:"probe"}]),n.once("packet",f=>{if(!r)if(f.type==="pong"&&f.data==="probe"){if(this.upgrading=!0,this.emitReserved("upgrading",n),!n)return;Jt.priorWebsocketSuccess=n.name==="websocket",this.transport.pause(()=>{r||this.readyState!=="closed"&&(d(),this.setTransport(n),n.send([{type:"upgrade"}]),this.emitReserved("upgrade",n),n=null,this.upgrading=!1,this.flush())})}else{const g=new Error("probe error");g.transport=n.name,this.emitReserved("upgradeError",g)}}))};function i(){r||(r=!0,d(),n.close(),n=null)}const o=f=>{const g=new Error("probe error: "+f);g.transport=n.name,i(),this.emitReserved("upgradeError",g)};function a(){o("transport closed")}function u(){o("socket closed")}function c(f){n&&f.name!==n.name&&i()}const d=()=>{n.removeListener("open",s),n.removeListener("error",o),n.removeListener("close",a),this.off("close",u),this.off("upgrading",c)};n.once("open",s),n.once("error",o),n.once("close",a),this.once("close",u),this.once("upgrading",c),this._upgrades.indexOf("webtransport")!==-1&&t!=="webtransport"?this.setTimeoutFn(()=>{r||n.open()},200):n.open()}onHandshake(t){this._upgrades=this._filterUpgrades(t.upgrades),super.onHandshake(t)}_filterUpgrades(t){const n=[];for(let r=0;rB0[s]).filter(s=>!!s)),super(t,r)}};function $0(e,t="",n){let r=e;n=n||typeof location<"u"&&location,e==null&&(e=n.protocol+"//"+n.host),typeof e=="string"&&(e.charAt(0)==="/"&&(e.charAt(1)==="/"?e=n.protocol+e:e=n.host+e),/^(https?|wss?):\/\//.test(e)||(typeof n<"u"?e=n.protocol+"//"+e:e="https://"+e),r=Ol(e)),r.port||(/^(http|ws)$/.test(r.protocol)?r.port="80":/^(http|ws)s$/.test(r.protocol)&&(r.port="443")),r.path=r.path||"/";const i=r.host.indexOf(":")!==-1?"["+r.host+"]":r.host;return r.id=r.protocol+"://"+i+":"+r.port+t,r.href=r.protocol+"://"+i+(n&&n.port===r.port?"":":"+r.port),r}const V0=typeof ArrayBuffer=="function",H0=e=>typeof ArrayBuffer.isView=="function"?ArrayBuffer.isView(e):e.buffer instanceof ArrayBuffer,Uh=Object.prototype.toString,W0=typeof Blob=="function"||typeof Blob<"u"&&Uh.call(Blob)==="[object BlobConstructor]",q0=typeof File=="function"||typeof File<"u"&&Uh.call(File)==="[object FileConstructor]";function $a(e){return V0&&(e instanceof ArrayBuffer||H0(e))||W0&&e instanceof Blob||q0&&e instanceof File}function Hs(e,t){if(!e||typeof e!="object")return!1;if(Array.isArray(e)){for(let n=0,r=e.length;n=0&&e.num{delete this.acks[t];for(let a=0;a{this.io.clearTimeoutFn(i),n.apply(this,a)};o.withError=!0,this.acks[t]=o}emitWithAck(t,...n){return new Promise((r,s)=>{const i=(o,a)=>o?s(o):r(a);i.withError=!0,n.push(i),this.emit(t,...n)})}_addToQueue(t){let n;typeof t[t.length-1]=="function"&&(n=t.pop());const r={id:this._queueSeq++,tryCount:0,pending:!1,args:t,flags:Object.assign({fromQueue:!0},this.flags)};t.push((s,...i)=>r!==this._queue[0]?void 0:(s!==null?r.tryCount>this._opts.retries&&(this._queue.shift(),n&&n(s)):(this._queue.shift(),n&&n(null,...i)),r.pending=!1,this._drainQueue())),this._queue.push(r),this._drainQueue()}_drainQueue(t=!1){if(!this.connected||this._queue.length===0)return;const n=this._queue[0];n.pending&&!t||(n.pending=!0,n.tryCount++,this.flags=n.flags,this.emit.apply(this,n.args))}packet(t){t.nsp=this.nsp,this.io._packet(t)}onopen(){typeof this.auth=="function"?this.auth(t=>{this._sendConnectPacket(t)}):this._sendConnectPacket(this.auth)}_sendConnectPacket(t){this.packet({type:$.CONNECT,data:this._pid?Object.assign({pid:this._pid,offset:this._lastOffset},t):t})}onerror(t){this.connected||this.emitReserved("connect_error",t)}onclose(t,n){this.connected=!1,delete this.id,this.emitReserved("disconnect",t,n),this._clearAcks()}_clearAcks(){Object.keys(this.acks).forEach(t=>{if(!this.sendBuffer.some(r=>String(r.id)===t)){const r=this.acks[t];delete this.acks[t],r.withError&&r.call(this,new Error("socket has been disconnected"))}})}onpacket(t){if(t.nsp===this.nsp)switch(t.type){case $.CONNECT:t.data&&t.data.sid?this.onconnect(t.data.sid,t.data.pid):this.emitReserved("connect_error",new Error("It seems you are trying to reach a Socket.IO server in v2.x with a v3.x client, but they are not compatible (more information here: https://socket.io/docs/v3/migrating-from-2-x-to-3-0/)"));break;case $.EVENT:case $.BINARY_EVENT:this.onevent(t);break;case $.ACK:case $.BINARY_ACK:this.onack(t);break;case $.DISCONNECT:this.ondisconnect();break;case $.CONNECT_ERROR:this.destroy();const r=new Error(t.data.message);r.data=t.data.data,this.emitReserved("connect_error",r);break}}onevent(t){const n=t.data||[];t.id!=null&&n.push(this.ack(t.id)),this.connected?this.emitEvent(n):this.receiveBuffer.push(Object.freeze(n))}emitEvent(t){if(this._anyListeners&&this._anyListeners.length){const n=this._anyListeners.slice();for(const r of n)r.apply(this,t)}super.emit.apply(this,t),this._pid&&t.length&&typeof t[t.length-1]=="string"&&(this._lastOffset=t[t.length-1])}ack(t){const n=this;let r=!1;return function(...s){r||(r=!0,n.packet({type:$.ACK,id:t,data:s}))}}onack(t){const n=this.acks[t.id];typeof n=="function"&&(delete this.acks[t.id],n.withError&&t.data.unshift(null),n.apply(this,t.data))}onconnect(t,n){this.id=t,this.recovered=n&&this._pid===n,this._pid=n,this.connected=!0,this.emitBuffered(),this.emitReserved("connect"),this._drainQueue(!0)}emitBuffered(){this.receiveBuffer.forEach(t=>this.emitEvent(t)),this.receiveBuffer=[],this.sendBuffer.forEach(t=>{this.notifyOutgoingListeners(t),this.packet(t)}),this.sendBuffer=[]}ondisconnect(){this.destroy(),this.onclose("io server disconnect")}destroy(){this.subs&&(this.subs.forEach(t=>t()),this.subs=void 0),this.io._destroy(this)}disconnect(){return this.connected&&this.packet({type:$.DISCONNECT}),this.destroy(),this.connected&&this.onclose("io client disconnect"),this}close(){return this.disconnect()}compress(t){return this.flags.compress=t,this}get volatile(){return this.flags.volatile=!0,this}timeout(t){return this.flags.timeout=t,this}onAny(t){return this._anyListeners=this._anyListeners||[],this._anyListeners.push(t),this}prependAny(t){return this._anyListeners=this._anyListeners||[],this._anyListeners.unshift(t),this}offAny(t){if(!this._anyListeners)return this;if(t){const n=this._anyListeners;for(let r=0;r0&&e.jitter<=1?e.jitter:0,this.attempts=0}sr.prototype.duration=function(){var e=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var t=Math.random(),n=Math.floor(t*this.jitter*e);e=Math.floor(t*10)&1?e+n:e-n}return Math.min(e,this.max)|0};sr.prototype.reset=function(){this.attempts=0};sr.prototype.setMin=function(e){this.ms=e};sr.prototype.setMax=function(e){this.max=e};sr.prototype.setJitter=function(e){this.jitter=e};class Bl extends ce{constructor(t,n){var r;super(),this.nsps={},this.subs=[],t&&typeof t=="object"&&(n=t,t=void 0),n=n||{},n.path=n.path||"/socket.io",this.opts=n,Mi(this,n),this.reconnection(n.reconnection!==!1),this.reconnectionAttempts(n.reconnectionAttempts||1/0),this.reconnectionDelay(n.reconnectionDelay||1e3),this.reconnectionDelayMax(n.reconnectionDelayMax||5e3),this.randomizationFactor((r=n.randomizationFactor)!==null&&r!==void 0?r:.5),this.backoff=new sr({min:this.reconnectionDelay(),max:this.reconnectionDelayMax(),jitter:this.randomizationFactor()}),this.timeout(n.timeout==null?2e4:n.timeout),this._readyState="closed",this.uri=t;const s=n.parser||Z0;this.encoder=new s.Encoder,this.decoder=new s.Decoder,this._autoConnect=n.autoConnect!==!1,this._autoConnect&&this.open()}reconnection(t){return arguments.length?(this._reconnection=!!t,t||(this.skipReconnect=!0),this):this._reconnection}reconnectionAttempts(t){return t===void 0?this._reconnectionAttempts:(this._reconnectionAttempts=t,this)}reconnectionDelay(t){var n;return t===void 0?this._reconnectionDelay:(this._reconnectionDelay=t,(n=this.backoff)===null||n===void 0||n.setMin(t),this)}randomizationFactor(t){var n;return t===void 0?this._randomizationFactor:(this._randomizationFactor=t,(n=this.backoff)===null||n===void 0||n.setJitter(t),this)}reconnectionDelayMax(t){var n;return t===void 0?this._reconnectionDelayMax:(this._reconnectionDelayMax=t,(n=this.backoff)===null||n===void 0||n.setMax(t),this)}timeout(t){return arguments.length?(this._timeout=t,this):this._timeout}maybeReconnectOnOpen(){!this._reconnecting&&this._reconnection&&this.backoff.attempts===0&&this.reconnect()}open(t){if(~this._readyState.indexOf("open"))return this;this.engine=new M0(this.uri,this.opts);const n=this.engine,r=this;this._readyState="opening",this.skipReconnect=!1;const s=it(n,"open",function(){r.onopen(),t&&t()}),i=a=>{this.cleanup(),this._readyState="closed",this.emitReserved("error",a),t?t(a):this.maybeReconnectOnOpen()},o=it(n,"error",i);if(this._timeout!==!1){const a=this._timeout,u=this.setTimeoutFn(()=>{s(),i(new Error("timeout")),n.close()},a);this.opts.autoUnref&&u.unref(),this.subs.push(()=>{this.clearTimeoutFn(u)})}return this.subs.push(s),this.subs.push(o),this}connect(t){return this.open(t)}onopen(){this.cleanup(),this._readyState="open",this.emitReserved("open");const t=this.engine;this.subs.push(it(t,"ping",this.onping.bind(this)),it(t,"data",this.ondata.bind(this)),it(t,"error",this.onerror.bind(this)),it(t,"close",this.onclose.bind(this)),it(this.decoder,"decoded",this.ondecoded.bind(this)))}onping(){this.emitReserved("ping")}ondata(t){try{this.decoder.add(t)}catch(n){this.onclose("parse error",n)}}ondecoded(t){zi(()=>{this.emitReserved("packet",t)},this.setTimeoutFn)}onerror(t){this.emitReserved("error",t)}socket(t,n){let r=this.nsps[t];return r?this._autoConnect&&!r.active&&r.connect():(r=new zh(this,t,n),this.nsps[t]=r),r}_destroy(t){const n=Object.keys(this.nsps);for(const r of n)if(this.nsps[r].active)return;this._close()}_packet(t){const n=this.encoder.encode(t);for(let r=0;rt()),this.subs.length=0,this.decoder.destroy()}_close(){this.skipReconnect=!0,this._reconnecting=!1,this.onclose("forced close")}disconnect(){return this._close()}onclose(t,n){var r;this.cleanup(),(r=this.engine)===null||r===void 0||r.close(),this.backoff.reset(),this._readyState="closed",this.emitReserved("close",t,n),this._reconnection&&!this.skipReconnect&&this.reconnect()}reconnect(){if(this._reconnecting||this.skipReconnect)return this;const t=this;if(this.backoff.attempts>=this._reconnectionAttempts)this.backoff.reset(),this.emitReserved("reconnect_failed"),this._reconnecting=!1;else{const n=this.backoff.duration();this._reconnecting=!0;const r=this.setTimeoutFn(()=>{t.skipReconnect||(this.emitReserved("reconnect_attempt",t.backoff.attempts),!t.skipReconnect&&t.open(s=>{s?(t._reconnecting=!1,t.reconnect(),this.emitReserved("reconnect_error",s)):t.onreconnect()}))},n);this.opts.autoUnref&&r.unref(),this.subs.push(()=>{this.clearTimeoutFn(r)})}}onreconnect(){const t=this.backoff.attempts;this._reconnecting=!1,this.backoff.reset(),this.emitReserved("reconnect",t)}}const mr={};function Ws(e,t){typeof e=="object"&&(t=e,e=void 0),t=t||{};const n=$0(e,t.path||"/socket.io"),r=n.source,s=n.id,i=n.path,o=mr[s]&&i in mr[s].nsps,a=t.forceNew||t["force new connection"]||t.multiplex===!1||o;let u;return a?u=new Bl(r,t):(mr[s]||(mr[s]=new Bl(r,t)),u=mr[s]),n.query&&!t.query&&(t.query=n.queryKey),u.socket(n.path,t)}Object.assign(Ws,{Manager:Bl,Socket:zh,io:Ws,connect:Ws});const tw="ws://localhost:8000";class nw{constructor(){Hi(this,"socket",null);Hi(this,"messageHandlers",[])}connect(t,n,r){var i;if((i=this.socket)!=null&&i.connected)return;const s=r==="streamer"||r==="admin"?"ws/streamer":"ws/user";this.socket=Ws(tw,{path:`/${s}/${n}`,query:{token:t},transports:["websocket"]}),this.socket.on("connect",()=>{console.log("WebSocket connected")}),this.socket.on("disconnect",()=>{console.log("WebSocket disconnected")}),this.socket.on("message",o=>{this.messageHandlers.forEach(a=>a(o))}),this.socket.on("connect_error",o=>{console.error("WebSocket connection error:",o)})}disconnect(){this.socket&&(this.socket.disconnect(),this.socket=null)}onMessage(t){return this.messageHandlers.push(t),()=>{this.messageHandlers=this.messageHandlers.filter(n=>n!==t)}}send(t){var n;(n=this.socket)!=null&&n.connected&&this.socket.emit("message",t)}}const Sr=new nw,Mh=x.createContext(void 0),rn=()=>{const e=x.useContext(Mh);if(!e)throw new Error("useAuth must be used within AuthProvider");return e},rw=({children:e})=>{const[t,n]=x.useState(null),[r,s]=x.useState(null),[i,o]=x.useState(!0);x.useEffect(()=>{const f=localStorage.getItem("token"),g=localStorage.getItem("user");if(f&&g){s(f),n(JSON.parse(g));const S=JSON.parse(g),y=S.role.toLowerCase();Sr.connect(f,S.id,y)}o(!1)},[]),x.useEffect(()=>{if(!t)return;const f=Sr.onMessage(g=>{if(g.type==="balance_update"){const S=g;n(y=>{if(!y)return null;const v={...y,balance:S.balance};return localStorage.setItem("user",JSON.stringify(v)),v})}});return()=>{f()}},[t]);const a=async(f,g)=>{const S=await No.login(f,g);s(S.access_token),n(S.user),localStorage.setItem("token",S.access_token),localStorage.setItem("user",JSON.stringify(S.user));const y=S.user.role.toLowerCase();return Sr.connect(S.access_token,S.user.id,y),S},u=async(f,g,S)=>{await No.register(f,g,S)},c=()=>{s(null),n(null),localStorage.removeItem("token"),localStorage.removeItem("user"),Sr.disconnect()},d=async()=>{try{const f=await No.getMe();n(f),localStorage.setItem("user",JSON.stringify(f))}catch(f){console.error("Failed to refresh user:",f)}};return l.jsx(Mh.Provider,{value:{user:t,token:r,loading:i,login:a,register:u,logout:c,refreshUser:d},children:e})},sw=()=>{const[e,t]=x.useState(""),[n,r]=x.useState(""),[s,i]=x.useState(""),[o,a]=x.useState(!1),{login:u}=rn(),c=nn(),d=async f=>{var g,S;f.preventDefault(),i(""),a(!0);try{const v=(await u(e,n)).user.role.toLowerCase();c(v==="admin"?"/admin":v==="streamer"?"/streamer":"/")}catch(y){i(((S=(g=y.response)==null?void 0:g.data)==null?void 0:S.detail)||"登录失败,请检查用户名和密码")}finally{a(!1)}};return l.jsx("div",{className:"auth-page",children:l.jsx("div",{className:"auth-container",children:l.jsxs("div",{className:"auth-card card",children:[l.jsx("h1",{className:"auth-title",children:"登录"}),l.jsx("p",{className:"auth-subtitle",children:"欢迎回到宝箱竞猜系统"}),s&&l.jsx("div",{className:"alert alert-danger",children:s}),l.jsxs("form",{onSubmit:d,children:[l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",htmlFor:"username",children:"用户名"}),l.jsx("input",{id:"username",type:"text",className:"form-input",value:e,onChange:f=>t(f.target.value),required:!0,placeholder:"请输入用户名"})]}),l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",htmlFor:"password",children:"密码"}),l.jsx("input",{id:"password",type:"password",className:"form-input",value:n,onChange:f=>r(f.target.value),required:!0,placeholder:"请输入密码"})]}),l.jsx("button",{type:"submit",className:"btn btn-primary w-100",disabled:o,children:o?"登录中...":"登录"})]}),l.jsxs("div",{className:"auth-footer",children:["还没有账号?",l.jsx(rt,{to:"/register",children:"立即注册"})]})]})})})},iw=()=>{const[e,t]=x.useState(""),[n,r]=x.useState(""),[s,i]=x.useState(""),[o,a]=x.useState(""),[u,c]=x.useState(""),[d,f]=x.useState(!1),{register:g,login:S}=rn(),y=nn(),v=async w=>{var p;if(w.preventDefault(),c(""),s!==o){c("两次输入的密码不一致");return}if(s.length<6){c("密码长度不能少于6位");return}if(s.length>72){c("密码长度不能超过72个字符");return}f(!0);try{await g(e,n,s),await S(e,s),y("/")}catch(h){console.error("Registration error:",h);let m="注册失败,请稍后重试";if(h.response){const N=(p=h.response.data)==null?void 0:p.detail;N?Array.isArray(N)?m=N.map(C=>C.msg||C.message||"未知错误").join(", "):m=String(N):m=`服务器错误: ${h.response.status}`}else h.request?m="网络错误,请检查网络连接":m=h.message||m;c(m)}finally{f(!1)}};return l.jsx("div",{className:"auth-page",children:l.jsx("div",{className:"auth-container",children:l.jsxs("div",{className:"auth-card card",children:[l.jsx("h2",{className:"auth-title",children:"注册"}),l.jsx("p",{className:"auth-subtitle",children:"创建您的宝箱竞猜账号"}),u&&l.jsx("div",{className:"alert alert-danger",children:u}),l.jsxs("form",{onSubmit:v,children:[l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",htmlFor:"username",children:"用户名"}),l.jsx("input",{id:"username",type:"text",className:"form-input",value:e,onChange:w=>t(w.target.value),required:!0,placeholder:"请输入用户名"})]}),l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",htmlFor:"email",children:"邮箱"}),l.jsx("input",{id:"email",type:"email",className:"form-input",value:n,onChange:w=>r(w.target.value),required:!0,placeholder:"请输入邮箱"})]}),l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",htmlFor:"password",children:"密码"}),l.jsx("input",{id:"password",type:"password",className:"form-input",value:s,onChange:w=>i(w.target.value),required:!0,placeholder:"请输入密码(6-72个字符)"}),l.jsx("small",{className:"form-text text-muted",children:"密码长度应在6-72个字符之间"})]}),l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",htmlFor:"confirmPassword",children:"确认密码"}),l.jsx("input",{id:"confirmPassword",type:"password",className:"form-input",value:o,onChange:w=>a(w.target.value),required:!0,placeholder:"请再次输入密码"})]}),l.jsx("button",{type:"submit",className:"btn btn-primary w-100",disabled:d,children:d?"注册中...":"注册"})]}),l.jsxs("div",{className:"auth-footer",children:["已有账号?",l.jsx(rt,{to:"/login",children:"立即登录"})]})]})})})},ow=({chest:e})=>{const t=s=>{switch(s){case 0:return"text-success";case 1:return"text-warning";case 2:return"text-warning";case 3:return"text-secondary";case 4:return"text-secondary";default:return"text-secondary"}},n=s=>{switch(s){case 0:return"下注中";case 1:return"已封盘";case 2:return"结算中";case 3:return"已结束";case 4:return"已退款";default:return"未知"}},r=e.pool_a+e.pool_b;return l.jsx(rt,{to:`/chests/${e.id}`,className:"chest-card-link",children:l.jsxs("div",{className:"card chest-card",children:[l.jsxs("div",{className:"chest-card-header",children:[l.jsx("h3",{className:"chest-title",children:e.title}),l.jsx("span",{className:`status ${t(e.status)}`,children:n(e.status)})]}),l.jsxs("div",{className:"chest-options",children:[l.jsxs("div",{className:"option",children:[l.jsx("span",{className:"option-label",children:"选项A"}),l.jsx("span",{className:"option-text",children:e.option_a}),l.jsxs("span",{className:"option-amount",children:[e.pool_a.toLocaleString()," 喵币"]})]}),l.jsxs("div",{className:"option",children:[l.jsx("span",{className:"option-label",children:"选项B"}),l.jsx("span",{className:"option-text",children:e.option_b}),l.jsxs("span",{className:"option-amount",children:[e.pool_b.toLocaleString()," 喵币"]})]})]}),l.jsxs("div",{className:"chest-footer",children:[l.jsxs("div",{className:"total-pool",children:[l.jsx("span",{children:"总奖池: "}),l.jsxs("strong",{children:[r.toLocaleString()," 喵币"]})]}),l.jsxs("div",{className:"bet-count",children:[e.total_bets," 人参与"]})]}),e.status===0&&e.countdown_seconds>0&&l.jsxs("div",{className:"countdown",children:["⏱️ 剩余 ",Math.floor(e.countdown_seconds/60),":",(e.countdown_seconds%60).toString().padStart(2,"0")]})]})})},is=({text:e="加载中..."})=>l.jsxs("div",{className:"loading-container",children:[l.jsx("div",{className:"loading"}),l.jsx("p",{className:"loading-text",children:e})]}),lw=()=>{const[e,t]=x.useState([]),[n,r]=x.useState([]),[s,i]=x.useState([]),[o,a]=x.useState(!0),[u,c]=x.useState(""),[d,f]=x.useState(0);x.useEffect(()=>{g()},[]),x.useEffect(()=>{if(n.length>1){const v=setInterval(()=>{f(w=>(w+1)%n.length)},5e3);return()=>clearInterval(v)}},[n.length]);const g=async()=>{try{a(!0);const[v,w,p]=await Promise.all([Ut.getChests(),l0.getActiveAnnouncements(5).catch(()=>[]),o0.getStreamers(0,10).catch(()=>[])]);t(v.filter(h=>h.status===0||h.status===1)),r(w),i(p)}catch(v){c("加载数据失败"),console.error(v)}finally{a(!1)}},S=v=>{switch(v){case"WARNING":return"badge-warning";case"PRIZE":return"badge-success";default:return"badge-info"}};if(o)return l.jsx(is,{text:"加载中..."});const y=n[d];return l.jsxs("div",{className:"home-page",children:[n.length>0&&y&&l.jsxs("div",{className:"announcement-bar",children:[l.jsx("div",{className:"announcement-icon",children:"📢"}),l.jsxs("div",{className:"announcement-content",children:[l.jsxs("h4",{children:[y.title,l.jsx("span",{className:`badge ${S(y.type)}`,style:{marginLeft:8},children:y.type==="WARNING"?"警告":y.type==="PRIZE"?"奖品":"信息"})]}),l.jsx("p",{children:y.content})]}),n.length>1&&l.jsx("div",{className:"announcement-dots",style:{display:"flex",gap:4},children:n.map((v,w)=>l.jsx("span",{onClick:()=>f(w),style:{width:8,height:8,borderRadius:"50%",background:w===d?"var(--primary-color)":"var(--border-color)",cursor:"pointer"}},w))})]}),u&&l.jsx("div",{className:"alert alert-danger",children:u}),s.length>0&&l.jsxs("div",{className:"streamers-section",children:[l.jsx("h2",{className:"section-title",children:"🌟 正在开奖的主播"}),l.jsx("div",{className:"streamers-grid",children:s.map(v=>{var w;return l.jsxs("div",{className:"streamer-card",children:[l.jsxs("div",{className:"streamer-info",children:[l.jsx("div",{className:"streamer-avatar",children:((w=v.nickname)==null?void 0:w.charAt(0).toUpperCase())||v.username.charAt(0).toUpperCase()}),l.jsxs("div",{className:"streamer-details",children:[l.jsx("h4",{children:v.nickname||v.username}),l.jsx("p",{className:"streamer-status",children:"● 正在开奖"})]})]}),l.jsxs("div",{className:"streamer-stats",children:[l.jsxs("span",{children:["活跃宝箱: ",e.filter(p=>p.streamer_id===v.id).length]}),l.jsxs("span",{children:["总余额: ¥",v.balance.toLocaleString()]})]})]},v.id)})})]}),l.jsxs("div",{className:"streamers-section",children:[l.jsx("h2",{className:"section-title",children:"🎁 活跃宝箱"}),e.length===0?l.jsxs("div",{className:"empty-state",children:[l.jsx("div",{className:"empty-icon",children:"📦"}),l.jsx("h3",{children:"暂无活跃宝箱"}),l.jsx("p",{children:"主播还没有创建宝箱,快去邀请他们吧!"})]}):l.jsx("div",{className:"chests-grid grid grid-2",children:e.map(v=>l.jsx(ow,{chest:v},v.id))})]})]})},Me=({children:e,title:t,className:n=""})=>l.jsxs("div",{className:`card ${n}`,children:[t&&l.jsx("div",{className:"card-header",children:l.jsx("h2",{className:"card-title",children:t})}),e]}),aw=()=>{const{id:e}=ry(),{user:t,token:n,refreshUser:r}=rn(),s=nn(),i=` - .user-bet-amount { - font-size: 1rem; - color: var(--warning-color); - font-weight: 600; - margin-top: 0.5rem; - padding: 0.3rem 0.8rem; - background: rgba(245, 158, 11, 0.1); - border-radius: 1rem; - display: inline-block; - } - - .user-total-bet { - color: var(--warning-color); - font-weight: 600; - font-size: 1rem; - margin-top: 0.5rem; - padding: 0.3rem 0.8rem; - background: rgba(245, 158, 11, 0.1); - border-radius: 1rem; - display: inline-block; - } - `,[o,a]=x.useState(null),[u,c]=x.useState([]),[d,f]=x.useState(!0),[g,S]=x.useState(""),[y,v]=x.useState(""),[w,p]=x.useState(null),[h,m]=x.useState(!1);x.useEffect(()=>{e&&N()},[e]),x.useEffect(()=>{if(n&&t)return Sr.onMessage(V=>{V.type==="pool_update"&&V.chest_id===Number(e)&&a(xe=>xe?{...xe,pool_a:V.pool_a,pool_b:V.pool_b,total_bets:V.total_bets}:null)})},[n,t,e]);const N=async()=>{try{f(!0);const F=await Ut.getChest(Number(e));a(F);const V=await Ut.getChestBets(Number(e));c(V)}catch(F){S("加载宝箱详情失败"),console.error(F)}finally{f(!1)}},C=async()=>{var V,xe;if(!w||!y||!t)return;const F=parseInt(y);if(isNaN(F)||F<=0){S("请输入有效的下注金额");return}if(F>t.balance){S("余额不足");return}try{m(!0),S(""),await Ut.placeBet({chest_id:Number(e),option:w,amount:F}),await N(),await r(),v(""),p(null),alert("下注成功!")}catch(W){S(((xe=(V=W.response)==null?void 0:V.data)==null?void 0:xe.detail)||"下注失败")}finally{m(!1)}},P=F=>{switch(F){case 0:return"下注中";case 1:return"已封盘";case 2:return"结算中";case 3:return"已结束";case 4:return"已退款";default:return"未知"}};if(d)return l.jsx(is,{text:"加载宝箱详情中..."});if(!o)return l.jsxs("div",{className:"error-page",children:[l.jsx("h2",{children:"宝箱不存在"}),l.jsx("button",{onClick:()=>s("/"),className:"btn btn-primary",children:"返回首页"})]});const T=o.pool_a+o.pool_b,O=T>0?T*.9/o.pool_a:0,I=T>0?T*.9/o.pool_b:0,b=u.filter(F=>F.option==="A"&&F.status==="PENDING").reduce((F,V)=>F+V.amount,0),Y=u.filter(F=>F.option==="B"&&F.status==="PENDING").reduce((F,V)=>F+V.amount,0),le=b+Y;return l.jsxs("div",{className:"chest-page",children:[l.jsx("style",{children:i}),l.jsx("button",{onClick:()=>s("/"),className:"btn btn-secondary back-btn",children:"← 返回列表"}),l.jsxs("div",{className:"chest-detail",children:[l.jsxs(Me,{children:[l.jsxs("div",{className:"chest-header",children:[l.jsx("h1",{className:"chest-title",children:o.title}),l.jsx("span",{className:"status-badge",children:P(o.status)})]}),l.jsxs("div",{className:"chest-info",children:[l.jsxs("div",{className:"info-item",children:[l.jsx("span",{className:"info-label",children:"选项A:"}),l.jsx("span",{className:"info-value",children:o.option_a})]}),l.jsxs("div",{className:"info-item",children:[l.jsx("span",{className:"info-label",children:"选项B:"}),l.jsx("span",{className:"info-value",children:o.option_b})]})]}),l.jsxs("div",{className:"pool-info",children:[l.jsxs("div",{className:"pool-item",children:[l.jsx("div",{className:"pool-header",children:"A 边奖池"}),l.jsxs("div",{className:"pool-amount",children:[o.pool_a.toLocaleString()," 喵币"]}),l.jsxs("div",{className:"pool-odds",children:["赔率: ",O.toFixed(2)]})]}),l.jsx("div",{className:"vs",children:"VS"}),l.jsxs("div",{className:"pool-item",children:[l.jsx("div",{className:"pool-header",children:"B 边奖池"}),l.jsxs("div",{className:"pool-amount",children:[o.pool_b.toLocaleString()," 喵币"]}),l.jsxs("div",{className:"pool-odds",children:["赔率: ",I.toFixed(2)]})]})]}),l.jsxs("div",{className:"total-pool",children:["总奖池: ",l.jsxs("strong",{children:[T.toLocaleString()," 喵币"]})]}),o.status===0&&t&&l.jsxs("div",{className:"bet-section",children:[l.jsx("h3",{children:"我要下注"}),le>0&&l.jsxs("div",{className:"user-total-bet mb-3",children:["您在此宝箱已累计下注: ",le.toLocaleString()," 喵币"]}),g&&l.jsx("div",{className:"alert alert-danger",children:g}),l.jsxs("div",{className:"bet-options",children:[l.jsxs("button",{className:`option-btn ${w==="A"?"selected":""}`,onClick:()=>p("A"),disabled:o.status!==0,children:[l.jsx("div",{children:o.option_a}),b>0&&l.jsxs("div",{className:"user-bet-amount",children:["我的下注: ",b.toLocaleString()," 喵币"]})]}),l.jsxs("button",{className:`option-btn ${w==="B"?"selected":""}`,onClick:()=>p("B"),disabled:o.status!==0,children:[l.jsx("div",{children:o.option_b}),Y>0&&l.jsxs("div",{className:"user-bet-amount",children:["我的下注: ",Y.toLocaleString()," 喵币"]})]})]}),l.jsxs("div",{className:"bet-input-group",children:[l.jsx("label",{className:"form-label",children:"下注金额 (喵币)"}),l.jsx("input",{type:"number",className:"form-input",value:y,onChange:F=>v(F.target.value),placeholder:"请输入下注金额",min:"1",max:t==null?void 0:t.balance,disabled:o.status!==0}),l.jsxs("div",{className:"quick-amounts",children:[l.jsx("button",{onClick:()=>v("100"),children:"100"}),l.jsx("button",{onClick:()=>v("500"),children:"500"}),l.jsx("button",{onClick:()=>v("1000"),children:"1000"}),l.jsx("button",{onClick:()=>v((t==null?void 0:t.balance.toString())||"0"),children:"全押"})]})]}),l.jsx("button",{className:"btn btn-primary btn-large",onClick:C,disabled:!w||!y||h||o.status!==0,children:h?"下注中...":"确认下注"})]}),o.status!==0&&l.jsx("div",{className:"bet-closed",children:"此宝箱已停止下注"})]}),l.jsx(Me,{title:"下注记录",className:"mt-3",children:u.length===0?l.jsx("p",{className:"text-center text-secondary",children:"暂无下注记录"}):l.jsx("div",{className:"bets-list",children:u.map(F=>l.jsxs("div",{className:"bet-item",children:[l.jsxs("span",{className:"bet-option",children:["选项 ",F.option]}),l.jsxs("span",{className:"bet-amount",children:[F.amount.toLocaleString()," 喵币"]}),l.jsx("span",{className:"bet-status",children:F.status})]},F.id))})})]})]})},uw=()=>{const{user:e}=rn(),t=nn(),[n,r]=x.useState([]),[s,i]=x.useState(!0),[o,a]=x.useState(""),[u,c]=x.useState(!1),[d,f]=x.useState(""),[g,S]=x.useState(""),[y,v]=x.useState(""),[w,p]=x.useState(300),[h,m]=x.useState(!1),[N,C]=x.useState(null),[P,T]=x.useState("A"),[O,I]=x.useState(!1);x.useEffect(()=>{if(!e){t("/login");return}if(e.role.toLowerCase()!=="streamer"&&e.role.toLowerCase()!=="admin"){t("/");return}b()},[e,t]);const b=async()=>{try{i(!0);const _=await Ut.getChests(e==null?void 0:e.id,!0);r(_)}catch(_){a("加载宝箱列表失败"),console.error(_)}finally{i(!1)}},Y=async _=>{var L,D;if(_.preventDefault(),!d||!g||!y){a("请填写完整信息");return}try{m(!0),a(""),await Ut.createChest({title:d,option_a:g,option_b:y,countdown_seconds:w}),f(""),S(""),v(""),p(300),c(!1),await b(),alert("宝箱创建成功!")}catch(U){a(((D=(L=U.response)==null?void 0:L.data)==null?void 0:D.detail)||"创建宝箱失败")}finally{m(!1)}},le=async _=>{var L,D;if(confirm("确定要封盘吗?封盘后将无法再下注。"))try{await Ut.lockChest(_),await b(),alert("封盘成功!请记得设置开奖结果以完成宝箱结算。"),setTimeout(()=>{const U=document.querySelector(".btn-settle");U&&(U.scrollIntoView({behavior:"smooth",block:"center"}),U.classList.add("highlight"),setTimeout(()=>{U.classList.remove("highlight")},2e3))},500)}catch(U){alert(((D=(L=U.response)==null?void 0:L.data)==null?void 0:D.detail)||"封盘失败")}},F=async _=>{var L,D;if(_.preventDefault(),!!N)try{I(!0),await Ut.settleChest(N.id,{result:P}),C(null),await b(),alert("结算成功!")}catch(U){alert(((D=(L=U.response)==null?void 0:L.data)==null?void 0:D.detail)||"结算失败")}finally{I(!1)}},V=_=>{switch(_){case 0:return"下注中";case 1:return"已封盘";case 2:return"结算中";case 3:return"已结束";case 4:return"已退款";default:return"未知"}},xe=_=>{switch(_){case 0:return"status-betting";case 1:return"status-locked";case 3:return"status-finished";case 4:return"status-refunded";default:return""}};if(s)return l.jsx(is,{text:"加载控制台中..."});const W=n.filter(_=>_.status===0||_.status===1),he=n.filter(_=>_.status===3||_.status===4),k=W.filter(_=>_.status===1);return l.jsxs("div",{className:"streamer-console",children:[l.jsxs("div",{className:"console-header",children:[l.jsx("h1",{className:"page-title",children:"🎮 主播控制台"}),l.jsx("button",{className:"btn btn-primary",onClick:()=>c(!u),children:u?"取消创建":"+ 创建宝箱"})]}),o&&l.jsx("div",{className:"alert alert-danger",children:o}),k.length>0&&l.jsx("div",{className:"locked-chests-alert",children:l.jsxs("div",{className:"alert alert-warning",children:[l.jsx("div",{className:"alert-icon",children:"⚠️"}),l.jsxs("div",{className:"alert-content",children:[l.jsx("h3",{children:"待处理宝箱"}),l.jsxs("p",{children:["您有 ",k.length," 个宝箱已封盘,请及时设置开奖结果完成结算。"]}),l.jsx("button",{className:"btn btn-warning btn-sm",onClick:()=>{const _=document.querySelector(".status-locked");_&&_.scrollIntoView({behavior:"smooth",block:"center"})},children:"查看并处理"})]})]})}),u&&l.jsx(Me,{title:"创建新宝箱",className:"mb-3",children:l.jsxs("form",{onSubmit:Y,children:[l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",children:"标题"}),l.jsx("input",{type:"text",className:"form-input",value:d,onChange:_=>f(_.target.value),placeholder:"例如: 这把能吃鸡吗?",required:!0})]}),l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",children:"选项A"}),l.jsx("input",{type:"text",className:"form-input",value:g,onChange:_=>S(_.target.value),placeholder:"例如: 能",required:!0})]}),l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",children:"选项B"}),l.jsx("input",{type:"text",className:"form-input",value:y,onChange:_=>v(_.target.value),placeholder:"例如: 不能",required:!0})]}),l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",children:"下注时长(秒)"}),l.jsx("input",{type:"number",className:"form-input",value:w,onChange:_=>p(parseInt(_.target.value)),min:"60",max:"3600",required:!0})]}),l.jsx("button",{type:"submit",className:"btn btn-primary",disabled:h,children:h?"创建中...":"确认创建"})]})}),l.jsxs(Me,{title:"活跃宝箱",className:"mb-3",children:[l.jsx("div",{className:"mb-2",children:l.jsx("small",{className:"text-warning",children:"💡 封盘后的宝箱需要设置开奖结果才能完成结算"})}),W.length===0?l.jsx("p",{className:"text-center text-secondary",children:"暂无活跃宝箱"}):l.jsx("div",{className:"chests-list",children:W.map(_=>l.jsxs("div",{className:"chest-item",children:[l.jsxs("div",{className:"chest-info",children:[l.jsx("h3",{children:_.title}),l.jsxs("p",{children:[_.option_a," vs ",_.option_b]}),l.jsxs("div",{className:"chest-stats",children:[l.jsxs("span",{className:xe(_.status),children:["状态: ",V(_.status)]}),l.jsxs("span",{children:["奖池: ",(_.pool_a+_.pool_b).toLocaleString()," 喵币"]}),l.jsxs("span",{children:[_.total_bets," 人参与"]})]}),_.status===1&&l.jsxs("div",{className:"locked-notice",children:[l.jsx("span",{className:"locked-notice-icon",children:"⚠️"}),l.jsx("span",{className:"locked-notice-text",children:"请设置开奖结果"})]})]}),l.jsxs("div",{className:"chest-actions",children:[_.status===0&&l.jsx("button",{className:"btn btn-warning",onClick:()=>le(_.id),children:"封盘"}),_.status===1&&l.jsxs("div",{className:"actions-settle",children:[l.jsx("button",{className:"btn btn-success btn-settle",onClick:()=>C(_),children:"设置开奖结果"}),l.jsx("div",{className:"settle-hint",children:"封盘后请设置开奖结果"})]})]})]},_.id))})]}),l.jsx(Me,{title:"历史宝箱",children:he.length===0?l.jsx("p",{className:"text-center text-secondary",children:"暂无历史记录"}):l.jsx("div",{className:"chests-list",children:he.map(_=>l.jsx("div",{className:"chest-item finished",children:l.jsxs("div",{className:"chest-info",children:[l.jsx("h3",{children:_.title}),l.jsxs("p",{children:[_.option_a," vs ",_.option_b]}),l.jsxs("div",{className:"chest-stats",children:[l.jsxs("span",{children:["状态: ",V(_.status)]}),_.result&&l.jsxs("span",{children:["结果: 选项",_.result]})]})]})},_.id))})}),N&&l.jsx("div",{className:"modal-overlay",onClick:()=>C(null),children:l.jsxs("div",{className:"modal",onClick:_=>_.stopPropagation(),children:[l.jsx("h2",{children:"结算宝箱"}),l.jsx("p",{className:"modal-chest-title",children:N.title}),l.jsxs("p",{children:[N.option_a," vs ",N.option_b]}),l.jsxs("form",{onSubmit:F,children:[l.jsxs("div",{className:"form-group",children:[l.jsx("p",{className:"mb-2",children:"请选择实际的比赛结果:"}),l.jsxs("div",{className:"radio-group",children:[l.jsxs("label",{className:"radio-label",children:[l.jsx("input",{type:"radio",name:"settleResult",value:"A",checked:P==="A",onChange:_=>T(_.target.value)}),l.jsxs("span",{className:"radio-text",children:["选项A: ",N.option_a]})]}),l.jsxs("label",{className:"radio-label",children:[l.jsx("input",{type:"radio",name:"settleResult",value:"B",checked:P==="B",onChange:_=>T(_.target.value)}),l.jsxs("span",{className:"radio-text",children:["选项B: ",N.option_b]})]}),l.jsxs("label",{className:"radio-label",children:[l.jsx("input",{type:"radio",name:"settleResult",value:"REFUND",checked:P==="REFUND",onChange:_=>T(_.target.value)}),l.jsx("span",{className:"radio-text",children:"流局退款"})]})]}),l.jsx("p",{className:"mt-2 small text-warning",children:"⚠️ 注意:选择后将立即结算,用户的奖金将自动发放"})]}),l.jsxs("div",{className:"modal-actions",children:[l.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>C(null),children:"取消"}),l.jsx("button",{type:"submit",className:"btn btn-success",disabled:O,children:O?"结算中...":"确认结算"})]})]})]})})]})},cw=()=>{const{user:e,refreshUser:t}=rn(),[n,r]=x.useState([]),[s,i]=x.useState([]),[o,a]=x.useState(!0),[u,c]=x.useState(!1),[d,f]=x.useState(null),[g,S]=x.useState({total_bets:0,total_winnings:0,win_rate:0}),[y,v]=x.useState(!1),[w,p]=x.useState(""),[h,m]=x.useState(""),[N,C]=x.useState(""),[P,T]=x.useState(!1),[O,I]=x.useState("");x.useEffect(()=>{b()},[]),x.useEffect(()=>{e&&b()},[e]);const b=async()=>{try{a(!0);const[k,_,L]=await Promise.all([pr.getMyTransactions(50),pr.getRichRanking(10),pr.getAllowanceInfo()]);r(k),i(_),f(L);const D=k.filter(Ce=>Ce.type==="BET"),U=k.filter(Ce=>Ce.type==="WIN"),ge=D.length,Se=U.reduce((Ce,et)=>Ce+et.amount,0),Ue=ge>0?U.length/ge*100:0;S({total_bets:ge,total_winnings:Se,win_rate:Ue})}catch(k){console.error("Failed to load data:",k)}finally{a(!1)}},Y=async()=>{var k,_;try{c(!0);const L=await pr.claimAllowance();alert(`领取成功!获得50喵币,当前余额: ${L.balance.toLocaleString()}`),await t(),await b()}catch(L){alert(((_=(k=L.response)==null?void 0:k.data)==null?void 0:_.detail)||"领取失败")}finally{c(!1)}},le=k=>{switch(k){case"BET":return"下注";case"WIN":return"获胜奖励";case"ALLOWANCE":return"低保";case"ADMIN_ADJUST":return"管理员调整";case"STREAMER_REVENUE":return"主播分润";case"PLATFORM_REVENUE":return"平台抽水";case"REGISTER":return"新用户注册奖励";default:return k}},F=k=>{switch(k){case"admin":return"管理员";case"streamer":return"主播";case"user":return"普通用户";default:return k}},V=k=>new Date(k).toLocaleString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}),xe=async k=>{var _,L;if(k.preventDefault(),I(""),!w){I("请输入当前密码");return}if(!h){I("请输入新密码");return}if(h.length<6){I("新密码长度不能少于6位");return}if(h.length>72){I("新密码长度不能超过72个字符");return}if(h!==N){I("两次输入的新密码不一致");return}if(w===h){I("新密码不能与当前密码相同");return}try{T(!0),await pr.changePassword(w,h),alert("密码修改成功"),v(!1),p(""),m(""),C("")}catch(D){I(((L=(_=D.response)==null?void 0:_.data)==null?void 0:L.detail)||"密码修改失败")}finally{T(!1)}},W=()=>{v(!0),I(""),p(""),m(""),C("")},he=()=>{v(!1),p(""),m(""),C(""),I("")};return o?l.jsx(is,{text:"加载用户信息中..."}):l.jsx("div",{className:"user-profile",children:l.jsxs("div",{className:"profile-container",children:[l.jsxs("div",{className:"profile-card",children:[l.jsx("div",{className:"user-avatar-large",children:e==null?void 0:e.username.charAt(0).toUpperCase()}),l.jsx("div",{className:"user-name-large",children:(e==null?void 0:e.nickname)||(e==null?void 0:e.username)}),l.jsx("div",{className:"user-role-text",children:F((e==null?void 0:e.role)||"")}),l.jsxs("div",{className:"balance-card",children:[l.jsx("div",{className:"balance-label",children:"当前余额"}),l.jsxs("div",{className:"balance-value-large",children:["¥",e==null?void 0:e.balance.toLocaleString()]})]}),e&&e.balance<1e3&&l.jsxs("div",{className:"allowance-card",children:[l.jsxs("div",{className:"allowance-header",children:[l.jsx("span",{className:"allowance-icon",children:"💰"}),l.jsx("span",{className:"allowance-title",children:"每日低保"})]}),d!=null&&d.can_claim?l.jsx("button",{className:"action-btn allowance-claim-btn",onClick:Y,disabled:u,children:l.jsx("div",{children:u?"领取中...":"立即领取"})}):l.jsxs("div",{className:"allowance-countdown",children:[l.jsx("div",{className:"countdown-label",children:"下次可领取:"}),l.jsx("div",{className:"countdown-time",children:d==null?void 0:d.formatted_time_left})]}),l.jsx("div",{className:"allowance-note",children:"系统每天凌晨自动发放低保,无需手动领取"})]}),l.jsxs("div",{className:"quick-actions",children:[l.jsxs("div",{className:"action-btn",children:[l.jsx("div",{className:"action-btn-icon",children:"📝"}),l.jsx("div",{children:"交易记录"})]}),l.jsxs("div",{className:"action-btn",children:[l.jsx("div",{className:"action-btn-icon",children:"🎤"}),l.jsx("div",{children:"成为主播"})]}),l.jsxs("div",{className:"action-btn",onClick:W,children:[l.jsx("div",{className:"action-btn-icon",children:"⚙️"}),l.jsx("div",{children:"设置"})]})]})]}),l.jsxs("div",{children:[l.jsxs("div",{className:"stats-grid-enhanced",children:[l.jsxs("div",{className:"stat-card-enhanced",children:[l.jsx("div",{className:"stat-label-enhanced",children:"总下注次数"}),l.jsx("div",{className:"stat-value-enhanced",children:g.total_bets})]}),l.jsxs("div",{className:"stat-card-enhanced",children:[l.jsx("div",{className:"stat-label-enhanced",children:"总获奖金额"}),l.jsxs("div",{className:"stat-value-enhanced",children:["¥",g.total_winnings.toLocaleString()]})]}),l.jsxs("div",{className:"stat-card-enhanced",children:[l.jsx("div",{className:"stat-label-enhanced",children:"胜率"}),l.jsxs("div",{className:"stat-value-enhanced",children:[g.win_rate.toFixed(1),"%"]})]})]}),l.jsxs("div",{className:"transactions-section",children:[l.jsx("h3",{style:{marginBottom:16},children:"最近交易"}),n.length===0?l.jsx("p",{className:"text-center text-secondary",children:"暂无交易记录"}):l.jsx("div",{className:"transaction-list-enhanced",children:n.slice(0,10).map(k=>l.jsxs("div",{className:"transaction-item-enhanced",children:[l.jsxs("div",{className:"transaction-info-enhanced",children:[l.jsx("h5",{children:le(k.type)}),l.jsx("p",{children:k.description?k.description:V(k.created_at)})]}),l.jsxs("div",{className:`transaction-amount-enhanced ${k.amount>0?"amount-positive":"amount-negative"}`,children:[k.amount>0?"+":"","¥",Math.abs(k.amount).toLocaleString()]})]},k.id))}),n.length>10&&l.jsx("div",{style:{textAlign:"center",marginTop:16},children:l.jsx("button",{className:"btn btn-primary",children:"查看更多"})})]}),l.jsxs("div",{className:"transactions-section",children:[l.jsx("h3",{style:{marginBottom:16},children:"💎 富豪榜"}),s.length===0?l.jsx("p",{className:"text-center text-secondary",children:"暂无排行数据"}):l.jsx("div",{className:"ranking-list",children:s.map((k,_)=>l.jsxs("div",{className:`ranking-item ${k.id===(e==null?void 0:e.id)?"current-user":""}`,children:[l.jsx("span",{className:"ranking-position",children:_+1}),l.jsxs("span",{className:"ranking-username",children:[k.nickname||k.username,k.id===(e==null?void 0:e.id)&&" (我)"]}),l.jsxs("span",{className:"ranking-balance",children:["¥",k.balance.toLocaleString()]})]},k.id))})]})]}),y&&l.jsx("div",{className:"modal-overlay",onClick:he,children:l.jsxs("div",{className:"modal",onClick:k=>k.stopPropagation(),children:[l.jsx("h2",{children:"修改密码"}),l.jsxs("form",{onSubmit:xe,children:[l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",children:"当前密码"}),l.jsx("input",{type:"password",className:"form-input",value:w,onChange:k=>p(k.target.value),placeholder:"请输入当前密码",required:!0})]}),l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",children:"新密码"}),l.jsx("input",{type:"password",className:"form-input",value:h,onChange:k=>m(k.target.value),placeholder:"请输入新密码(6-72个字符)",required:!0}),l.jsx("small",{className:"form-text text-muted",children:"密码长度应在6-72个字符之间"})]}),l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",children:"确认新密码"}),l.jsx("input",{type:"password",className:"form-input",value:N,onChange:k=>C(k.target.value),placeholder:"请再次输入新密码",required:!0})]}),O&&l.jsx("div",{className:"alert alert-danger",style:{marginBottom:"16px"},children:O}),l.jsxs("div",{className:"modal-actions",children:[l.jsx("button",{type:"button",className:"btn btn-secondary",onClick:he,disabled:P,children:"取消"}),l.jsx("button",{type:"submit",className:"btn btn-primary",disabled:P,children:P?"修改中...":"确认修改"})]})]})]})})]})})},dw=()=>{const{user:e}=rn(),t=nn(),[n,r]=x.useState("dashboard"),[s,i]=x.useState(!0),[o,a]=x.useState([]),[u,c]=x.useState([]),[d,f]=x.useState([]),[g,S]=x.useState([]),[y,v]=x.useState(null),[w,p]=x.useState(null),[h,m]=x.useState(null),[N,C]=x.useState(null),[P,T]=x.useState(""),[O,I]=x.useState(""),[b,Y]=x.useState(""),[le,F]=x.useState(""),[V,xe]=x.useState(""),[W,he]=x.useState({config_key:"",config_value:"",config_type:"STRING",description:""}),[k,_]=x.useState({title:"",content:"",type:"INFO",is_pinned:!1,priority:0}),[L,D]=x.useState(null),[U,ge]=x.useState("");x.useEffect(()=>{if(!e||e.role.toLowerCase()!=="admin"){t("/");return}Se()},[e,t]);const Se=async()=>{try{i(!0),await Promise.all([Ue(),Ce(),et(),$i()])}catch(j){console.error("Failed to load data:",j)}finally{i(!1)}},Ue=async()=>{try{const j=await Eo.getUsers({search:b,role:le,status:V});a(j)}catch(j){console.error("Failed to load users:",j)}},Ce=async()=>{try{const j=await Tc.getStreamers({});c(j)}catch(j){console.error("Failed to load streamers:",j)}},et=async()=>{try{const j=await ks.getConfigs();f(j)}catch(j){console.error("Failed to load configs:",j)}},$i=async()=>{try{const j=await ko.getAnnouncements({});S(j)}catch(j){console.error("Failed to load announcements:",j)}},$h=async j=>{var Z,ae;if(j.preventDefault(),!y||!P)return;const q=parseInt(P);if(isNaN(q)||q===0){alert("请输入有效的调整金额");return}try{const sn=await Eo.adjustBalance(y.id,q,O||"管理员调整");alert("调整成功!新余额: "+sn.new_balance.toLocaleString()),v(null),T(""),I(""),await Ue()}catch(sn){alert(((ae=(Z=sn.response)==null?void 0:Z.data)==null?void 0:ae.detail)||"调整失败")}},Vh=async j=>{var q,Z;j.preventDefault();try{await ks.createConfig(W),alert("配置创建成功"),he({config_key:"",config_value:"",config_type:"STRING",description:""}),await et()}catch(ae){alert(((Z=(q=ae.response)==null?void 0:q.data)==null?void 0:Z.detail)||"创建失败")}},Hh=async j=>{var q,Z;if(window.confirm("确定要删除这个配置吗?"))try{await ks.deleteConfig(j),alert("配置删除成功"),await et()}catch(ae){alert(((Z=(q=ae.response)==null?void 0:q.data)==null?void 0:Z.detail)||"删除失败")}},Ha=async(j,q)=>{var Z,ae;try{await ks.updateConfig(j,{config_value:q}),alert("配置更新成功"),D(null),ge(""),await et()}catch(sn){alert(((ae=(Z=sn.response)==null?void 0:Z.data)==null?void 0:ae.detail)||"更新失败")}},Wh=(j,q)=>{D(j),ge(q)},Wa=()=>{D(null),ge("")},qh=async j=>{var q,Z;j.preventDefault();try{await ko.createAnnouncement(k),alert("公告发布成功"),_({title:"",content:"",type:"INFO",is_pinned:!1,priority:0}),await $i()}catch(ae){alert(((Z=(q=ae.response)==null?void 0:q.data)==null?void 0:Z.detail)||"发布失败")}},Kh=async j=>{var q,Z;if(window.confirm("确定要删除这个公告吗?"))try{await ko.deleteAnnouncement(j),alert("公告删除成功"),await $i()}catch(ae){alert(((Z=(q=ae.response)==null?void 0:q.data)==null?void 0:Z.detail)||"删除失败")}},Qh=async j=>{var q,Z;try{const ae=await Tc.getStreamerStatistics(j);m(ae)}catch(ae){alert(((Z=(q=ae.response)==null?void 0:q.data)==null?void 0:Z.detail)||"加载统计失败")}},Vi=async(j,q)=>{var Z,ae;try{await Eo.setUserRole(j,q.toUpperCase()),q.toUpperCase()==="STREAMER"?alert("用户身份设置成功。请注意:还需要为主播用户创建主播配置才能正常使用主播功能。"):alert("用户身份设置成功"),C(null),await Ue()}catch(sn){alert(((ae=(Z=sn.response)==null?void 0:Z.data)==null?void 0:ae.detail)||"设置失败")}},qa=j=>{switch(j){case"admin":return"管理员";case"streamer":return"主播";case"user":return"用户";default:return j}},Ka=j=>{switch(j){case"ACTIVE":return"正常";case"DISABLED":return"禁用";case"BANNED":return"封禁";default:return j||""}},Qa=j=>{switch(j){case"ACTIVE":return"badge-success";case"DISABLED":return"badge-warning";case"BANNED":return"badge-error";default:return"badge-info"}},Jh=j=>{switch(j){case"INFO":return"信息";case"WARNING":return"警告";case"PRIZE":return"奖品";default:return j}};return s?l.jsx(is,{text:"加载管理面板中..."}):l.jsxs("div",{className:"admin-panel",children:[l.jsxs("div",{className:"panel-header",children:[l.jsx("h1",{className:"page-title",children:"🛠️ 管理后台"}),l.jsxs("div",{className:"tabs",children:[l.jsx("button",{className:`tab ${n==="dashboard"?"active":""}`,onClick:()=>r("dashboard"),children:"数据概览"}),l.jsx("button",{className:`tab ${n==="users"?"active":""}`,onClick:()=>r("users"),children:"用户管理"}),l.jsx("button",{className:`tab ${n==="streamers"?"active":""}`,onClick:()=>r("streamers"),children:"主播管理"}),l.jsx("button",{className:`tab ${n==="system"?"active":""}`,onClick:()=>r("system"),children:"系统设置"}),l.jsx("button",{className:`tab ${n==="announcements"?"active":""}`,onClick:()=>r("announcements"),children:"公告管理"})]})]}),n==="dashboard"&&l.jsxs("div",{className:"dashboard-grid",children:[l.jsxs(Me,{children:[l.jsx("h3",{children:"用户统计"}),l.jsx("div",{className:"stat-value",children:o.length}),l.jsx("p",{children:"总用户数"})]}),l.jsxs(Me,{children:[l.jsx("h3",{children:"主播统计"}),l.jsx("div",{className:"stat-value",children:u.length}),l.jsx("p",{children:"总主播数"})]}),l.jsxs(Me,{children:[l.jsx("h3",{children:"配置统计"}),l.jsx("div",{className:"stat-value",children:d.length}),l.jsx("p",{children:"系统配置项"})]}),l.jsxs(Me,{children:[l.jsx("h3",{children:"公告统计"}),l.jsx("div",{className:"stat-value",children:g.length}),l.jsx("p",{children:"活跃公告"})]})]}),n==="users"&&l.jsxs(Me,{title:"用户管理",children:[l.jsxs("div",{className:"filters",children:[l.jsx("input",{type:"text",placeholder:"搜索用户名/邮箱/昵称",value:b,onChange:j=>Y(j.target.value),className:"form-input"}),l.jsxs("select",{value:le,onChange:j=>F(j.target.value),className:"form-select",children:[l.jsx("option",{value:"",children:"全部角色"}),l.jsx("option",{value:"USER",children:"普通用户"}),l.jsx("option",{value:"STREAMER",children:"主播"}),l.jsx("option",{value:"ADMIN",children:"管理员"})]}),l.jsxs("select",{value:V,onChange:j=>xe(j.target.value),className:"form-select",children:[l.jsx("option",{value:"",children:"全部状态"}),l.jsx("option",{value:"ACTIVE",children:"正常"}),l.jsx("option",{value:"DISABLED",children:"禁用"}),l.jsx("option",{value:"BANNED",children:"封禁"})]}),l.jsx("button",{className:"btn btn-primary",onClick:Ue,children:"搜索"})]}),l.jsx("div",{className:"table-container",children:l.jsxs("table",{className:"table",children:[l.jsx("thead",{children:l.jsxs("tr",{children:[l.jsx("th",{children:"ID"}),l.jsx("th",{children:"用户名"}),l.jsx("th",{children:"邮箱"}),l.jsx("th",{children:"角色"}),l.jsx("th",{children:"状态"}),l.jsx("th",{children:"余额"}),l.jsx("th",{children:"登录次数"}),l.jsx("th",{children:"操作"})]})}),l.jsx("tbody",{children:o.map(j=>l.jsxs("tr",{children:[l.jsx("td",{children:j.id}),l.jsx("td",{children:j.username}),l.jsx("td",{children:j.email}),l.jsx("td",{children:qa(j.role)}),l.jsx("td",{children:l.jsx("span",{className:`badge ${Qa(j.status||"")}`,children:Ka(j.status||"")})}),l.jsx("td",{children:j.balance.toLocaleString()}),l.jsx("td",{children:j.login_count}),l.jsxs("td",{children:[l.jsx("button",{className:"btn btn-sm btn-primary",onClick:()=>v(j),style:{marginRight:"5px"},children:"调整余额"}),l.jsx("button",{className:"btn btn-sm btn-secondary",onClick:()=>C(j),children:"设置身份"})]})]},j.id))})]})})]}),n==="streamers"&&l.jsx(Me,{title:"主播管理",children:l.jsx("div",{className:"table-container",children:l.jsxs("table",{className:"table",children:[l.jsx("thead",{children:l.jsxs("tr",{children:[l.jsx("th",{children:"ID"}),l.jsx("th",{children:"主播名称"}),l.jsx("th",{children:"抽成比例"}),l.jsx("th",{children:"宝箱数量"}),l.jsx("th",{children:"总收益"}),l.jsx("th",{children:"状态"}),l.jsx("th",{children:"操作"})]})}),l.jsx("tbody",{children:u.map(j=>l.jsxs("tr",{children:[l.jsx("td",{children:j.id}),l.jsx("td",{children:j.display_name||j.user_id}),l.jsxs("td",{children:[j.commission_rate,"%"]}),l.jsxs("td",{children:[j.total_chests||0,"/",j.max_active_chests]}),l.jsx("td",{children:j.total_winnings.toLocaleString()}),l.jsx("td",{children:l.jsx("span",{className:`badge ${Qa(j.status)}`,children:Ka(j.status)})}),l.jsx("td",{children:l.jsx("button",{className:"btn btn-sm btn-primary",onClick:()=>{p(j),Qh(j.id)},children:"查看统计"})})]},j.id))})]})})}),n==="system"&&l.jsxs(Me,{title:"系统设置",children:[l.jsx("div",{className:"table-container",children:l.jsxs("table",{className:"table",children:[l.jsx("thead",{children:l.jsxs("tr",{children:[l.jsx("th",{children:"配置键"}),l.jsx("th",{children:"配置值"}),l.jsx("th",{children:"类型"}),l.jsx("th",{children:"描述"}),l.jsx("th",{children:"操作"})]})}),l.jsx("tbody",{children:d.map(j=>l.jsxs("tr",{children:[l.jsx("td",{children:j.config_key}),l.jsx("td",{children:L===j.config_key?l.jsxs("div",{style:{display:"flex",gap:"5px",alignItems:"center"},children:[l.jsx("input",{type:"text",className:"form-input",style:{width:"200px"},value:U,onChange:q=>ge(q.target.value),onKeyDown:q=>{q.key==="Enter"?Ha(j.config_key,U):q.key==="Escape"&&Wa()},autoFocus:!0}),l.jsx("button",{className:"btn btn-sm btn-success",onClick:()=>Ha(j.config_key,U),children:"✓"}),l.jsx("button",{className:"btn btn-sm btn-secondary",onClick:Wa,children:"✕"})]}):l.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"10px"},children:[l.jsx("span",{children:j.config_value}),l.jsx("button",{className:"btn btn-sm btn-primary",onClick:()=>Wh(j.config_key,j.config_value),children:"编辑"})]})}),l.jsx("td",{children:j.config_type}),l.jsx("td",{children:j.description}),l.jsx("td",{children:l.jsx("button",{className:"btn btn-sm btn-danger",onClick:()=>Hh(j.config_key),children:"删除"})})]},j.id))})]})}),l.jsxs("div",{className:"mt-4",children:[l.jsx("h3",{children:"添加新配置"}),l.jsxs("form",{onSubmit:Vh,className:"form-grid",children:[l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",children:"配置键"}),l.jsx("input",{type:"text",className:"form-input",value:W.config_key,onChange:j=>he({...W,config_key:j.target.value}),required:!0})]}),l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",children:"配置值"}),l.jsx("input",{type:"text",className:"form-input",value:W.config_value,onChange:j=>he({...W,config_value:j.target.value}),required:!0})]}),l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",children:"类型"}),l.jsxs("select",{className:"form-select",value:W.config_type,onChange:j=>he({...W,config_type:j.target.value}),children:[l.jsx("option",{value:"STRING",children:"字符串"}),l.jsx("option",{value:"NUMBER",children:"数字"}),l.jsx("option",{value:"BOOLEAN",children:"布尔"}),l.jsx("option",{value:"JSON",children:"JSON"})]})]}),l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",children:"描述"}),l.jsx("input",{type:"text",className:"form-input",value:W.description,onChange:j=>he({...W,description:j.target.value})})]}),l.jsx("div",{className:"form-group full-width",children:l.jsx("button",{type:"submit",className:"btn btn-primary",children:"创建配置"})})]})]})]}),n==="announcements"&&l.jsxs(Me,{title:"公告管理",children:[l.jsx("div",{className:"table-container",children:l.jsxs("table",{className:"table",children:[l.jsx("thead",{children:l.jsxs("tr",{children:[l.jsx("th",{children:"ID"}),l.jsx("th",{children:"标题"}),l.jsx("th",{children:"类型"}),l.jsx("th",{children:"优先级"}),l.jsx("th",{children:"是否置顶"}),l.jsx("th",{children:"过期时间"}),l.jsx("th",{children:"操作"})]})}),l.jsx("tbody",{children:g.map(j=>l.jsxs("tr",{children:[l.jsx("td",{children:j.id}),l.jsx("td",{children:j.title}),l.jsx("td",{children:Jh(j.type)}),l.jsx("td",{children:j.priority}),l.jsx("td",{children:j.is_pinned?"是":"否"}),l.jsx("td",{children:j.expires_at||"-"}),l.jsx("td",{children:l.jsx("button",{className:"btn btn-sm btn-danger",onClick:()=>Kh(j.id),children:"删除"})})]},j.id))})]})}),l.jsxs("div",{className:"mt-4",children:[l.jsx("h3",{children:"发布新公告"}),l.jsxs("form",{onSubmit:qh,className:"form-grid",children:[l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",children:"标题"}),l.jsx("input",{type:"text",className:"form-input",value:k.title,onChange:j=>_({...k,title:j.target.value}),required:!0})]}),l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",children:"类型"}),l.jsxs("select",{className:"form-select",value:k.type,onChange:j=>_({...k,type:j.target.value}),children:[l.jsx("option",{value:"INFO",children:"信息"}),l.jsx("option",{value:"WARNING",children:"警告"}),l.jsx("option",{value:"PRIZE",children:"奖品"})]})]}),l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",children:"优先级"}),l.jsx("input",{type:"number",className:"form-input",value:k.priority,onChange:j=>_({...k,priority:parseInt(j.target.value)})})]}),l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",children:"是否置顶"}),l.jsx("input",{type:"checkbox",checked:k.is_pinned,onChange:j=>_({...k,is_pinned:j.target.checked})})]}),l.jsxs("div",{className:"form-group full-width",children:[l.jsx("label",{className:"form-label",children:"内容"}),l.jsx("textarea",{className:"form-input",rows:4,value:k.content,onChange:j=>_({...k,content:j.target.value}),required:!0})]}),l.jsx("div",{className:"form-group full-width",children:l.jsx("button",{type:"submit",className:"btn btn-primary",children:"发布公告"})})]})]})]}),y&&l.jsx("div",{className:"modal-overlay",onClick:()=>v(null),children:l.jsxs("div",{className:"modal",onClick:j=>j.stopPropagation(),children:[l.jsx("h2",{children:"调整用户余额"}),l.jsxs("div",{className:"modal-user-info",children:[l.jsxs("p",{children:["用户: ",l.jsx("strong",{children:y.username})]}),l.jsxs("p",{children:["当前余额: ",l.jsx("strong",{children:y.balance.toLocaleString()})," 喵币"]})]}),l.jsxs("form",{onSubmit:$h,children:[l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",children:"调整金额(正数为增加,负数为减少)"}),l.jsx("input",{type:"number",className:"form-input",value:P,onChange:j=>T(j.target.value),placeholder:"例如: 1000 或 -500",required:!0})]}),l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",children:"调整原因"}),l.jsx("input",{type:"text",className:"form-input",value:O,onChange:j=>I(j.target.value),placeholder:"请输入调整原因"})]}),l.jsxs("div",{className:"modal-actions",children:[l.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>v(null),children:"取消"}),l.jsx("button",{type:"submit",className:"btn btn-success",children:"确认调整"})]})]})]})}),N&&l.jsx("div",{className:"modal-overlay",onClick:()=>C(null),children:l.jsxs("div",{className:"modal",onClick:j=>j.stopPropagation(),children:[l.jsx("h2",{children:"设置用户身份"}),l.jsxs("div",{className:"modal-user-info",children:[l.jsxs("p",{children:["用户: ",l.jsx("strong",{children:N.username})]}),l.jsxs("p",{children:["当前身份: ",l.jsx("strong",{children:qa(N.role)})]})]}),l.jsxs("div",{className:"form-group",children:[l.jsx("label",{className:"form-label",children:"选择新身份:"}),l.jsxs("div",{style:{marginTop:"10px"},children:[l.jsx("button",{className:"btn btn-sm btn-primary",style:{marginRight:"10px"},onClick:()=>Vi(N.id,"USER"),children:"普通用户"}),l.jsx("button",{className:"btn btn-sm btn-warning",style:{marginRight:"10px"},onClick:()=>Vi(N.id,"STREAMER"),children:"主播"}),l.jsx("button",{className:"btn btn-sm btn-error",onClick:()=>Vi(N.id,"ADMIN"),children:"管理员"})]})]}),l.jsx("div",{className:"modal-actions",children:l.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>C(null),children:"取消"})})]})}),w&&h&&l.jsx("div",{className:"modal-overlay",onClick:()=>p(null),children:l.jsxs("div",{className:"modal",onClick:j=>j.stopPropagation(),children:[l.jsx("h2",{children:"主播统计"}),l.jsxs("div",{className:"stats-grid",children:[l.jsxs("div",{className:"stat-card",children:[l.jsx("h4",{children:"宝箱总数"}),l.jsx("div",{className:"stat-value",children:h.total_chests})]}),l.jsxs("div",{className:"stat-card",children:[l.jsx("h4",{children:"活跃宝箱"}),l.jsx("div",{className:"stat-value",children:h.active_chests})]}),l.jsxs("div",{className:"stat-card",children:[l.jsx("h4",{children:"总收益"}),l.jsx("div",{className:"stat-value",children:h.total_winnings.toLocaleString()})]}),l.jsxs("div",{className:"stat-card",children:[l.jsx("h4",{children:"抽成收益"}),l.jsx("div",{className:"stat-value",children:h.total_commission.toLocaleString()})]}),l.jsxs("div",{className:"stat-card",children:[l.jsx("h4",{children:"平均宝箱价值"}),l.jsx("div",{className:"stat-value",children:h.average_chest_value.toLocaleString()})]}),l.jsxs("div",{className:"stat-card",children:[l.jsx("h4",{children:"成功率"}),l.jsxs("div",{className:"stat-value",children:[(h.success_rate*100).toFixed(1),"%"]})]})]}),l.jsx("div",{className:"modal-actions",children:l.jsx("button",{type:"button",className:"btn btn-primary",onClick:()=>p(null),children:"关闭"})})]})})]})},fw=()=>{const{user:e,logout:t}=rn(),n=nn(),r=tr(),s=()=>{t(),n("/login")},i=o=>r.pathname===o;return l.jsx("header",{className:"header",children:l.jsxs("div",{className:"header-container",children:[l.jsx(rt,{to:"/",className:"logo",children:l.jsx("h1",{children:"🎯 开宝箱"})}),l.jsxs("nav",{className:"nav",children:[l.jsx(rt,{to:"/",className:`nav-link ${i("/")?"active":""}`,children:"首页"}),e?l.jsxs(l.Fragment,{children:[l.jsx(rt,{to:"/profile",className:`nav-link ${i("/profile")?"active":""}`,children:"我的"}),l.jsx(rt,{to:"/profile",className:"nav-link",children:l.jsxs("span",{className:"user-balance",children:["💰 ",e.balance.toLocaleString()," 喵币"]})}),e.role.toLowerCase()==="streamer"&&l.jsx(rt,{to:"/streamer",className:`nav-link ${i("/streamer")?"active":""}`,children:"主播控制台"}),e.role.toLowerCase()==="admin"&&l.jsx(rt,{to:"/admin",className:`nav-link ${i("/admin")?"active":""}`,children:"管理后台"}),l.jsxs("div",{className:"user-menu",children:[l.jsx("span",{className:"user-name",children:e.nickname||e.username}),l.jsx("button",{onClick:s,className:"btn btn-secondary",children:"退出"})]})]}):l.jsxs(l.Fragment,{children:[l.jsx(rt,{to:"/login",className:"btn btn-primary",children:"登录"}),l.jsx(rt,{to:"/register",className:"btn btn-secondary",children:"注册"})]})]})]})})},Ro=({children:e,requiredRole:t})=>{const{user:n,loading:r}=rn();return r?null:n?t&&n.role.toLowerCase()!==t.toLowerCase()?l.jsx(El,{to:"/",replace:!0}):l.jsx(l.Fragment,{children:e}):l.jsx(El,{to:"/login",replace:!0})};function hw(){return l.jsx(rw,{children:l.jsx(jy,{children:l.jsxs("div",{className:"app",children:[l.jsx(fw,{}),l.jsx("main",{className:"main-content",children:l.jsxs(wy,{children:[l.jsx(wt,{path:"/",element:l.jsx(lw,{})}),l.jsx(wt,{path:"/login",element:l.jsx(sw,{})}),l.jsx(wt,{path:"/register",element:l.jsx(iw,{})}),l.jsx(wt,{path:"/chests/:id",element:l.jsx(aw,{})}),l.jsx(wt,{path:"/streamer",element:l.jsx(Ro,{requiredRole:"streamer",children:l.jsx(uw,{})})}),l.jsx(wt,{path:"/profile",element:l.jsx(Ro,{children:l.jsx(cw,{})})}),l.jsx(wt,{path:"/admin",element:l.jsx(Ro,{requiredRole:"admin",children:l.jsx(dw,{})})}),l.jsx(wt,{path:"*",element:l.jsx(El,{to:"/",replace:!0})})]})})]})})})}To.createRoot(document.getElementById("root")).render(l.jsx(Wc.StrictMode,{children:l.jsx(hw,{})})); diff --git a/frontend/dist/index.html b/frontend/dist/index.html index 2a710f2..3687c8e 100644 --- a/frontend/dist/index.html +++ b/frontend/dist/index.html @@ -5,8 +5,8 @@ 互动竞猜开宝箱系统 - - + +
diff --git a/frontend/src/pages/HomePage.tsx b/frontend/src/pages/HomePage.tsx index 5c5f64d..65e1d2e 100644 --- a/frontend/src/pages/HomePage.tsx +++ b/frontend/src/pages/HomePage.tsx @@ -1,14 +1,13 @@ import { useState, useEffect } from 'react'; -import { gameApi, announcementApi, streamerApi } from '../services/api'; +import { gameApi, announcementApi } from '../services/api'; import { websocketService } from '../services/websocket'; import ChestCard from '../components/ChestCard'; import Loading from '../components/Loading'; -import type { Chest, Announcement, User, CountdownUpdateMessage, ChestStatusMessage } from '../types'; +import type { Chest, Announcement, CountdownUpdateMessage, ChestStatusMessage } from '../types'; const HomePage = () => { const [chests, setChests] = useState([]); const [announcements, setAnnouncements] = useState([]); - const [activeStreamers, setActiveStreamers] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [currentAnnouncementIndex, setCurrentAnnouncementIndex] = useState(0); @@ -79,10 +78,9 @@ const HomePage = () => { const loadData = async () => { try { setLoading(true); - const [chestsData, announcementsData, streamersData] = await Promise.all([ + const [chestsData, announcementsData] = await Promise.all([ gameApi.getChests(), announcementApi.getActiveAnnouncements(5).catch(() => []), - streamerApi.getStreamers(0, 10).catch(() => []), ]); // 调试:打印宝箱数据 @@ -96,7 +94,6 @@ const HomePage = () => { console.log('[HomePage] Active chests:', activeChests); setChests(activeChests); setAnnouncements(announcementsData); - setActiveStreamers(streamersData); } catch (err: any) { setError('加载数据失败'); console.error(err); @@ -161,32 +158,6 @@ const HomePage = () => {
{error}
)} - {/* 正在开奖的主播 */} - {activeStreamers.length > 0 && ( -
-

🌟 正在开奖的主播

-
- {activeStreamers.map((streamer) => ( -
-
-
- {streamer.nickname?.charAt(0).toUpperCase() || streamer.username.charAt(0).toUpperCase()} -
-
-

{streamer.nickname || streamer.username}

-

● 正在开奖

-
-
-
- 活跃宝箱: {chests.filter(c => c.streamer_id === streamer.id).length} - 总余额: ¥{streamer.balance.toLocaleString()} -
-
- ))} -
-
- )} - {/* 活跃宝箱列表 */}

🎁 活跃宝箱

diff --git a/frontend/src/services/websocket.ts b/frontend/src/services/websocket.ts index 6bf2b4e..badde02 100644 --- a/frontend/src/services/websocket.ts +++ b/frontend/src/services/websocket.ts @@ -1,4 +1,3 @@ -import { io, Socket } from 'socket.io-client'; import type { WebSocketMessage } from '../types'; const API_BASE_URL = import.meta.env.VITE_WEBSOCKET_BASE_URL || 'ws://localhost:8000'; @@ -6,7 +5,7 @@ const API_BASE_URL = import.meta.env.VITE_WEBSOCKET_BASE_URL || 'ws://localhost: type MessageHandler = (message: WebSocketMessage) => void; class WebSocketService { - private ws: Socket | null = null; + private ws: WebSocket | null = null; private listeners: Array<(message: any) => void> = []; private reconnectAttempts = 0; private maxReconnectAttempts = 5; @@ -17,7 +16,7 @@ class WebSocketService { private token: string | null = null; connect(role: 'user' | 'streamer', id: number, token: string) { - console.log(`Connecting Socket.IO for ${role} ${id} with token: ${token.substring(0, 20)}...`); + console.log(`Connecting WebSocket for ${role} ${id} with token: ${token.substring(0, 20)}...`); // 保存连接参数 this.role = role; @@ -37,58 +36,49 @@ class WebSocketService { return; } - // 构建Socket.IO连接URL - 移除socket.io路径,让客户端自动处理 - const url = API_BASE_URL; - console.log(`Socket.IO connection URL: ${url}`); + // 构建原生 WebSocket 连接 URL + // 后端路由: /ws/streamer/{streamer_id} 和 /ws/user/{user_id} + const wsUrl = `${API_BASE_URL}/ws/${role}/${id}?token=${encodeURIComponent(token)}`; + console.log(`WebSocket connection URL: ${wsUrl}`); - // 创建Socket.IO连接 - this.ws = io(url, { - transports: ['websocket'], - query: { - role, - id: id.toString(), - token - }, - reconnection: false, // 禁用自动重连,使用手动重连 - timeout: 10000, // 10秒超时(开发环境) - forceNew: true // 强制新连接 - }); + // 创建原生 WebSocket 连接 + this.ws = new WebSocket(wsUrl); - // 监听连接事件 - 使用Socket.IO事件 - this.ws.on('connect', () => { - console.log('Socket.IO connected successfully'); + // 监听连接事件 + this.ws.onopen = () => { + console.log('WebSocket connected successfully'); this.reconnectAttempts = 0; // 启动心跳 this.startHeartbeat(); - }); + }; - this.ws.on('connect_error', (error) => { - console.error('Socket.IO connection error:', error); - this.handleReconnect(); - }); + this.ws.onerror = (error) => { + console.error('WebSocket connection error:', error); + }; - this.ws.on('disconnect', (reason) => { - console.log('Socket.IO disconnected:', reason); + this.ws.onclose = (event) => { + console.log('WebSocket disconnected:', event.code, event.reason); // 停止心跳 this.stopHeartbeat(); - // 自动重连(除非是客户端主动断开) - if (reason !== 'io client disconnect' && this.reconnectAttempts < this.maxReconnectAttempts) { + // 自动重连(除非是正常关闭) + if (event.code !== 1000 && this.reconnectAttempts < this.maxReconnectAttempts) { this.handleReconnect(); } - }); + }; // 监听消息事件 - this.ws.on('message', (data: any) => { + this.ws.onmessage = (event) => { try { - console.log('Received Socket.IO message:', data); + const data = JSON.parse(event.data); + console.log('Received WebSocket message:', data); this.listeners.forEach(listener => listener(data)); } catch (error) { - console.error('Failed to process Socket.IO message:', error); + console.error('Failed to process WebSocket message:', error); } - }); + }; } private handleReconnect() { @@ -115,9 +105,9 @@ class WebSocketService { private startHeartbeat() { this.stopHeartbeat(); this.heartbeatTimer = window.setInterval(() => { - if (this.ws?.connected) { - // 发送心跳(可选) - // this.ws.emit('ping'); + if (this.ws?.readyState === WebSocket.OPEN) { + // 发送心跳 ping + this.ws.send(JSON.stringify({ type: 'ping' })); } }, 30000); // 30秒心跳 } @@ -139,7 +129,7 @@ class WebSocketService { // 关闭连接 if (this.ws) { - this.ws.disconnect(); + this.ws.close(1000, 'Client disconnect'); this.ws = null; } @@ -157,17 +147,17 @@ class WebSocketService { } send(data: any) { - if (this.ws?.connected) { - this.ws.emit('message', data); + if (this.ws?.readyState === WebSocket.OPEN) { + this.ws.send(JSON.stringify(data)); } else { - console.warn('Socket.IO is not connected'); + console.warn('WebSocket is not connected'); } } isConnected(): boolean { - return this.ws?.connected || false; + return this.ws?.readyState === WebSocket.OPEN; } } export const websocketService = new WebSocketService(); -export default WebSocketService; \ No newline at end of file +export default WebSocketService; diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 3934b8f..17f43b1 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -12,8 +12,8 @@ "noEmit": true, "jsx": "react-jsx", "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, + "noUnusedLocals": false, + "noUnusedParameters": false, "noFallthroughCasesInSwitch": true }, "include": ["src"], diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 3a965aa..1d35401 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -5,6 +5,7 @@ import react from '@vitejs/plugin-react' export default defineConfig({ plugins: [react()], server: { + host: '0.0.0.0', port: 3000, proxy: { '/api': { diff --git a/init_mysql.sql b/init_mysql.sql deleted file mode 100644 index dbc9347..0000000 --- a/init_mysql.sql +++ /dev/null @@ -1,199 +0,0 @@ --- ============================================ --- 宝箱游戏系统 MySQL 初始化脚本 --- 生成时间: 2025-12-13 --- 字符集: utf8mb4 --- ============================================ - --- 创建数据库(如果不存在) -CREATE DATABASE IF NOT EXISTS treasure_box_game - CHARACTER SET utf8mb4 - COLLATE utf8mb4_unicode_ci; - -USE treasure_box_game; - --- ============================================ --- 1. 用户表 (users) --- ============================================ -CREATE TABLE IF NOT EXISTS users ( - id INT AUTO_INCREMENT PRIMARY KEY, - username VARCHAR(50) NOT NULL UNIQUE COMMENT '用户名', - email VARCHAR(100) NOT NULL UNIQUE COMMENT '邮箱', - hashed_password VARCHAR(255) NOT NULL COMMENT '哈希密码', - role ENUM('USER', 'STREAMER', 'ADMIN') NOT NULL DEFAULT 'USER' COMMENT '用户角色', - nickname VARCHAR(64) DEFAULT NULL COMMENT '用户昵称', - avatar_url VARCHAR(255) DEFAULT NULL COMMENT '头像URL', - phone VARCHAR(20) DEFAULT NULL COMMENT '手机号', - status ENUM('ACTIVE', 'DISABLED', 'BANNED') NOT NULL DEFAULT 'ACTIVE' COMMENT '用户状态', - balance BIGINT NOT NULL DEFAULT 0 COMMENT '余额(单位:分)', - version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', - last_login_at DATETIME DEFAULT NULL COMMENT '最后登录时间', - login_count INT NOT NULL DEFAULT 0 COMMENT '登录次数', - is_active TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否激活', - created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - INDEX idx_username (username), - INDEX idx_email (email) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表'; - --- ============================================ --- 2. 交易记录表 (transactions) --- ============================================ -CREATE TABLE IF NOT EXISTS transactions ( - id INT AUTO_INCREMENT PRIMARY KEY, - user_id INT NOT NULL COMMENT '用户ID', - type VARCHAR(30) NOT NULL COMMENT '交易类型', - amount BIGINT NOT NULL COMMENT '金额(单位:分)', - balance_after BIGINT NOT NULL COMMENT '交易后余额', - related_id INT DEFAULT NULL COMMENT '关联ID', - description TEXT DEFAULT NULL COMMENT '描述', - created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - INDEX idx_user_id (user_id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='交易记录表'; - --- ============================================ --- 3. 宝箱表 (chests) --- ============================================ -CREATE TABLE IF NOT EXISTS chests ( - id INT AUTO_INCREMENT PRIMARY KEY, - streamer_id INT NOT NULL COMMENT '主播ID', - title VARCHAR(200) NOT NULL COMMENT '宝箱标题', - option_a VARCHAR(100) NOT NULL COMMENT '选项A', - option_b VARCHAR(100) NOT NULL COMMENT '选项B', - status ENUM('BETTING', 'LOCKED', 'SETTLING', 'FINISHED', 'REFUNDED') NOT NULL DEFAULT 'BETTING' COMMENT '宝箱状态', - pool_a BIGINT NOT NULL DEFAULT 0 COMMENT 'A边奖池(单位:分)', - pool_b BIGINT NOT NULL DEFAULT 0 COMMENT 'B边奖池(单位:分)', - total_bets INT NOT NULL DEFAULT 0 COMMENT '总下注次数', - countdown_seconds INT DEFAULT NULL COMMENT '倒计时(秒)', - locked_at DATETIME DEFAULT NULL COMMENT '封盘时间', - settled_at DATETIME DEFAULT NULL COMMENT '结算时间', - result VARCHAR(10) DEFAULT NULL COMMENT '结算结果', - created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - INDEX idx_streamer_id (streamer_id), - INDEX idx_status (status) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='宝箱表'; - --- ============================================ --- 4. 下注记录表 (bets) --- ============================================ -CREATE TABLE IF NOT EXISTS bets ( - id INT AUTO_INCREMENT PRIMARY KEY, - user_id INT NOT NULL COMMENT '用户ID', - chest_id INT NOT NULL COMMENT '宝箱ID', - `option` CHAR(1) NOT NULL COMMENT '下注选项(A或B)', - amount BIGINT NOT NULL COMMENT '下注金额(单位:分)', - payout BIGINT DEFAULT NULL COMMENT '获奖金额(单位:分)', - status VARCHAR(20) NOT NULL DEFAULT 'PENDING' COMMENT '状态', - created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - INDEX idx_user_id (user_id), - INDEX idx_chest_id (chest_id), - CONSTRAINT fk_bets_chest FOREIGN KEY (chest_id) REFERENCES chests(id) ON DELETE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='下注记录表'; - --- ============================================ --- 5. 系统配置表 (system_configs) --- ============================================ -CREATE TABLE IF NOT EXISTS system_configs ( - id INT AUTO_INCREMENT PRIMARY KEY, - config_key VARCHAR(64) NOT NULL UNIQUE COMMENT '配置键', - config_value TEXT DEFAULT NULL COMMENT '配置值', - config_type ENUM('STRING', 'NUMBER', 'BOOLEAN', 'JSON') NOT NULL DEFAULT 'STRING' COMMENT '配置类型', - category ENUM('GAME_ECONOMY', 'GAME_LOGIC', 'SYSTEM_OPERATIONS', 'UI_DISPLAY') NOT NULL COMMENT '配置分类', - description VARCHAR(255) DEFAULT NULL COMMENT '配置描述', - is_editable TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否可编辑', - is_public TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否对前端公开', - display_order INT NOT NULL DEFAULT 0 COMMENT '显示顺序', - created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - INDEX idx_config_key (config_key), - INDEX idx_category (category) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统配置表'; - --- ============================================ --- 6. 主播资料表 (streamer_profiles) --- ============================================ -CREATE TABLE IF NOT EXISTS streamer_profiles ( - id INT AUTO_INCREMENT PRIMARY KEY, - user_id INT NOT NULL UNIQUE COMMENT '用户ID', - display_name VARCHAR(64) DEFAULT NULL COMMENT '主播展示名称', - avatar_url VARCHAR(255) DEFAULT NULL COMMENT '主播头像', - bio TEXT DEFAULT NULL COMMENT '主播简介', - commission_rate DECIMAL(5,2) NOT NULL DEFAULT 5.00 COMMENT '主播抽成比例(%)', - max_active_chests INT NOT NULL DEFAULT 10 COMMENT '最大活跃宝箱数', - total_chests INT NOT NULL DEFAULT 0 COMMENT '历史宝箱总数', - total_winnings DECIMAL(15,2) NOT NULL DEFAULT 0.00 COMMENT '历史获奖总额', - status ENUM('ACTIVE', 'SUSPENDED', 'BANNED') NOT NULL DEFAULT 'ACTIVE' COMMENT '主播状态', - created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - INDEX idx_user_id (user_id), - INDEX idx_status (status) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='主播资料表'; - --- ============================================ --- 7. 用户操作日志表 (user_operation_logs) --- ============================================ -CREATE TABLE IF NOT EXISTS user_operation_logs ( - id INT AUTO_INCREMENT PRIMARY KEY, - user_id INT NOT NULL COMMENT '操作用户ID', - operator_id INT DEFAULT NULL COMMENT '操作人ID(管理员)', - operation_type VARCHAR(64) NOT NULL COMMENT '操作类型', - operation_details TEXT DEFAULT NULL COMMENT '操作详情(JSON格式)', - ip_address VARCHAR(45) DEFAULT NULL COMMENT 'IP地址', - created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - INDEX idx_user_id (user_id), - INDEX idx_operator_id (operator_id), - INDEX idx_operation_type (operation_type), - INDEX idx_created_at (created_at) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户操作日志表'; - --- ============================================ --- 8. 公告表 (announcements) --- ============================================ -CREATE TABLE IF NOT EXISTS announcements ( - id INT AUTO_INCREMENT PRIMARY KEY, - title VARCHAR(255) NOT NULL COMMENT '公告标题', - content TEXT NOT NULL COMMENT '公告内容', - type ENUM('INFO', 'WARNING', 'PRIZE') NOT NULL DEFAULT 'INFO' COMMENT '公告类型', - is_pinned TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否置顶', - priority INT NOT NULL DEFAULT 0 COMMENT '优先级(数字越大优先级越高)', - starts_at DATETIME DEFAULT NULL COMMENT '生效时间', - expires_at DATETIME DEFAULT NULL COMMENT '过期时间', - created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - INDEX idx_type (type), - INDEX idx_is_pinned (is_pinned), - INDEX idx_starts_at (starts_at), - INDEX idx_expires_at (expires_at) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='公告表'; - --- ============================================ --- 初始化默认数据 --- ============================================ - --- 插入默认管理员账户 (密码: admin123,请及时修改) --- 密码使用 bcrypt 加密,此处为示例哈希值 -INSERT INTO users (username, email, hashed_password, role, nickname, status, is_active) -VALUES ('admin', 'admin@example.com', '$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/X4.qXaFn8c0LsMLQe', 'ADMIN', '系统管理员', 'ACTIVE', 1) -ON DUPLICATE KEY UPDATE username = username; - --- 插入默认系统配置 -INSERT INTO system_configs (config_key, config_value, config_type, category, description, is_editable, is_public, display_order) VALUES --- 游戏经济配置 -('min_bet_amount', '100', 'NUMBER', 'GAME_ECONOMY', '最小下注金额(分)', 1, 1, 1), -('max_bet_amount', '100000', 'NUMBER', 'GAME_ECONOMY', '最大下注金额(分)', 1, 1, 2), -('platform_fee_rate', '5', 'NUMBER', 'GAME_ECONOMY', '平台抽成比例(%)', 1, 0, 3), -('default_commission_rate', '5', 'NUMBER', 'GAME_ECONOMY', '默认主播抽成比例(%)', 1, 0, 4), --- 游戏逻辑配置 -('default_countdown_seconds', '60', 'NUMBER', 'GAME_LOGIC', '默认倒计时秒数', 1, 1, 10), -('max_active_chests_per_streamer', '10', 'NUMBER', 'GAME_LOGIC', '每个主播最大活跃宝箱数', 1, 0, 11), --- 系统运营配置 -('maintenance_mode', 'false', 'BOOLEAN', 'SYSTEM_OPERATIONS', '维护模式', 1, 1, 20), -('registration_enabled', 'true', 'BOOLEAN', 'SYSTEM_OPERATIONS', '是否开放注册', 1, 1, 21), --- UI显示配置 -('site_name', '宝箱游戏', 'STRING', 'UI_DISPLAY', '网站名称', 1, 1, 30), -('site_logo_url', '', 'STRING', 'UI_DISPLAY', '网站Logo URL', 1, 1, 31) -ON DUPLICATE KEY UPDATE config_key = config_key; - --- ============================================ --- 完成 --- ============================================ -SELECT '数据库初始化完成!' AS message; diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 39017ff..0000000 --- a/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "demo07", - "lockfileVersion": 3, - "requires": true, - "packages": {} -} diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index 5a7b8e7..0000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,6 +0,0 @@ -# 开发依赖 --r requirements.txt - -pytest==7.4.3 -pytest-asyncio==0.21.1 -httpx==0.25.2