您好,{username}:
+我们检测到 {reason_text}。
+如果这不是您本人操作,请尽快修改密码并联系管理员。
+ + + """ + + return send_email( + to_email=email, + subject=subject, + body=text_body, + html_body=html_body, + email_type=EMAIL_TYPE_SECURITY_ALERT, + user_id=user_id, + ) + + # ============ 异步发送队列 ============ class EmailQueue: diff --git a/routes/admin_api/core.py b/routes/admin_api/core.py index d99cfe7..2024345 100644 --- a/routes/admin_api/core.py +++ b/routes/admin_api/core.py @@ -10,6 +10,7 @@ from datetime import datetime import database import email_service import requests +from app_config import get_config from app_logger import get_logger from app_security import ( get_rate_limit_ip, @@ -32,6 +33,10 @@ from services.state import ( safe_iter_task_status_items, safe_remove_user_accounts, safe_verify_and_consume_captcha, + check_login_ip_user_locked, + check_login_rate_limits, + get_login_failure_delay_seconds, + record_login_username_attempt, check_ip_request_rate, check_login_captcha_required, clear_login_failures, @@ -41,6 +46,20 @@ from services.tasks import get_task_scheduler, submit_account_task from services.time_utils import BEIJING_TZ, get_beijing_now logger = get_logger("app") +config = get_config() + + +def _admin_reauth_required() -> bool: + try: + return time.time() > float(session.get("admin_reauth_until", 0) or 0) + except Exception: + return True + + +def _require_admin_reauth(): + if _admin_reauth_required(): + return jsonify({"error": "需要二次确认", "code": "reauth_required"}), 401 + return None @admin_api_bp.route("/debug-config", methods=["GET"]) @@ -83,13 +102,29 @@ def admin_login(): need_captcha = data.get("need_captcha", False) client_ip = get_rate_limit_ip() + username_key = username + + scan_locked = record_login_username_attempt(client_ip, username_key) + is_locked, remaining = check_login_ip_user_locked(client_ip, username_key) + if is_locked: + wait_hint = f"{remaining // 60 + 1}分钟" if remaining >= 60 else f"{remaining}秒" + if request.is_json: + return jsonify({"error": f"账号短时锁定,请{wait_hint}后再试", "need_captcha": True}), 429 + return redirect(url_for("pages.admin_login_page")) + allowed, error_msg = check_ip_request_rate(client_ip, "login") if not allowed: if request.is_json: return jsonify({"error": error_msg, "need_captcha": True}), 429 return redirect(url_for("pages.admin_login_page")) - captcha_required = check_login_captcha_required(client_ip) or bool(need_captcha) + allowed, error_msg = check_login_rate_limits(client_ip, username_key) + if not allowed: + if request.is_json: + return jsonify({"error": error_msg, "need_captcha": True}), 429 + return redirect(url_for("pages.admin_login_page")) + + captcha_required = check_login_captcha_required(client_ip, username_key) or scan_locked or bool(need_captcha) if captcha_required: if not captcha_session or not captcha_code: if request.is_json: @@ -97,18 +132,19 @@ def admin_login(): return redirect(url_for("pages.admin_login_page")) success, message = safe_verify_and_consume_captcha(captcha_session, captcha_code) if not success: - record_login_failure(client_ip) + record_login_failure(client_ip, username_key) if request.is_json: return jsonify({"error": message, "need_captcha": True}), 400 return redirect(url_for("pages.admin_login_page")) admin = database.verify_admin(username, password) if admin: - clear_login_failures(client_ip) + clear_login_failures(client_ip, username_key) session.pop("admin_id", None) session.pop("admin_username", None) session["admin_id"] = admin["id"] session["admin_username"] = admin["username"] + session["admin_reauth_until"] = time.time() + int(config.ADMIN_REAUTH_WINDOW_SECONDS) session.permanent = True session.modified = True @@ -118,7 +154,10 @@ def admin_login(): return jsonify({"success": True, "redirect": "/yuyx/admin"}) return redirect(url_for("pages.admin_page")) - record_login_failure(client_ip) + record_login_failure(client_ip, username_key) + delay = get_login_failure_delay_seconds(client_ip, username_key) + if delay > 0: + time.sleep(delay) logger.warning(f"[admin_login] 管理员 {username} 登录失败 - 用户名或密码错误") if request.is_json: return jsonify({"error": "管理员用户名或密码错误", "need_captcha": check_login_captcha_required(client_ip)}), 401 @@ -131,9 +170,32 @@ def admin_logout(): """管理员登出""" session.pop("admin_id", None) session.pop("admin_username", None) + session.pop("admin_reauth_until", None) return jsonify({"success": True}) +@admin_api_bp.route("/admin/reauth", methods=["POST"]) +@admin_required +def admin_reauth(): + """管理员敏感操作二次确认""" + data = request.json or {} + password = (data.get("password") or "").strip() + if not password: + return jsonify({"error": "密码不能为空"}), 400 + + username = session.get("admin_username") + if not username: + return jsonify({"error": "未登录"}), 401 + + admin = database.verify_admin(username, password) + if not admin: + return jsonify({"error": "密码错误"}), 401 + + session["admin_reauth_until"] = time.time() + int(config.ADMIN_REAUTH_WINDOW_SECONDS) + session.modified = True + return jsonify({"success": True, "expires_in": int(config.ADMIN_REAUTH_WINDOW_SECONDS)}) + + # ==================== 公告管理API(管理员) ==================== @@ -761,6 +823,9 @@ def restart_docker_container(): import subprocess try: + reauth_response = _require_admin_reauth() + if reauth_response: + return reauth_response if not os.path.exists("/.dockerenv"): return jsonify({"error": "当前不在Docker容器中运行"}), 400 diff --git a/routes/admin_api/update.py b/routes/admin_api/update.py index cd2e0cd..735d2e9 100644 --- a/routes/admin_api/update.py +++ b/routes/admin_api/update.py @@ -3,6 +3,7 @@ from __future__ import annotations import os +import time import uuid from flask import jsonify, request, session @@ -65,6 +66,13 @@ def _parse_bool_field(data: dict, key: str) -> bool | None: raise ValueError(f"{key} 必须是 0/1 或 true/false") +def _admin_reauth_required() -> bool: + try: + return time.time() > float(session.get("admin_reauth_until", 0) or 0) + except Exception: + return True + + @admin_api_bp.route("/update/status", methods=["GET"]) @admin_required def get_update_status_api(): @@ -146,6 +154,8 @@ def request_update_check_api(): def request_update_run_api(): """请求宿主机 Update-Agent 执行一键更新并重启服务。""" ensure_update_dirs() + if _admin_reauth_required(): + return jsonify({"error": "需要二次确认", "code": "reauth_required"}), 401 if _has_pending_request(): return jsonify({"error": "已有更新请求正在处理中,请稍后再试"}), 409 diff --git a/routes/api_auth.py b/routes/api_auth.py index 1655e5a..6080314 100644 --- a/routes/api_auth.py +++ b/routes/api_auth.py @@ -8,6 +8,7 @@ import time import database import email_service +from app_config import get_config from app_logger import get_logger from app_security import get_rate_limit_ip, require_ip_not_locked, validate_email, validate_password, validate_username from flask import Blueprint, jsonify, redirect, render_template, request, url_for @@ -17,17 +18,24 @@ from services.accounts_service import load_user_accounts from services.models import User from services.state import ( check_ip_request_rate, + check_email_rate_limit, + check_login_ip_user_locked, + check_login_rate_limits, check_login_captcha_required, clear_login_failures, + get_login_failure_delay_seconds, record_failed_captcha, record_login_failure, + record_login_username_attempt, safe_cleanup_expired_captcha, safe_delete_captcha, safe_set_captcha, safe_verify_and_consume_captcha, + should_send_login_alert, ) logger = get_logger("app") +config = get_config() api_auth_bp = Blueprint("api_auth", __name__) @@ -181,6 +189,9 @@ def resend_verify_email(): client_ip = get_rate_limit_ip() allowed, error_msg = check_ip_request_rate(client_ip, "email") + if not allowed: + return jsonify({"error": error_msg}), 429 + allowed, error_msg = check_email_rate_limit(email, "resend_verify") if not allowed: return jsonify({"error": error_msg}), 429 @@ -238,6 +249,9 @@ def forgot_password(): client_ip = get_rate_limit_ip() allowed, error_msg = check_ip_request_rate(client_ip, "email") + if not allowed: + return jsonify({"error": error_msg}), 429 + allowed, error_msg = check_email_rate_limit(email, "forgot_password") if not allowed: return jsonify({"error": error_msg}), 429 @@ -323,6 +337,15 @@ def request_password_reset(): if not is_valid: return jsonify({"error": error_msg}), 400 + client_ip = get_rate_limit_ip() + allowed, error_msg = check_ip_request_rate(client_ip, "email") + if not allowed: + return jsonify({"error": error_msg}), 429 + if email: + allowed, error_msg = check_email_rate_limit(email, "reset_request") + if not allowed: + return jsonify({"error": error_msg}), 429 + user = database.get_user_by_username(username) if user: @@ -416,31 +439,66 @@ def login(): need_captcha = data.get("need_captcha", False) client_ip = get_rate_limit_ip() + username_key = username + + scan_locked = record_login_username_attempt(client_ip, username_key) + is_locked, remaining = check_login_ip_user_locked(client_ip, username_key) + if is_locked: + wait_hint = f"{remaining // 60 + 1}分钟" if remaining >= 60 else f"{remaining}秒" + return jsonify({"error": f"账号短时锁定,请{wait_hint}后再试", "need_captcha": True}), 429 + allowed, error_msg = check_ip_request_rate(client_ip, "login") if not allowed: return jsonify({"error": error_msg, "need_captcha": True}), 429 - captcha_required = check_login_captcha_required(client_ip) or bool(need_captcha) + allowed, error_msg = check_login_rate_limits(client_ip, username_key) + if not allowed: + return jsonify({"error": error_msg, "need_captcha": True}), 429 + + captcha_required = check_login_captcha_required(client_ip, username_key) or scan_locked or bool(need_captcha) if captcha_required: if not captcha_session or not captcha_code: return jsonify({"error": "请填写验证码", "need_captcha": True}), 400 success, message = safe_verify_and_consume_captcha(captcha_session, captcha_code) if not success: - record_login_failure(client_ip) + record_login_failure(client_ip, username_key) return jsonify({"error": message, "need_captcha": True}), 400 user = database.verify_user(username, password) if not user: - record_login_failure(client_ip) - return jsonify({"error": "用户名或密码错误", "need_captcha": check_login_captcha_required(client_ip)}), 401 + record_login_failure(client_ip, username_key) + delay = get_login_failure_delay_seconds(client_ip, username_key) + if delay > 0: + time.sleep(delay) + return jsonify({"error": "用户名或密码错误", "need_captcha": check_login_captcha_required(client_ip, username_key)}), 401 if user["status"] != "approved": return jsonify({"error": "账号未审核,请等待管理员审核", "need_captcha": False}), 401 - clear_login_failures(client_ip) + clear_login_failures(client_ip, username_key) user_obj = User(user["id"]) login_user(user_obj) load_user_accounts(user["id"]) + + try: + user_agent = request.headers.get("User-Agent", "") + context = database.record_login_context(user["id"], client_ip, user_agent) + if context and (context.get("new_ip") or context.get("new_device")): + if config.LOGIN_ALERT_ENABLED and should_send_login_alert(user["id"], client_ip): + user_info = database.get_user_by_id(user["id"]) or {} + if user_info.get("email") and user_info.get("email_verified"): + if database.get_user_email_notify(user["id"]): + email_service.send_security_alert_email( + email=user_info.get("email"), + username=user_info.get("username") or username, + ip_address=client_ip, + user_agent=user_agent, + new_ip=context.get("new_ip", False), + new_device=context.get("new_device", False), + user_id=user["id"], + ) + except Exception: + pass return jsonify({"success": True}) diff --git a/routes/api_user.py b/routes/api_user.py index 8648801..1c1ba8b 100644 --- a/routes/api_user.py +++ b/routes/api_user.py @@ -9,7 +9,7 @@ from app_security import get_rate_limit_ip, require_ip_not_locked, validate_emai from flask import Blueprint, jsonify, request from flask_login import current_user, login_required from routes.pages import render_app_spa_or_legacy -from services.state import check_ip_request_rate, safe_iter_task_status_items +from services.state import check_email_rate_limit, check_ip_request_rate, safe_iter_task_status_items logger = get_logger("app") @@ -164,6 +164,9 @@ def bind_user_email(): client_ip = get_rate_limit_ip() allowed, error_msg = check_ip_request_rate(client_ip, "email") + if not allowed: + return jsonify({"error": error_msg}), 429 + allowed, error_msg = check_email_rate_limit(email, "bind_email") if not allowed: return jsonify({"error": error_msg}), 429 diff --git a/services/state.py b/services/state.py index a8d393f..3725026 100644 --- a/services/state.py +++ b/services/state.py @@ -12,6 +12,7 @@ from __future__ import annotations import threading import time +import random from typing import Any, Dict, List, Optional, Tuple from app_config import get_config @@ -423,48 +424,291 @@ def cleanup_expired_ip_request_rates(now_ts: Optional[float] = None) -> int: return removed -# ==================== 登录失败追踪(触发验证码) ==================== +# ==================== 登录风控(验证码/限流/延迟/锁定) ==================== _login_failures: Dict[str, Dict[str, Any]] = {} _login_failures_lock = threading.RLock() +_login_rate_limits: Dict[str, Dict[str, Any]] = {} +_login_rate_limits_lock = threading.RLock() + +_login_scan_state: Dict[str, Dict[str, Any]] = {} +_login_scan_lock = threading.RLock() + +_login_ip_user_locks: Dict[str, Dict[str, Any]] = {} +_login_ip_user_lock = threading.RLock() + +_login_alert_state: Dict[int, Dict[str, Any]] = {} +_login_alert_lock = threading.RLock() + + +def _normalize_login_key(kind: str, ip_address: str, username: Optional[str] = None) -> str: + ip_key = str(ip_address or "") + user_key = str(username or "").strip().lower() + if kind == "ip": + return f"ip:{ip_key}" + if kind == "user": + return f"user:{user_key}" if user_key else "" + return f"ipuser:{ip_key}:{user_key}" if user_key else "" + def _get_login_captcha_config() -> Tuple[int, int]: return int(config.LOGIN_CAPTCHA_AFTER_FAILURES), int(config.LOGIN_CAPTCHA_WINDOW_SECONDS) -def record_login_failure(ip_address: str) -> None: +def _get_login_rate_limit_config() -> Tuple[int, int, int, int]: + return ( + int(config.LOGIN_IP_MAX_ATTEMPTS), + int(config.LOGIN_USERNAME_MAX_ATTEMPTS), + int(config.LOGIN_IP_USERNAME_MAX_ATTEMPTS), + int(config.LOGIN_RATE_LIMIT_WINDOW_SECONDS), + ) + + +def _get_login_lock_config() -> Tuple[int, int, int]: + return ( + int(config.LOGIN_ACCOUNT_LOCK_FAILURES), + int(config.LOGIN_ACCOUNT_LOCK_WINDOW_SECONDS), + int(config.LOGIN_ACCOUNT_LOCK_SECONDS), + ) + + +def _get_login_scan_config() -> Tuple[int, int, int]: + return ( + int(config.LOGIN_SCAN_UNIQUE_USERNAME_THRESHOLD), + int(config.LOGIN_SCAN_WINDOW_SECONDS), + int(config.LOGIN_SCAN_COOLDOWN_SECONDS), + ) + + +def _get_or_reset_bucket(data: Optional[Dict[str, Any]], now_ts: float, window_seconds: int) -> Dict[str, Any]: + if not data or (now_ts - float(data.get("window_start", 0) or 0)) > window_seconds: + return {"window_start": now_ts, "count": 0} + return data + + +def record_login_username_attempt(ip_address: str, username: str) -> bool: now_ts = time.time() - max_failures, window_seconds = _get_login_captcha_config() + threshold, window_seconds, cooldown_seconds = _get_login_scan_config() ip_key = str(ip_address or "") - with _login_failures_lock: - data = _login_failures.get(ip_key) - if not data or (now_ts - float(data.get("first_failed", 0) or 0)) > window_seconds: - data = {"first_failed": now_ts, "count": 0} - _login_failures[ip_key] = data - data["count"] = int(data.get("count", 0) or 0) + 1 - if int(data["count"]) > max_failures * 5: - data["count"] = max_failures * 5 + user_key = str(username or "").strip().lower() + if not ip_key or not user_key: + return False + + with _login_scan_lock: + data = _login_scan_state.get(ip_key) + if not data or (now_ts - float(data.get("first_seen", 0) or 0)) > window_seconds: + data = {"first_seen": now_ts, "usernames": set(), "scan_until": 0} + _login_scan_state[ip_key] = data + + data["usernames"].add(user_key) + if len(data["usernames"]) >= threshold: + data["scan_until"] = max(float(data.get("scan_until", 0) or 0), now_ts + cooldown_seconds) + + return now_ts < float(data.get("scan_until", 0) or 0) -def clear_login_failures(ip_address: str) -> None: - ip_key = str(ip_address or "") - with _login_failures_lock: - _login_failures.pop(ip_key, None) - - -def check_login_captcha_required(ip_address: str) -> bool: +def is_login_scan_locked(ip_address: str) -> bool: now_ts = time.time() - max_failures, window_seconds = _get_login_captcha_config() ip_key = str(ip_address or "") - with _login_failures_lock: - data = _login_failures.get(ip_key) + with _login_scan_lock: + data = _login_scan_state.get(ip_key) if not data: return False - if (now_ts - float(data.get("first_failed", 0) or 0)) > window_seconds: - _login_failures.pop(ip_key, None) + if now_ts >= float(data.get("scan_until", 0) or 0): return False - return int(data.get("count", 0) or 0) >= max_failures + return True + + +def check_login_rate_limits(ip_address: str, username: str) -> Tuple[bool, Optional[str]]: + now_ts = time.time() + ip_max, user_max, ip_user_max, window_seconds = _get_login_rate_limit_config() + ip_key = _normalize_login_key("ip", ip_address) + user_key = _normalize_login_key("user", "", username) + ip_user_key = _normalize_login_key("ipuser", ip_address, username) + + def _check(key: str, max_requests: int) -> Tuple[bool, Optional[str]]: + if not key or max_requests <= 0: + return True, None + data = _get_or_reset_bucket(_login_rate_limits.get(key), now_ts, window_seconds) + if int(data.get("count", 0) or 0) >= max_requests: + remaining = max(1, int(window_seconds - (now_ts - float(data.get("window_start", 0) or 0)))) + wait_hint = f"{remaining // 60 + 1}分钟" if remaining >= 60 else f"{remaining}秒" + return False, f"请求过于频繁,请{wait_hint}后再试" + data["count"] = int(data.get("count", 0) or 0) + 1 + _login_rate_limits[key] = data + return True, None + + with _login_rate_limits_lock: + allowed, msg = _check(ip_key, ip_max) + if not allowed: + return False, msg + allowed, msg = _check(ip_user_key, ip_user_max) + if not allowed: + return False, msg + allowed, msg = _check(user_key, user_max) + if not allowed: + return False, msg + + return True, None + + +def _update_login_failure(key: str, now_ts: float, window_seconds: int) -> int: + data = _login_failures.get(key) + if not data or (now_ts - float(data.get("first_failed", 0) or 0)) > window_seconds: + data = {"first_failed": now_ts, "count": 0} + _login_failures[key] = data + data["count"] = int(data.get("count", 0) or 0) + 1 + return int(data["count"]) + + +def record_login_failure(ip_address: str, username: Optional[str] = None) -> None: + now_ts = time.time() + max_failures, window_seconds = _get_login_captcha_config() + lock_failures, lock_window, lock_seconds = _get_login_lock_config() + ip_key = _normalize_login_key("ip", ip_address) + user_key = _normalize_login_key("user", "", username or "") + ip_user_key = _normalize_login_key("ipuser", ip_address, username or "") + + with _login_failures_lock: + ip_count = _update_login_failure(ip_key, now_ts, window_seconds) + user_count = _update_login_failure(user_key, now_ts, window_seconds) + ip_user_count = _update_login_failure(ip_user_key, now_ts, window_seconds) + + for key in (ip_key, user_key, ip_user_key): + data = _login_failures.get(key) + if data and int(data.get("count", 0) or 0) > max_failures * 5: + data["count"] = max_failures * 5 + + if username: + ip_user_lock_key = _normalize_login_key("ipuser", ip_address, username) + with _login_ip_user_lock: + if ip_user_count >= lock_failures: + _login_ip_user_locks[ip_user_lock_key] = { + "lock_until": now_ts + lock_seconds, + "first_failed": now_ts - lock_window, + } + + +def clear_login_failures(ip_address: str, username: Optional[str] = None) -> None: + ip_key = _normalize_login_key("ip", ip_address) + user_key = _normalize_login_key("user", "", username or "") + ip_user_key = _normalize_login_key("ipuser", ip_address, username or "") + with _login_failures_lock: + _login_failures.pop(ip_key, None) + _login_failures.pop(user_key, None) + _login_failures.pop(ip_user_key, None) + with _login_ip_user_lock: + _login_ip_user_locks.pop(ip_user_key, None) + + +def _get_login_failure_count(ip_address: str, username: Optional[str] = None) -> int: + now_ts = time.time() + _, window_seconds = _get_login_captcha_config() + ip_user_key = _normalize_login_key("ipuser", ip_address, username or "") + with _login_failures_lock: + data = _login_failures.get(ip_user_key) + if not data: + return 0 + if (now_ts - float(data.get("first_failed", 0) or 0)) > window_seconds: + _login_failures.pop(ip_user_key, None) + return 0 + return int(data.get("count", 0) or 0) + + +def check_login_captcha_required(ip_address: str, username: Optional[str] = None) -> bool: + now_ts = time.time() + max_failures, window_seconds = _get_login_captcha_config() + ip_key = _normalize_login_key("ip", ip_address) + ip_user_key = _normalize_login_key("ipuser", ip_address, username or "") + + with _login_failures_lock: + ip_data = _login_failures.get(ip_key) + if ip_data and (now_ts - float(ip_data.get("first_failed", 0) or 0)) <= window_seconds: + if int(ip_data.get("count", 0) or 0) >= max_failures: + return True + ip_user_data = _login_failures.get(ip_user_key) + if ip_user_data and (now_ts - float(ip_user_data.get("first_failed", 0) or 0)) <= window_seconds: + if int(ip_user_data.get("count", 0) or 0) >= max_failures: + return True + + if is_login_scan_locked(ip_address): + return True + + return False + + +def check_login_ip_user_locked(ip_address: str, username: Optional[str]) -> Tuple[bool, int]: + now_ts = time.time() + if not username: + return False, 0 + ip_user_key = _normalize_login_key("ipuser", ip_address, username) + with _login_ip_user_lock: + data = _login_ip_user_locks.get(ip_user_key) + if not data: + return False, 0 + lock_until = float(data.get("lock_until", 0) or 0) + if now_ts >= lock_until: + _login_ip_user_locks.pop(ip_user_key, None) + return False, 0 + remaining = int(lock_until - now_ts) + return True, max(1, remaining) + + +def get_login_failure_delay_seconds(ip_address: str, username: Optional[str]) -> float: + fail_count = _get_login_failure_count(ip_address, username) + if fail_count <= 0: + return 0.0 + base_ms = max(0, int(config.LOGIN_FAIL_DELAY_BASE_MS)) + max_ms = max(base_ms, int(config.LOGIN_FAIL_DELAY_MAX_MS)) + delay_ms = min(max_ms, int(base_ms * (1.6 ** max(0, fail_count - 1)))) + jitter = random.randint(0, max(50, int(base_ms * 0.3))) + return float(delay_ms + jitter) / 1000.0 + + +def should_send_login_alert(user_id: int, ip_address: str) -> bool: + now_ts = time.time() + min_interval = int(config.LOGIN_ALERT_MIN_INTERVAL_SECONDS) + with _login_alert_lock: + data = _login_alert_state.get(int(user_id)) + if not data: + _login_alert_state[int(user_id)] = {"last_sent": now_ts, "last_ip": ip_address} + return True + last_sent = float(data.get("last_sent", 0) or 0) + last_ip = str(data.get("last_ip", "") or "") + if ip_address and ip_address != last_ip: + _login_alert_state[int(user_id)] = {"last_sent": now_ts, "last_ip": ip_address} + return True + if (now_ts - last_sent) >= min_interval: + _login_alert_state[int(user_id)] = {"last_sent": now_ts, "last_ip": ip_address} + return True + return False + + +# ==================== 邮箱维度限流 ==================== + +_email_rate_limit: Dict[str, Dict[str, Any]] = {} +_email_rate_limit_lock = threading.RLock() + + +def check_email_rate_limit(email: str, action: str) -> Tuple[bool, Optional[str]]: + now_ts = time.time() + max_requests = int(config.EMAIL_RATE_LIMIT_MAX) + window_seconds = int(config.EMAIL_RATE_LIMIT_WINDOW_SECONDS) + email_key = str(email or "").strip().lower() + if not email_key: + return True, None + key = f"{action}:{email_key}" + + with _email_rate_limit_lock: + data = _get_or_reset_bucket(_email_rate_limit.get(key), now_ts, window_seconds) + if int(data.get("count", 0) or 0) >= max_requests: + remaining = max(1, int(window_seconds - (now_ts - float(data.get("window_start", 0) or 0)))) + wait_hint = f"{remaining // 60 + 1}分钟" if remaining >= 60 else f"{remaining}秒" + return False, f"请求过于频繁,请{wait_hint}后再试" + data["count"] = int(data.get("count", 0) or 0) + 1 + _email_rate_limit[key] = data + return True, None # ==================== Batch screenshots(批次任务截图收集) ==================== diff --git a/static/admin/.vite/manifest.json b/static/admin/.vite/manifest.json index 28f8ab3..e2105f5 100644 --- a/static/admin/.vite/manifest.json +++ b/static/admin/.vite/manifest.json @@ -1,34 +1,34 @@ { - "_email-BfqhxXOq.js": { - "file": "assets/email-BfqhxXOq.js", + "_email-BsKBHU5S.js": { + "file": "assets/email-BsKBHU5S.js", "name": "email", "imports": [ "index.html" ] }, - "_tasks-BtWKY-g7.js": { - "file": "assets/tasks-BtWKY-g7.js", + "_tasks-DpslJtm_.js": { + "file": "assets/tasks-DpslJtm_.js", "name": "tasks", "imports": [ "index.html" ] }, - "_update-BrAMPxiF.js": { - "file": "assets/update-BrAMPxiF.js", + "_update-DcFD-YxU.js": { + "file": "assets/update-DcFD-YxU.js", "name": "update", "imports": [ "index.html" ] }, - "_users-CToznuvL.js": { - "file": "assets/users-CToznuvL.js", + "_users-CC9BckjT.js": { + "file": "assets/users-CC9BckjT.js", "name": "users", "imports": [ "index.html" ] }, "index.html": { - "file": "assets/index-Da0EvMWc.js", + "file": "assets/index-CdjS44Uj.js", "name": "index", "src": "index.html", "isEntry": true, @@ -47,7 +47,7 @@ ] }, "src/pages/AnnouncementsPage.vue": { - "file": "assets/AnnouncementsPage-CbLi3NFK.js", + "file": "assets/AnnouncementsPage-Djmq3Wb7.js", "name": "AnnouncementsPage", "src": "src/pages/AnnouncementsPage.vue", "isDynamicEntry": true, @@ -59,20 +59,20 @@ ] }, "src/pages/EmailPage.vue": { - "file": "assets/EmailPage-CaUZghxJ.js", + "file": "assets/EmailPage-q6nJlTue.js", "name": "EmailPage", "src": "src/pages/EmailPage.vue", "isDynamicEntry": true, "imports": [ - "_email-BfqhxXOq.js", + "_email-BsKBHU5S.js", "index.html" ], "css": [ - "assets/EmailPage-DD73oBux.css" + "assets/EmailPage-BxzHc6tN.css" ] }, "src/pages/FeedbacksPage.vue": { - "file": "assets/FeedbacksPage-DCz_21CH.js", + "file": "assets/FeedbacksPage-Drw6uvSR.js", "name": "FeedbacksPage", "src": "src/pages/FeedbacksPage.vue", "isDynamicEntry": true, @@ -84,13 +84,13 @@ ] }, "src/pages/LogsPage.vue": { - "file": "assets/LogsPage-k6AvTEc_.js", + "file": "assets/LogsPage-DQd9IS3I.js", "name": "LogsPage", "src": "src/pages/LogsPage.vue", "isDynamicEntry": true, "imports": [ - "_users-CToznuvL.js", - "_tasks-BtWKY-g7.js", + "_users-CC9BckjT.js", + "_tasks-DpslJtm_.js", "index.html" ], "css": [ @@ -98,22 +98,22 @@ ] }, "src/pages/ReportPage.vue": { - "file": "assets/ReportPage-BkB6FuHA.js", + "file": "assets/ReportPage-Dnk3wsl3.js", "name": "ReportPage", "src": "src/pages/ReportPage.vue", "isDynamicEntry": true, "imports": [ "index.html", - "_email-BfqhxXOq.js", - "_tasks-BtWKY-g7.js", - "_update-BrAMPxiF.js" + "_email-BsKBHU5S.js", + "_tasks-DpslJtm_.js", + "_update-DcFD-YxU.js" ], "css": [ "assets/ReportPage-TpqQWWvU.css" ] }, "src/pages/SettingsPage.vue": { - "file": "assets/SettingsPage-CeJoz6yA.js", + "file": "assets/SettingsPage-YOW1Apwk.js", "name": "SettingsPage", "src": "src/pages/SettingsPage.vue", "isDynamicEntry": true, @@ -125,12 +125,12 @@ ] }, "src/pages/SystemPage.vue": { - "file": "assets/SystemPage-Dmtz_emI.js", + "file": "assets/SystemPage-DCcH_SAQ.js", "name": "SystemPage", "src": "src/pages/SystemPage.vue", "isDynamicEntry": true, "imports": [ - "_update-BrAMPxiF.js", + "_update-DcFD-YxU.js", "index.html" ], "css": [ @@ -138,12 +138,12 @@ ] }, "src/pages/UsersPage.vue": { - "file": "assets/UsersPage-JTbL8-nm.js", + "file": "assets/UsersPage-DhTO_5zp.js", "name": "UsersPage", "src": "src/pages/UsersPage.vue", "isDynamicEntry": true, "imports": [ - "_users-CToznuvL.js", + "_users-CC9BckjT.js", "index.html" ], "css": [ diff --git a/static/admin/assets/AnnouncementsPage-CbLi3NFK.js b/static/admin/assets/AnnouncementsPage-Djmq3Wb7.js similarity index 84% rename from static/admin/assets/AnnouncementsPage-CbLi3NFK.js rename to static/admin/assets/AnnouncementsPage-Djmq3Wb7.js index 9759be9..f8a44f6 100644 --- a/static/admin/assets/AnnouncementsPage-CbLi3NFK.js +++ b/static/admin/assets/AnnouncementsPage-Djmq3Wb7.js @@ -1 +1 @@ -import{S as v,_ as U,r as y,o as L,e as P,f as c,g as e,w as n,n as d,I as F,x as w,y as r,J as H,h as C,m as h,L as u,K as g}from"./index-Da0EvMWc.js";async function J(){const{data:i}=await v.get("/announcements");return i}async function K(i){const{data:s}=await v.post("/announcements",i);return s}async function j(i){const{data:s}=await v.post(`/announcements/${i}/activate`);return s}async function q(i){const{data:s}=await v.post(`/announcements/${i}/deactivate`);return s}async function G(i){const{data:s}=await v.delete(`/announcements/${i}`);return s}const O={class:"page-stack"},Q={class:"app-page-title"},R={class:"actions"},W={class:"table-wrap"},X=["title"],Y={class:"actions"},Z={__name:"AnnouncementsPage",setup(i){const s=y(""),_=y(""),x=y(!1),b=y([]);async function f(){x.value=!0;try{b.value=await J()}catch{b.value=[]}finally{x.value=!1}}function B(){s.value="",_.value=""}async function T(o){const t=s.value.trim(),l=_.value.trim();if(!t||!l){u.error("标题和内容不能为空");return}try{const m=await K({title:t,content:l,is_active:!!o});if(!m?.success){u.error(m?.error||"保存失败");return}u.success("保存成功"),B(),await f()}catch{}}async function A(o){await g.alert(o.content||"",o.title||"公告",{confirmButtonText:"关闭",dangerouslyUseHTMLString:!1})}async function D(o){try{await g.confirm("确定启用该公告吗?启用后将自动停用其他公告。","启用公告",{confirmButtonText:"启用",cancelButtonText:"取消",type:"warning"})}catch{return}try{const t=await j(o.id);if(!t?.success){u.error(t?.error||"启用失败");return}u.success("已启用"),await f()}catch{}}async function z(o){try{await g.confirm("确定停用该公告吗?","停用公告",{confirmButtonText:"停用",cancelButtonText:"取消",type:"warning"})}catch{return}try{const t=await q(o.id);if(!t?.success){u.error(t?.error||"停用失败");return}u.success("已停用"),await f()}catch{}}async function M(o){try{await g.confirm("确定删除该公告吗?删除后无法恢复。","删除公告",{confirmButtonText:"删除",cancelButtonText:"取消",type:"error"})}catch{return}try{const t=await G(o.id);if(!t?.success){u.error(t?.error||"删除失败");return}u.success("已删除"),await f()}catch{}}return L(f),(o,t)=>{const l=d("el-button"),m=d("el-input"),V=d("el-form-item"),E=d("el-form"),$=d("el-card"),p=d("el-table-column"),I=d("el-tag"),N=d("el-table"),S=F("loading");return w(),P("div",O,[c("div",Q,[t[5]||(t[5]=c("h2",null,"公告管理",-1)),c("div",null,[e(l,{onClick:f},{default:n(()=>[...t[4]||(t[4]=[r("刷新",-1)])]),_:1})])]),e($,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:n(()=>[t[9]||(t[9]=c("h3",{class:"section-title"},"创建公告",-1)),e(E,{"label-width":"90px"},{default:n(()=>[e(V,{label:"公告标题"},{default:n(()=>[e(m,{modelValue:s.value,"onUpdate:modelValue":t[0]||(t[0]=a=>s.value=a),placeholder:"请输入公告标题",maxlength:"100","show-word-limit":""},null,8,["modelValue"])]),_:1}),e(V,{label:"公告内容"},{default:n(()=>[e(m,{modelValue:_.value,"onUpdate:modelValue":t[1]||(t[1]=a=>_.value=a),type:"textarea",rows:5,placeholder:"请输入公告内容(将以弹窗形式展示)",maxlength:"2000","show-word-limit":""},null,8,["modelValue"])]),_:1})]),_:1}),c("div",R,[e(l,{type:"primary",onClick:t[2]||(t[2]=a=>T(!0))},{default:n(()=>[...t[6]||(t[6]=[r("发布并启用",-1)])]),_:1}),e(l,{onClick:t[3]||(t[3]=a=>T(!1))},{default:n(()=>[...t[7]||(t[7]=[r("保存但不启用",-1)])]),_:1}),e(l,{onClick:B},{default:n(()=>[...t[8]||(t[8]=[r("清空",-1)])]),_:1})]),t[10]||(t[10]=c("div",{class:"help"}," 说明:启用公告后,用户登录进入系统将弹窗提示;用户可选择“当次关闭”或“永久关闭本次公告”。 ",-1))]),_:1}),e($,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:n(()=>[t[15]||(t[15]=c("h3",{class:"section-title"},"公告列表",-1)),c("div",W,[H((w(),C(N,{data:b.value,style:{width:"100%"}},{default:n(()=>[e(p,{prop:"id",label:"ID",width:"80"}),e(p,{label:"标题","min-width":"240"},{default:n(({row:a})=>[c("span",{class:"ellipsis",title:a.title},h(a.title),9,X)]),_:1}),e(p,{label:"状态",width:"120"},{default:n(({row:a})=>[e(I,{type:a.is_active?"success":"info",effect:"light"},{default:n(()=>[r(h(a.is_active?"启用":"停用"),1)]),_:2},1032,["type"])]),_:1}),e(p,{prop:"created_at",label:"创建时间",width:"180"}),e(p,{label:"操作",width:"260",fixed:"right"},{default:n(({row:a})=>[c("div",Y,[e(l,{size:"small",onClick:k=>A(a)},{default:n(()=>[...t[11]||(t[11]=[r("查看",-1)])]),_:1},8,["onClick"]),a.is_active?(w(),C(l,{key:0,size:"small",onClick:k=>z(a)},{default:n(()=>[...t[12]||(t[12]=[r("停用",-1)])]),_:1},8,["onClick"])):(w(),C(l,{key:1,type:"success",size:"small",onClick:k=>D(a)},{default:n(()=>[...t[13]||(t[13]=[r("启用",-1)])]),_:1},8,["onClick"])),e(l,{type:"danger",size:"small",onClick:k=>M(a)},{default:n(()=>[...t[14]||(t[14]=[r("删除",-1)])]),_:1},8,["onClick"])])]),_:1})]),_:1},8,["data"])),[[S,x.value]])])]),_:1})])}}},et=U(Z,[["__scopeId","data-v-a7b3418e"]]);export{et as default}; +import{S as v,_ as U,r as y,o as L,e as d,I as P,f as j,g as w,h as c,j as e,w as n,p as r,J as q,m as C,q as h,L as u,K as g}from"./index-CdjS44Uj.js";async function F(){const{data:i}=await v.get("/announcements");return i}async function H(i){const{data:s}=await v.post("/announcements",i);return s}async function J(i){const{data:s}=await v.post(`/announcements/${i}/activate`);return s}async function K(i){const{data:s}=await v.post(`/announcements/${i}/deactivate`);return s}async function G(i){const{data:s}=await v.delete(`/announcements/${i}`);return s}const O={class:"page-stack"},Q={class:"app-page-title"},R={class:"actions"},W={class:"table-wrap"},X=["title"],Y={class:"actions"},Z={__name:"AnnouncementsPage",setup(i){const s=y(""),_=y(""),x=y(!1),b=y([]);async function f(){x.value=!0;try{b.value=await F()}catch{b.value=[]}finally{x.value=!1}}function B(){s.value="",_.value=""}async function T(o){const t=s.value.trim(),l=_.value.trim();if(!t||!l){u.error("标题和内容不能为空");return}try{const m=await H({title:t,content:l,is_active:!!o});if(!m?.success){u.error(m?.error||"保存失败");return}u.success("保存成功"),B(),await f()}catch{}}async function A(o){await g.alert(o.content||"",o.title||"公告",{confirmButtonText:"关闭",dangerouslyUseHTMLString:!1})}async function D(o){try{await g.confirm("确定启用该公告吗?启用后将自动停用其他公告。","启用公告",{confirmButtonText:"启用",cancelButtonText:"取消",type:"warning"})}catch{return}try{const t=await J(o.id);if(!t?.success){u.error(t?.error||"启用失败");return}u.success("已启用"),await f()}catch{}}async function z(o){try{await g.confirm("确定停用该公告吗?","停用公告",{confirmButtonText:"停用",cancelButtonText:"取消",type:"warning"})}catch{return}try{const t=await K(o.id);if(!t?.success){u.error(t?.error||"停用失败");return}u.success("已停用"),await f()}catch{}}async function M(o){try{await g.confirm("确定删除该公告吗?删除后无法恢复。","删除公告",{confirmButtonText:"删除",cancelButtonText:"取消",type:"error"})}catch{return}try{const t=await G(o.id);if(!t?.success){u.error(t?.error||"删除失败");return}u.success("已删除"),await f()}catch{}}return L(f),(o,t)=>{const l=d("el-button"),m=d("el-input"),V=d("el-form-item"),E=d("el-form"),$=d("el-card"),p=d("el-table-column"),I=d("el-tag"),N=d("el-table"),S=P("loading");return w(),j("div",O,[c("div",Q,[t[5]||(t[5]=c("h2",null,"公告管理",-1)),c("div",null,[e(l,{onClick:f},{default:n(()=>[...t[4]||(t[4]=[r("刷新",-1)])]),_:1})])]),e($,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:n(()=>[t[9]||(t[9]=c("h3",{class:"section-title"},"创建公告",-1)),e(E,{"label-width":"90px"},{default:n(()=>[e(V,{label:"公告标题"},{default:n(()=>[e(m,{modelValue:s.value,"onUpdate:modelValue":t[0]||(t[0]=a=>s.value=a),placeholder:"请输入公告标题",maxlength:"100","show-word-limit":""},null,8,["modelValue"])]),_:1}),e(V,{label:"公告内容"},{default:n(()=>[e(m,{modelValue:_.value,"onUpdate:modelValue":t[1]||(t[1]=a=>_.value=a),type:"textarea",rows:5,placeholder:"请输入公告内容(将以弹窗形式展示)",maxlength:"2000","show-word-limit":""},null,8,["modelValue"])]),_:1})]),_:1}),c("div",R,[e(l,{type:"primary",onClick:t[2]||(t[2]=a=>T(!0))},{default:n(()=>[...t[6]||(t[6]=[r("发布并启用",-1)])]),_:1}),e(l,{onClick:t[3]||(t[3]=a=>T(!1))},{default:n(()=>[...t[7]||(t[7]=[r("保存但不启用",-1)])]),_:1}),e(l,{onClick:B},{default:n(()=>[...t[8]||(t[8]=[r("清空",-1)])]),_:1})]),t[10]||(t[10]=c("div",{class:"help"}," 说明:启用公告后,用户登录进入系统将弹窗提示;用户可选择“当次关闭”或“永久关闭本次公告”。 ",-1))]),_:1}),e($,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:n(()=>[t[15]||(t[15]=c("h3",{class:"section-title"},"公告列表",-1)),c("div",W,[q((w(),C(N,{data:b.value,style:{width:"100%"}},{default:n(()=>[e(p,{prop:"id",label:"ID",width:"80"}),e(p,{label:"标题","min-width":"240"},{default:n(({row:a})=>[c("span",{class:"ellipsis",title:a.title},h(a.title),9,X)]),_:1}),e(p,{label:"状态",width:"120"},{default:n(({row:a})=>[e(I,{type:a.is_active?"success":"info",effect:"light"},{default:n(()=>[r(h(a.is_active?"启用":"停用"),1)]),_:2},1032,["type"])]),_:1}),e(p,{prop:"created_at",label:"创建时间",width:"180"}),e(p,{label:"操作",width:"260",fixed:"right"},{default:n(({row:a})=>[c("div",Y,[e(l,{size:"small",onClick:k=>A(a)},{default:n(()=>[...t[11]||(t[11]=[r("查看",-1)])]),_:1},8,["onClick"]),a.is_active?(w(),C(l,{key:0,size:"small",onClick:k=>z(a)},{default:n(()=>[...t[12]||(t[12]=[r("停用",-1)])]),_:1},8,["onClick"])):(w(),C(l,{key:1,type:"success",size:"small",onClick:k=>D(a)},{default:n(()=>[...t[13]||(t[13]=[r("启用",-1)])]),_:1},8,["onClick"])),e(l,{type:"danger",size:"small",onClick:k=>M(a)},{default:n(()=>[...t[14]||(t[14]=[r("删除",-1)])]),_:1},8,["onClick"])])]),_:1})]),_:1},8,["data"])),[[S,x.value]])])]),_:1})])}}},et=U(Z,[["__scopeId","data-v-a7b3418e"]]);export{et as default}; diff --git a/static/admin/assets/EmailPage-BxzHc6tN.css b/static/admin/assets/EmailPage-BxzHc6tN.css new file mode 100644 index 0000000..d3ef509 --- /dev/null +++ b/static/admin/assets/EmailPage-BxzHc6tN.css @@ -0,0 +1 @@ +.page-stack[data-v-ff849557]{display:flex;flex-direction:column;gap:12px}.toolbar[data-v-ff849557]{display:flex;gap:10px;align-items:center;flex-wrap:wrap}.card[data-v-ff849557]{border-radius:var(--app-radius);border:1px solid var(--app-border)}.section-head[data-v-ff849557]{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin-bottom:12px;flex-wrap:wrap}.section-title[data-v-ff849557]{margin:0;font-size:14px;font-weight:800}.help[data-v-ff849557]{margin-top:8px;font-size:12px;color:var(--app-muted)}.table-wrap[data-v-ff849557]{overflow-x:auto}.stat-card[data-v-ff849557]{border-radius:var(--app-radius);border:1px solid var(--app-border)}.stat-value[data-v-ff849557]{font-size:20px;font-weight:900;line-height:1.1}.stat-label[data-v-ff849557]{margin-top:6px;font-size:12px;color:var(--app-muted)}.ok[data-v-ff849557]{color:#047857}.err[data-v-ff849557]{color:#b91c1c}.sub-stats[data-v-ff849557]{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.ellipsis[data-v-ff849557]{display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pagination[data-v-ff849557]{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:14px;flex-wrap:wrap}.page-hint[data-v-ff849557]{font-size:12px}.dialog-actions[data-v-ff849557]{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.spacer[data-v-ff849557]{flex:1} diff --git a/static/admin/assets/EmailPage-CaUZghxJ.js b/static/admin/assets/EmailPage-CaUZghxJ.js deleted file mode 100644 index 4730f72..0000000 --- a/static/admin/assets/EmailPage-CaUZghxJ.js +++ /dev/null @@ -1 +0,0 @@ -import{a as $e,f as Ae,b as De,c as He,u as Ne}from"./email-BfqhxXOq.js";import{S as L,_ as Fe,r as p,T as pe,U as ze,c as ce,o as Ie,e as T,f as o,J as O,g as l,w as n,n as f,I as Qe,h as M,x as _,y as d,m as u,j as C,F as ae,p as fe,K as U,L as c}from"./index-Da0EvMWc.js";async function je(){const{data:v}=await L.get("/smtp/configs");return v}async function Ke(v){const{data:y}=await L.post("/smtp/configs",v);return y}async function Oe(v,y){const{data:h}=await L.put(`/smtp/configs/${v}`,y);return h}async function Ge(v){const{data:y}=await L.delete(`/smtp/configs/${v}`);return y}async function Je(v,y){const{data:h}=await L.post(`/smtp/configs/${v}/test`,{email:y});return h}async function Re(v){const{data:y}=await L.post(`/smtp/configs/${v}/primary`);return y}async function We(){const{data:v}=await L.post("/smtp/configs/primary/clear");return v}const Xe={class:"page-stack"},Ye={class:"app-page-title"},Ze={class:"toolbar"},el={class:"help app-muted"},ll={class:"section-head"},tl={class:"table-wrap"},al={class:"stat-value"},sl={class:"stat-value ok"},nl={class:"stat-value err"},ol={class:"stat-value"},il={class:"sub-stats"},ul={class:"help app-muted"},rl={class:"section-head"},dl={class:"toolbar"},ml={class:"table-wrap"},pl=["title"],cl=["title"],fl=["title"],_l={class:"pagination"},vl={class:"page-hint app-muted"},yl={style:{width:"100%"}},bl={key:0,class:"help"},gl={key:0},hl={key:0},wl={key:0},kl={class:"dialog-actions"},_e=15,Vl={__name:"EmailPage",setup(v){const y=p(!1),h=p(!1),r=pe({enabled:!1,failover_enabled:!0,register_verify_enabled:!1,task_notify_enabled:!1,base_url:"",updated_at:null});let E=null;async function se(){y.value=!0;try{const s=await $e();r.enabled=!!s.enabled,r.failover_enabled=!!s.failover_enabled,r.register_verify_enabled=!!s.register_verify_enabled,r.task_notify_enabled=!!s.task_notify_enabled,r.base_url=s.base_url||"",r.updated_at=s.updated_at||null}catch{}finally{y.value=!1}}async function ve(){if(!y.value){h.value=!0;try{const s=await Ne({enabled:r.enabled,failover_enabled:r.failover_enabled,register_verify_enabled:r.register_verify_enabled,task_notify_enabled:r.task_notify_enabled,base_url:(r.base_url||"").trim()});if(!s?.success){c.error(s?.error||"更新失败");return}c.success("邮件设置已更新"),await se()}catch{}finally{h.value=!1}}}function D(){E&&window.clearTimeout(E),E=window.setTimeout(ve,300)}ze(()=>{E&&window.clearTimeout(E),E=null});const G=p(!1),J=p([]),S=p(!1),g=p(!1),R=p(!1),N=p(!1),a=pe({id:null,name:"默认配置",enabled:!0,host:"",port:465,username:"",password:"",use_ssl:!0,use_tls:!1,sender_name:"自动化学习",sender_email:"",daily_limit:0,priority:0}),F=[{key:"custom",label:"自定义(手动填写)",defaults:null,note:"适用于其他邮箱/自建SMTP",links:[]},{key:"gmail",label:"Gmail",defaults:{host:"smtp.gmail.com",port:465,use_ssl:!0,use_tls:!1},note:"通常需要开启两步验证并创建应用专用密码(App Password)",links:[{label:"SMTP 设置说明",url:"https://support.google.com/mail/answer/7126229?hl=zh-Hans"},{label:"App Password",url:"https://myaccount.google.com/apppasswords"}]},{key:"qq",label:"QQ 邮箱",defaults:{host:"smtp.qq.com",port:465,use_ssl:!0,use_tls:!1},note:"需要在邮箱设置中开启 SMTP 并获取授权码(不是QQ登录密码)",links:[{label:"QQ邮箱 SMTP 帮助",url:"https://service.mail.qq.com/cgi-bin/help?subtype=1&id=28&no=1001256"}]},{key:"163",label:"163 邮箱",defaults:{host:"smtp.163.com",port:465,use_ssl:!0,use_tls:!1},note:"需要在邮箱设置中开启 SMTP 并使用授权码/客户端授权密码",links:[{label:"网易邮箱 SMTP 帮助",url:"https://help.mail.163.com/faqDetail.do?code=d7a5dc8471a22b76"}]},{key:"126",label:"126 邮箱",defaults:{host:"smtp.126.com",port:465,use_ssl:!0,use_tls:!1},note:"需要在邮箱设置中开启 SMTP 并使用授权码/客户端授权密码",links:[{label:"网易邮箱帮助",url:"https://help.mail.163.com/"}]},{key:"outlook",label:"Outlook/Hotmail",defaults:{host:"smtp-mail.outlook.com",port:587,use_ssl:!1,use_tls:!0},note:"建议使用 TLS 587(部分账号需开启 SMTP AUTH)",links:[{label:"微软 SMTP 设置",url:"https://support.microsoft.com/office/pop-imap-and-smtp-settings-for-outlook-com-d088b0b7-0d38-4f9a-bc5d-509f9e4c6d3d"}]},{key:"office365",label:"Microsoft 365/Exchange",defaults:{host:"smtp.office365.com",port:587,use_ssl:!1,use_tls:!0},note:"企业邮箱常用配置(需启用 SMTP AUTH)",links:[{label:"微软官方说明",url:"https://learn.microsoft.com/exchange/clients-and-mobile-in-exchange-online/authenticated-client-smtp-submission"}]},{key:"icloud",label:"iCloud",defaults:{host:"smtp.mail.me.com",port:587,use_ssl:!1,use_tls:!0},note:"需要在 Apple ID 中生成“App 专用密码”",links:[{label:"Apple 邮件服务器设置",url:"https://support.apple.com/zh-cn/HT202304"}]},{key:"tencent_exmail",label:"腾讯企业邮箱",defaults:{host:"smtp.exmail.qq.com",port:465,use_ssl:!0,use_tls:!1},note:"企业邮箱常用配置",links:[{label:"腾讯企业邮箱帮助",url:"https://service.exmail.qq.com/cgi-bin/help?subtype=1&id=23&no=1001068"}]},{key:"aliyun_exmail",label:"阿里企业邮箱",defaults:{host:"smtp.mxhichina.com",port:465,use_ssl:!0,use_tls:!1},note:"企业邮箱常用配置",links:[{label:"阿里云文档",url:"https://help.aliyun.com/document_detail/50652.html"}]}],q=p("custom"),k=ce(()=>F.find(s=>s.key===q.value)||F[0]),ye=ce(()=>g.value&&R.value?"留空保持不变":"SMTP密码或授权码");function be(s){const e=String(s?.host||"").trim().toLowerCase();return e&&{"smtp.gmail.com":"gmail","smtp.qq.com":"qq","smtp.163.com":"163","smtp.126.com":"126","smtp-mail.outlook.com":"outlook","smtp.office365.com":"office365","smtp.mail.me.com":"icloud","smtp.exmail.qq.com":"tencent_exmail","smtp.mxhichina.com":"aliyun_exmail"}[e]||"custom"}function ge(s){const e=F.find(i=>i.key===s);!e||!e.defaults||(a.host=e.defaults.host,a.port=e.defaults.port,a.use_ssl=e.defaults.use_ssl,a.use_tls=e.defaults.use_tls)}function ne(){a.id=null,a.name="默认配置",a.enabled=!0,a.host="",a.port=465,a.username="",a.password="",a.use_ssl=!0,a.use_tls=!1,a.sender_name="自动化学习",a.sender_email="",a.daily_limit=0,a.priority=0,R.value=!1,N.value=!1,q.value="custom"}async function $(){G.value=!0;try{J.value=await je()}catch{J.value=[]}finally{G.value=!1}}function he(){g.value=!1,ne(),q.value="custom",S.value=!0}function we(s){g.value=!0,ne(),a.id=s.id,a.name=s.name||"默认配置",a.enabled=!!s.enabled,a.host=s.host||"",a.port=s.port||465,a.username=s.username||"",a.password="",a.use_ssl=!!s.use_ssl,a.use_tls=!!s.use_tls,a.sender_name=s.sender_name||"自动化学习",a.sender_email=s.sender_email||"",a.daily_limit=s.daily_limit??0,a.priority=s.priority??0,R.value=!!s.has_password,N.value=!!s.is_primary,q.value=be(s),S.value=!0}function oe(s){return s.is_primary?{label:"主",type:"warning"}:s.enabled?{label:"备用",type:"success"}:{label:"禁用",type:"info"}}function ke(s){return s.daily_limit&&s.daily_limit>0?`${s.daily_sent}/${s.daily_limit}`:`${s.daily_sent}/∞`}async function Ve(){if(!a.host.trim()){c.error("SMTP服务器地址不能为空");return}if(!a.username.trim()){c.error("SMTP用户名不能为空");return}const s={name:a.name.trim()||"默认配置",enabled:!!a.enabled,priority:Number(a.priority)||0,host:a.host.trim(),port:Number(a.port)||465,username:a.username.trim(),use_ssl:!!a.use_ssl,use_tls:!!a.use_tls,sender_name:(a.sender_name||"").trim(),sender_email:(a.sender_email||"").trim(),daily_limit:Number(a.daily_limit)||0};try{if(g.value){const e={...s};a.password&&(e.password=a.password);const i=await Oe(a.id,e);if(!i?.success){c.error(i?.error||"更新失败");return}c.success("保存成功")}else{const e={...s};a.password&&(e.password=a.password);const i=await Ke(e);if(!i?.success){c.error(i?.error||"创建失败");return}c.success("创建成功")}S.value=!1,await $()}catch{}}async function Se(){if(!g.value||!a.id){c.error("请先保存配置后再测试");return}let s;try{const e=await U.prompt("请输入测试收件邮箱","测试连接",{inputPlaceholder:"name@example.com",confirmButtonText:"发送测试邮件",cancelButtonText:"取消",inputValidator:i=>/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(i||"").trim()),inputErrorMessage:"邮箱格式不正确"});s=String(e.value||"").trim()}catch{return}try{const e=await Je(a.id,s);e?.success?(c.success("测试成功,邮件已发送"),await $()):await U.alert(e?.error||"测试失败","测试失败",{confirmButtonText:"知道了"})}catch{}}async function xe(){if(!(!g.value||!a.id)){try{await U.confirm("确定将该配置设为主配置吗?","设为主配置",{confirmButtonText:"设为主配置",cancelButtonText:"取消",type:"warning"})}catch{return}try{const s=await Re(a.id);if(!s?.success){c.error(s?.error||"设置失败");return}c.success("已设为主配置"),S.value=!1,await $()}catch{}}}async function Te(){if(g.value){try{await U.confirm("确定取消主配置吗?取消后将按优先级选择可用SMTP。","取消主配置",{confirmButtonText:"取消主配置",cancelButtonText:"保留",type:"warning"})}catch{return}try{const s=await We();if(!s?.success){c.error(s?.error||"操作失败");return}c.success("已取消主配置"),S.value=!1,await $()}catch{}}}async function Pe(){if(!(!g.value||!a.id)){try{await U.confirm("确定删除该SMTP配置吗?此操作不可恢复。","删除配置",{confirmButtonText:"删除",cancelButtonText:"取消",type:"error"})}catch{return}try{const s=await Ge(a.id);if(!s?.success){c.error(s?.error||"删除失败");return}c.success("已删除"),S.value=!1,await $()}catch{}}}const W=p(!1),w=p({}),X=p(!1),z=p(""),I=p(""),Q=p(1),Y=p([]),Z=p(0),ee=p(1);function Ce(s){return{register:"注册验证",reset:"密码重置",bind:"邮箱绑定",task_complete:"任务完成"}[s]||s}function ie(s){return s?.username&&s?.user_id?`${s.username} (#${s.user_id})`:s?.user_id?`用户#${s.user_id}`:"系统"}async function Be(){W.value=!0;try{w.value=await Ae()}catch{w.value={}}finally{W.value=!1}}async function H(s=1){X.value=!0;try{const e={page:s,page_size:_e};z.value&&(e.type=z.value),I.value&&(e.status=I.value);const i=await De(e);Y.value=i?.logs||[],Z.value=i?.total||0,Q.value=i?.page||s,ee.value=i?.total_pages||1}catch{Y.value=[],Z.value=0,ee.value=1}finally{X.value=!1}}async function Me(){let s;try{const e=await U.prompt("请输入保留天数(将删除该天数之前的日志)","清理日志",{inputValue:"30",confirmButtonText:"清理",cancelButtonText:"取消",inputValidator:i=>{const V=parseInt(String(i),10);return Number.isFinite(V)&&V>=7},inputErrorMessage:"天数必须大于等于7"});s=parseInt(String(e.value),10)}catch{return}try{await U.confirm(`确定删除 ${s} 天之前的邮件日志吗?`,"二次确认",{confirmButtonText:"删除",cancelButtonText:"取消",type:"warning"})}catch{return}try{const e=await He(s);if(!e?.success){c.error(e?.error||"清理失败");return}c.success(`已清理 ${e.deleted} 条日志`),await H(1)}catch{}}async function ue(){await Promise.all([se(),$(),Be(),H(1)])}return Ie(ue),(s,e)=>{const i=f("el-button"),V=f("el-switch"),m=f("el-form-item"),B=f("el-input"),re=f("el-form"),P=f("el-card"),A=f("el-tag"),b=f("el-table-column"),de=f("el-table"),j=f("el-col"),Ue=f("el-row"),x=f("el-option"),le=f("el-select"),Le=f("el-pagination"),Ee=f("el-link"),te=f("el-input-number"),qe=f("el-dialog"),K=Qe("loading");return _(),T("div",Xe,[o("div",Ye,[e[26]||(e[26]=o("h2",null,"邮件配置",-1)),o("div",Ze,[l(i,{onClick:ue},{default:n(()=>[...e[25]||(e[25]=[d("刷新",-1)])]),_:1})])]),O((_(),M(P,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:n(()=>[e[28]||(e[28]=o("h3",{class:"section-title"},"全局设置",-1)),l(re,{"label-width":"140px"},{default:n(()=>[l(m,{label:"启用邮件功能"},{default:n(()=>[l(V,{modelValue:r.enabled,"onUpdate:modelValue":e[0]||(e[0]=t=>r.enabled=t),disabled:h.value,onChange:D},null,8,["modelValue","disabled"])]),_:1}),l(m,{label:"启用故障转移"},{default:n(()=>[l(V,{modelValue:r.failover_enabled,"onUpdate:modelValue":e[1]||(e[1]=t=>r.failover_enabled=t),disabled:h.value,onChange:D},null,8,["modelValue","disabled"])]),_:1}),l(m,{label:"启用注册邮箱验证"},{default:n(()=>[l(V,{modelValue:r.register_verify_enabled,"onUpdate:modelValue":e[2]||(e[2]=t=>r.register_verify_enabled=t),disabled:h.value,onChange:D},null,8,["modelValue","disabled"])]),_:1}),l(m,{label:"启用任务完成通知"},{default:n(()=>[l(V,{modelValue:r.task_notify_enabled,"onUpdate:modelValue":e[3]||(e[3]=t=>r.task_notify_enabled=t),disabled:h.value,onChange:D},null,8,["modelValue","disabled"])]),_:1}),l(m,{label:"网站基础URL"},{default:n(()=>[l(B,{modelValue:r.base_url,"onUpdate:modelValue":e[4]||(e[4]=t=>r.base_url=t),placeholder:"例如: https://example.com",disabled:h.value,onBlur:D},null,8,["modelValue","disabled"]),e[27]||(e[27]=o("div",{class:"help"},"用于生成邮件中的验证链接,留空则使用默认配置。",-1))]),_:1})]),_:1}),o("div",el,"最近更新时间:"+u(r.updated_at||"-"),1)]),_:1})),[[K,y.value]]),l(P,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:n(()=>[o("div",ll,[e[30]||(e[30]=o("h3",{class:"section-title"},"SMTP配置列表",-1)),l(i,{type:"primary",onClick:he},{default:n(()=>[...e[29]||(e[29]=[d("+ 添加配置",-1)])]),_:1})]),o("div",tl,[O((_(),M(de,{data:J.value,style:{width:"100%"}},{default:n(()=>[l(b,{label:"状态",width:"90"},{default:n(({row:t})=>[l(A,{type:oe(t).type,effect:"light"},{default:n(()=>[d(u(oe(t).label),1)]),_:2},1032,["type"])]),_:1}),l(b,{prop:"name",label:"名称","min-width":"160"}),l(b,{label:"服务器","min-width":"200"},{default:n(({row:t})=>[d(u(t.host)+":"+u(t.port),1)]),_:1}),l(b,{label:"今日/限额",width:"110"},{default:n(({row:t})=>[d(u(ke(t)),1)]),_:1}),l(b,{label:"成功率",width:"100"},{default:n(({row:t})=>[d(u(t.success_rate)+"%",1)]),_:1}),l(b,{label:"操作",width:"120",fixed:"right"},{default:n(({row:t})=>[l(i,{size:"small",onClick:me=>we(t)},{default:n(()=>[...e[31]||(e[31]=[d("编辑",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[K,G.value]])])]),_:1}),O((_(),M(P,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:n(()=>[e[36]||(e[36]=o("h3",{class:"section-title"},"邮件发送统计",-1)),l(Ue,{gutter:12},{default:n(()=>[l(j,{xs:12,sm:6},{default:n(()=>[l(P,{shadow:"never",class:"stat-card","body-style":{padding:"14px"}},{default:n(()=>[o("div",al,u(w.value.total_sent||0),1),e[32]||(e[32]=o("div",{class:"stat-label"},"总发送",-1))]),_:1})]),_:1}),l(j,{xs:12,sm:6},{default:n(()=>[l(P,{shadow:"never",class:"stat-card","body-style":{padding:"14px"}},{default:n(()=>[o("div",sl,u(w.value.total_success||0),1),e[33]||(e[33]=o("div",{class:"stat-label"},"成功",-1))]),_:1})]),_:1}),l(j,{xs:12,sm:6},{default:n(()=>[l(P,{shadow:"never",class:"stat-card","body-style":{padding:"14px"}},{default:n(()=>[o("div",nl,u(w.value.total_failed||0),1),e[34]||(e[34]=o("div",{class:"stat-label"},"失败",-1))]),_:1})]),_:1}),l(j,{xs:12,sm:6},{default:n(()=>[l(P,{shadow:"never",class:"stat-card","body-style":{padding:"14px"}},{default:n(()=>[o("div",ol,u(w.value.success_rate||0)+"%",1),e[35]||(e[35]=o("div",{class:"stat-label"},"成功率",-1))]),_:1})]),_:1})]),_:1}),o("div",il,[l(A,{effect:"light"},{default:n(()=>[d("注册验证 "+u(w.value.register_sent||0),1)]),_:1}),l(A,{effect:"light"},{default:n(()=>[d("密码重置 "+u(w.value.reset_sent||0),1)]),_:1}),l(A,{effect:"light"},{default:n(()=>[d("邮箱绑定 "+u(w.value.bind_sent||0),1)]),_:1}),l(A,{effect:"light"},{default:n(()=>[d("任务完成 "+u(w.value.task_complete_sent||0),1)]),_:1})]),o("div",ul,"最后更新:"+u(w.value.last_updated||"-"),1)]),_:1})),[[K,W.value]]),l(P,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:n(()=>[o("div",rl,[e[38]||(e[38]=o("h3",{class:"section-title"},"邮件发送日志",-1)),o("div",dl,[l(le,{modelValue:z.value,"onUpdate:modelValue":e[5]||(e[5]=t=>z.value=t),style:{width:"140px"},onChange:e[6]||(e[6]=t=>H(1))},{default:n(()=>[l(x,{label:"全部类型",value:""}),l(x,{label:"注册验证",value:"register"}),l(x,{label:"密码重置",value:"reset"}),l(x,{label:"邮箱绑定",value:"bind"}),l(x,{label:"任务完成",value:"task_complete"})]),_:1},8,["modelValue"]),l(le,{modelValue:I.value,"onUpdate:modelValue":e[7]||(e[7]=t=>I.value=t),style:{width:"120px"},onChange:e[8]||(e[8]=t=>H(1))},{default:n(()=>[l(x,{label:"全部状态",value:""}),l(x,{label:"成功",value:"success"}),l(x,{label:"失败",value:"failed"})]),_:1},8,["modelValue"]),l(i,{type:"danger",plain:"",onClick:Me},{default:n(()=>[...e[37]||(e[37]=[d("清理日志",-1)])]),_:1})])]),o("div",ml,[O((_(),M(de,{data:Y.value,style:{width:"100%"}},{default:n(()=>[l(b,{prop:"created_at",label:"时间",width:"180"}),l(b,{prop:"email_to",label:"收件人","min-width":"180"}),l(b,{label:"来源用户","min-width":"160"},{default:n(({row:t})=>[o("span",{class:"ellipsis",title:ie(t)},u(ie(t)),9,pl)]),_:1}),l(b,{label:"类型",width:"120"},{default:n(({row:t})=>[d(u(Ce(t.email_type)),1)]),_:1}),l(b,{label:"主题","min-width":"220"},{default:n(({row:t})=>[o("span",{class:"ellipsis",title:t.subject},u(t.subject),9,cl)]),_:1}),l(b,{label:"状态",width:"90"},{default:n(({row:t})=>[l(A,{type:t.status==="success"?"success":"danger",effect:"light"},{default:n(()=>[d(u(t.status==="success"?"成功":"失败"),1)]),_:2},1032,["type"])]),_:1}),l(b,{label:"错误","min-width":"200"},{default:n(({row:t})=>[o("span",{class:"ellipsis",title:t.error_message||""},u(t.error_message||"-"),9,fl)]),_:1})]),_:1},8,["data"])),[[K,X.value]])]),o("div",_l,[l(Le,{"current-page":Q.value,"onUpdate:currentPage":e[9]||(e[9]=t=>Q.value=t),"page-size":_e,total:Z.value,layout:"prev, pager, next, ->, total",onCurrentChange:H},null,8,["current-page","total"]),o("div",vl,"第 "+u(Q.value)+" / "+u(ee.value)+" 页",1)])]),_:1}),l(qe,{modelValue:S.value,"onUpdate:modelValue":e[24]||(e[24]=t=>S.value=t),title:g.value?"编辑SMTP配置":"添加SMTP配置",width:"min(560px, 92vw)"},{footer:n(()=>[o("div",kl,[l(i,{onClick:Se},{default:n(()=>[...e[39]||(e[39]=[d("测试连接",-1)])]),_:1}),g.value&&N.value?(_(),M(i,{key:0,type:"warning",plain:"",onClick:Te},{default:n(()=>[...e[40]||(e[40]=[d("取消主配置",-1)])]),_:1})):C("",!0),g.value&&!N.value?(_(),M(i,{key:1,onClick:xe},{default:n(()=>[...e[41]||(e[41]=[d("设为主配置",-1)])]),_:1})):C("",!0),g.value?(_(),M(i,{key:2,type:"danger",plain:"",onClick:Pe},{default:n(()=>[...e[42]||(e[42]=[d("删除配置",-1)])]),_:1})):C("",!0),e[45]||(e[45]=o("div",{class:"spacer"},null,-1)),l(i,{onClick:e[23]||(e[23]=t=>S.value=!1)},{default:n(()=>[...e[43]||(e[43]=[d("取消",-1)])]),_:1}),l(i,{type:"primary",onClick:Ve},{default:n(()=>[...e[44]||(e[44]=[d("保存",-1)])]),_:1})])]),default:n(()=>[l(re,{"label-width":"120px"},{default:n(()=>[l(m,{label:"名称"},{default:n(()=>[l(B,{modelValue:a.name,"onUpdate:modelValue":e[10]||(e[10]=t=>a.name=t)},null,8,["modelValue"])]),_:1}),l(m,{label:"启用"},{default:n(()=>[l(V,{modelValue:a.enabled,"onUpdate:modelValue":e[11]||(e[11]=t=>a.enabled=t)},null,8,["modelValue"])]),_:1}),l(m,{label:"邮箱模板"},{default:n(()=>[o("div",yl,[l(le,{modelValue:q.value,"onUpdate:modelValue":e[12]||(e[12]=t=>q.value=t),placeholder:"选择常用邮箱模板",style:{width:"100%"},onChange:ge},{default:n(()=>[(_(),T(ae,null,fe(F,t=>l(x,{key:t.key,label:t.label,value:t.key},null,8,["label","value"])),64))]),_:1},8,["modelValue"]),k.value.note||k.value.links&&k.value.links.length?(_(),T("div",bl,[k.value.note?(_(),T("span",gl,u(k.value.note),1)):C("",!0),k.value.links&&k.value.links.length?(_(),T(ae,{key:1},[k.value.note?(_(),T("span",hl," · ")):C("",!0),(_(!0),T(ae,null,fe(k.value.links,(t,me)=>(_(),T("span",{key:t.url},[l(Ee,{href:t.url,target:"_blank",type:"primary",underline:!1},{default:n(()=>[d(u(t.label),1)]),_:2},1032,["href"]),me(_(),F(He,null,[J(gb,{move:l.value,ratio:c.value,size:r.value,always:v.always},null,8,["move","ratio","size","always"]),J(gb,{move:a.value,ratio:u.value,size:i.value,vertical:"",always:v.always},null,8,["move","ratio","size","always"])],64))}});var V6=Te(F6,[["__file","bar.vue"]]);const H6=Se({distance:{type:Number,default:0},height:{type:[String,Number],default:""},maxHeight:{type:[String,Number],default:""},native:Boolean,wrapStyle:{type:Q([String,Object,Array]),default:""},wrapClass:{type:[String,Array],default:""},viewClass:{type:[String,Array],default:""},viewStyle:{type:[String,Array,Object],default:""},noresize:Boolean,tag:{type:String,default:"div"},always:Boolean,minSize:{type:Number,default:20},tabindex:{type:[String,Number],default:void 0},id:String,role:String,...Pn(["ariaLabel","ariaOrientation"])}),jS={"end-reached":e=>["left","right","top","bottom"].includes(e),scroll:({scrollTop:e,scrollLeft:t})=>[e,t].every(je)},z6="ElScrollbar",K6=q({name:z6}),W6=q({...K6,props:H6,emits:jS,setup(e,{expose:t,emit:n}){const o=e,l=be("scrollbar");let a,r,i,u=0,c=0,d="";const f={bottom:!1,top:!1,right:!1,left:!1},v=L(),p=L(),m=L(),h=L(),g=S(()=>{const I={};return o.height&&(I.height=Qt(o.height)),o.maxHeight&&(I.maxHeight=Qt(o.maxHeight)),[o.wrapStyle,I]}),b=S(()=>[o.wrapClass,l.e("wrap"),{[l.em("wrap","hidden-default")]:!o.native}]),C=S(()=>[l.e("view"),o.viewClass]),y=I=>{var P;return(P=f[I])!=null?P:!1},w={top:"bottom",bottom:"top",left:"right",right:"left"},k=I=>{const P=w[d];if(!P)return;const K=I[d],B=I[P];K&&!f[d]&&(f[d]=!0),!B&&f[P]&&(f[P]=!1)},E=()=>{var I;if(p.value){(I=h.value)==null||I.handleScroll(p.value);const P=u,K=c;u=p.value.scrollTop,c=p.value.scrollLeft;const B={bottom:u+p.value.clientHeight>=p.value.scrollHeight-o.distance,top:u<=o.distance&&P!==0,right:c+p.value.clientWidth>=p.value.scrollWidth-o.distance&&K!==c,left:c<=o.distance&&K!==0};if(n("scroll",{scrollTop:u,scrollLeft:c}),P!==u&&(d=u>P?"bottom":"top"),K!==c&&(d=c>K?"right":"left"),o.distance>0){if(y(d))return;k(B)}B[d]&&n("end-reached",d)}};function T(I,P){et(I)?p.value.scrollTo(I):je(I)&&je(P)&&p.value.scrollTo(I,P)}const x=I=>{je(I)&&(p.value.scrollTop=I)},N=I=>{je(I)&&(p.value.scrollLeft=I)},O=()=>{var I;(I=h.value)==null||I.update(),f[d]=!1};return pe(()=>o.noresize,I=>{I?(a?.(),r?.(),i?.()):({stop:a}=qt(m,O),{stop:r}=qt(p,O),i=At("resize",O))},{immediate:!0}),pe(()=>[o.maxHeight,o.height],()=>{o.native||Le(()=>{var I;O(),p.value&&((I=h.value)==null||I.handleScroll(p.value))})}),ut(Hh,_t({scrollbarElement:v,wrapElement:p})),Id(()=>{p.value&&(p.value.scrollTop=u,p.value.scrollLeft=c)}),rt(()=>{o.native||Le(()=>{O()})}),el(()=>O()),t({wrapRef:p,update:O,scrollTo:T,setScrollTop:x,setScrollLeft:N,handleScroll:E}),(I,P)=>(_(),F("div",{ref_key:"scrollbarRef",ref:v,class:$(s(l).b())},[z("div",{ref_key:"wrapRef",ref:p,class:$(s(b)),style:We(s(g)),tabindex:I.tabindex,onScroll:E},[(_(),ie(at(I.tag),{id:I.id,ref_key:"resizeRef",ref:m,class:$(s(C)),style:We(I.viewStyle),role:I.role,"aria-label":I.ariaLabel,"aria-orientation":I.ariaOrientation},{default:ee(()=>[oe(I.$slots,"default")]),_:3},8,["id","class","style","role","aria-label","aria-orientation"]))],46,["tabindex"]),I.native?re("v-if",!0):(_(),ie(V6,{key:0,ref_key:"barRef",ref:h,always:I.always,"min-size":I.minSize},null,8,["always","min-size"]))],2))}});var j6=Te(W6,[["__file","scrollbar.vue"]]);const Xo=Ze(j6),zh=Symbol("popper"),US=Symbol("popperContent"),qS=["dialog","grid","group","listbox","menu","navigation","tooltip","tree"],YS=Se({role:{type:String,values:qS,default:"tooltip"}}),U6=q({name:"ElPopper",inheritAttrs:!1}),q6=q({...U6,props:YS,setup(e,{expose:t}){const n=e,o=L(),l=L(),a=L(),r=L(),i=S(()=>n.role),u={triggerRef:o,popperInstanceRef:l,contentRef:a,referenceRef:r,role:i};return t(u),ut(zh,u),(c,d)=>oe(c.$slots,"default")}});var Y6=Te(q6,[["__file","popper.vue"]]);const G6=q({name:"ElPopperArrow",inheritAttrs:!1}),X6=q({...G6,setup(e,{expose:t}){const n=be("popper"),{arrowRef:o,arrowStyle:l}=Pe(US,void 0);return Rt(()=>{o.value=void 0}),t({arrowRef:o}),(a,r)=>(_(),F("span",{ref_key:"arrowRef",ref:o,class:$(s(n).e("arrow")),style:We(s(l)),"data-popper-arrow":""},null,6))}});var J6=Te(X6,[["__file","arrow.vue"]]);const GS=Se({virtualRef:{type:Q(Object)},virtualTriggering:Boolean,onMouseenter:{type:Q(Function)},onMouseleave:{type:Q(Function)},onClick:{type:Q(Function)},onKeydown:{type:Q(Function)},onFocus:{type:Q(Function)},onBlur:{type:Q(Function)},onContextmenu:{type:Q(Function)},id:String,open:Boolean}),XS=Symbol("elForwardRef"),Z6=e=>{ut(XS,{setForwardRef:n=>{e.value=n}})},Q6=e=>({mounted(t){e(t)},updated(t){e(t)},unmounted(){e(null)}}),e8="ElOnlyChild",JS=q({name:e8,setup(e,{slots:t,attrs:n}){var o;const l=Pe(XS),a=Q6((o=l?.setForwardRef)!=null?o:Nt);return()=>{var r;const i=(r=t.default)==null?void 0:r.call(t,n);if(!i)return null;const[u,c]=ZS(i);return u?nt(Wl(u,n),[[a]]):null}}});function ZS(e){if(!e)return[null,0];const t=e,n=t.filter(o=>o.type!==on).length;for(const o of t){if(et(o))switch(o.type){case on:continue;case Ts:case"svg":return[bb(o),n];case He:return ZS(o.children);default:return[o,n]}return[bb(o),n]}return[null,0]}function bb(e){const t=be("only-child");return J("span",{class:t.e("content")},[e])}const t8=q({name:"ElPopperTrigger",inheritAttrs:!1}),n8=q({...t8,props:GS,setup(e,{expose:t}){const n=e,{role:o,triggerRef:l}=Pe(zh,void 0);Z6(l);const a=S(()=>i.value?n.id:void 0),r=S(()=>{if(o&&o.value==="tooltip")return n.open&&n.id?n.id:void 0}),i=S(()=>{if(o&&o.value!=="tooltip")return o.value}),u=S(()=>i.value?`${n.open}`:void 0);let c;const d=["onMouseenter","onMouseleave","onClick","onKeydown","onFocus","onBlur","onContextmenu"];return rt(()=>{pe(()=>n.virtualRef,f=>{f&&(l.value=hn(f))},{immediate:!0}),pe(l,(f,v)=>{c?.(),c=void 0,yo(f)&&(d.forEach(p=>{var m;const h=n[p];h&&(f.addEventListener(p.slice(2).toLowerCase(),h,["onFocus","onBlur"].includes(p)),(m=v?.removeEventListener)==null||m.call(v,p.slice(2).toLowerCase(),h,["onFocus","onBlur"].includes(p)))}),Di(f)&&(c=pe([a,r,i,u],p=>{["aria-controls","aria-describedby","aria-haspopup","aria-expanded"].forEach((m,h)=>{rn(p[h])?f.removeAttribute(m):f.setAttribute(m,p[h])})},{immediate:!0}))),yo(v)&&Di(v)&&["aria-controls","aria-describedby","aria-haspopup","aria-expanded"].forEach(p=>v.removeAttribute(p))},{immediate:!0})}),Rt(()=>{if(c?.(),c=void 0,l.value&&yo(l.value)){const f=l.value;d.forEach(v=>{const p=n[v];p&&f.removeEventListener(v.slice(2).toLowerCase(),p,["onFocus","onBlur"].includes(v))}),l.value=void 0}}),t({triggerRef:l}),(f,v)=>f.virtualTriggering?re("v-if",!0):(_(),ie(s(JS),ot({key:0},f.$attrs,{"aria-controls":s(a),"aria-describedby":s(r),"aria-expanded":s(u),"aria-haspopup":s(i)}),{default:ee(()=>[oe(f.$slots,"default")]),_:3},16,["aria-controls","aria-describedby","aria-expanded","aria-haspopup"]))}});var o8=Te(n8,[["__file","trigger.vue"]]);const Wf="focus-trap.focus-after-trapped",jf="focus-trap.focus-after-released",l8="focus-trap.focusout-prevented",yb={cancelable:!0,bubbles:!1},a8={cancelable:!0,bubbles:!1},wb="focusAfterTrapped",Cb="focusAfterReleased",Kh=Symbol("elFocusTrap"),Wh=L(),Zd=L(0),jh=L(0);let Wu=0;const QS=e=>{const t=[],n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT,{acceptNode:o=>{const l=o.tagName==="INPUT"&&o.type==="hidden";return o.disabled||o.hidden||l?NodeFilter.FILTER_SKIP:o.tabIndex>=0||o===document.activeElement?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}});for(;n.nextNode();)t.push(n.currentNode);return t},Sb=(e,t)=>{for(const n of e)if(!r8(n,t))return n},r8=(e,t)=>{if(getComputedStyle(e).visibility==="hidden")return!0;for(;e;){if(t&&e===t)return!1;if(getComputedStyle(e).display==="none")return!0;e=e.parentElement}return!1},s8=e=>{const t=QS(e),n=Sb(t,e),o=Sb(t.reverse(),e);return[n,o]},i8=e=>e instanceof HTMLInputElement&&"select"in e,ia=(e,t)=>{if(e){const n=document.activeElement;hu(e,{preventScroll:!0}),jh.value=window.performance.now(),e!==n&&i8(e)&&t&&e.select()}};function kb(e,t){const n=[...e],o=e.indexOf(t);return o!==-1&&n.splice(o,1),n}const u8=()=>{let e=[];return{push:o=>{const l=e[0];l&&o!==l&&l.pause(),e=kb(e,o),e.unshift(o)},remove:o=>{var l,a;e=kb(e,o),(a=(l=e[0])==null?void 0:l.resume)==null||a.call(l)}}},c8=(e,t=!1)=>{const n=document.activeElement;for(const o of e)if(ia(o,t),document.activeElement!==n)return},Eb=u8(),d8=()=>Zd.value>jh.value,ju=()=>{Wh.value="pointer",Zd.value=window.performance.now()},_b=()=>{Wh.value="keyboard",Zd.value=window.performance.now()},f8=()=>(rt(()=>{Wu===0&&(document.addEventListener("mousedown",ju),document.addEventListener("touchstart",ju),document.addEventListener("keydown",_b)),Wu++}),Rt(()=>{Wu--,Wu<=0&&(document.removeEventListener("mousedown",ju),document.removeEventListener("touchstart",ju),document.removeEventListener("keydown",_b))}),{focusReason:Wh,lastUserFocusTimestamp:Zd,lastAutomatedFocusTimestamp:jh}),Uu=e=>new CustomEvent(l8,{...a8,detail:e}),xe={tab:"Tab",enter:"Enter",space:"Space",left:"ArrowLeft",up:"ArrowUp",right:"ArrowRight",down:"ArrowDown",esc:"Escape",delete:"Delete",backspace:"Backspace",numpadEnter:"NumpadEnter",pageUp:"PageUp",pageDown:"PageDown",home:"Home",end:"End"};let Dr=[];const Tb=e=>{e.code===xe.esc&&Dr.forEach(t=>t(e))},p8=e=>{rt(()=>{Dr.length===0&&document.addEventListener("keydown",Tb),kt&&Dr.push(e)}),Rt(()=>{Dr=Dr.filter(t=>t!==e),Dr.length===0&&kt&&document.removeEventListener("keydown",Tb)})},v8=q({name:"ElFocusTrap",inheritAttrs:!1,props:{loop:Boolean,trapped:Boolean,focusTrapEl:Object,focusStartEl:{type:[Object,String],default:"first"}},emits:[wb,Cb,"focusin","focusout","focusout-prevented","release-requested"],setup(e,{emit:t}){const n=L();let o,l;const{focusReason:a}=f8();p8(m=>{e.trapped&&!r.paused&&t("release-requested",m)});const r={paused:!1,pause(){this.paused=!0},resume(){this.paused=!1}},i=m=>{if(!e.loop&&!e.trapped||r.paused)return;const{code:h,altKey:g,ctrlKey:b,metaKey:C,currentTarget:y,shiftKey:w}=m,{loop:k}=e,E=h===xe.tab&&!g&&!b&&!C,T=document.activeElement;if(E&&T){const x=y,[N,O]=s8(x);if(N&&O){if(!w&&T===O){const P=Uu({focusReason:a.value});t("focusout-prevented",P),P.defaultPrevented||(m.preventDefault(),k&&ia(N,!0))}else if(w&&[N,x].includes(T)){const P=Uu({focusReason:a.value});t("focusout-prevented",P),P.defaultPrevented||(m.preventDefault(),k&&ia(O,!0))}}else if(T===x){const P=Uu({focusReason:a.value});t("focusout-prevented",P),P.defaultPrevented||m.preventDefault()}}};ut(Kh,{focusTrapRef:n,onKeydown:i}),pe(()=>e.focusTrapEl,m=>{m&&(n.value=m)},{immediate:!0}),pe([n],([m],[h])=>{m&&(m.addEventListener("keydown",i),m.addEventListener("focusin",d),m.addEventListener("focusout",f)),h&&(h.removeEventListener("keydown",i),h.removeEventListener("focusin",d),h.removeEventListener("focusout",f))});const u=m=>{t(wb,m)},c=m=>t(Cb,m),d=m=>{const h=s(n);if(!h)return;const g=m.target,b=m.relatedTarget,C=g&&h.contains(g);e.trapped||b&&h.contains(b)||(o=b),C&&t("focusin",m),!r.paused&&e.trapped&&(C?l=g:ia(l,!0))},f=m=>{const h=s(n);if(!(r.paused||!h))if(e.trapped){const g=m.relatedTarget;!rn(g)&&!h.contains(g)&&setTimeout(()=>{if(!r.paused&&e.trapped){const b=Uu({focusReason:a.value});t("focusout-prevented",b),b.defaultPrevented||ia(l,!0)}},0)}else{const g=m.target;g&&h.contains(g)||t("focusout",m)}};async function v(){await Le();const m=s(n);if(m){Eb.push(r);const h=m.contains(document.activeElement)?o:document.activeElement;if(o=h,!m.contains(h)){const b=new Event(Wf,yb);m.addEventListener(Wf,u),m.dispatchEvent(b),b.defaultPrevented||Le(()=>{let C=e.focusStartEl;Fe(C)||(ia(C),document.activeElement!==C&&(C="first")),C==="first"&&c8(QS(m),!0),(document.activeElement===h||C==="container")&&ia(m)})}}}function p(){const m=s(n);if(m){m.removeEventListener(Wf,u);const h=new CustomEvent(jf,{...yb,detail:{focusReason:a.value}});m.addEventListener(jf,c),m.dispatchEvent(h),!h.defaultPrevented&&(a.value=="keyboard"||!d8()||m.contains(document.activeElement))&&ia(o??document.body),m.removeEventListener(jf,c),Eb.remove(r),o=null,l=null}}return rt(()=>{e.trapped&&v(),pe(()=>e.trapped,m=>{m?v():p()})}),Rt(()=>{e.trapped&&p(),n.value&&(n.value.removeEventListener("keydown",i),n.value.removeEventListener("focusin",d),n.value.removeEventListener("focusout",f),n.value=void 0)}),{onKeydown:i}}});function h8(e,t,n,o,l,a){return oe(e.$slots,"default",{handleKeydown:e.onKeydown})}var kr=Te(v8,[["render",h8],["__file","focus-trap.vue"]]),so="top",Po="bottom",xo="right",io="left",Uh="auto",gu=[so,Po,xo,io],ds="start",Bi="end",m8="clippingParents",e2="viewport",qs="popper",g8="reference",Ob=gu.reduce(function(e,t){return e.concat([t+"-"+ds,t+"-"+Bi])},[]),na=[].concat(gu,[Uh]).reduce(function(e,t){return e.concat([t,t+"-"+ds,t+"-"+Bi])},[]),b8="beforeRead",y8="read",w8="afterRead",C8="beforeMain",S8="main",k8="afterMain",E8="beforeWrite",_8="write",T8="afterWrite",O8=[b8,y8,w8,C8,S8,k8,E8,_8,T8];function wl(e){return e?(e.nodeName||"").toLowerCase():null}function ol(e){if(e==null)return window;if(e.toString()!=="[object Window]"){var t=e.ownerDocument;return t&&t.defaultView||window}return e}function fs(e){var t=ol(e).Element;return e instanceof t||e instanceof Element}function Ro(e){var t=ol(e).HTMLElement;return e instanceof t||e instanceof HTMLElement}function qh(e){if(typeof ShadowRoot>"u")return!1;var t=ol(e).ShadowRoot;return e instanceof t||e instanceof ShadowRoot}function $8(e){var t=e.state;Object.keys(t.elements).forEach(function(n){var o=t.styles[n]||{},l=t.attributes[n]||{},a=t.elements[n];!Ro(a)||!wl(a)||(Object.assign(a.style,o),Object.keys(l).forEach(function(r){var i=l[r];i===!1?a.removeAttribute(r):a.setAttribute(r,i===!0?"":i)}))})}function R8(e){var t=e.state,n={popper:{position:t.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(t.elements.popper.style,n.popper),t.styles=n,t.elements.arrow&&Object.assign(t.elements.arrow.style,n.arrow),function(){Object.keys(t.elements).forEach(function(o){var l=t.elements[o],a=t.attributes[o]||{},r=Object.keys(t.styles.hasOwnProperty(o)?t.styles[o]:n[o]),i=r.reduce(function(u,c){return u[c]="",u},{});!Ro(l)||!wl(l)||(Object.assign(l.style,i),Object.keys(a).forEach(function(u){l.removeAttribute(u)}))})}}var t2={name:"applyStyles",enabled:!0,phase:"write",fn:$8,effect:R8,requires:["computeStyles"]};function hl(e){return e.split("-")[0]}var tr=Math.max,Qc=Math.min,ps=Math.round;function vs(e,t){t===void 0&&(t=!1);var n=e.getBoundingClientRect(),o=1,l=1;if(Ro(e)&&t){var a=e.offsetHeight,r=e.offsetWidth;r>0&&(o=ps(n.width)/r||1),a>0&&(l=ps(n.height)/a||1)}return{width:n.width/o,height:n.height/l,top:n.top/l,right:n.right/o,bottom:n.bottom/l,left:n.left/o,x:n.left/o,y:n.top/l}}function Yh(e){var t=vs(e),n=e.offsetWidth,o=e.offsetHeight;return Math.abs(t.width-n)<=1&&(n=t.width),Math.abs(t.height-o)<=1&&(o=t.height),{x:e.offsetLeft,y:e.offsetTop,width:n,height:o}}function n2(e,t){var n=t.getRootNode&&t.getRootNode();if(e.contains(t))return!0;if(n&&qh(n)){var o=t;do{if(o&&e.isSameNode(o))return!0;o=o.parentNode||o.host}while(o)}return!1}function Ul(e){return ol(e).getComputedStyle(e)}function N8(e){return["table","td","th"].indexOf(wl(e))>=0}function Ma(e){return((fs(e)?e.ownerDocument:e.document)||window.document).documentElement}function Qd(e){return wl(e)==="html"?e:e.assignedSlot||e.parentNode||(qh(e)?e.host:null)||Ma(e)}function $b(e){return!Ro(e)||Ul(e).position==="fixed"?null:e.offsetParent}function I8(e){var t=navigator.userAgent.toLowerCase().indexOf("firefox")!==-1,n=navigator.userAgent.indexOf("Trident")!==-1;if(n&&Ro(e)){var o=Ul(e);if(o.position==="fixed")return null}var l=Qd(e);for(qh(l)&&(l=l.host);Ro(l)&&["html","body"].indexOf(wl(l))<0;){var a=Ul(l);if(a.transform!=="none"||a.perspective!=="none"||a.contain==="paint"||["transform","perspective"].indexOf(a.willChange)!==-1||t&&a.willChange==="filter"||t&&a.filter&&a.filter!=="none")return l;l=l.parentNode}return null}function bu(e){for(var t=ol(e),n=$b(e);n&&N8(n)&&Ul(n).position==="static";)n=$b(n);return n&&(wl(n)==="html"||wl(n)==="body"&&Ul(n).position==="static")?t:n||I8(e)||t}function Gh(e){return["top","bottom"].indexOf(e)>=0?"x":"y"}function bi(e,t,n){return tr(e,Qc(t,n))}function P8(e,t,n){var o=bi(e,t,n);return o>n?n:o}function o2(){return{top:0,right:0,bottom:0,left:0}}function l2(e){return Object.assign({},o2(),e)}function a2(e,t){return t.reduce(function(n,o){return n[o]=e,n},{})}var x8=function(e,t){return e=typeof e=="function"?e(Object.assign({},t.rects,{placement:t.placement})):e,l2(typeof e!="number"?e:a2(e,gu))};function M8(e){var t,n=e.state,o=e.name,l=e.options,a=n.elements.arrow,r=n.modifiersData.popperOffsets,i=hl(n.placement),u=Gh(i),c=[io,xo].indexOf(i)>=0,d=c?"height":"width";if(!(!a||!r)){var f=x8(l.padding,n),v=Yh(a),p=u==="y"?so:io,m=u==="y"?Po:xo,h=n.rects.reference[d]+n.rects.reference[u]-r[u]-n.rects.popper[d],g=r[u]-n.rects.reference[u],b=bu(a),C=b?u==="y"?b.clientHeight||0:b.clientWidth||0:0,y=h/2-g/2,w=f[p],k=C-v[d]-f[m],E=C/2-v[d]/2+y,T=bi(w,E,k),x=u;n.modifiersData[o]=(t={},t[x]=T,t.centerOffset=T-E,t)}}function A8(e){var t=e.state,n=e.options,o=n.element,l=o===void 0?"[data-popper-arrow]":o;l!=null&&(typeof l=="string"&&(l=t.elements.popper.querySelector(l),!l)||!n2(t.elements.popper,l)||(t.elements.arrow=l))}var L8={name:"arrow",enabled:!0,phase:"main",fn:M8,effect:A8,requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function hs(e){return e.split("-")[1]}var D8={top:"auto",right:"auto",bottom:"auto",left:"auto"};function B8(e){var t=e.x,n=e.y,o=window,l=o.devicePixelRatio||1;return{x:ps(t*l)/l||0,y:ps(n*l)/l||0}}function Rb(e){var t,n=e.popper,o=e.popperRect,l=e.placement,a=e.variation,r=e.offsets,i=e.position,u=e.gpuAcceleration,c=e.adaptive,d=e.roundOffsets,f=e.isFixed,v=r.x,p=v===void 0?0:v,m=r.y,h=m===void 0?0:m,g=typeof d=="function"?d({x:p,y:h}):{x:p,y:h};p=g.x,h=g.y;var b=r.hasOwnProperty("x"),C=r.hasOwnProperty("y"),y=io,w=so,k=window;if(c){var E=bu(n),T="clientHeight",x="clientWidth";if(E===ol(n)&&(E=Ma(n),Ul(E).position!=="static"&&i==="absolute"&&(T="scrollHeight",x="scrollWidth")),E=E,l===so||(l===io||l===xo)&&a===Bi){w=Po;var N=f&&E===k&&k.visualViewport?k.visualViewport.height:E[T];h-=N-o.height,h*=u?1:-1}if(l===io||(l===so||l===Po)&&a===Bi){y=xo;var O=f&&E===k&&k.visualViewport?k.visualViewport.width:E[x];p-=O-o.width,p*=u?1:-1}}var I=Object.assign({position:i},c&&D8),P=d===!0?B8({x:p,y:h}):{x:p,y:h};if(p=P.x,h=P.y,u){var K;return Object.assign({},I,(K={},K[w]=C?"0":"",K[y]=b?"0":"",K.transform=(k.devicePixelRatio||1)<=1?"translate("+p+"px, "+h+"px)":"translate3d("+p+"px, "+h+"px, 0)",K))}return Object.assign({},I,(t={},t[w]=C?h+"px":"",t[y]=b?p+"px":"",t.transform="",t))}function F8(e){var t=e.state,n=e.options,o=n.gpuAcceleration,l=o===void 0?!0:o,a=n.adaptive,r=a===void 0?!0:a,i=n.roundOffsets,u=i===void 0?!0:i,c={placement:hl(t.placement),variation:hs(t.placement),popper:t.elements.popper,popperRect:t.rects.popper,gpuAcceleration:l,isFixed:t.options.strategy==="fixed"};t.modifiersData.popperOffsets!=null&&(t.styles.popper=Object.assign({},t.styles.popper,Rb(Object.assign({},c,{offsets:t.modifiersData.popperOffsets,position:t.options.strategy,adaptive:r,roundOffsets:u})))),t.modifiersData.arrow!=null&&(t.styles.arrow=Object.assign({},t.styles.arrow,Rb(Object.assign({},c,{offsets:t.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:u})))),t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-placement":t.placement})}var r2={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:F8,data:{}},qu={passive:!0};function V8(e){var t=e.state,n=e.instance,o=e.options,l=o.scroll,a=l===void 0?!0:l,r=o.resize,i=r===void 0?!0:r,u=ol(t.elements.popper),c=[].concat(t.scrollParents.reference,t.scrollParents.popper);return a&&c.forEach(function(d){d.addEventListener("scroll",n.update,qu)}),i&&u.addEventListener("resize",n.update,qu),function(){a&&c.forEach(function(d){d.removeEventListener("scroll",n.update,qu)}),i&&u.removeEventListener("resize",n.update,qu)}}var s2={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:V8,data:{}},H8={left:"right",right:"left",bottom:"top",top:"bottom"};function fc(e){return e.replace(/left|right|bottom|top/g,function(t){return H8[t]})}var z8={start:"end",end:"start"};function Nb(e){return e.replace(/start|end/g,function(t){return z8[t]})}function Xh(e){var t=ol(e),n=t.pageXOffset,o=t.pageYOffset;return{scrollLeft:n,scrollTop:o}}function Jh(e){return vs(Ma(e)).left+Xh(e).scrollLeft}function K8(e){var t=ol(e),n=Ma(e),o=t.visualViewport,l=n.clientWidth,a=n.clientHeight,r=0,i=0;return o&&(l=o.width,a=o.height,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(r=o.offsetLeft,i=o.offsetTop)),{width:l,height:a,x:r+Jh(e),y:i}}function W8(e){var t,n=Ma(e),o=Xh(e),l=(t=e.ownerDocument)==null?void 0:t.body,a=tr(n.scrollWidth,n.clientWidth,l?l.scrollWidth:0,l?l.clientWidth:0),r=tr(n.scrollHeight,n.clientHeight,l?l.scrollHeight:0,l?l.clientHeight:0),i=-o.scrollLeft+Jh(e),u=-o.scrollTop;return Ul(l||n).direction==="rtl"&&(i+=tr(n.clientWidth,l?l.clientWidth:0)-a),{width:a,height:r,x:i,y:u}}function Zh(e){var t=Ul(e),n=t.overflow,o=t.overflowX,l=t.overflowY;return/auto|scroll|overlay|hidden/.test(n+l+o)}function i2(e){return["html","body","#document"].indexOf(wl(e))>=0?e.ownerDocument.body:Ro(e)&&Zh(e)?e:i2(Qd(e))}function yi(e,t){var n;t===void 0&&(t=[]);var o=i2(e),l=o===((n=e.ownerDocument)==null?void 0:n.body),a=ol(o),r=l?[a].concat(a.visualViewport||[],Zh(o)?o:[]):o,i=t.concat(r);return l?i:i.concat(yi(Qd(r)))}function zp(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}function j8(e){var t=vs(e);return t.top=t.top+e.clientTop,t.left=t.left+e.clientLeft,t.bottom=t.top+e.clientHeight,t.right=t.left+e.clientWidth,t.width=e.clientWidth,t.height=e.clientHeight,t.x=t.left,t.y=t.top,t}function Ib(e,t){return t===e2?zp(K8(e)):fs(t)?j8(t):zp(W8(Ma(e)))}function U8(e){var t=yi(Qd(e)),n=["absolute","fixed"].indexOf(Ul(e).position)>=0,o=n&&Ro(e)?bu(e):e;return fs(o)?t.filter(function(l){return fs(l)&&n2(l,o)&&wl(l)!=="body"}):[]}function q8(e,t,n){var o=t==="clippingParents"?U8(e):[].concat(t),l=[].concat(o,[n]),a=l[0],r=l.reduce(function(i,u){var c=Ib(e,u);return i.top=tr(c.top,i.top),i.right=Qc(c.right,i.right),i.bottom=Qc(c.bottom,i.bottom),i.left=tr(c.left,i.left),i},Ib(e,a));return r.width=r.right-r.left,r.height=r.bottom-r.top,r.x=r.left,r.y=r.top,r}function u2(e){var t=e.reference,n=e.element,o=e.placement,l=o?hl(o):null,a=o?hs(o):null,r=t.x+t.width/2-n.width/2,i=t.y+t.height/2-n.height/2,u;switch(l){case so:u={x:r,y:t.y-n.height};break;case Po:u={x:r,y:t.y+t.height};break;case xo:u={x:t.x+t.width,y:i};break;case io:u={x:t.x-n.width,y:i};break;default:u={x:t.x,y:t.y}}var c=l?Gh(l):null;if(c!=null){var d=c==="y"?"height":"width";switch(a){case ds:u[c]=u[c]-(t[d]/2-n[d]/2);break;case Bi:u[c]=u[c]+(t[d]/2-n[d]/2);break}}return u}function Fi(e,t){t===void 0&&(t={});var n=t,o=n.placement,l=o===void 0?e.placement:o,a=n.boundary,r=a===void 0?m8:a,i=n.rootBoundary,u=i===void 0?e2:i,c=n.elementContext,d=c===void 0?qs:c,f=n.altBoundary,v=f===void 0?!1:f,p=n.padding,m=p===void 0?0:p,h=l2(typeof m!="number"?m:a2(m,gu)),g=d===qs?g8:qs,b=e.rects.popper,C=e.elements[v?g:d],y=q8(fs(C)?C:C.contextElement||Ma(e.elements.popper),r,u),w=vs(e.elements.reference),k=u2({reference:w,element:b,placement:l}),E=zp(Object.assign({},b,k)),T=d===qs?E:w,x={top:y.top-T.top+h.top,bottom:T.bottom-y.bottom+h.bottom,left:y.left-T.left+h.left,right:T.right-y.right+h.right},N=e.modifiersData.offset;if(d===qs&&N){var O=N[l];Object.keys(x).forEach(function(I){var P=[xo,Po].indexOf(I)>=0?1:-1,K=[so,Po].indexOf(I)>=0?"y":"x";x[I]+=O[K]*P})}return x}function Y8(e,t){t===void 0&&(t={});var n=t,o=n.placement,l=n.boundary,a=n.rootBoundary,r=n.padding,i=n.flipVariations,u=n.allowedAutoPlacements,c=u===void 0?na:u,d=hs(o),f=d?i?Ob:Ob.filter(function(m){return hs(m)===d}):gu,v=f.filter(function(m){return c.indexOf(m)>=0});v.length===0&&(v=f);var p=v.reduce(function(m,h){return m[h]=Fi(e,{placement:h,boundary:l,rootBoundary:a,padding:r})[hl(h)],m},{});return Object.keys(p).sort(function(m,h){return p[m]-p[h]})}function G8(e){if(hl(e)===Uh)return[];var t=fc(e);return[Nb(e),t,Nb(t)]}function X8(e){var t=e.state,n=e.options,o=e.name;if(!t.modifiersData[o]._skip){for(var l=n.mainAxis,a=l===void 0?!0:l,r=n.altAxis,i=r===void 0?!0:r,u=n.fallbackPlacements,c=n.padding,d=n.boundary,f=n.rootBoundary,v=n.altBoundary,p=n.flipVariations,m=p===void 0?!0:p,h=n.allowedAutoPlacements,g=t.options.placement,b=hl(g),C=b===g,y=u||(C||!m?[fc(g)]:G8(g)),w=[g].concat(y).reduce(function(te,le){return te.concat(hl(le)===Uh?Y8(t,{placement:le,boundary:d,rootBoundary:f,padding:c,flipVariations:m,allowedAutoPlacements:h}):le)},[]),k=t.rects.reference,E=t.rects.popper,T=new Map,x=!0,N=w[0],O=0;O (_(),F(He,null,[J(wb,{move:l.value,ratio:c.value,size:r.value,always:v.always},null,8,["move","ratio","size","always"]),J(wb,{move:a.value,ratio:u.value,size:i.value,vertical:"",always:v.always},null,8,["move","ratio","size","always"])],64))}});var H6=Te(V6,[["__file","bar.vue"]]);const z6=Se({distance:{type:Number,default:0},height:{type:[String,Number],default:""},maxHeight:{type:[String,Number],default:""},native:Boolean,wrapStyle:{type:Q([String,Object,Array]),default:""},wrapClass:{type:[String,Array],default:""},viewClass:{type:[String,Array],default:""},viewStyle:{type:[String,Array,Object],default:""},noresize:Boolean,tag:{type:String,default:"div"},always:Boolean,minSize:{type:Number,default:20},tabindex:{type:[String,Number],default:void 0},id:String,role:String,...Pn(["ariaLabel","ariaOrientation"])}),YS={"end-reached":e=>["left","right","top","bottom"].includes(e),scroll:({scrollTop:e,scrollLeft:t})=>[e,t].every(je)},K6="ElScrollbar",W6=q({name:K6}),j6=q({...W6,props:z6,emits:YS,setup(e,{expose:t,emit:n}){const o=e,l=be("scrollbar");let a,r,i,u=0,c=0,d="";const f={bottom:!1,top:!1,right:!1,left:!1},v=L(),p=L(),m=L(),h=L(),g=S(()=>{const I={};return o.height&&(I.height=Qt(o.height)),o.maxHeight&&(I.maxHeight=Qt(o.maxHeight)),[o.wrapStyle,I]}),b=S(()=>[o.wrapClass,l.e("wrap"),{[l.em("wrap","hidden-default")]:!o.native}]),C=S(()=>[l.e("view"),o.viewClass]),y=I=>{var P;return(P=f[I])!=null?P:!1},w={top:"bottom",bottom:"top",left:"right",right:"left"},k=I=>{const P=w[d];if(!P)return;const K=I[d],B=I[P];K&&!f[d]&&(f[d]=!0),!B&&f[P]&&(f[P]=!1)},E=()=>{var I;if(p.value){(I=h.value)==null||I.handleScroll(p.value);const P=u,K=c;u=p.value.scrollTop,c=p.value.scrollLeft;const B={bottom:u+p.value.clientHeight>=p.value.scrollHeight-o.distance,top:u<=o.distance&&P!==0,right:c+p.value.clientWidth>=p.value.scrollWidth-o.distance&&K!==c,left:c<=o.distance&&K!==0};if(n("scroll",{scrollTop:u,scrollLeft:c}),P!==u&&(d=u>P?"bottom":"top"),K!==c&&(d=c>K?"right":"left"),o.distance>0){if(y(d))return;k(B)}B[d]&&n("end-reached",d)}};function T(I,P){et(I)?p.value.scrollTo(I):je(I)&&je(P)&&p.value.scrollTo(I,P)}const x=I=>{je(I)&&(p.value.scrollTop=I)},N=I=>{je(I)&&(p.value.scrollLeft=I)},O=()=>{var I;(I=h.value)==null||I.update(),f[d]=!1};return pe(()=>o.noresize,I=>{I?(a?.(),r?.(),i?.()):({stop:a}=qt(m,O),{stop:r}=qt(p,O),i=At("resize",O))},{immediate:!0}),pe(()=>[o.maxHeight,o.height],()=>{o.native||Le(()=>{var I;O(),p.value&&((I=h.value)==null||I.handleScroll(p.value))})}),ut(zh,_t({scrollbarElement:v,wrapElement:p})),Pd(()=>{p.value&&(p.value.scrollTop=u,p.value.scrollLeft=c)}),rt(()=>{o.native||Le(()=>{O()})}),el(()=>O()),t({wrapRef:p,update:O,scrollTo:T,setScrollTop:x,setScrollLeft:N,handleScroll:E}),(I,P)=>(_(),F("div",{ref_key:"scrollbarRef",ref:v,class:$(s(l).b())},[z("div",{ref_key:"wrapRef",ref:p,class:$(s(b)),style:We(s(g)),tabindex:I.tabindex,onScroll:E},[(_(),ie(at(I.tag),{id:I.id,ref_key:"resizeRef",ref:m,class:$(s(C)),style:We(I.viewStyle),role:I.role,"aria-label":I.ariaLabel,"aria-orientation":I.ariaOrientation},{default:ee(()=>[oe(I.$slots,"default")]),_:3},8,["id","class","style","role","aria-label","aria-orientation"]))],46,["tabindex"]),I.native?re("v-if",!0):(_(),ie(H6,{key:0,ref_key:"barRef",ref:h,always:I.always,"min-size":I.minSize},null,8,["always","min-size"]))],2))}});var U6=Te(j6,[["__file","scrollbar.vue"]]);const Xo=Ze(U6),Kh=Symbol("popper"),GS=Symbol("popperContent"),XS=["dialog","grid","group","listbox","menu","navigation","tooltip","tree"],JS=Se({role:{type:String,values:XS,default:"tooltip"}}),q6=q({name:"ElPopper",inheritAttrs:!1}),Y6=q({...q6,props:JS,setup(e,{expose:t}){const n=e,o=L(),l=L(),a=L(),r=L(),i=S(()=>n.role),u={triggerRef:o,popperInstanceRef:l,contentRef:a,referenceRef:r,role:i};return t(u),ut(Kh,u),(c,d)=>oe(c.$slots,"default")}});var G6=Te(Y6,[["__file","popper.vue"]]);const X6=q({name:"ElPopperArrow",inheritAttrs:!1}),J6=q({...X6,setup(e,{expose:t}){const n=be("popper"),{arrowRef:o,arrowStyle:l}=Pe(GS,void 0);return Rt(()=>{o.value=void 0}),t({arrowRef:o}),(a,r)=>(_(),F("span",{ref_key:"arrowRef",ref:o,class:$(s(n).e("arrow")),style:We(s(l)),"data-popper-arrow":""},null,6))}});var Z6=Te(J6,[["__file","arrow.vue"]]);const ZS=Se({virtualRef:{type:Q(Object)},virtualTriggering:Boolean,onMouseenter:{type:Q(Function)},onMouseleave:{type:Q(Function)},onClick:{type:Q(Function)},onKeydown:{type:Q(Function)},onFocus:{type:Q(Function)},onBlur:{type:Q(Function)},onContextmenu:{type:Q(Function)},id:String,open:Boolean}),QS=Symbol("elForwardRef"),Q6=e=>{ut(QS,{setForwardRef:n=>{e.value=n}})},e8=e=>({mounted(t){e(t)},updated(t){e(t)},unmounted(){e(null)}}),t8="ElOnlyChild",e2=q({name:t8,setup(e,{slots:t,attrs:n}){var o;const l=Pe(QS),a=e8((o=l?.setForwardRef)!=null?o:Nt);return()=>{var r;const i=(r=t.default)==null?void 0:r.call(t,n);if(!i)return null;const[u,c]=t2(i);return u?nt(Wl(u,n),[[a]]):null}}});function t2(e){if(!e)return[null,0];const t=e,n=t.filter(o=>o.type!==on).length;for(const o of t){if(et(o))switch(o.type){case on:continue;case Ts:case"svg":return[Cb(o),n];case He:return t2(o.children);default:return[o,n]}return[Cb(o),n]}return[null,0]}function Cb(e){const t=be("only-child");return J("span",{class:t.e("content")},[e])}const n8=q({name:"ElPopperTrigger",inheritAttrs:!1}),o8=q({...n8,props:ZS,setup(e,{expose:t}){const n=e,{role:o,triggerRef:l}=Pe(Kh,void 0);Q6(l);const a=S(()=>i.value?n.id:void 0),r=S(()=>{if(o&&o.value==="tooltip")return n.open&&n.id?n.id:void 0}),i=S(()=>{if(o&&o.value!=="tooltip")return o.value}),u=S(()=>i.value?`${n.open}`:void 0);let c;const d=["onMouseenter","onMouseleave","onClick","onKeydown","onFocus","onBlur","onContextmenu"];return rt(()=>{pe(()=>n.virtualRef,f=>{f&&(l.value=hn(f))},{immediate:!0}),pe(l,(f,v)=>{c?.(),c=void 0,wo(f)&&(d.forEach(p=>{var m;const h=n[p];h&&(f.addEventListener(p.slice(2).toLowerCase(),h,["onFocus","onBlur"].includes(p)),(m=v?.removeEventListener)==null||m.call(v,p.slice(2).toLowerCase(),h,["onFocus","onBlur"].includes(p)))}),Bi(f)&&(c=pe([a,r,i,u],p=>{["aria-controls","aria-describedby","aria-haspopup","aria-expanded"].forEach((m,h)=>{rn(p[h])?f.removeAttribute(m):f.setAttribute(m,p[h])})},{immediate:!0}))),wo(v)&&Bi(v)&&["aria-controls","aria-describedby","aria-haspopup","aria-expanded"].forEach(p=>v.removeAttribute(p))},{immediate:!0})}),Rt(()=>{if(c?.(),c=void 0,l.value&&wo(l.value)){const f=l.value;d.forEach(v=>{const p=n[v];p&&f.removeEventListener(v.slice(2).toLowerCase(),p,["onFocus","onBlur"].includes(v))}),l.value=void 0}}),t({triggerRef:l}),(f,v)=>f.virtualTriggering?re("v-if",!0):(_(),ie(s(e2),ot({key:0},f.$attrs,{"aria-controls":s(a),"aria-describedby":s(r),"aria-expanded":s(u),"aria-haspopup":s(i)}),{default:ee(()=>[oe(f.$slots,"default")]),_:3},16,["aria-controls","aria-describedby","aria-expanded","aria-haspopup"]))}});var l8=Te(o8,[["__file","trigger.vue"]]);const jf="focus-trap.focus-after-trapped",Uf="focus-trap.focus-after-released",a8="focus-trap.focusout-prevented",Sb={cancelable:!0,bubbles:!1},r8={cancelable:!0,bubbles:!1},kb="focusAfterTrapped",Eb="focusAfterReleased",Wh=Symbol("elFocusTrap"),jh=L(),Qd=L(0),Uh=L(0);let ju=0;const n2=e=>{const t=[],n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT,{acceptNode:o=>{const l=o.tagName==="INPUT"&&o.type==="hidden";return o.disabled||o.hidden||l?NodeFilter.FILTER_SKIP:o.tabIndex>=0||o===document.activeElement?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}});for(;n.nextNode();)t.push(n.currentNode);return t},_b=(e,t)=>{for(const n of e)if(!s8(n,t))return n},s8=(e,t)=>{if(getComputedStyle(e).visibility==="hidden")return!0;for(;e;){if(t&&e===t)return!1;if(getComputedStyle(e).display==="none")return!0;e=e.parentElement}return!1},i8=e=>{const t=n2(e),n=_b(t,e),o=_b(t.reverse(),e);return[n,o]},u8=e=>e instanceof HTMLInputElement&&"select"in e,ia=(e,t)=>{if(e){const n=document.activeElement;mu(e,{preventScroll:!0}),Uh.value=window.performance.now(),e!==n&&u8(e)&&t&&e.select()}};function Tb(e,t){const n=[...e],o=e.indexOf(t);return o!==-1&&n.splice(o,1),n}const c8=()=>{let e=[];return{push:o=>{const l=e[0];l&&o!==l&&l.pause(),e=Tb(e,o),e.unshift(o)},remove:o=>{var l,a;e=Tb(e,o),(a=(l=e[0])==null?void 0:l.resume)==null||a.call(l)}}},d8=(e,t=!1)=>{const n=document.activeElement;for(const o of e)if(ia(o,t),document.activeElement!==n)return},Ob=c8(),f8=()=>Qd.value>Uh.value,Uu=()=>{jh.value="pointer",Qd.value=window.performance.now()},$b=()=>{jh.value="keyboard",Qd.value=window.performance.now()},p8=()=>(rt(()=>{ju===0&&(document.addEventListener("mousedown",Uu),document.addEventListener("touchstart",Uu),document.addEventListener("keydown",$b)),ju++}),Rt(()=>{ju--,ju<=0&&(document.removeEventListener("mousedown",Uu),document.removeEventListener("touchstart",Uu),document.removeEventListener("keydown",$b))}),{focusReason:jh,lastUserFocusTimestamp:Qd,lastAutomatedFocusTimestamp:Uh}),qu=e=>new CustomEvent(a8,{...r8,detail:e}),xe={tab:"Tab",enter:"Enter",space:"Space",left:"ArrowLeft",up:"ArrowUp",right:"ArrowRight",down:"ArrowDown",esc:"Escape",delete:"Delete",backspace:"Backspace",numpadEnter:"NumpadEnter",pageUp:"PageUp",pageDown:"PageDown",home:"Home",end:"End"};let Dr=[];const Rb=e=>{e.code===xe.esc&&Dr.forEach(t=>t(e))},v8=e=>{rt(()=>{Dr.length===0&&document.addEventListener("keydown",Rb),kt&&Dr.push(e)}),Rt(()=>{Dr=Dr.filter(t=>t!==e),Dr.length===0&&kt&&document.removeEventListener("keydown",Rb)})},h8=q({name:"ElFocusTrap",inheritAttrs:!1,props:{loop:Boolean,trapped:Boolean,focusTrapEl:Object,focusStartEl:{type:[Object,String],default:"first"}},emits:[kb,Eb,"focusin","focusout","focusout-prevented","release-requested"],setup(e,{emit:t}){const n=L();let o,l;const{focusReason:a}=p8();v8(m=>{e.trapped&&!r.paused&&t("release-requested",m)});const r={paused:!1,pause(){this.paused=!0},resume(){this.paused=!1}},i=m=>{if(!e.loop&&!e.trapped||r.paused)return;const{code:h,altKey:g,ctrlKey:b,metaKey:C,currentTarget:y,shiftKey:w}=m,{loop:k}=e,E=h===xe.tab&&!g&&!b&&!C,T=document.activeElement;if(E&&T){const x=y,[N,O]=i8(x);if(N&&O){if(!w&&T===O){const P=qu({focusReason:a.value});t("focusout-prevented",P),P.defaultPrevented||(m.preventDefault(),k&&ia(N,!0))}else if(w&&[N,x].includes(T)){const P=qu({focusReason:a.value});t("focusout-prevented",P),P.defaultPrevented||(m.preventDefault(),k&&ia(O,!0))}}else if(T===x){const P=qu({focusReason:a.value});t("focusout-prevented",P),P.defaultPrevented||m.preventDefault()}}};ut(Wh,{focusTrapRef:n,onKeydown:i}),pe(()=>e.focusTrapEl,m=>{m&&(n.value=m)},{immediate:!0}),pe([n],([m],[h])=>{m&&(m.addEventListener("keydown",i),m.addEventListener("focusin",d),m.addEventListener("focusout",f)),h&&(h.removeEventListener("keydown",i),h.removeEventListener("focusin",d),h.removeEventListener("focusout",f))});const u=m=>{t(kb,m)},c=m=>t(Eb,m),d=m=>{const h=s(n);if(!h)return;const g=m.target,b=m.relatedTarget,C=g&&h.contains(g);e.trapped||b&&h.contains(b)||(o=b),C&&t("focusin",m),!r.paused&&e.trapped&&(C?l=g:ia(l,!0))},f=m=>{const h=s(n);if(!(r.paused||!h))if(e.trapped){const g=m.relatedTarget;!rn(g)&&!h.contains(g)&&setTimeout(()=>{if(!r.paused&&e.trapped){const b=qu({focusReason:a.value});t("focusout-prevented",b),b.defaultPrevented||ia(l,!0)}},0)}else{const g=m.target;g&&h.contains(g)||t("focusout",m)}};async function v(){await Le();const m=s(n);if(m){Ob.push(r);const h=m.contains(document.activeElement)?o:document.activeElement;if(o=h,!m.contains(h)){const b=new Event(jf,Sb);m.addEventListener(jf,u),m.dispatchEvent(b),b.defaultPrevented||Le(()=>{let C=e.focusStartEl;Fe(C)||(ia(C),document.activeElement!==C&&(C="first")),C==="first"&&d8(n2(m),!0),(document.activeElement===h||C==="container")&&ia(m)})}}}function p(){const m=s(n);if(m){m.removeEventListener(jf,u);const h=new CustomEvent(Uf,{...Sb,detail:{focusReason:a.value}});m.addEventListener(Uf,c),m.dispatchEvent(h),!h.defaultPrevented&&(a.value=="keyboard"||!f8()||m.contains(document.activeElement))&&ia(o??document.body),m.removeEventListener(Uf,c),Ob.remove(r),o=null,l=null}}return rt(()=>{e.trapped&&v(),pe(()=>e.trapped,m=>{m?v():p()})}),Rt(()=>{e.trapped&&p(),n.value&&(n.value.removeEventListener("keydown",i),n.value.removeEventListener("focusin",d),n.value.removeEventListener("focusout",f),n.value=void 0)}),{onKeydown:i}}});function m8(e,t,n,o,l,a){return oe(e.$slots,"default",{handleKeydown:e.onKeydown})}var kr=Te(h8,[["render",m8],["__file","focus-trap.vue"]]),so="top",xo="bottom",Mo="right",io="left",qh="auto",bu=[so,xo,Mo,io],ds="start",Fi="end",g8="clippingParents",o2="viewport",qs="popper",b8="reference",Nb=bu.reduce(function(e,t){return e.concat([t+"-"+ds,t+"-"+Fi])},[]),na=[].concat(bu,[qh]).reduce(function(e,t){return e.concat([t,t+"-"+ds,t+"-"+Fi])},[]),y8="beforeRead",w8="read",C8="afterRead",S8="beforeMain",k8="main",E8="afterMain",_8="beforeWrite",T8="write",O8="afterWrite",$8=[y8,w8,C8,S8,k8,E8,_8,T8,O8];function wl(e){return e?(e.nodeName||"").toLowerCase():null}function ol(e){if(e==null)return window;if(e.toString()!=="[object Window]"){var t=e.ownerDocument;return t&&t.defaultView||window}return e}function fs(e){var t=ol(e).Element;return e instanceof t||e instanceof Element}function No(e){var t=ol(e).HTMLElement;return e instanceof t||e instanceof HTMLElement}function Yh(e){if(typeof ShadowRoot>"u")return!1;var t=ol(e).ShadowRoot;return e instanceof t||e instanceof ShadowRoot}function R8(e){var t=e.state;Object.keys(t.elements).forEach(function(n){var o=t.styles[n]||{},l=t.attributes[n]||{},a=t.elements[n];!No(a)||!wl(a)||(Object.assign(a.style,o),Object.keys(l).forEach(function(r){var i=l[r];i===!1?a.removeAttribute(r):a.setAttribute(r,i===!0?"":i)}))})}function N8(e){var t=e.state,n={popper:{position:t.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(t.elements.popper.style,n.popper),t.styles=n,t.elements.arrow&&Object.assign(t.elements.arrow.style,n.arrow),function(){Object.keys(t.elements).forEach(function(o){var l=t.elements[o],a=t.attributes[o]||{},r=Object.keys(t.styles.hasOwnProperty(o)?t.styles[o]:n[o]),i=r.reduce(function(u,c){return u[c]="",u},{});!No(l)||!wl(l)||(Object.assign(l.style,i),Object.keys(a).forEach(function(u){l.removeAttribute(u)}))})}}var l2={name:"applyStyles",enabled:!0,phase:"write",fn:R8,effect:N8,requires:["computeStyles"]};function hl(e){return e.split("-")[0]}var tr=Math.max,ed=Math.min,ps=Math.round;function vs(e,t){t===void 0&&(t=!1);var n=e.getBoundingClientRect(),o=1,l=1;if(No(e)&&t){var a=e.offsetHeight,r=e.offsetWidth;r>0&&(o=ps(n.width)/r||1),a>0&&(l=ps(n.height)/a||1)}return{width:n.width/o,height:n.height/l,top:n.top/l,right:n.right/o,bottom:n.bottom/l,left:n.left/o,x:n.left/o,y:n.top/l}}function Gh(e){var t=vs(e),n=e.offsetWidth,o=e.offsetHeight;return Math.abs(t.width-n)<=1&&(n=t.width),Math.abs(t.height-o)<=1&&(o=t.height),{x:e.offsetLeft,y:e.offsetTop,width:n,height:o}}function a2(e,t){var n=t.getRootNode&&t.getRootNode();if(e.contains(t))return!0;if(n&&Yh(n)){var o=t;do{if(o&&e.isSameNode(o))return!0;o=o.parentNode||o.host}while(o)}return!1}function Ul(e){return ol(e).getComputedStyle(e)}function I8(e){return["table","td","th"].indexOf(wl(e))>=0}function Ma(e){return((fs(e)?e.ownerDocument:e.document)||window.document).documentElement}function ef(e){return wl(e)==="html"?e:e.assignedSlot||e.parentNode||(Yh(e)?e.host:null)||Ma(e)}function Ib(e){return!No(e)||Ul(e).position==="fixed"?null:e.offsetParent}function P8(e){var t=navigator.userAgent.toLowerCase().indexOf("firefox")!==-1,n=navigator.userAgent.indexOf("Trident")!==-1;if(n&&No(e)){var o=Ul(e);if(o.position==="fixed")return null}var l=ef(e);for(Yh(l)&&(l=l.host);No(l)&&["html","body"].indexOf(wl(l))<0;){var a=Ul(l);if(a.transform!=="none"||a.perspective!=="none"||a.contain==="paint"||["transform","perspective"].indexOf(a.willChange)!==-1||t&&a.willChange==="filter"||t&&a.filter&&a.filter!=="none")return l;l=l.parentNode}return null}function yu(e){for(var t=ol(e),n=Ib(e);n&&I8(n)&&Ul(n).position==="static";)n=Ib(n);return n&&(wl(n)==="html"||wl(n)==="body"&&Ul(n).position==="static")?t:n||P8(e)||t}function Xh(e){return["top","bottom"].indexOf(e)>=0?"x":"y"}function yi(e,t,n){return tr(e,ed(t,n))}function x8(e,t,n){var o=yi(e,t,n);return o>n?n:o}function r2(){return{top:0,right:0,bottom:0,left:0}}function s2(e){return Object.assign({},r2(),e)}function i2(e,t){return t.reduce(function(n,o){return n[o]=e,n},{})}var M8=function(e,t){return e=typeof e=="function"?e(Object.assign({},t.rects,{placement:t.placement})):e,s2(typeof e!="number"?e:i2(e,bu))};function A8(e){var t,n=e.state,o=e.name,l=e.options,a=n.elements.arrow,r=n.modifiersData.popperOffsets,i=hl(n.placement),u=Xh(i),c=[io,Mo].indexOf(i)>=0,d=c?"height":"width";if(!(!a||!r)){var f=M8(l.padding,n),v=Gh(a),p=u==="y"?so:io,m=u==="y"?xo:Mo,h=n.rects.reference[d]+n.rects.reference[u]-r[u]-n.rects.popper[d],g=r[u]-n.rects.reference[u],b=yu(a),C=b?u==="y"?b.clientHeight||0:b.clientWidth||0:0,y=h/2-g/2,w=f[p],k=C-v[d]-f[m],E=C/2-v[d]/2+y,T=yi(w,E,k),x=u;n.modifiersData[o]=(t={},t[x]=T,t.centerOffset=T-E,t)}}function L8(e){var t=e.state,n=e.options,o=n.element,l=o===void 0?"[data-popper-arrow]":o;l!=null&&(typeof l=="string"&&(l=t.elements.popper.querySelector(l),!l)||!a2(t.elements.popper,l)||(t.elements.arrow=l))}var D8={name:"arrow",enabled:!0,phase:"main",fn:A8,effect:L8,requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function hs(e){return e.split("-")[1]}var B8={top:"auto",right:"auto",bottom:"auto",left:"auto"};function F8(e){var t=e.x,n=e.y,o=window,l=o.devicePixelRatio||1;return{x:ps(t*l)/l||0,y:ps(n*l)/l||0}}function Pb(e){var t,n=e.popper,o=e.popperRect,l=e.placement,a=e.variation,r=e.offsets,i=e.position,u=e.gpuAcceleration,c=e.adaptive,d=e.roundOffsets,f=e.isFixed,v=r.x,p=v===void 0?0:v,m=r.y,h=m===void 0?0:m,g=typeof d=="function"?d({x:p,y:h}):{x:p,y:h};p=g.x,h=g.y;var b=r.hasOwnProperty("x"),C=r.hasOwnProperty("y"),y=io,w=so,k=window;if(c){var E=yu(n),T="clientHeight",x="clientWidth";if(E===ol(n)&&(E=Ma(n),Ul(E).position!=="static"&&i==="absolute"&&(T="scrollHeight",x="scrollWidth")),E=E,l===so||(l===io||l===Mo)&&a===Fi){w=xo;var N=f&&E===k&&k.visualViewport?k.visualViewport.height:E[T];h-=N-o.height,h*=u?1:-1}if(l===io||(l===so||l===xo)&&a===Fi){y=Mo;var O=f&&E===k&&k.visualViewport?k.visualViewport.width:E[x];p-=O-o.width,p*=u?1:-1}}var I=Object.assign({position:i},c&&B8),P=d===!0?F8({x:p,y:h}):{x:p,y:h};if(p=P.x,h=P.y,u){var K;return Object.assign({},I,(K={},K[w]=C?"0":"",K[y]=b?"0":"",K.transform=(k.devicePixelRatio||1)<=1?"translate("+p+"px, "+h+"px)":"translate3d("+p+"px, "+h+"px, 0)",K))}return Object.assign({},I,(t={},t[w]=C?h+"px":"",t[y]=b?p+"px":"",t.transform="",t))}function V8(e){var t=e.state,n=e.options,o=n.gpuAcceleration,l=o===void 0?!0:o,a=n.adaptive,r=a===void 0?!0:a,i=n.roundOffsets,u=i===void 0?!0:i,c={placement:hl(t.placement),variation:hs(t.placement),popper:t.elements.popper,popperRect:t.rects.popper,gpuAcceleration:l,isFixed:t.options.strategy==="fixed"};t.modifiersData.popperOffsets!=null&&(t.styles.popper=Object.assign({},t.styles.popper,Pb(Object.assign({},c,{offsets:t.modifiersData.popperOffsets,position:t.options.strategy,adaptive:r,roundOffsets:u})))),t.modifiersData.arrow!=null&&(t.styles.arrow=Object.assign({},t.styles.arrow,Pb(Object.assign({},c,{offsets:t.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:u})))),t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-placement":t.placement})}var u2={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:V8,data:{}},Yu={passive:!0};function H8(e){var t=e.state,n=e.instance,o=e.options,l=o.scroll,a=l===void 0?!0:l,r=o.resize,i=r===void 0?!0:r,u=ol(t.elements.popper),c=[].concat(t.scrollParents.reference,t.scrollParents.popper);return a&&c.forEach(function(d){d.addEventListener("scroll",n.update,Yu)}),i&&u.addEventListener("resize",n.update,Yu),function(){a&&c.forEach(function(d){d.removeEventListener("scroll",n.update,Yu)}),i&&u.removeEventListener("resize",n.update,Yu)}}var c2={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:H8,data:{}},z8={left:"right",right:"left",bottom:"top",top:"bottom"};function pc(e){return e.replace(/left|right|bottom|top/g,function(t){return z8[t]})}var K8={start:"end",end:"start"};function xb(e){return e.replace(/start|end/g,function(t){return K8[t]})}function Jh(e){var t=ol(e),n=t.pageXOffset,o=t.pageYOffset;return{scrollLeft:n,scrollTop:o}}function Zh(e){return vs(Ma(e)).left+Jh(e).scrollLeft}function W8(e){var t=ol(e),n=Ma(e),o=t.visualViewport,l=n.clientWidth,a=n.clientHeight,r=0,i=0;return o&&(l=o.width,a=o.height,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(r=o.offsetLeft,i=o.offsetTop)),{width:l,height:a,x:r+Zh(e),y:i}}function j8(e){var t,n=Ma(e),o=Jh(e),l=(t=e.ownerDocument)==null?void 0:t.body,a=tr(n.scrollWidth,n.clientWidth,l?l.scrollWidth:0,l?l.clientWidth:0),r=tr(n.scrollHeight,n.clientHeight,l?l.scrollHeight:0,l?l.clientHeight:0),i=-o.scrollLeft+Zh(e),u=-o.scrollTop;return Ul(l||n).direction==="rtl"&&(i+=tr(n.clientWidth,l?l.clientWidth:0)-a),{width:a,height:r,x:i,y:u}}function Qh(e){var t=Ul(e),n=t.overflow,o=t.overflowX,l=t.overflowY;return/auto|scroll|overlay|hidden/.test(n+l+o)}function d2(e){return["html","body","#document"].indexOf(wl(e))>=0?e.ownerDocument.body:No(e)&&Qh(e)?e:d2(ef(e))}function wi(e,t){var n;t===void 0&&(t=[]);var o=d2(e),l=o===((n=e.ownerDocument)==null?void 0:n.body),a=ol(o),r=l?[a].concat(a.visualViewport||[],Qh(o)?o:[]):o,i=t.concat(r);return l?i:i.concat(wi(ef(r)))}function Kp(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}function U8(e){var t=vs(e);return t.top=t.top+e.clientTop,t.left=t.left+e.clientLeft,t.bottom=t.top+e.clientHeight,t.right=t.left+e.clientWidth,t.width=e.clientWidth,t.height=e.clientHeight,t.x=t.left,t.y=t.top,t}function Mb(e,t){return t===o2?Kp(W8(e)):fs(t)?U8(t):Kp(j8(Ma(e)))}function q8(e){var t=wi(ef(e)),n=["absolute","fixed"].indexOf(Ul(e).position)>=0,o=n&&No(e)?yu(e):e;return fs(o)?t.filter(function(l){return fs(l)&&a2(l,o)&&wl(l)!=="body"}):[]}function Y8(e,t,n){var o=t==="clippingParents"?q8(e):[].concat(t),l=[].concat(o,[n]),a=l[0],r=l.reduce(function(i,u){var c=Mb(e,u);return i.top=tr(c.top,i.top),i.right=ed(c.right,i.right),i.bottom=ed(c.bottom,i.bottom),i.left=tr(c.left,i.left),i},Mb(e,a));return r.width=r.right-r.left,r.height=r.bottom-r.top,r.x=r.left,r.y=r.top,r}function f2(e){var t=e.reference,n=e.element,o=e.placement,l=o?hl(o):null,a=o?hs(o):null,r=t.x+t.width/2-n.width/2,i=t.y+t.height/2-n.height/2,u;switch(l){case so:u={x:r,y:t.y-n.height};break;case xo:u={x:r,y:t.y+t.height};break;case Mo:u={x:t.x+t.width,y:i};break;case io:u={x:t.x-n.width,y:i};break;default:u={x:t.x,y:t.y}}var c=l?Xh(l):null;if(c!=null){var d=c==="y"?"height":"width";switch(a){case ds:u[c]=u[c]-(t[d]/2-n[d]/2);break;case Fi:u[c]=u[c]+(t[d]/2-n[d]/2);break}}return u}function Vi(e,t){t===void 0&&(t={});var n=t,o=n.placement,l=o===void 0?e.placement:o,a=n.boundary,r=a===void 0?g8:a,i=n.rootBoundary,u=i===void 0?o2:i,c=n.elementContext,d=c===void 0?qs:c,f=n.altBoundary,v=f===void 0?!1:f,p=n.padding,m=p===void 0?0:p,h=s2(typeof m!="number"?m:i2(m,bu)),g=d===qs?b8:qs,b=e.rects.popper,C=e.elements[v?g:d],y=Y8(fs(C)?C:C.contextElement||Ma(e.elements.popper),r,u),w=vs(e.elements.reference),k=f2({reference:w,element:b,placement:l}),E=Kp(Object.assign({},b,k)),T=d===qs?E:w,x={top:y.top-T.top+h.top,bottom:T.bottom-y.bottom+h.bottom,left:y.left-T.left+h.left,right:T.right-y.right+h.right},N=e.modifiersData.offset;if(d===qs&&N){var O=N[l];Object.keys(x).forEach(function(I){var P=[Mo,xo].indexOf(I)>=0?1:-1,K=[so,xo].indexOf(I)>=0?"y":"x";x[I]+=O[K]*P})}return x}function G8(e,t){t===void 0&&(t={});var n=t,o=n.placement,l=n.boundary,a=n.rootBoundary,r=n.padding,i=n.flipVariations,u=n.allowedAutoPlacements,c=u===void 0?na:u,d=hs(o),f=d?i?Nb:Nb.filter(function(m){return hs(m)===d}):bu,v=f.filter(function(m){return c.indexOf(m)>=0});v.length===0&&(v=f);var p=v.reduce(function(m,h){return m[h]=Vi(e,{placement:h,boundary:l,rootBoundary:a,padding:r})[hl(h)],m},{});return Object.keys(p).sort(function(m,h){return p[m]-p[h]})}function X8(e){if(hl(e)===qh)return[];var t=pc(e);return[xb(e),t,xb(t)]}function J8(e){var t=e.state,n=e.options,o=e.name;if(!t.modifiersData[o]._skip){for(var l=n.mainAxis,a=l===void 0?!0:l,r=n.altAxis,i=r===void 0?!0:r,u=n.fallbackPlacements,c=n.padding,d=n.boundary,f=n.rootBoundary,v=n.altBoundary,p=n.flipVariations,m=p===void 0?!0:p,h=n.allowedAutoPlacements,g=t.options.placement,b=hl(g),C=b===g,y=u||(C||!m?[pc(g)]:X8(g)),w=[g].concat(y).reduce(function(te,le){return te.concat(hl(le)===qh?G8(t,{placement:le,boundary:d,rootBoundary:f,padding:c,flipVariations:m,allowedAutoPlacements:h}):le)},[]),k=t.rects.reference,E=t.rects.popper,T=new Map,x=!0,N=w[0],O=0;O B<=0)){var I,P;const B=(((I=a.flip)==null?void 0:I.index)||0)+1,Y=T[B];if(Y&&(!(f==="alignment"?C!==wa(Y):!1)||O.every(R=>wa(R.placement)===C?R.overflows[0]>0:!0)))return{data:{index:B,overflows:O},reset:{placement:Y}};let M=(P=O.filter(A=>A.overflows[0]<=0).sort((A,R)=>A.overflows[1]-R.overflows[1])[0])==null?void 0:P.placement;if(!M)switch(p){case"bestFit":{var K;const A=(K=O.filter(R=>{if(E){const D=wa(R.placement);return D===C||D==="y"}return!0}).map(R=>[R.placement,R.overflows.filter(D=>D>0).reduce((D,V)=>D+V,0)]).sort((R,D)=>R[1]-D[1])[0])==null?void 0:K[0];A&&(M=A);break}case"initialPlacement":M=i;break}if(l!==M)return{reset:{placement:M}}}return{}}}},rX=new Set(["left","top"]);async function sX(e,t){const{placement:n,platform:o,elements:l}=e,a=await(o.isRTL==null?void 0:o.isRTL(l.floating)),r=pr(n),i=Eu(n),u=wa(n)==="y",c=rX.has(r)?-1:1,d=a&&u?-1:1,f=ku(t,e);let{mainAxis:v,crossAxis:p,alignmentAxis:m}=typeof f=="number"?{mainAxis:f,crossAxis:0,alignmentAxis:null}:{mainAxis:f.mainAxis||0,crossAxis:f.crossAxis||0,alignmentAxis:f.alignmentAxis};return i&&typeof m=="number"&&(p=i==="end"?m*-1:m),u?{x:p*d,y:v*c}:{x:v*c,y:p*d}}const iX=function(e){return e===void 0&&(e=0),{name:"offset",options:e,async fn(t){var n,o;const{x:l,y:a,placement:r,middlewareData:i}=t,u=await sX(t,e);return r===((n=i.offset)==null?void 0:n.placement)&&(o=i.arrow)!=null&&o.alignmentOffset?{}:{x:l+u.x,y:a+u.y,data:{...u,placement:r}}}}},uX=function(e){return e===void 0&&(e={}),{name:"shift",options:e,async fn(t){const{x:n,y:o,placement:l}=t,{mainAxis:a=!0,crossAxis:r=!1,limiter:i={fn:g=>{let{x:b,y:C}=g;return{x:b,y:C}}},...u}=ku(e,t),c={x:n,y:o},d=await Xm(t,u),f=wa(pr(l)),v=ZE(f);let p=c[v],m=c[f];if(a){const g=v==="y"?"top":"left",b=v==="y"?"bottom":"right",C=p+d[g],y=p-d[b];p=Ov(C,p,y)}if(r){const g=f==="y"?"top":"left",b=f==="y"?"bottom":"right",C=m+d[g],y=m-d[b];m=Ov(C,m,y)}const h=i.fn({...t,[v]:p,[f]:m});return{...h,data:{x:h.x-n,y:h.y-o,enabled:{[v]:a,[f]:r}}}}}};function df(){return typeof window<"u"}function Ds(e){return e_(e)?(e.nodeName||"").toLowerCase():"#document"}function wo(e){var t;return(e==null||(t=e.ownerDocument)==null?void 0:t.defaultView)||window}function _l(e){var t;return(t=(e_(e)?e.ownerDocument:e.document)||window.document)==null?void 0:t.documentElement}function e_(e){return df()?e instanceof Node||e instanceof wo(e).Node:!1}function Zo(e){return df()?e instanceof Element||e instanceof wo(e).Element:!1}function Cl(e){return df()?e instanceof HTMLElement||e instanceof wo(e).HTMLElement:!1}function Zy(e){return!df()||typeof ShadowRoot>"u"?!1:e instanceof ShadowRoot||e instanceof wo(e).ShadowRoot}const cX=new Set(["inline","contents"]);function _u(e){const{overflow:t,overflowX:n,overflowY:o,display:l}=Qo(e);return/auto|scroll|overlay|hidden|clip/.test(t+o+n)&&!cX.has(l)}const dX=new Set(["table","td","th"]);function fX(e){return dX.has(Ds(e))}const pX=[":popover-open",":modal"];function ff(e){return pX.some(t=>{try{return e.matches(t)}catch{return!1}})}const vX=["transform","translate","scale","rotate","perspective"],hX=["transform","translate","scale","rotate","perspective","filter"],mX=["paint","layout","strict","content"];function Jm(e){const t=Zm(),n=Zo(e)?Qo(e):e;return vX.some(o=>n[o]?n[o]!=="none":!1)||(n.containerType?n.containerType!=="normal":!1)||!t&&(n.backdropFilter?n.backdropFilter!=="none":!1)||!t&&(n.filter?n.filter!=="none":!1)||hX.some(o=>(n.willChange||"").includes(o))||mX.some(o=>(n.contain||"").includes(o))}function gX(e){let t=Pa(e);for(;Cl(t)&&!Ss(t);){if(Jm(t))return t;if(ff(t))return null;t=Pa(t)}return null}function Zm(){return typeof CSS>"u"||!CSS.supports?!1:CSS.supports("-webkit-backdrop-filter","none")}const bX=new Set(["html","body","#document"]);function Ss(e){return bX.has(Ds(e))}function Qo(e){return wo(e).getComputedStyle(e)}function pf(e){return Zo(e)?{scrollLeft:e.scrollLeft,scrollTop:e.scrollTop}:{scrollLeft:e.scrollX,scrollTop:e.scrollY}}function Pa(e){if(Ds(e)==="html")return e;const t=e.assignedSlot||e.parentNode||Zy(e)&&e.host||_l(e);return Zy(t)?t.host:t}function t_(e){const t=Pa(e);return Ss(t)?e.ownerDocument?e.ownerDocument.body:e.body:Cl(t)&&_u(t)?t:t_(t)}function Zi(e,t,n){var o;t===void 0&&(t=[]),n===void 0&&(n=!0);const l=t_(e),a=l===((o=e.ownerDocument)==null?void 0:o.body),r=wo(l);if(a){const i=Rv(r);return t.concat(r,r.visualViewport||[],_u(l)?l:[],i&&n?Zi(i):[])}return t.concat(l,Zi(l,[],n))}function Rv(e){return e.parent&&Object.getPrototypeOf(e.parent)?e.frameElement:null}function n_(e){const t=Qo(e);let n=parseFloat(t.width)||0,o=parseFloat(t.height)||0;const l=Cl(e),a=l?e.offsetWidth:n,r=l?e.offsetHeight:o,i=hd(n)!==a||hd(o)!==r;return i&&(n=a,o=r),{width:n,height:o,$:i}}function Qm(e){return Zo(e)?e:e.contextElement}function Qr(e){const t=Qm(e);if(!Cl(t))return ml(1);const n=t.getBoundingClientRect(),{width:o,height:l,$:a}=n_(t);let r=(a?hd(n.width):n.width)/o,i=(a?hd(n.height):n.height)/l;return(!r||!Number.isFinite(r))&&(r=1),(!i||!Number.isFinite(i))&&(i=1),{x:r,y:i}}const yX=ml(0);function o_(e){const t=wo(e);return!Zm()||!t.visualViewport?yX:{x:t.visualViewport.offsetLeft,y:t.visualViewport.offsetTop}}function wX(e,t,n){return t===void 0&&(t=!1),!n||t&&n!==wo(e)?!1:t}function vr(e,t,n,o){t===void 0&&(t=!1),n===void 0&&(n=!1);const l=e.getBoundingClientRect(),a=Qm(e);let r=ml(1);t&&(o?Zo(o)&&(r=Qr(o)):r=Qr(e));const i=wX(a,n,o)?o_(a):ml(0);let u=(l.left+i.x)/r.x,c=(l.top+i.y)/r.y,d=l.width/r.x,f=l.height/r.y;if(a){const v=wo(a),p=o&&Zo(o)?wo(o):o;let m=v,h=Rv(m);for(;h&&o&&p!==m;){const g=Qr(h),b=h.getBoundingClientRect(),C=Qo(h),y=b.left+(h.clientLeft+parseFloat(C.paddingLeft))*g.x,w=b.top+(h.clientTop+parseFloat(C.paddingTop))*g.y;u*=g.x,c*=g.y,d*=g.x,f*=g.y,u+=y,c+=w,m=wo(h),h=Rv(m)}}return gd({width:d,height:f,x:u,y:c})}function vf(e,t){const n=pf(e).scrollLeft;return t?t.left+n:vr(_l(e)).left+n}function l_(e,t){const n=e.getBoundingClientRect(),o=n.left+t.scrollLeft-vf(e,n),l=n.top+t.scrollTop;return{x:o,y:l}}function CX(e){let{elements:t,rect:n,offsetParent:o,strategy:l}=e;const a=l==="fixed",r=_l(o),i=t?ff(t.floating):!1;if(o===r||i&&a)return n;let u={scrollLeft:0,scrollTop:0},c=ml(1);const d=ml(0),f=Cl(o);if((f||!f&&!a)&&((Ds(o)!=="body"||_u(r))&&(u=pf(o)),Cl(o))){const p=vr(o);c=Qr(o),d.x=p.x+o.clientLeft,d.y=p.y+o.clientTop}const v=r&&!f&&!a?l_(r,u):ml(0);return{width:n.width*c.x,height:n.height*c.y,x:n.x*c.x-u.scrollLeft*c.x+d.x+v.x,y:n.y*c.y-u.scrollTop*c.y+d.y+v.y}}function SX(e){return Array.from(e.getClientRects())}function kX(e){const t=_l(e),n=pf(e),o=e.ownerDocument.body,l=or(t.scrollWidth,t.clientWidth,o.scrollWidth,o.clientWidth),a=or(t.scrollHeight,t.clientHeight,o.scrollHeight,o.clientHeight);let r=-n.scrollLeft+vf(e);const i=-n.scrollTop;return Qo(o).direction==="rtl"&&(r+=or(t.clientWidth,o.clientWidth)-l),{width:l,height:a,x:r,y:i}}const Qy=25;function EX(e,t){const n=wo(e),o=_l(e),l=n.visualViewport;let a=o.clientWidth,r=o.clientHeight,i=0,u=0;if(l){a=l.width,r=l.height;const d=Zm();(!d||d&&t==="fixed")&&(i=l.offsetLeft,u=l.offsetTop)}const c=vf(o);if(c<=0){const d=o.ownerDocument,f=d.body,v=getComputedStyle(f),p=d.compatMode==="CSS1Compat"&&parseFloat(v.marginLeft)+parseFloat(v.marginRight)||0,m=Math.abs(o.clientWidth-f.clientWidth-p);m<=Qy&&(a-=m)}else c<=Qy&&(a+=c);return{width:a,height:r,x:i,y:u}}const _X=new Set(["absolute","fixed"]);function TX(e,t){const n=vr(e,!0,t==="fixed"),o=n.top+e.clientTop,l=n.left+e.clientLeft,a=Cl(e)?Qr(e):ml(1),r=e.clientWidth*a.x,i=e.clientHeight*a.y,u=l*a.x,c=o*a.y;return{width:r,height:i,x:u,y:c}}function ew(e,t,n){let o;if(t==="viewport")o=EX(e,n);else if(t==="document")o=kX(_l(e));else if(Zo(t))o=TX(t,n);else{const l=o_(e);o={x:t.x-l.x,y:t.y-l.y,width:t.width,height:t.height}}return gd(o)}function a_(e,t){const n=Pa(e);return n===t||!Zo(n)||Ss(n)?!1:Qo(n).position==="fixed"||a_(n,t)}function OX(e,t){const n=t.get(e);if(n)return n;let o=Zi(e,[],!1).filter(i=>Zo(i)&&Ds(i)!=="body"),l=null;const a=Qo(e).position==="fixed";let r=a?Pa(e):e;for(;Zo(r)&&!Ss(r);){const i=Qo(r),u=Jm(r);!u&&i.position==="fixed"&&(l=null),(a?!u&&!l:!u&&i.position==="static"&&!!l&&_X.has(l.position)||_u(r)&&!u&&a_(e,r))?o=o.filter(d=>d!==r):l=i,r=Pa(r)}return t.set(e,o),o}function $X(e){let{element:t,boundary:n,rootBoundary:o,strategy:l}=e;const r=[...n==="clippingAncestors"?ff(t)?[]:OX(t,this._c):[].concat(n),o],i=r[0],u=r.reduce((c,d)=>{const f=ew(t,d,l);return c.top=or(f.top,c.top),c.right=Cs(f.right,c.right),c.bottom=Cs(f.bottom,c.bottom),c.left=or(f.left,c.left),c},ew(t,i,l));return{width:u.right-u.left,height:u.bottom-u.top,x:u.left,y:u.top}}function RX(e){const{width:t,height:n}=n_(e);return{width:t,height:n}}function NX(e,t,n){const o=Cl(t),l=_l(t),a=n==="fixed",r=vr(e,!0,a,t);let i={scrollLeft:0,scrollTop:0};const u=ml(0);function c(){u.x=vf(l)}if(o||!o&&!a)if((Ds(t)!=="body"||_u(l))&&(i=pf(t)),o){const p=vr(t,!0,a,t);u.x=p.x+t.clientLeft,u.y=p.y+t.clientTop}else l&&c();a&&!o&&l&&c();const d=l&&!o&&!a?l_(l,i):ml(0),f=r.left+i.scrollLeft-u.x-d.x,v=r.top+i.scrollTop-u.y-d.y;return{x:f,y:v,width:r.width,height:r.height}}function cp(e){return Qo(e).position==="static"}function tw(e,t){if(!Cl(e)||Qo(e).position==="fixed")return null;if(t)return t(e);let n=e.offsetParent;return _l(e)===n&&(n=n.ownerDocument.body),n}function r_(e,t){const n=wo(e);if(ff(e))return n;if(!Cl(e)){let l=Pa(e);for(;l&&!Ss(l);){if(Zo(l)&&!cp(l))return l;l=Pa(l)}return n}let o=tw(e,t);for(;o&&fX(o)&&cp(o);)o=tw(o,t);return o&&Ss(o)&&cp(o)&&!Jm(o)?n:o||gX(e)||n}const IX=async function(e){const t=this.getOffsetParent||r_,n=this.getDimensions,o=await n(e.floating);return{reference:NX(e.reference,await t(e.floating),e.strategy),floating:{x:0,y:0,width:o.width,height:o.height}}};function PX(e){return Qo(e).direction==="rtl"}const xX={convertOffsetParentRelativeRectToViewportRelativeRect:CX,getDocumentElement:_l,getClippingRect:$X,getOffsetParent:r_,getElementRects:IX,getClientRects:SX,getDimensions:RX,getScale:Qr,isElement:Zo,isRTL:PX};function s_(e,t){return e.x===t.x&&e.y===t.y&&e.width===t.width&&e.height===t.height}function MX(e,t){let n=null,o;const l=_l(e);function a(){var i;clearTimeout(o),(i=n)==null||i.disconnect(),n=null}function r(i,u){i===void 0&&(i=!1),u===void 0&&(u=1),a();const c=e.getBoundingClientRect(),{left:d,top:f,width:v,height:p}=c;if(i||t(),!v||!p)return;const m=ec(f),h=ec(l.clientWidth-(d+v)),g=ec(l.clientHeight-(f+p)),b=ec(d),y={rootMargin:-m+"px "+-h+"px "+-g+"px "+-b+"px",threshold:or(0,Cs(1,u))||1};let w=!0;function k(E){const T=E[0].intersectionRatio;if(T!==u){if(!w)return r();T?r(!1,T):o=setTimeout(()=>{r(!1,1e-7)},1e3)}T===1&&!s_(c,e.getBoundingClientRect())&&r(),w=!1}try{n=new IntersectionObserver(k,{...y,root:l.ownerDocument})}catch{n=new IntersectionObserver(k,y)}n.observe(e)}return r(!0),a}function AX(e,t,n,o){o===void 0&&(o={});const{ancestorScroll:l=!0,ancestorResize:a=!0,elementResize:r=typeof ResizeObserver=="function",layoutShift:i=typeof IntersectionObserver=="function",animationFrame:u=!1}=o,c=Qm(e),d=l||a?[...c?Zi(c):[],...Zi(t)]:[];d.forEach(b=>{l&&b.addEventListener("scroll",n,{passive:!0}),a&&b.addEventListener("resize",n)});const f=c&&i?MX(c,n):null;let v=-1,p=null;r&&(p=new ResizeObserver(b=>{let[C]=b;C&&C.target===c&&p&&(p.unobserve(t),cancelAnimationFrame(v),v=requestAnimationFrame(()=>{var y;(y=p)==null||y.observe(t)})),n()}),c&&!u&&p.observe(c),p.observe(t));let m,h=u?vr(e):null;u&&g();function g(){const b=vr(e);h&&!s_(h,b)&&n(),h=b,m=requestAnimationFrame(g)}return n(),()=>{var b;d.forEach(C=>{l&&C.removeEventListener("scroll",n),a&&C.removeEventListener("resize",n)}),f?.(),(b=p)==null||b.disconnect(),p=null,u&&cancelAnimationFrame(m)}}const LX=Xm,i_=iX,DX=uX,BX=aX,u_=lX,c_=(e,t,n)=>{const o=new Map,l={platform:xX,...n},a={...l.platform,_c:o};return oX(e,t,{...l,platform:a})},FX=Se({style:{type:Q([String,Object,Array]),default:()=>({})}}),VX=q({name:"ElVisuallyHidden"}),HX=q({...VX,props:FX,setup(e){const t=e,n=S(()=>[t.style,{position:"absolute",border:0,width:1,height:1,padding:0,margin:-1,overflow:"hidden",clip:"rect(0, 0, 0, 0)",whiteSpace:"nowrap",wordWrap:"normal"}]);return(o,l)=>(_(),F("span",ot(o.$attrs,{style:s(n)}),[oe(o.$slots,"default")],16))}});var zX=Te(HX,[["__file","visual-hidden.vue"]]);Se({});const KX=e=>{if(!kt)return;if(!e)return e;const t=hn(e);return t||(Kt(e)?t:e)},WX=({middleware:e,placement:t,strategy:n})=>{const o=L(),l=L(),a=L(),r=L(),i=L({}),u={x:a,y:r,placement:t,strategy:n,middlewareData:i},c=async()=>{if(!kt)return;const d=KX(o),f=hn(l);if(!d||!f)return;const v=await c_(d,f,{placement:s(t),strategy:s(n),middleware:s(e)});cs(u).forEach(p=>{u[p].value=v[p]})};return rt(()=>{Kn(()=>{c()})}),{...u,update:c,referenceRef:o,contentRef:l}},jX=({arrowRef:e,padding:t})=>({name:"arrow",options:{element:e,padding:t},fn(n){const o=s(e);return o?u_({element:o,padding:t}).fn(n):{}}}),UX=q({name:"ElTooltipV2Content"}),qX=q({...UX,props:{...jm,...GE},setup(e){const t=e,{triggerRef:n,contentId:o}=Pe(cf),l=L(t.placement),a=L(t.strategy),r=L(null),{referenceRef:i,contentRef:u,middlewareData:c,x:d,y:f,update:v}=WX({placement:l,strategy:a,middleware:S(()=>{const y=[i_(t.offset)];return t.showArrow&&y.push(jX({arrowRef:r})),y})}),p=Ps().nextZIndex(),m=be("tooltip-v2"),h=S(()=>l.value.split("-")[0]),g=S(()=>({position:s(a),top:`${s(f)||0}px`,left:`${s(d)||0}px`,zIndex:p})),b=S(()=>{if(!t.showArrow)return{};const{arrow:y}=s(c);return{[`--${m.namespace.value}-tooltip-v2-arrow-x`]:`${y?.x}px`||"",[`--${m.namespace.value}-tooltip-v2-arrow-y`]:`${y?.y}px`||""}}),C=S(()=>[m.e("content"),m.is("dark",t.effect==="dark"),m.is(s(a)),t.contentClass]);return pe(r,()=>v()),pe(()=>t.placement,y=>l.value=y),rt(()=>{pe(()=>t.reference||n.value,y=>{i.value=y||void 0},{immediate:!0})}),ut(JE,{arrowRef:r}),(y,w)=>(_(),F("div",{ref_key:"contentRef",ref:u,style:We(s(g)),"data-tooltip-v2-root":""},[y.nowrap?re("v-if",!0):(_(),F("div",{key:0,"data-side":s(h),class:$(s(C))},[oe(y.$slots,"default",{contentStyle:s(g),contentClass:s(C)}),J(s(zX),{id:s(o),role:"tooltip"},{default:ee(()=>[y.ariaLabel?(_(),F(He,{key:0},[gt(Ee(y.ariaLabel),1)],64)):oe(y.$slots,"default",{key:1})]),_:3},8,["id"]),oe(y.$slots,"arrow",{style:We(s(b)),side:s(h)})],10,["data-side"]))],4))}});var nw=Te(qX,[["__file","content.vue"]]);const YX=Se({setRef:{type:Q(Function),required:!0},onlyChild:Boolean});var GX=q({props:YX,setup(e,{slots:t}){const n=L(),o=af(n,l=>{l?e.setRef(l.nextElementSibling):e.setRef(null)});return()=>{var l;const[a]=((l=t.default)==null?void 0:l.call(t))||[],r=e.onlyChild?BB(a.children):a.children;return J(He,{ref:o},[r])}}});const XX=q({name:"ElTooltipV2Trigger"}),JX=q({...XX,props:{...GE,...qm},setup(e){const t=e,{onClose:n,onOpen:o,onDelayOpen:l,triggerRef:a,contentId:r}=Pe(cf);let i=!1;const u=C=>{a.value=C},c=()=>{i=!1},d=nn(t.onMouseEnter,l),f=nn(t.onMouseLeave,n),v=nn(t.onMouseDown,()=>{n(),i=!0,document.addEventListener("mouseup",c,{once:!0})}),p=nn(t.onFocus,()=>{i||o()}),m=nn(t.onBlur,n),h=nn(t.onClick,C=>{C.detail===0&&n()}),g={blur:m,click:h,focus:p,mousedown:v,mouseenter:d,mouseleave:f},b=(C,y,w)=>{C&&Object.entries(y).forEach(([k,E])=>{C[w](k,E)})};return pe(a,(C,y)=>{b(C,g,"addEventListener"),b(y,g,"removeEventListener"),C&&C.setAttribute("aria-describedby",r.value)}),Rt(()=>{b(a.value,g,"removeEventListener"),document.removeEventListener("mouseup",c)}),(C,y)=>C.nowrap?(_(),ie(s(GX),{key:0,"set-ref":u,"only-child":""},{default:ee(()=>[oe(C.$slots,"default")]),_:3})):(_(),F("button",ot({key:1,ref_key:"triggerRef",ref:a},C.$attrs),[oe(C.$slots,"default")],16))}});var ZX=Te(JX,[["__file","trigger.vue"]]);const QX=q({name:"ElTooltipV2"}),eJ=q({...QX,props:HG,setup(e){const n=mn(e),o=_t(mo(n,Object.keys(Wm))),l=_t(mo(n,Object.keys(jm))),a=_t(mo(n,Object.keys(Um))),r=_t(mo(n,Object.keys(qm)));return(i,u)=>(_(),ie(WG,Jn(Ko(a)),{default:ee(({open:c})=>[J(ZX,ot(r,{nowrap:""}),{default:ee(()=>[oe(i.$slots,"trigger")]),_:3},16),J(s(Ms),{to:i.to,disabled:!i.teleported},{default:ee(()=>[i.fullTransition?(_(),ie(En,Jn(ot({key:0},i.transitionProps)),{default:ee(()=>[i.alwaysOn||c?(_(),ie(nw,Jn(ot({key:0},l)),{arrow:ee(({style:d,side:f})=>[i.showArrow?(_(),ie(Yy,ot({key:0},o,{style:d,side:f}),null,16,["style","side"])):re("v-if",!0)]),default:ee(()=>[oe(i.$slots,"default")]),_:3},16)):re("v-if",!0)]),_:2},1040)):(_(),F(He,{key:1},[i.alwaysOn||c?(_(),ie(nw,Jn(ot({key:0},l)),{arrow:ee(({style:d,side:f})=>[i.showArrow?(_(),ie(Yy,ot({key:0},o,{style:d,side:f}),null,16,["style","side"])):re("v-if",!0)]),default:ee(()=>[oe(i.$slots,"default")]),_:3},16)):re("v-if",!0)],64))]),_:2},1032,["to","disabled"])]),_:3},16))}});var tJ=Te(eJ,[["__file","tooltip.vue"]]);const nJ=Ze(tJ),d_="left-check-change",f_="right-check-change",Fr=Se({data:{type:Q(Array),default:()=>[]},titles:{type:Q(Array),default:()=>[]},buttonTexts:{type:Q(Array),default:()=>[]},filterPlaceholder:String,filterMethod:{type:Q(Function)},leftDefaultChecked:{type:Q(Array),default:()=>[]},rightDefaultChecked:{type:Q(Array),default:()=>[]},renderContent:{type:Q(Function)},modelValue:{type:Q(Array),default:()=>[]},format:{type:Q(Object),default:()=>({})},filterable:Boolean,props:{type:Q(Object),default:()=>Gt({label:"label",key:"key",disabled:"disabled"})},targetOrder:{type:String,values:["original","push","unshift"],default:"original"},validateEvent:{type:Boolean,default:!0}}),Nv=(e,t)=>[e,t].every(ye)||ye(e)&&rn(t),oJ={[ht]:(e,t,n)=>[e,n].every(ye)&&["left","right"].includes(t),[Ge]:e=>ye(e),[d_]:Nv,[f_]:Nv},Iv="checked-change",lJ=Se({data:Fr.data,optionRender:{type:Q(Function)},placeholder:String,title:String,filterable:Boolean,format:Fr.format,filterMethod:Fr.filterMethod,defaultChecked:Fr.leftDefaultChecked,props:Fr.props}),aJ={[Iv]:Nv},Tu=e=>{const t={label:"label",key:"key",disabled:"disabled"};return S(()=>({...t,...e.props}))},rJ=(e,t,n)=>{const o=Tu(e),l=S(()=>e.data.filter(d=>ze(e.filterMethod)?e.filterMethod(t.query,d):String(d[o.value.label]||d[o.value.key]).toLowerCase().includes(t.query.toLowerCase()))),a=S(()=>l.value.filter(d=>!d[o.value.disabled])),r=S(()=>{const d=t.checked.length,f=e.data.length,{noChecked:v,hasChecked:p}=e.format;return v&&p?d>0?p.replace(/\${checked}/g,d.toString()).replace(/\${total}/g,f.toString()):v.replace(/\${total}/g,f.toString()):`${d}/${f}`}),i=S(()=>{const d=t.checked.length;return d>0&&d[A.indicatorPosition!=="none"?(_(),F("ul",{key:0,class:$(s(B))},[(_(!0),F(He,null,mt(s(f),(D,V)=>nt((_(),F("li",{key:V,class:$([s(I).e("indicator"),s(I).em("indicator",A.direction),s(I).is("active",V===s(a))]),onMouseenter:H=>s(O)(V),onClick:qe(H=>s(g)(V),["stop"])},[z("button",{class:$(s(I).e("button")),"aria-label":s(P)("el.carousel.indicator",{index:V+1})},[s(u)?(_(),F("span",{key:0},Ee(D.props.label),1)):re("v-if",!0)],10,["aria-label"])],42,["onMouseenter","onClick"])),[[Et,s(T)(V)]])),128))],2)):re("v-if",!0)]),_:1}),o.motionBlur?(_(),F("svg",{key:2,xmlns:"http://www.w3.org/2000/svg",version:"1.1",style:{display:"none"}},[z("defs",null,[z("filter",{id:"elCarouselHorizontal"},[z("feGaussianBlur",{in:"SourceGraphic",stdDeviation:"12,0"})]),z("filter",{id:"elCarouselVertical"},[z("feGaussianBlur",{in:"SourceGraphic",stdDeviation:"0,10"})])])])):re("v-if",!0)],42,["onMouseenter","onMouseleave"]))}});var WB=Te(KB,[["__file","carousel.vue"]]);const jB=Se({name:{type:String,default:""},label:{type:[String,Number],default:""}}),UB=e=>{const t=Pe($2),n=it(),o=L(),l=L(!1),a=L(0),r=L(1),i=L(!1),u=L(!1),c=L(!1),d=L(!1),{isCardType:f,isVertical:v,cardScale:p}=t;function m(w,k,E){const T=E-1,x=k-1,N=k+1,O=E/2;return k===0&&w===T?-1:k===T&&w===0?E:w[A.indicatorPosition!=="none"?(_(),F("ul",{key:0,class:$(s(B))},[(_(!0),F(He,null,mt(s(f),(D,V)=>nt((_(),F("li",{key:V,class:$([s(I).e("indicator"),s(I).em("indicator",A.direction),s(I).is("active",V===s(a))]),onMouseenter:H=>s(O)(V),onClick:qe(H=>s(g)(V),["stop"])},[z("button",{class:$(s(I).e("button")),"aria-label":s(P)("el.carousel.indicator",{index:V+1})},[s(u)?(_(),F("span",{key:0},Ee(D.props.label),1)):re("v-if",!0)],10,["aria-label"])],42,["onMouseenter","onClick"])),[[Et,s(T)(V)]])),128))],2)):re("v-if",!0)]),_:1}),o.motionBlur?(_(),F("svg",{key:2,xmlns:"http://www.w3.org/2000/svg",version:"1.1",style:{display:"none"}},[z("defs",null,[z("filter",{id:"elCarouselHorizontal"},[z("feGaussianBlur",{in:"SourceGraphic",stdDeviation:"12,0"})]),z("filter",{id:"elCarouselVertical"},[z("feGaussianBlur",{in:"SourceGraphic",stdDeviation:"0,10"})])])])):re("v-if",!0)],42,["onMouseenter","onMouseleave"]))}});var jB=Te(WB,[["__file","carousel.vue"]]);const UB=Se({name:{type:String,default:""},label:{type:[String,Number],default:""}}),qB=e=>{const t=Pe(I2),n=it(),o=L(),l=L(!1),a=L(0),r=L(1),i=L(!1),u=L(!1),c=L(!1),d=L(!1),{isCardType:f,isVertical:v,cardScale:p}=t;function m(w,k,E){const T=E-1,x=k-1,N=k+1,O=E/2;return k===0&&w===T?-1:k===T&&w===0?E:w