diff --git a/.gitignore b/.gitignore index 185a360..a24df91 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ success_images/ build/ config.json +frontend/node_modules + # Wails 自动生成的前端绑定 frontend/wailsjs/ diff --git a/build.sh b/build.sh index 6e11e0b..8fd33c1 100755 --- a/build.sh +++ b/build.sh @@ -1,20 +1,207 @@ #!/bin/bash -# 构建带版本号的产物 -# 用法: ./build.sh # 构建当前平台 -# GOOS=windows ./build.sh # 构建 Windows -# GOOS=linux ./build.sh # 构建 Linux +# 斗鱼抢购系统 - 一键启动/构建脚本 +# 用法: +# ./build.sh # 开发模式(带热更新) +# ./build.sh dev # 开发模式(带热更新) +# ./build.sh build # 生产构建 +# ./build.sh win # 构建 Windows 版本 +# ./build.sh linux # 构建 Linux 版本 +# ./build.sh clean # 清理构建产物 +# ./build.sh install # 安装前端依赖 + set -e -VERSION=$(grep '"version"' wails.json | head -1 | sed 's/.*"version": *"//;s/".*//') -echo "版本: v${VERSION}" +# 获取脚本所在目录 +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR" -if [ "$GOOS" = "windows" ]; then - wails build -platform windows/amd64 -o "douyu_go_v${VERSION}.exe" -elif [ "$GOOS" = "linux" ]; then - wails build -platform linux/amd64 -o "douyu_go_v${VERSION}" -else +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# 获取版本号 +get_version() { + grep '"version"' wails.json | head -1 | sed 's/.*"version": *"//;s/".*//' +} + +# 打印带颜色的消息 +info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +error() { + echo -e "${RED}[ERROR]${NC} $1" + exit 1 +} + +# 检查依赖 +check_deps() { + local missing=() + + if ! command -v wails &> /dev/null; then + missing+=("wails") + fi + + if ! command -v go &> /dev/null; then + missing+=("go") + fi + + if ! command -v node &> /dev/null; then + missing+=("node") + fi + + if ! command -v npm &> /dev/null; then + missing+=("npm") + fi + + if [ ${#missing[@]} -ne 0 ]; then + error "缺少依赖: ${missing[*]}" + fi +} + +# 安装前端依赖 +install_deps() { + info "安装前端依赖..." + cd frontend + npm install + cd .. + success "前端依赖安装完成" +} + +# 开发模式 +dev_mode() { + local VERSION=$(get_version) + info "启动开发模式 v${VERSION}" + info "前端热更新 + 后端自动重编译" + echo "" + echo -e "${YELLOW}提示: 按 Ctrl+C 退出${NC}" + echo "" + + wails dev +} + +# 生产构建 +build_production() { + local VERSION=$(get_version) + info "开始生产构建 v${VERSION}" + + # 类型检查 + info "TypeScript 类型检查..." + cd frontend + npm run type-check + cd .. + + # Wails 构建 wails build -fi -echo "=== 构建产物 ===" -ls -lh build/bin/ + success "构建完成!" + echo "" + echo "=== 构建产物 ===" + ls -lh build/bin/ +} + +# 构建 Windows 版本 +build_windows() { + local VERSION=$(get_version) + info "构建 Windows 版本 v${VERSION}" + + GOOS=windows GOARCH=amd64 wails build -platform windows/amd64 -o "douyu_go_v${VERSION}.exe" + + success "Windows 构建完成!" + echo "" + echo "=== 构建产物 ===" + ls -lh build/bin/ +} + +# 构建 Linux 版本 +build_linux() { + local VERSION=$(get_version) + info "构建 Linux 版本 v${VERSION}" + + GOOS=linux GOARCH=amd64 wails build -platform linux/amd64 -o "douyu_go_v${VERSION}" + + success "Linux 构建完成!" + echo "" + echo "=== 构建产物 ===" + ls -lh build/bin/ +} + +# 清理构建产物 +clean_build() { + info "清理构建产物..." + + rm -rf build/bin/* + rm -rf frontend/dist + rm -rf frontend/node_modules/.vite + + success "清理完成" +} + +# 显示帮助 +show_help() { + echo "斗鱼抢购系统 - 一键启动/构建脚本" + echo "" + echo "用法:" + echo " ./build.sh # 开发模式(带热更新)" + echo " ./build.sh dev # 开发模式(带热更新)" + echo " ./build.sh build # 生产构建" + echo " ./build.sh win # 构建 Windows 版本" + echo " ./build.sh linux # 构建 Linux 版本" + echo " ./build.sh clean # 清理构建产物" + echo " ./build.sh install # 安装前端依赖" + echo " ./build.sh help # 显示此帮助" + echo "" + echo "环境变量:" + echo " GOOS 目标操作系统 (windows/linux/darwin)" + echo " GOARCH 目标架构 (amd64/arm64)" +} + +# 主函数 +main() { + # 检查依赖 + check_deps + + # 解析命令 + local command="${1:-dev}" + + case "$command" in + dev) + dev_mode + ;; + build) + build_production + ;; + win|windows) + build_windows + ;; + linux) + build_linux + ;; + clean) + clean_build + ;; + install) + install_deps + ;; + help|-h|--help) + show_help + ;; + *) + error "未知命令: $command\n\n使用 ./build.sh help 查看帮助" + ;; + esac +} + +# 运行主函数 +main "$@" diff --git a/frontend/dist/assets/index-Blthttbm.css b/frontend/dist/assets/index-Blthttbm.css new file mode 100644 index 0000000..a932b5d --- /dev/null +++ b/frontend/dist/assets/index-Blthttbm.css @@ -0,0 +1 @@ +.product-search[data-v-819c56b1]{display:flex;align-items:center;gap:8px;background:var(--field);border:1px solid var(--line);border-radius:var(--radius-sm);padding:0 10px;transition:.15s}.product-search[data-v-819c56b1]:focus-within{border-color:var(--accent);box-shadow:var(--focus)}.product-search input[data-v-819c56b1]{flex:1;min-width:0;height:32px;border:0;outline:0;background:transparent;font-size:13px}.product-search input[data-v-819c56b1]::placeholder{color:var(--muted-2)}.search-icon[data-v-819c56b1]{color:var(--muted-2);font-size:13px}.search-clear[data-v-819c56b1]{width:20px;height:20px;border:0;border-radius:4px;background:transparent;color:var(--muted);cursor:pointer;font-size:14px;display:flex;align-items:center;justify-content:center}.search-clear[data-v-819c56b1]:hover{background:var(--surface-3);color:var(--text-strong)}.product-list[data-v-a05105ef]{flex:1;overflow-y:auto;padding:6px 8px 12px;min-height:0}.product-list-inner[data-v-a05105ef]{width:100%}.prod-item[data-v-a05105ef]{display:grid;grid-template-columns:40px minmax(0,1fr);gap:10px;padding:8px 10px;margin:2px 0;border-radius:var(--radius-sm);cursor:pointer;border:1px solid transparent;transition:.12s}.prod-item[data-v-a05105ef]:hover{background:var(--surface-2)}.prod-item.active[data-v-a05105ef]{background:var(--accent-soft);border-color:var(--accent-border)}.prod-item img[data-v-a05105ef]{width:40px;height:40px;border-radius:var(--radius-sm);object-fit:cover;background:var(--field);border:1px solid var(--line)}.pinfo[data-v-a05105ef]{min-width:0;display:flex;flex-direction:column;justify-content:center;gap:4px}.pname[data-v-a05105ef]{font-size:12.5px;font-weight:500;color:var(--text-strong);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.3}.pmeta[data-v-a05105ef]{font-size:11px;color:var(--muted);display:flex;gap:6px;flex-wrap:wrap}.selected-product-card[data-v-b1ab3b9f]{padding:12px;border:1px solid var(--line);border-radius:var(--radius);background:var(--surface-2)}.selected-product-card.has-product[data-v-b1ab3b9f]{border-color:var(--accent-border);background:var(--accent-soft)}.selected-product-label[data-v-b1ab3b9f]{font-size:10px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.08em;margin-bottom:6px}.selected-product-name[data-v-b1ab3b9f]{font-size:13px;color:var(--text-strong);font-weight:600;line-height:1.4;word-break:break-all}.selected-product-meta[data-v-b1ab3b9f]{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px}.left[data-v-5a20b760]{background:var(--surface);border-right:1px solid var(--line);display:flex;flex-direction:column;min-width:0;min-height:0;overflow:hidden}.brand[data-v-5a20b760]{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:16px 18px;border-bottom:1px solid var(--line)}.brand h1[data-v-5a20b760]{font-size:15px;font-weight:600;color:var(--text-strong);letter-spacing:-.01em}.brand-sub[data-v-5a20b760]{font-size:11px;color:var(--muted);margin-top:3px;letter-spacing:.02em}.left-header[data-v-5a20b760]{padding:14px 16px;border-bottom:1px solid var(--line);display:flex;flex-direction:column;gap:10px}.product-actions[data-v-5a20b760]{display:flex;gap:6px;align-items:center}.product-actions .btn-primary[data-v-5a20b760]{flex:1}.product-meta[data-v-5a20b760]{font-size:11px;color:var(--muted);padding:0 2px}.product-meta.good[data-v-5a20b760]{color:var(--success)}.product-meta.warn[data-v-5a20b760]{color:var(--warning)}@media(max-width:1180px){.left[data-v-5a20b760]{height:auto;overflow:visible;border-right:0;border-bottom:1px solid var(--line)}}.status-grid[data-v-9217deda]{display:flex;gap:24px;padding:12px 20px;background:var(--surface);border-bottom:1px solid var(--line);align-items:center}.metric[data-v-9217deda]{display:flex;align-items:baseline;gap:6px;min-width:0}.metric-label[data-v-9217deda]{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;font-weight:500}.metric-value[data-v-9217deda]{color:var(--text-strong);font-weight:600;font-size:14px;font-variant-numeric:tabular-nums}.metric-value.server[data-v-9217deda]{color:var(--accent)}.metric-value.success-num[data-v-9217deda]{color:var(--success)}.metric-value.fail-num[data-v-9217deda]{color:var(--danger)}@media(max-width:1180px){.status-grid[data-v-9217deda]{flex-wrap:wrap;gap:14px 24px}}.control-strip[data-v-81e7b618]{padding:12px 20px;background:var(--surface);border-bottom:1px solid var(--line);display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap}.action-group[data-v-81e7b618]{display:flex;gap:6px;align-items:center;flex-wrap:wrap}.schedule-bar[data-v-81e7b618]{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.schedule-item[data-v-81e7b618]{display:flex;align-items:center;gap:6px}.schedule-bar label[data-v-81e7b618]{color:var(--muted);font-size:12px;white-space:nowrap}.schedule-bar input[data-v-81e7b618]{height:30px;padding:0 10px;background:var(--field);color:var(--text-strong);border:1px solid var(--line);border-radius:var(--radius-sm);font-size:12.5px;font-variant-numeric:tabular-nums;transition:.15s}.schedule-bar input[data-v-81e7b618]:focus{outline:0;border-color:var(--accent);box-shadow:var(--focus)}.schedule-bar input[type=time][data-v-81e7b618]{width:108px;text-align:center}.schedule-bar input[type=number][data-v-81e7b618]{width:72px;text-align:center}@media(max-width:1180px){.control-strip[data-v-81e7b618]{flex-direction:column;align-items:stretch}.schedule-bar[data-v-81e7b618]{justify-content:flex-end}}.panel[data-v-9686f816]{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);min-width:0;min-height:0;display:flex;flex-direction:column;overflow:hidden;height:100%}.panel-head[data-v-9686f816]{padding:10px 14px;border-bottom:1px solid var(--line);display:flex;align-items:center;justify-content:space-between;gap:10px;background:var(--surface)}.panel-title[data-v-9686f816]{font-size:13px;font-weight:600;color:var(--text-strong)}.panel-sub[data-v-9686f816]{font-size:11.5px;color:var(--muted);margin-left:8px;font-weight:400}.panel-head label.stat-pill[data-v-9686f816]{cursor:pointer}.panel-head label.stat-pill input[data-v-9686f816]{margin:0;cursor:pointer}.table-wrap[data-v-9686f816]{flex:1;overflow:auto;min-height:0}table[data-v-9686f816]{width:100%;border-collapse:separate;border-spacing:0;font-size:12.5px}th[data-v-9686f816]{background:var(--surface-2);padding:8px 12px;text-align:left;border-bottom:1px solid var(--line);position:sticky;top:0;z-index:1;color:var(--muted);font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;white-space:nowrap}td[data-v-9686f816]{padding:9px 12px;border-bottom:1px solid var(--line);vertical-align:middle}tbody tr:last-child td[data-v-9686f816]{border-bottom:0}tbody tr[data-v-9686f816]{transition:.1s}tbody tr[data-v-9686f816]:hover{background:var(--surface-2)}.select-cell[data-v-9686f816]{width:36px}.status-col[data-v-9686f816]{width:96px}.account-name[data-v-9686f816]{font-weight:500;color:var(--text-strong)}.account-sub[data-v-9686f816]{font-size:11px;color:var(--muted);margin-top:2px}.account-check[data-v-9686f816]{display:inline-flex;align-items:center;cursor:pointer}.check-box[data-v-9686f816]{width:16px;height:16px;border-radius:4px;border:1.5px solid var(--line-strong);background:transparent;display:flex;align-items:center;justify-content:center;transition:.15s;color:#fff;font-size:10px;font-weight:700}.check-box.checked[data-v-9686f816]{border-color:var(--accent);background:var(--accent)}.prod-tag[data-v-9686f816]{display:inline-flex;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;background:var(--surface-2);color:var(--text);border:1px solid var(--line);padding:2px 8px;border-radius:999px;font-size:11.5px}@media(max-width:1180px){.table-wrap[data-v-9686f816]{max-height:520px}}.log-wrap[data-v-b57afed1]{flex:1;min-height:0}.log-header[data-v-b57afed1]{padding:8px 12px;border-bottom:1px solid var(--line);display:flex;justify-content:space-between;align-items:center;gap:8px;background:var(--surface)}.log-tabs[data-v-b57afed1]{display:flex;gap:2px;align-items:center}.log-tab[data-v-b57afed1]{height:26px;padding:0 10px;border-radius:var(--radius-sm);border:0;background:transparent;color:var(--muted);cursor:pointer;font-size:11.5px;font-weight:500;transition:.12s}.log-tab[data-v-b57afed1]:hover{color:var(--text-strong);background:var(--surface-2)}.log-tab.active[data-v-b57afed1]{background:var(--accent-soft);color:var(--accent)}.log-panel[data-v-b57afed1]{flex:1;min-height:0;overflow:auto;padding:10px 12px;font-family:SF Mono,Monaco,Consolas,Courier New,monospace;font-size:11.5px;line-height:1.7;background:var(--field)}.log-s[data-v-b57afed1]{color:var(--success)}.log-e[data-v-b57afed1]{color:var(--danger)}.log-i[data-v-b57afed1]{color:var(--accent)}.log-w[data-v-b57afed1]{color:var(--warning)}.log-d[data-v-b57afed1]{color:var(--muted-2)}.log-result[data-v-b57afed1]{background:var(--surface);padding:6px 9px;margin:4px 0;border-radius:var(--radius-sm);word-break:break-all;border:1px solid var(--line)}.log-cat[data-v-b57afed1]{display:inline-block;min-width:32px;text-align:center;margin-right:6px;padding:0 5px;border:1px solid var(--line);border-radius:3px;color:var(--muted);font-size:10px;line-height:1.5;background:var(--surface)}.result-empty[data-v-b57afed1]{color:var(--muted);padding:14px 4px;font-style:italic}.panel[data-v-b57afed1]{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);min-width:0;min-height:0;display:flex;flex-direction:column;overflow:hidden;height:100%}@media(max-width:1180px){.log-wrap[data-v-b57afed1]{height:360px}}.modal-overlay[data-v-6aaf64c9]{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;z-index:9000;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.modal[data-v-6aaf64c9]{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);width:520px;max-width:92vw;max-height:85vh;overflow-y:auto;box-shadow:var(--shadow)}.modal-header[data-v-6aaf64c9]{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid var(--line)}.modal-header h3[data-v-6aaf64c9]{font-size:16px;font-weight:600;color:var(--text-strong);display:flex;align-items:center;gap:8px}.modal-close[data-v-6aaf64c9]{width:32px;height:32px;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--muted);cursor:pointer;font-size:20px;display:flex;align-items:center;justify-content:center;transition:.15s}.modal-close[data-v-6aaf64c9]:hover{background:var(--surface-2);color:var(--text-strong)}.modal-body[data-v-6aaf64c9]{padding:20px}.form-section[data-v-6aaf64c9]{margin-top:20px;padding-top:16px;border-top:1px solid var(--line)}.form-section-title[data-v-6aaf64c9]{font-size:13px;font-weight:600;color:var(--text-strong);margin-bottom:14px}.form-group[data-v-6aaf64c9]{margin-bottom:16px}.form-group[data-v-6aaf64c9]:last-child{margin-bottom:0}.form-label[data-v-6aaf64c9]{display:block;font-size:12.5px;font-weight:500;color:var(--text);margin-bottom:6px}.form-hint[data-v-6aaf64c9]{font-size:11px;color:var(--muted);margin-top:4px;line-height:1.5}.form-row[data-v-6aaf64c9]{display:flex;gap:16px}.form-row .form-group[data-v-6aaf64c9]{flex:1}.form-input[data-v-6aaf64c9],.form-select[data-v-6aaf64c9]{width:100%;height:36px;padding:0 12px;background:var(--field);color:var(--text-strong);border:1px solid var(--line);border-radius:var(--radius-sm);font-size:13px;transition:.15s}.form-input[data-v-6aaf64c9]:focus,.form-select[data-v-6aaf64c9]:focus{outline:0;border-color:var(--accent);box-shadow:var(--focus)}.input-with-unit[data-v-6aaf64c9]{display:flex;align-items:center;gap:8px}.input-with-unit .form-input[data-v-6aaf64c9]{flex:1}.input-unit[data-v-6aaf64c9]{font-size:12px;color:var(--muted);white-space:nowrap}.toggle-row[data-v-6aaf64c9]{display:flex;align-items:center;justify-content:space-between;gap:16px}.toggle-label[data-v-6aaf64c9]{font-size:13px;color:var(--text-strong);font-weight:500}.toggle[data-v-6aaf64c9]{position:relative;width:44px;height:24px;cursor:pointer;flex-shrink:0}.toggle input[data-v-6aaf64c9]{opacity:0;width:0;height:0}.toggle-slider[data-v-6aaf64c9]{position:absolute;top:0;right:0;bottom:0;left:0;background:var(--line-strong);border-radius:999px;transition:.2s}.toggle-slider[data-v-6aaf64c9]:before{content:"";position:absolute;left:2px;top:2px;width:20px;height:20px;background:#fff;border-radius:50%;transition:.2s}.toggle input:checked+.toggle-slider[data-v-6aaf64c9]{background:var(--accent)}.toggle input:checked+.toggle-slider[data-v-6aaf64c9]:before{transform:translate(20px)}.modal-footer[data-v-6aaf64c9]{padding:16px 20px;border-top:1px solid var(--line);display:flex;justify-content:flex-end;gap:10px}.info-card[data-v-6aaf64c9]{margin-top:16px;padding:14px;background:var(--accent-soft);border:1px solid var(--accent-border);border-radius:var(--radius-sm)}.info-card-warn[data-v-6aaf64c9]{background:var(--warning-soft);border-color:var(--warning)}.info-card-warn .info-title[data-v-6aaf64c9]{color:var(--warning)}.info-title[data-v-6aaf64c9]{font-size:12.5px;font-weight:600;color:var(--accent);margin-bottom:10px}.info-list[data-v-6aaf64c9]{margin:0;padding-left:18px;font-size:12px;color:var(--text);line-height:1.8}.info-list li[data-v-6aaf64c9]{margin-bottom:4px}.info-list li[data-v-6aaf64c9]:last-child{margin-bottom:0}.info-list strong[data-v-6aaf64c9]{color:var(--text-strong);font-weight:600}.modal-enter-active[data-v-6aaf64c9],.modal-leave-active[data-v-6aaf64c9]{transition:all .2s ease}.modal-enter-from[data-v-6aaf64c9],.modal-leave-to[data-v-6aaf64c9]{opacity:0}.modal-enter-from .modal[data-v-6aaf64c9],.modal-leave-to .modal[data-v-6aaf64c9]{transform:scale(.95);opacity:0}.right[data-v-0e645076]{display:flex;flex-direction:column;min-width:0;min-height:0;overflow:hidden}.console-head[data-v-0e645076]{padding:14px 20px;border-bottom:1px solid var(--line);background:var(--surface);display:flex;align-items:center;justify-content:space-between;gap:16px}.headline[data-v-0e645076]{display:flex;align-items:center;gap:14px;min-width:0}.headline-title[data-v-0e645076]{font-size:15px;font-weight:600;color:var(--text-strong);letter-spacing:-.01em}.headline-meta[data-v-0e645076]{font-size:12px;color:var(--muted);margin-top:2px}.top-actions[data-v-0e645076]{display:flex;align-items:center;gap:6px}.countdown-badge[data-v-0e645076]{display:inline-flex;align-items:center;padding:4px 10px;border-radius:999px;background:var(--danger-soft);color:var(--danger);border:1px solid var(--danger);font-weight:600;font-size:12px;font-variant-numeric:tabular-nums}.workspace[data-v-0e645076]{display:grid;grid-template-columns:minmax(0,1fr) 380px;gap:14px;padding:14px 20px 20px;align-items:stretch;flex:1;min-height:0;overflow:hidden}.side-stack[data-v-0e645076]{display:flex;flex-direction:column;gap:14px;min-height:0;height:100%}@media(max-width:1180px){.right[data-v-0e645076]{overflow:visible;min-height:auto}.workspace[data-v-0e645076]{grid-template-columns:1fr;padding:14px;overflow:visible}}.app-shell[data-v-08a2f527]{display:grid;grid-template-columns:300px minmax(0,1fr);height:100vh;min-width:1080px;overflow:hidden}@media(max-width:1180px){.app-shell[data-v-08a2f527]{display:block;min-width:0;height:auto;overflow:visible}}.toast-container[data-v-c5ddc5d1]{position:fixed;top:20px;right:-420px;z-index:9999;transition:right .35s cubic-bezier(.16,1,.3,1)}.toast-container.show[data-v-c5ddc5d1]{right:20px}.toast[data-v-c5ddc5d1]{background:var(--surface);border:1px solid var(--line);border-left-width:3px;border-radius:var(--radius);padding:12px 14px;margin-bottom:8px;min-width:300px;max-width:380px;box-shadow:var(--shadow);cursor:pointer;transition:opacity .3s,transform .3s}.toast-title[data-v-c5ddc5d1]{font-size:12.5px;font-weight:600;margin-bottom:3px;color:var(--text-strong)}.toast-body[data-v-c5ddc5d1]{font-size:12px;color:var(--muted);line-height:1.6}.toast-success[data-v-c5ddc5d1]{border-left-color:var(--success)}.toast-success .toast-title[data-v-c5ddc5d1]{color:var(--success)}.toast-info[data-v-c5ddc5d1]{border-left-color:var(--accent)}.toast-info .toast-title[data-v-c5ddc5d1]{color:var(--accent)}.toast-warn[data-v-c5ddc5d1]{border-left-color:var(--warning)}.toast-warn .toast-title[data-v-c5ddc5d1]{color:var(--warning)}.toast-error[data-v-c5ddc5d1]{border-left-color:var(--danger)}.toast-error .toast-title[data-v-c5ddc5d1]{color:var(--danger)}.toast-enter-active[data-v-c5ddc5d1],.toast-leave-active[data-v-c5ddc5d1]{transition:all .3s ease}.toast-enter-from[data-v-c5ddc5d1],.toast-leave-to[data-v-c5ddc5d1]{opacity:0;transform:translate(30px)}:root{color-scheme:dark;--bg: #0f1419;--surface: #161b22;--surface-2: #1c232c;--surface-3: #232b36;--field: #0d1117;--text: #c9d1d9;--text-strong: #f0f6fc;--muted: #8b949e;--muted-2: #6e7681;--line: #21262d;--line-strong: #30363d;--accent: #388bfd;--accent-soft: rgba(56, 139, 253, .12);--accent-border: rgba(56, 139, 253, .35);--danger: #f85149;--danger-soft: rgba(248, 81, 73, .12);--success: #3fb950;--success-soft: rgba(63, 185, 80, .12);--warning: #d29922;--warning-soft: rgba(210, 153, 34, .12);--orange: #f78166;--orange-soft: rgba(247, 129, 102, .12);--shadow: 0 1px 0 rgba(0, 0, 0, .04), 0 8px 24px rgba(0, 0, 0, .18);--radius: 8px;--radius-sm: 6px;--focus: 0 0 0 3px rgba(56, 139, 253, .3)}body[data-theme=light]{color-scheme:light;--bg: #f6f8fa;--surface: #ffffff;--surface-2: #f6f8fa;--surface-3: #eaeef2;--field: #ffffff;--text: #1f2328;--text-strong: #0d1117;--muted: #656d76;--muted-2: #8c959f;--line: #d0d7de;--line-strong: #afb8c1;--accent: #0969da;--accent-soft: rgba(9, 105, 218, .08);--accent-border: rgba(9, 105, 218, .3);--danger: #cf222e;--danger-soft: rgba(207, 34, 46, .08);--success: #1a7f37;--success-soft: rgba(26, 127, 55, .08);--warning: #9a6700;--warning-soft: rgba(154, 103, 0, .1);--orange: #bc4c00;--orange-soft: rgba(188, 76, 0, .08);--shadow: 0 1px 0 rgba(31, 35, 40, .04), 0 8px 24px rgba(140, 149, 159, .15);--focus: 0 0 0 3px rgba(9, 105, 218, .3)}*{margin:0;padding:0;box-sizing:border-box}html,body{height:100vh;overflow:hidden}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,Microsoft YaHei,sans-serif;background:var(--bg);color:var(--text);font-size:13px;line-height:1.5;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}button,input,select{font:inherit;color:inherit}::selection{background:var(--accent-soft);color:var(--text-strong)}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--line-strong);border-radius:999px}::-webkit-scrollbar-thumb:hover{background:var(--muted-2)}.btn{height:30px;padding:0 12px;border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--surface-2);color:var(--text);cursor:pointer;font-size:12.5px;font-weight:500;white-space:nowrap;transition:.12s;display:inline-flex;align-items:center;justify-content:center;gap:6px}.btn:hover{background:var(--surface-3);border-color:var(--line-strong)}.btn:focus-visible{outline:0;box-shadow:var(--focus)}.btn:disabled{opacity:.55;cursor:not-allowed}.btn-primary{background:var(--accent);border-color:var(--accent);color:#fff}.btn-primary:hover{filter:brightness(1.08)}.btn-danger{background:var(--danger);border-color:var(--danger);color:#fff}.btn-danger:hover{filter:brightness(1.08)}.btn-success{background:var(--success);border-color:var(--success);color:#fff}.btn-success:hover{filter:brightness(1.08)}.btn-cancel{background:transparent;color:var(--danger);border-color:var(--danger)}.btn-cancel:hover{background:var(--danger-soft)}.btn-ghost{background:transparent;border-color:transparent;color:var(--muted)}.btn-ghost:hover{color:var(--text-strong);background:var(--surface-2);border-color:var(--line)}.icon-btn{width:36px;height:36px;padding:0;font-size:18px}.btn-compact{height:26px;font-size:11.5px;padding:0 10px}.stat-pill{display:inline-flex;align-items:center;gap:6px;height:24px;padding:0 10px;border:1px solid var(--line);border-radius:999px;background:var(--surface-2);color:var(--muted);font-size:11.5px;font-variant-numeric:tabular-nums}.chip{display:inline-flex;align-items:center;gap:3px;padding:1px 7px;border-radius:999px;background:var(--surface-3);font-size:11px;font-weight:500;white-space:nowrap;color:var(--muted)}.chip-score{color:var(--warning);background:var(--warning-soft)}.chip-stock{color:var(--success);background:var(--success-soft)}.chip-stock.low{color:var(--danger);background:var(--danger-soft)}.status-badge{display:inline-flex;align-items:center;padding:2px 8px;border-radius:999px;border:1px solid var(--line);background:var(--surface-2);font-size:11px;font-weight:500;white-space:nowrap}.status-idle{color:var(--muted)}.status-ready{color:var(--accent);background:var(--accent-soft);border-color:var(--accent-border)}.status-success{color:var(--success);background:var(--success-soft);border-color:var(--success)}.status-fail{color:var(--danger);background:var(--danger-soft);border-color:var(--danger)}.status-warn{color:var(--warning);background:var(--warning-soft);border-color:var(--warning)}.form-input,.form-select{width:100%;height:32px;padding:0 10px;background:var(--field);color:var(--text-strong);border:1px solid var(--line);border-radius:var(--radius-sm);font-size:12.5px;transition:.15s}.form-input:focus,.form-select:focus{outline:0;border-color:var(--accent);box-shadow:var(--focus)}.empty-state{text-align:center;color:var(--muted);padding:48px 16px;font-size:12px;line-height:1.7} diff --git a/frontend/dist/assets/index-VurY-Kh_.js b/frontend/dist/assets/index-VurY-Kh_.js new file mode 100644 index 0000000..b2cca93 --- /dev/null +++ b/frontend/dist/assets/index-VurY-Kh_.js @@ -0,0 +1,21 @@ +(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))n(i);new MutationObserver(i=>{for(const o of i)if(o.type==="childList")for(const r of o.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&n(r)}).observe(document,{childList:!0,subtree:!0});function s(i){const o={};return i.integrity&&(o.integrity=i.integrity),i.referrerPolicy&&(o.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?o.credentials="include":i.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function n(i){if(i.ep)return;i.ep=!0;const o=s(i);fetch(i.href,o)}})();/** +* @vue/shared v3.5.39 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function ei(e){const t=Object.create(null);for(const s of e.split(","))t[s]=1;return s=>s in t}const ie={},jt=[],Xe=()=>{},xo=()=>!1,sn=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),nn=e=>e.startsWith("onUpdate:"),he=Object.assign,ti=(e,t)=>{const s=e.indexOf(t);s>-1&&e.splice(s,1)},Jr=Object.prototype.hasOwnProperty,X=(e,t)=>Jr.call(e,t),k=Array.isArray,Vt=e=>ws(e)==="[object Map]",Gt=e=>ws(e)==="[object Set]",Mi=e=>ws(e)==="[object Date]",B=e=>typeof e=="function",ae=e=>typeof e=="string",Qe=e=>typeof e=="symbol",Q=e=>e!==null&&typeof e=="object",wo=e=>(Q(e)||B(e))&&B(e.then)&&B(e.catch),To=Object.prototype.toString,ws=e=>To.call(e),Yr=e=>ws(e).slice(8,-1),Co=e=>ws(e)==="[object Object]",si=e=>ae(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,cs=ei(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),on=e=>{const t=Object.create(null);return(s=>t[s]||(t[s]=e(s)))},Xr=/-\w/g,ke=on(e=>e.replace(Xr,t=>t.slice(1).toUpperCase())),Qr=/\B([A-Z])/g,Lt=on(e=>e.replace(Qr,"-$1").toLowerCase()),Eo=on(e=>e.charAt(0).toUpperCase()+e.slice(1)),mn=on(e=>e?`on${Eo(e)}`:""),Ye=(e,t)=>!Object.is(e,t),zs=(e,...t)=>{for(let s=0;s{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:n,value:s})},rn=e=>{const t=parseFloat(e);return isNaN(t)?e:t},Zr=e=>{const t=ae(e)?Number(e):NaN;return isNaN(t)?e:t};let Oi;const ln=()=>Oi||(Oi=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Bt(e){if(k(e)){const t={};for(let s=0;s{if(s){const n=s.split(tl);n.length>1&&(t[n[0].trim()]=n[1].trim())}}),t}function _e(e){let t="";if(ae(e))t=e;else if(k(e))for(let s=0;sqt(s,t))}const Mo=e=>!!(e&&e.__v_isRef===!0),W=e=>ae(e)?e:e==null?"":k(e)||Q(e)&&(e.toString===To||!B(e.toString))?Mo(e)?W(e.value):JSON.stringify(e,Oo,2):String(e),Oo=(e,t)=>Mo(t)?Oo(e,t.value):Vt(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((s,[n,i],o)=>(s[vn(n,o)+" =>"]=i,s),{})}:Gt(t)?{[`Set(${t.size})`]:[...t.values()].map(s=>vn(s))}:Qe(t)?vn(t):Q(t)&&!k(t)&&!Co(t)?String(t):t,vn=(e,t="")=>{var s;return Qe(e)?`Symbol(${(s=e.description)!=null?s:t})`:e};/** +* @vue/reactivity v3.5.39 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let pe;class $o{constructor(t=!1){this.detached=t,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this._warnOnRun=!0,this.__v_skip=!0,!t&&pe&&(pe.active?(this.parent=pe,this.index=(pe.scopes||(pe.scopes=[])).push(this)-1):(this._active=!1,this._warnOnRun=!1))}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let t,s;if(this.scopes)for(t=0,s=this.scopes.length;t0&&--this._on===0){if(pe===this)pe=this.prevScope;else{let t=pe;for(;t;){if(t.prevScope===this){t.prevScope=this.prevScope;break}t=t.prevScope}}this.prevScope=void 0}}stop(t){if(this._active){this._active=!1;let s,n;for(s=0,n=this.effects.length;s0)return;if(us){let t=us;for(us=void 0;t;){const s=t.next;t.next=void 0,t.flags&=-9,t=s}}let e;for(;as;){let t=as;for(as=void 0;t;){const s=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(n){e||(e=n)}t=s}}if(e)throw e}function Fo(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function Do(e){let t,s=e.depsTail,n=s;for(;n;){const i=n.prevDep;n.version===-1?(n===s&&(s=i),ri(n),ul(n)):t=n,n.dep.activeLink=n.prevActiveLink,n.prevActiveLink=void 0,n=i}e.deps=t,e.depsTail=s}function jn(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(ko(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function ko(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===gs)||(e.globalVersion=gs,!e.isSSR&&e.flags&128&&(!e.deps&&!e._dirty||!jn(e))))return;e.flags|=2;const t=e.dep,s=le,n=Ne;le=e,Ne=!0;try{Fo(e);const i=e.fn(e._value);(t.version===0||Ye(i,e._value))&&(e.flags|=128,e._value=i,t.version++)}catch(i){throw t.version++,i}finally{le=s,Ne=n,Do(e),e.flags&=-3}}function ri(e,t=!1){const{dep:s,prevSub:n,nextSub:i}=e;if(n&&(n.nextSub=i,e.prevSub=void 0),i&&(i.prevSub=n,e.nextSub=void 0),s.subs===e&&(s.subs=n,!n&&s.computed)){s.computed.flags&=-5;for(let o=s.computed.deps;o;o=o.nextDep)ri(o,!0)}!t&&!--s.sc&&s.map&&s.map.delete(s.key)}function ul(e){const{prevDep:t,nextDep:s}=e;t&&(t.nextDep=s,e.prevDep=void 0),s&&(s.prevDep=t,e.nextDep=void 0)}let Ne=!0;const No=[];function Ze(){No.push(Ne),Ne=!1}function et(){const e=No.pop();Ne=e===void 0?!0:e}function $i(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const s=le;le=void 0;try{t()}finally{le=s}}}let gs=0;class fl{constructor(t,s){this.sub=t,this.dep=s,this.version=s.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class li{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(t){if(!le||!Ne||le===this.computed)return;let s=this.activeLink;if(s===void 0||s.sub!==le)s=this.activeLink=new fl(le,this),le.deps?(s.prevDep=le.depsTail,le.depsTail.nextDep=s,le.depsTail=s):le.deps=le.depsTail=s,jo(s);else if(s.version===-1&&(s.version=this.version,s.nextDep)){const n=s.nextDep;n.prevDep=s.prevDep,s.prevDep&&(s.prevDep.nextDep=n),s.prevDep=le.depsTail,s.nextDep=void 0,le.depsTail.nextDep=s,le.depsTail=s,le.deps===s&&(le.deps=n)}return s}trigger(t){this.version++,gs++,this.notify(t)}notify(t){ii();try{for(let s=this.subs;s;s=s.prevSub)s.sub.notify()&&s.sub.dep.notify()}finally{oi()}}}function jo(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let n=t.deps;n;n=n.nextDep)jo(n)}const s=e.dep.subs;s!==e&&(e.prevSub=s,s&&(s.nextSub=e)),e.dep.subs=e}}const Vn=new WeakMap,Mt=Symbol(""),zn=Symbol(""),ms=Symbol("");function be(e,t,s){if(Ne&&le){let n=Vn.get(e);n||Vn.set(e,n=new Map);let i=n.get(s);i||(n.set(s,i=new li),i.map=n,i.key=s),i.track()}}function rt(e,t,s,n,i,o){const r=Vn.get(e);if(!r){gs++;return}const l=c=>{c&&c.trigger()};if(ii(),t==="clear")r.forEach(l);else{const c=k(e),u=c&&si(s);if(c&&s==="length"){const a=Number(n);r.forEach((f,h)=>{(h==="length"||h===ms||!Qe(h)&&h>=a)&&l(f)})}else switch((s!==void 0||r.has(void 0))&&l(r.get(s)),u&&l(r.get(ms)),t){case"add":c?u&&l(r.get("length")):(l(r.get(Mt)),Vt(e)&&l(r.get(zn)));break;case"delete":c||(l(r.get(Mt)),Vt(e)&&l(r.get(zn)));break;case"set":Vt(e)&&l(r.get(Mt));break}}oi()}function Dt(e){const t=J(e);return t===e?t:(be(t,"iterate",ms),Le(e)?t:t.map(je))}function cn(e){return be(e=J(e),"iterate",ms),e}function qe(e,t){return at(e)?Wt(Ot(e)?je(t):t):je(t)}const dl={__proto__:null,[Symbol.iterator](){return bn(this,Symbol.iterator,e=>qe(this,e))},concat(...e){return Dt(this).concat(...e.map(t=>k(t)?Dt(t):t))},entries(){return bn(this,"entries",e=>(e[1]=qe(this,e[1]),e))},every(e,t){return nt(this,"every",e,t,void 0,arguments)},filter(e,t){return nt(this,"filter",e,t,s=>s.map(n=>qe(this,n)),arguments)},find(e,t){return nt(this,"find",e,t,s=>qe(this,s),arguments)},findIndex(e,t){return nt(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return nt(this,"findLast",e,t,s=>qe(this,s),arguments)},findLastIndex(e,t){return nt(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return nt(this,"forEach",e,t,void 0,arguments)},includes(...e){return yn(this,"includes",e)},indexOf(...e){return yn(this,"indexOf",e)},join(e){return Dt(this).join(e)},lastIndexOf(...e){return yn(this,"lastIndexOf",e)},map(e,t){return nt(this,"map",e,t,void 0,arguments)},pop(){return Zt(this,"pop")},push(...e){return Zt(this,"push",e)},reduce(e,...t){return Pi(this,"reduce",e,t)},reduceRight(e,...t){return Pi(this,"reduceRight",e,t)},shift(){return Zt(this,"shift")},some(e,t){return nt(this,"some",e,t,void 0,arguments)},splice(...e){return Zt(this,"splice",e)},toReversed(){return Dt(this).toReversed()},toSorted(e){return Dt(this).toSorted(e)},toSpliced(...e){return Dt(this).toSpliced(...e)},unshift(...e){return Zt(this,"unshift",e)},values(){return bn(this,"values",e=>qe(this,e))}};function bn(e,t,s){const n=cn(e),i=n[t]();return n!==e&&!Le(e)&&(i._next=i.next,i.next=()=>{const o=i._next();return o.done||(o.value=s(o.value)),o}),i}const hl=Array.prototype;function nt(e,t,s,n,i,o){const r=cn(e),l=r!==e&&!Le(e),c=r[t];if(c!==hl[t]){const f=c.apply(e,o);return l?je(f):f}let u=s;r!==e&&(l?u=function(f,h){return s.call(this,qe(e,f),h,e)}:s.length>2&&(u=function(f,h){return s.call(this,f,h,e)}));const a=c.call(r,u,n);return l&&i?i(a):a}function Pi(e,t,s,n){const i=cn(e),o=i!==e&&!Le(e);let r=s,l=!1;i!==e&&(o?(l=n.length===0,r=function(u,a,f){return l&&(l=!1,u=qe(e,u)),s.call(this,u,qe(e,a),f,e)}):s.length>3&&(r=function(u,a,f){return s.call(this,u,a,f,e)}));const c=i[t](r,...n);return l?qe(e,c):c}function yn(e,t,s){const n=J(e);be(n,"iterate",ms);const i=n[t](...s);return(i===-1||i===!1)&&fi(s[0])?(s[0]=J(s[0]),n[t](...s)):i}function Zt(e,t,s=[]){Ze(),ii();const n=J(e)[t].apply(e,s);return oi(),et(),n}const pl=ei("__proto__,__v_isRef,__isVue"),Vo=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(Qe));function gl(e){Qe(e)||(e=String(e));const t=J(this);return be(t,"has",e),t.hasOwnProperty(e)}class zo{constructor(t=!1,s=!1){this._isReadonly=t,this._isShallow=s}get(t,s,n){if(s==="__v_skip")return t.__v_skip;const i=this._isReadonly,o=this._isShallow;if(s==="__v_isReactive")return!i;if(s==="__v_isReadonly")return i;if(s==="__v_isShallow")return o;if(s==="__v_raw")return n===(i?o?Cl:Ko:o?Wo:Bo).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(n)?t:void 0;const r=k(t);if(!i){let c;if(r&&(c=dl[s]))return c;if(s==="hasOwnProperty")return gl}const l=Reflect.get(t,s,ye(t)?t:n);if((Qe(s)?Vo.has(s):pl(s))||(i||be(t,"get",s),o))return l;if(ye(l)){const c=r&&si(s)?l:l.value;return i&&Q(c)?Bn(c):c}return Q(l)?i?Bn(l):ai(l):l}}class Ho extends zo{constructor(t=!1){super(!1,t)}set(t,s,n,i){let o=t[s];const r=k(t)&&si(s);if(!this._isShallow){const u=at(o);if(!Le(n)&&!at(n)&&(o=J(o),n=J(n)),!r&&ye(o)&&!ye(n))return u||(o.value=n),!0}const l=r?Number(s)e,Ms=e=>Reflect.getPrototypeOf(e);function yl(e,t,s){return function(...n){const i=this.__v_raw,o=J(i),r=Vt(o),l=e==="entries"||e===Symbol.iterator&&r,c=e==="keys"&&r,u=i[e](...n),a=s?Hn:t?Wt:je;return!t&&be(o,"iterate",c?zn:Mt),he(Object.create(u),{next(){const{value:f,done:h}=u.next();return h?{value:f,done:h}:{value:l?[a(f[0]),a(f[1])]:a(f),done:h}}})}}function Os(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function Sl(e,t){const s={get(i){const o=this.__v_raw,r=J(o),l=J(i);e||(Ye(i,l)&&be(r,"get",i),be(r,"get",l));const{has:c}=Ms(r),u=t?Hn:e?Wt:je;if(c.call(r,i))return u(o.get(i));if(c.call(r,l))return u(o.get(l));o!==r&&o.get(i)},get size(){const i=this.__v_raw;return!e&&be(J(i),"iterate",Mt),i.size},has(i){const o=this.__v_raw,r=J(o),l=J(i);return e||(Ye(i,l)&&be(r,"has",i),be(r,"has",l)),i===l?o.has(i):o.has(i)||o.has(l)},forEach(i,o){const r=this,l=r.__v_raw,c=J(l),u=t?Hn:e?Wt:je;return!e&&be(c,"iterate",Mt),l.forEach((a,f)=>i.call(o,u(a),u(f),r))}};return he(s,e?{add:Os("add"),set:Os("set"),delete:Os("delete"),clear:Os("clear")}:{add(i){const o=J(this),r=Ms(o),l=J(i),c=!t&&!Le(i)&&!at(i)?l:i;return r.has.call(o,c)||Ye(i,c)&&r.has.call(o,i)||Ye(l,c)&&r.has.call(o,l)||(o.add(c),rt(o,"add",c,c)),this},set(i,o){!t&&!Le(o)&&!at(o)&&(o=J(o));const r=J(this),{has:l,get:c}=Ms(r);let u=l.call(r,i);u||(i=J(i),u=l.call(r,i));const a=c.call(r,i);return r.set(i,o),u?Ye(o,a)&&rt(r,"set",i,o):rt(r,"add",i,o),this},delete(i){const o=J(this),{has:r,get:l}=Ms(o);let c=r.call(o,i);c||(i=J(i),c=r.call(o,i)),l&&l.call(o,i);const u=o.delete(i);return c&&rt(o,"delete",i,void 0),u},clear(){const i=J(this),o=i.size!==0,r=i.clear();return o&&rt(i,"clear",void 0,void 0),r}}),["keys","values","entries",Symbol.iterator].forEach(i=>{s[i]=yl(i,e,t)}),s}function ci(e,t){const s=Sl(e,t);return(n,i,o)=>i==="__v_isReactive"?!e:i==="__v_isReadonly"?e:i==="__v_raw"?n:Reflect.get(X(s,i)&&i in n?s:n,i,o)}const xl={get:ci(!1,!1)},wl={get:ci(!1,!0)},Tl={get:ci(!0,!1)};const Bo=new WeakMap,Wo=new WeakMap,Ko=new WeakMap,Cl=new WeakMap;function El(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function ai(e){return at(e)?e:ui(e,!1,vl,xl,Bo)}function Al(e){return ui(e,!1,bl,wl,Wo)}function Bn(e){return ui(e,!0,_l,Tl,Ko)}function ui(e,t,s,n,i){if(!Q(e)||e.__v_raw&&!(t&&e.__v_isReactive)||e.__v_skip||!Object.isExtensible(e))return e;const o=i.get(e);if(o)return o;const r=El(Yr(e));if(r===0)return e;const l=new Proxy(e,r===2?n:s);return i.set(e,l),l}function Ot(e){return at(e)?Ot(e.__v_raw):!!(e&&e.__v_isReactive)}function at(e){return!!(e&&e.__v_isReadonly)}function Le(e){return!!(e&&e.__v_isShallow)}function fi(e){return e?!!e.__v_raw:!1}function J(e){const t=e&&e.__v_raw;return t?J(t):e}function Uo(e){return!X(e,"__v_skip")&&Object.isExtensible(e)&&Ao(e,"__v_skip",!0),e}const je=e=>Q(e)?ai(e):e,Wt=e=>Q(e)?Bn(e):e;function ye(e){return e?e.__v_isRef===!0:!1}function U(e){return Go(e,!1)}function Il(e){return Go(e,!0)}function Go(e,t){return ye(e)?e:new Ml(e,t)}class Ml{constructor(t,s){this.dep=new li,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=s?t:J(t),this._value=s?t:je(t),this.__v_isShallow=s}get value(){return this.dep.track(),this._value}set value(t){const s=this._rawValue,n=this.__v_isShallow||Le(t)||at(t);t=n?t:J(t),Ye(t,s)&&(this._rawValue=t,this._value=n?t:je(t),this.dep.trigger())}}function Ri(e){e.dep&&e.dep.trigger()}function C(e){return ye(e)?e.value:e}const Ol={get:(e,t,s)=>t==="__v_raw"?e:C(Reflect.get(e,t,s)),set:(e,t,s,n)=>{const i=e[t];return ye(i)&&!ye(s)?(i.value=s,!0):Reflect.set(e,t,s,n)}};function qo(e){return Ot(e)?e:new Proxy(e,Ol)}class $l{constructor(t,s,n){this.fn=t,this.setter=s,this._value=void 0,this.dep=new li(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=gs-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!s,this.isSSR=n}notify(){if(this.flags|=16,!(this.flags&8)&&le!==this)return Lo(this,!0),!0}get value(){const t=this.dep.track();return ko(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function Pl(e,t,s=!1){let n,i;return B(e)?n=e:(n=e.get,i=e.set),new $l(n,i,s)}const $s={},Ws=new WeakMap;let Ct;function Rl(e,t=!1,s=Ct){if(s){let n=Ws.get(s);n||Ws.set(s,n=[]),n.push(e)}}function Ll(e,t,s=ie){const{immediate:n,deep:i,once:o,scheduler:r,augmentJob:l,call:c}=s,u=P=>i?P:Le(P)||i===!1||i===0?lt(P,1):lt(P);let a,f,h,v,m=!1,_=!1;if(ye(e)?(f=()=>e.value,m=Le(e)):Ot(e)?(f=()=>u(e),m=!0):k(e)?(_=!0,m=e.some(P=>Ot(P)||Le(P)),f=()=>e.map(P=>{if(ye(P))return P.value;if(Ot(P))return u(P);if(B(P))return c?c(P,2):P()})):B(e)?t?f=c?()=>c(e,2):e:f=()=>{if(h){Ze();try{h()}finally{et()}}const P=Ct;Ct=a;try{return c?c(e,3,[v]):e(v)}finally{Ct=P}}:f=Xe,t&&i){const P=f,K=i===!0?1/0:i;f=()=>lt(P(),K)}const I=cl(),$=()=>{a.stop(),I&&I.active&&ti(I.effects,a)};if(o&&t){const P=t;t=(...K)=>{const Z=P(...K);return $(),Z}}let M=_?new Array(e.length).fill($s):$s;const L=P=>{if(!(!(a.flags&1)||!a.dirty&&!P))if(t){const K=a.run();if(P||i||m||(_?K.some((Z,j)=>Ye(Z,M[j])):Ye(K,M))){h&&h();const Z=Ct;Ct=a;try{const j=[K,M===$s?void 0:_&&M[0]===$s?[]:M,v];M=K,c?c(t,3,j):t(...j)}finally{Ct=Z}}}else a.run()};return l&&l(L),a=new Po(f),a.scheduler=r?()=>r(L,!1):L,v=P=>Rl(P,!1,a),h=a.onStop=()=>{const P=Ws.get(a);if(P){if(c)c(P,4);else for(const K of P)K();Ws.delete(a)}},t?n?L(!0):M=a.run():r?r(L.bind(null,!0),!0):a.run(),$.pause=a.pause.bind(a),$.resume=a.resume.bind(a),$.stop=$,$}function lt(e,t=1/0,s){if(t<=0||!Q(e)||e.__v_skip||(s=s||new Map,(s.get(e)||0)>=t))return e;if(s.set(e,t),t--,ye(e))lt(e.value,t,s);else if(k(e))for(let n=0;n{lt(n,t,s)});else if(Co(e)){for(const n in e)lt(e[n],t,s);for(const n of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,n)&<(e[n],t,s)}return e}/** +* @vue/runtime-core v3.5.39 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function Ts(e,t,s,n){try{return n?e(...n):e()}catch(i){an(i,t,s)}}function Fe(e,t,s,n){if(B(e)){const i=Ts(e,t,s,n);return i&&wo(i)&&i.catch(o=>{an(o,t,s)}),i}if(k(e)){const i=[];for(let o=0;o>>1,i=we[n],o=vs(i);o=vs(s)?we.push(e):we.splice(Dl(t),0,e),e.flags|=1,Yo()}}function Yo(){Ks||(Ks=Jo.then(Qo))}function kl(e){k(e)?zt.push(...e):mt&&e.id===-1?mt.splice(Nt+1,0,e):e.flags&1||(zt.push(e),e.flags|=1),Yo()}function Li(e,t,s=Ge+1){for(;svs(s)-vs(n));if(zt.length=0,mt){mt.push(...t);return}for(mt=t,Nt=0;Nte.id==null?e.flags&2?-1:1/0:e.id;function Qo(e){try{for(Ge=0;Ge{n._d&&Js(-1);const o=Us(t);let r;try{r=e(...i)}finally{Us(o),n._d&&Js(1)}return r};return n._n=!0,n._c=!0,n._d=!0,n}function Pe(e,t){if(Re===null)return e;const s=pn(Re),n=e.dirs||(e.dirs=[]);for(let i=0;i1)return s&&B(t)?t.call(n&&n.proxy):t}}const jl=Symbol.for("v-scx"),Vl=()=>Hs(jl);function $t(e,t,s){return er(e,t,s)}function er(e,t,s=ie){const{immediate:n,deep:i,flush:o,once:r}=s,l=he({},s),c=t&&n||!t&&o!=="post";let u;if(Ss){if(o==="sync"){const v=Vl();u=v.__watcherHandles||(v.__watcherHandles=[])}else if(!c){const v=()=>{};return v.stop=Xe,v.resume=Xe,v.pause=Xe,v}}const a=Ce;l.call=(v,m,_)=>Fe(v,a,m,_);let f=!1;o==="post"?l.scheduler=v=>{xe(v,a&&a.suspense)}:o!=="sync"&&(f=!0,l.scheduler=(v,m)=>{m?v():hi(v)}),l.augmentJob=v=>{t&&(v.flags|=4),f&&(v.flags|=2,a&&(v.id=a.uid,v.i=a))};const h=Ll(e,t,l);return Ss&&(u?u.push(h):c&&h()),h}function zl(e,t,s){const n=this.proxy,i=ae(e)?e.includes(".")?tr(n,e):()=>n[e]:e.bind(n,n);let o;B(t)?o=t:(o=t.handler,s=t);const r=Cs(this),l=er(i,o.bind(n),s);return r(),l}function tr(e,t){const s=t.split(".");return()=>{let n=e;for(let i=0;ie.__isTeleport,Et=e=>e&&(e.disabled||e.disabled===""),Hl=e=>e&&(e.defer||e.defer===""),Fi=e=>typeof SVGElement<"u"&&e instanceof SVGElement,Di=e=>typeof MathMLElement=="function"&&e instanceof MathMLElement,Wn=(e,t)=>{const s=e&&e.to;return ae(s)?t?t(s):null:s},Bl={name:"Teleport",__isTeleport:!0,process(e,t,s,n,i,o,r,l,c,u){const{mc:a,pc:f,pbc:h,o:{insert:v,querySelector:m,createText:_,createComment:I,parentNode:$}}=u,M=Et(t.props);let{dynamicChildren:L}=t;const P=(j,Y,F)=>{j.shapeFlag&16&&a(j.children,Y,F,i,o,r,l,c)},K=(j=t)=>{const Y=Et(j.props),F=j.target=Wn(j.props,m),G=Kn(F,j,_,v);F&&(r!=="svg"&&Fi(F)?r="svg":r!=="mathml"&&Di(F)&&(r="mathml"),i&&i.isCE&&(i.ce._teleportTargets||(i.ce._teleportTargets=new Set)).add(F),Y||(P(j,F,G),os(j,!1)))},Z=j=>{const Y=()=>{if(pt.get(j)===Y){if(pt.delete(j),Et(j.props)){const F=$(j.el)||s;P(j,F,j.anchor),os(j,!0)}K(j)}};pt.set(j,Y),xe(Y,o)};if(e==null){const j=t.el=_(""),Y=t.anchor=_("");if(v(j,s,n),v(Y,s,n),Hl(t.props)||o&&o.pendingBranch){Z(t);return}M&&(P(t,s,Y),os(t,!0)),K()}else{t.el=e.el;const j=t.anchor=e.anchor,Y=pt.get(e);if(Y){Y.flags|=8,pt.delete(e),Z(t);return}t.targetStart=e.targetStart;const F=t.target=e.target,G=t.targetAnchor=e.targetAnchor,ee=Et(e.props),R=ee?s:F,oe=ee?j:G;if(r==="svg"||Fi(F)?r="svg":(r==="mathml"||Di(F))&&(r="mathml"),L?(h(e.dynamicChildren,L,R,i,o,r,l),yi(e,t,!0)):c||f(e,t,R,oe,i,o,r,l,!1),M)ee?t.props&&e.props&&t.props.to!==e.props.to&&(t.props.to=e.props.to):Ps(t,s,j,u,1);else if((t.props&&t.props.to)!==(e.props&&e.props.to)){const fe=Wn(t.props,m);fe&&(t.target=fe,Ps(t,fe,null,u,0))}else ee&&Ps(t,F,G,u,1);os(t,M)}},remove(e,t,s,{um:n,o:{remove:i}},o){const{shapeFlag:r,children:l,anchor:c,targetStart:u,targetAnchor:a,target:f,props:h}=e,v=Et(h),m=o||!v,_=pt.get(e);if(_&&(_.flags|=8,pt.delete(e)),f&&(i(u),i(a)),o&&i(c),!_&&(v||f)&&r&16)for(let I=0;I{e.isMounted=!0}),dr(()=>{e.isUnmounting=!0}),e}const Oe=[Function,Array],or={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:Oe,onEnter:Oe,onAfterEnter:Oe,onEnterCancelled:Oe,onBeforeLeave:Oe,onLeave:Oe,onAfterLeave:Oe,onLeaveCancelled:Oe,onBeforeAppear:Oe,onAppear:Oe,onAfterAppear:Oe,onAppearCancelled:Oe},rr=e=>{const t=e.subTree;return t.component?rr(t.component):t},Ul={name:"BaseTransition",props:or,setup(e,{slots:t}){const s=Si(),n=ir();return()=>{const i=t.default&&gi(t.default(),!0),o=i&&i.length?lr(i):s.subTree?Rt():void 0;if(!o)return;const r=J(e),{mode:l}=r;if(n.isLeaving)return Sn(o);const c=ki(o);if(!c)return Sn(o);let u=_s(c,r,n,s,f=>u=f);c.type!==Te&&Pt(c,u);let a=s.subTree&&ki(s.subTree);if(a&&a.type!==Te&&!At(a,c)&&rr(s).type!==Te){let f=_s(a,r,n,s);if(Pt(a,f),l==="out-in"&&c.type!==Te)return n.isLeaving=!0,f.afterLeave=()=>{n.isLeaving=!1,s.job.flags&8||s.update(),delete f.afterLeave,a=void 0},Sn(o);l==="in-out"&&c.type!==Te?f.delayLeave=(h,v,m)=>{const _=cr(n,a);_[String(a.key)]=a,h[$e]=()=>{v(),h[$e]=void 0,delete u.delayedLeave,a=void 0},u.delayedLeave=()=>{m(),delete u.delayedLeave,a=void 0}}:a=void 0}else a&&(a=void 0);return o}}};function lr(e){let t=e[0];if(e.length>1){for(const s of e)if(s.type!==Te){t=s;break}}return t}const Gl=Ul;function cr(e,t){const{leavingVNodes:s}=e;let n=s.get(t.type);return n||(n=Object.create(null),s.set(t.type,n)),n}function _s(e,t,s,n,i){const{appear:o,mode:r,persisted:l=!1,onBeforeEnter:c,onEnter:u,onAfterEnter:a,onEnterCancelled:f,onBeforeLeave:h,onLeave:v,onAfterLeave:m,onLeaveCancelled:_,onBeforeAppear:I,onAppear:$,onAfterAppear:M,onAppearCancelled:L}=t,P=String(e.key),K=cr(s,e),Z=(F,G)=>{F&&Fe(F,n,9,G)},j=(F,G)=>{const ee=G[1];Z(F,G),k(F)?F.every(R=>R.length<=1)&&ee():F.length<=1&&ee()},Y={mode:r,persisted:l,beforeEnter(F){let G=c;if(!s.isMounted)if(o)G=I||c;else return;F[$e]&&F[$e](!0);const ee=K[P];ee&&At(e,ee)&&ee.el[$e]&&ee.el[$e](),Z(G,[F])},enter(F){if(K[P]===e)return;let G=u,ee=a,R=f;if(!s.isMounted)if(o)G=$||u,ee=M||a,R=L||f;else return;let oe=!1;F[es]=st=>{oe||(oe=!0,st?Z(R,[F]):Z(ee,[F]),Y.delayedLeave&&Y.delayedLeave(),F[es]=void 0)};const fe=F[es].bind(null,!1);G?j(G,[F,fe]):fe()},leave(F,G){const ee=String(e.key);if(F[es]&&F[es](!0),s.isUnmounting)return G();Z(h,[F]);let R=!1;F[$e]=fe=>{R||(R=!0,G(),fe?Z(_,[F]):Z(m,[F]),F[$e]=void 0,K[ee]===e&&delete K[ee])};const oe=F[$e].bind(null,!1);K[ee]=e,v?j(v,[F,oe]):oe()},clone(F){const G=_s(F,t,s,n,i);return i&&i(G),G}};return Y}function Sn(e){if(un(e))return e=_t(e),e.children=null,e}function ki(e){if(!un(e))return nr(e.type)&&e.children?lr(e.children):e;if(e.component)return e.component.subTree;const{shapeFlag:t,children:s}=e;if(s){if(t&16)return s[0];if(t&32&&B(s.default))return s.default()}}function Pt(e,t){e.shapeFlag&6&&e.component?(e.transition=t,Pt(e.component.subTree,t)):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function gi(e,t=!1,s){let n=[],i=0;for(let o=0;o1)for(let o=0;ofs(_,t&&(k(t)?t[I]:t),s,n,i));return}if(ds(n)&&!i){n.shapeFlag&512&&n.type.__asyncResolved&&n.component.subTree.component&&fs(e,t,s,n.component.subTree);return}const o=n.shapeFlag&4?pn(n.component):n.el,r=i?null:o,{i:l,r:c}=e,u=t&&t.r,a=l.refs===ie?l.refs={}:l.refs,f=l.setupState,h=J(f),v=f===ie?xo:_=>Ni(a,_)?!1:X(h,_),m=(_,I)=>!(I&&Ni(a,I));if(u!=null&&u!==c){if(ji(t),ae(u))a[u]=null,v(u)&&(f[u]=null);else if(ye(u)){const _=t;m(u,_.k)&&(u.value=null),_.k&&(a[_.k]=null)}}if(B(c)){Ze();try{Ts(c,l,12,[r,a])}finally{et()}}else{const _=ae(c),I=ye(c);if(_||I){const $=()=>{if(e.f){const M=_?v(c)?f[c]:a[c]:m()||!e.k?c.value:a[e.k];if(i)k(M)&&ti(M,o);else if(k(M))M.includes(o)||M.push(o);else if(_)a[c]=[o],v(c)&&(f[c]=a[c]);else{const L=[o];m(c,e.k)&&(c.value=L),e.k&&(a[e.k]=L)}}else _?(a[c]=r,v(c)&&(f[c]=r)):I&&(m(c,e.k)&&(c.value=r),e.k&&(a[e.k]=r))};if(r){const M=()=>{$(),Gs.delete(e)};M.id=-1,Gs.set(e,M),xe(M,s)}else ji(e),$()}}}function ji(e){const t=Gs.get(e);t&&(t.flags|=8,Gs.delete(e))}ln().requestIdleCallback;ln().cancelIdleCallback;const ds=e=>!!e.type.__asyncLoader,un=e=>e.type.__isKeepAlive;function ql(e,t){ur(e,"a",t)}function Jl(e,t){ur(e,"da",t)}function ur(e,t,s=Ce){const n=e.__wdc||(e.__wdc=()=>{let i=s;for(;i;){if(i.isDeactivated)return;i=i.parent}return e()});if(fn(t,n,s),s){let i=s.parent;for(;i&&i.parent;)un(i.parent.vnode)&&Yl(n,t,s,i),i=i.parent}}function Yl(e,t,s,n){const i=fn(t,e,n,!0);vi(()=>{ti(n[t],i)},s)}function fn(e,t,s=Ce,n=!1){if(s){const i=s[e]||(s[e]=[]),o=t.__weh||(t.__weh=(...r)=>{Ze();const l=Cs(s),c=Fe(t,s,e,r);return l(),et(),c});return n?i.unshift(o):i.push(o),o}}const ut=e=>(t,s=Ce)=>{(!Ss||e==="sp")&&fn(e,(...n)=>t(...n),s)},Xl=ut("bm"),mi=ut("m"),Ql=ut("bu"),fr=ut("u"),dr=ut("bum"),vi=ut("um"),Zl=ut("sp"),ec=ut("rtg"),tc=ut("rtc");function sc(e,t=Ce){fn("ec",e,t)}const nc=Symbol.for("v-ndc");function bs(e,t,s,n){let i;const o=s,r=k(e);if(r||ae(e)){const l=r&&Ot(e);let c=!1,u=!1;l&&(c=!Le(e),u=at(e),e=cn(e)),i=new Array(e.length);for(let a=0,f=e.length;at(l,c,void 0,o));else{const l=Object.keys(e);i=new Array(l.length);for(let c=0,u=l.length;ce?Pr(e)?pn(e):Un(e.parent):null,hs=he(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Un(e.parent),$root:e=>Un(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>pr(e),$forceUpdate:e=>e.f||(e.f=()=>{hi(e.update)}),$nextTick:e=>e.n||(e.n=di.bind(e.proxy)),$watch:e=>zl.bind(e)}),xn=(e,t)=>e!==ie&&!e.__isScriptSetup&&X(e,t),ic={get({_:e},t){if(t==="__v_skip")return!0;const{ctx:s,setupState:n,data:i,props:o,accessCache:r,type:l,appContext:c}=e;if(t[0]!=="$"){const h=r[t];if(h!==void 0)switch(h){case 1:return n[t];case 2:return i[t];case 4:return s[t];case 3:return o[t]}else{if(xn(n,t))return r[t]=1,n[t];if(i!==ie&&X(i,t))return r[t]=2,i[t];if(X(o,t))return r[t]=3,o[t];if(s!==ie&&X(s,t))return r[t]=4,s[t];Gn&&(r[t]=0)}}const u=hs[t];let a,f;if(u)return t==="$attrs"&&be(e.attrs,"get",""),u(e);if((a=l.__cssModules)&&(a=a[t]))return a;if(s!==ie&&X(s,t))return r[t]=4,s[t];if(f=c.config.globalProperties,X(f,t))return f[t]},set({_:e},t,s){const{data:n,setupState:i,ctx:o}=e;return xn(i,t)?(i[t]=s,!0):n!==ie&&X(n,t)?(n[t]=s,!0):X(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(o[t]=s,!0)},has({_:{data:e,setupState:t,accessCache:s,ctx:n,appContext:i,props:o,type:r}},l){let c;return!!(s[l]||e!==ie&&l[0]!=="$"&&X(e,l)||xn(t,l)||X(o,l)||X(n,l)||X(hs,l)||X(i.config.globalProperties,l)||(c=r.__cssModules)&&c[l])},defineProperty(e,t,s){return s.get!=null?e._.accessCache[t]=0:X(s,"value")&&this.set(e,t,s.value,null),Reflect.defineProperty(e,t,s)}};function Vi(e){return k(e)?e.reduce((t,s)=>(t[s]=null,t),{}):e}let Gn=!0;function oc(e){const t=pr(e),s=e.proxy,n=e.ctx;Gn=!1,t.beforeCreate&&zi(t.beforeCreate,e,"bc");const{data:i,computed:o,methods:r,watch:l,provide:c,inject:u,created:a,beforeMount:f,mounted:h,beforeUpdate:v,updated:m,activated:_,deactivated:I,beforeDestroy:$,beforeUnmount:M,destroyed:L,unmounted:P,render:K,renderTracked:Z,renderTriggered:j,errorCaptured:Y,serverPrefetch:F,expose:G,inheritAttrs:ee,components:R,directives:oe,filters:fe}=t;if(u&&rc(u,n,null),r)for(const ue in r){const re=r[ue];B(re)&&(n[ue]=re.bind(s))}if(i){const ue=i.call(s,s);Q(ue)&&(e.data=ai(ue))}if(Gn=!0,o)for(const ue in o){const re=o[ue],bt=B(re)?re.bind(s,s):B(re.get)?re.get.bind(s,s):Xe,As=!B(re)&&B(re.set)?re.set.bind(s):Xe,yt=tt({get:bt,set:As});Object.defineProperty(n,ue,{enumerable:!0,configurable:!0,get:()=>yt.value,set:Ve=>yt.value=Ve})}if(l)for(const ue in l)hr(l[ue],n,s,ue);if(c){const ue=B(c)?c.call(s):c;Reflect.ownKeys(ue).forEach(re=>{Nl(re,ue[re])})}a&&zi(a,e,"c");function ge(ue,re){k(re)?re.forEach(bt=>ue(bt.bind(s))):re&&ue(re.bind(s))}if(ge(Xl,f),ge(mi,h),ge(Ql,v),ge(fr,m),ge(ql,_),ge(Jl,I),ge(sc,Y),ge(tc,Z),ge(ec,j),ge(dr,M),ge(vi,P),ge(Zl,F),k(G))if(G.length){const ue=e.exposed||(e.exposed={});G.forEach(re=>{Object.defineProperty(ue,re,{get:()=>s[re],set:bt=>s[re]=bt,enumerable:!0})})}else e.exposed||(e.exposed={});K&&e.render===Xe&&(e.render=K),ee!=null&&(e.inheritAttrs=ee),R&&(e.components=R),oe&&(e.directives=oe),F&&ar(e)}function rc(e,t,s=Xe){k(e)&&(e=qn(e));for(const n in e){const i=e[n];let o;Q(i)?"default"in i?o=Hs(i.from||n,i.default,!0):o=Hs(i.from||n):o=Hs(i),ye(o)?Object.defineProperty(t,n,{enumerable:!0,configurable:!0,get:()=>o.value,set:r=>o.value=r}):t[n]=o}}function zi(e,t,s){Fe(k(e)?e.map(n=>n.bind(t.proxy)):e.bind(t.proxy),t,s)}function hr(e,t,s,n){let i=n.includes(".")?tr(s,n):()=>s[n];if(ae(e)){const o=t[e];B(o)&&$t(i,o)}else if(B(e))$t(i,e.bind(s));else if(Q(e))if(k(e))e.forEach(o=>hr(o,t,s,n));else{const o=B(e.handler)?e.handler.bind(s):t[e.handler];B(o)&&$t(i,o,e)}}function pr(e){const t=e.type,{mixins:s,extends:n}=t,{mixins:i,optionsCache:o,config:{optionMergeStrategies:r}}=e.appContext,l=o.get(t);let c;return l?c=l:!i.length&&!s&&!n?c=t:(c={},i.length&&i.forEach(u=>qs(c,u,r,!0)),qs(c,t,r)),Q(t)&&o.set(t,c),c}function qs(e,t,s,n=!1){const{mixins:i,extends:o}=t;o&&qs(e,o,s,!0),i&&i.forEach(r=>qs(e,r,s,!0));for(const r in t)if(!(n&&r==="expose")){const l=lc[r]||s&&s[r];e[r]=l?l(e[r],t[r]):t[r]}return e}const lc={data:Hi,props:Bi,emits:Bi,methods:rs,computed:rs,beforeCreate:Se,created:Se,beforeMount:Se,mounted:Se,beforeUpdate:Se,updated:Se,beforeDestroy:Se,beforeUnmount:Se,destroyed:Se,unmounted:Se,activated:Se,deactivated:Se,errorCaptured:Se,serverPrefetch:Se,components:rs,directives:rs,watch:ac,provide:Hi,inject:cc};function Hi(e,t){return t?e?function(){return he(B(e)?e.call(this,this):e,B(t)?t.call(this,this):t)}:t:e}function cc(e,t){return rs(qn(e),qn(t))}function qn(e){if(k(e)){const t={};for(let s=0;st==="modelValue"||t==="model-value"?e.modelModifiers:e[`${t}Modifiers`]||e[`${ke(t)}Modifiers`]||e[`${Lt(t)}Modifiers`];function hc(e,t,...s){if(e.isUnmounted)return;const n=e.vnode.props||ie;let i=s;const o=t.startsWith("update:"),r=o&&dc(n,t.slice(7));r&&(r.trim&&(i=s.map(a=>ae(a)?a.trim():a)),r.number&&(i=s.map(rn)));let l,c=n[l=mn(t)]||n[l=mn(ke(t))];!c&&o&&(c=n[l=mn(Lt(t))]),c&&Fe(c,e,6,i);const u=n[l+"Once"];if(u){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,Fe(u,e,6,i)}}const pc=new WeakMap;function mr(e,t,s=!1){const n=s?pc:t.emitsCache,i=n.get(e);if(i!==void 0)return i;const o=e.emits;let r={},l=!1;if(!B(e)){const c=u=>{const a=mr(u,t,!0);a&&(l=!0,he(r,a))};!s&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}return!o&&!l?(Q(e)&&n.set(e,null),null):(k(o)?o.forEach(c=>r[c]=null):he(r,o),Q(e)&&n.set(e,r),r)}function dn(e,t){return!e||!sn(t)?!1:(t=t.slice(2),t=t==="Once"?t:t.replace(/Once$/,""),X(e,t[0].toLowerCase()+t.slice(1))||X(e,Lt(t))||X(e,t))}function Wi(e){const{type:t,vnode:s,proxy:n,withProxy:i,propsOptions:[o],slots:r,attrs:l,emit:c,render:u,renderCache:a,props:f,data:h,setupState:v,ctx:m,inheritAttrs:_}=e,I=Us(e);let $,M;try{if(s.shapeFlag&4){const P=i||n,K=P;$=Je(u.call(K,P,a,f,v,h,m)),M=l}else{const P=t;$=Je(P.length>1?P(f,{attrs:l,slots:r,emit:c}):P(f,null)),M=t.props?l:gc(l)}}catch(P){ps.length=0,an(P,e,1),$=se(Te)}let L=$;if(M&&_!==!1){const P=Object.keys(M),{shapeFlag:K}=L;P.length&&K&7&&(o&&P.some(nn)&&(M=mc(M,o)),L=_t(L,M,!1,!0))}return s.dirs&&(L=_t(L,null,!1,!0),L.dirs=L.dirs?L.dirs.concat(s.dirs):s.dirs),s.transition&&Pt(L,s.transition),$=L,Us(I),$}const gc=e=>{let t;for(const s in e)(s==="class"||s==="style"||sn(s))&&((t||(t={}))[s]=e[s]);return t},mc=(e,t)=>{const s={};for(const n in e)(!nn(n)||!(n.slice(9)in t))&&(s[n]=e[n]);return s};function vc(e,t,s){const{props:n,children:i,component:o}=e,{props:r,children:l,patchFlag:c}=t,u=o.emitsOptions;if(t.dirs||t.transition)return!0;if(s&&c>=0){if(c&1024)return!0;if(c&16)return n?Ki(n,r,u):!!r;if(c&8){const a=t.dynamicProps;for(let f=0;fObject.create(_r),yr=e=>Object.getPrototypeOf(e)===_r;function bc(e,t,s,n=!1){const i={},o=br();e.propsDefaults=Object.create(null),Sr(e,t,i,o);for(const r in e.propsOptions[0])r in i||(i[r]=void 0);s?e.props=n?i:Al(i):e.type.props?e.props=i:e.props=o,e.attrs=o}function yc(e,t,s,n){const{props:i,attrs:o,vnode:{patchFlag:r}}=e,l=J(i),[c]=e.propsOptions;let u=!1;if((n||r>0)&&!(r&16)){if(r&8){const a=e.vnode.dynamicProps;for(let f=0;f{c=!0;const[h,v]=xr(f,t,!0);he(r,h),v&&l.push(...v)};!s&&t.mixins.length&&t.mixins.forEach(a),e.extends&&a(e.extends),e.mixins&&e.mixins.forEach(a)}if(!o&&!c)return Q(e)&&n.set(e,jt),jt;if(k(o))for(let a=0;ae==="_"||e==="_ctx"||e==="$stable",bi=e=>k(e)?e.map(Je):[Je(e)],xc=(e,t,s)=>{if(t._n)return t;const n=pi((...i)=>bi(t(...i)),s);return n._c=!1,n},wr=(e,t,s)=>{const n=e._ctx;for(const i in e){if(_i(i))continue;const o=e[i];if(B(o))t[i]=xc(i,o,n);else if(o!=null){const r=bi(o);t[i]=()=>r}}},Tr=(e,t)=>{const s=bi(t);e.slots.default=()=>s},Cr=(e,t,s)=>{for(const n in t)(s||!_i(n))&&(e[n]=t[n])},wc=(e,t,s)=>{const n=e.slots=br();if(e.vnode.shapeFlag&32){const i=t._;i?(Cr(n,t,s),s&&Ao(n,"_",i,!0)):wr(t,n)}else t&&Tr(e,t)},Tc=(e,t,s)=>{const{vnode:n,slots:i}=e;let o=!0,r=ie;if(n.shapeFlag&32){const l=t._;l?s&&l===1?o=!1:Cr(i,t,s):(o=!t.$stable,wr(t,i)),r=t}else t&&(Tr(e,t),r={default:1});if(o)for(const l in i)!_i(l)&&r[l]==null&&delete i[l]},xe=Mc;function Cc(e){return Ec(e)}function Ec(e,t){const s=ln();s.__VUE__=!0;const{insert:n,remove:i,patchProp:o,createElement:r,createText:l,createComment:c,setText:u,setElementText:a,parentNode:f,nextSibling:h,setScopeId:v=Xe,insertStaticContent:m}=e,_=(d,p,b,w=null,x=null,y=null,A=void 0,E=null,T=!!p.dynamicChildren)=>{if(d===p)return;d&&!At(d,p)&&(w=Is(d),Ve(d,x,y,!0),d=null),p.patchFlag===-2&&(T=!1,p.dynamicChildren=null);const{type:S,ref:N,shapeFlag:O}=p;switch(S){case hn:I(d,p,b,w);break;case Te:$(d,p,b,w);break;case Tn:d==null&&M(p,b,w,A);break;case ce:R(d,p,b,w,x,y,A,E,T);break;default:O&1?K(d,p,b,w,x,y,A,E,T):O&6?oe(d,p,b,w,x,y,A,E,T):(O&64||O&128)&&S.process(d,p,b,w,x,y,A,E,T,Xt)}N!=null&&x?fs(N,d&&d.ref,y,p||d,!p):N==null&&d&&d.ref!=null&&fs(d.ref,null,y,d,!0)},I=(d,p,b,w)=>{if(d==null)n(p.el=l(p.children),b,w);else{const x=p.el=d.el;p.children!==d.children&&u(x,p.children)}},$=(d,p,b,w)=>{d==null?n(p.el=c(p.children||""),b,w):p.el=d.el},M=(d,p,b,w)=>{[d.el,d.anchor]=m(d.children,p,b,w,d.el,d.anchor)},L=({el:d,anchor:p},b,w)=>{let x;for(;d&&d!==p;)x=h(d),n(d,b,w),d=x;n(p,b,w)},P=({el:d,anchor:p})=>{let b;for(;d&&d!==p;)b=h(d),i(d),d=b;i(p)},K=(d,p,b,w,x,y,A,E,T)=>{if(p.type==="svg"?A="svg":p.type==="math"&&(A="mathml"),d==null)Z(p,b,w,x,y,A,E,T);else{const S=d.el&&d.el._isVueCE?d.el:null;try{S&&S._beginPatch(),F(d,p,x,y,A,E,T)}finally{S&&S._endPatch()}}},Z=(d,p,b,w,x,y,A,E)=>{let T,S;const{props:N,shapeFlag:O,transition:D,dirs:z}=d;if(T=d.el=r(d.type,y,N&&N.is,N),O&8?a(T,d.children):O&16&&Y(d.children,T,null,w,x,wn(d,y),A,E),z&&St(d,null,w,"created"),j(T,d,d.scopeId,A,w),N){for(const ne in N)ne!=="value"&&!cs(ne)&&o(T,ne,null,N[ne],y,w);"value"in N&&o(T,"value",null,N.value,y),(S=N.onVnodeBeforeMount)&&We(S,w,d)}z&&St(d,null,w,"beforeMount");const q=Ac(x,D);q&&D.beforeEnter(T),n(T,p,b),((S=N&&N.onVnodeMounted)||q||z)&&xe(()=>{try{S&&We(S,w,d),q&&D.enter(T),z&&St(d,null,w,"mounted")}finally{}},x)},j=(d,p,b,w,x)=>{if(b&&v(d,b),w)for(let y=0;y{for(let S=T;S{const E=p.el=d.el;let{patchFlag:T,dynamicChildren:S,dirs:N}=p;T|=d.patchFlag&16;const O=d.props||ie,D=p.props||ie;let z;if(b&&xt(b,!1),(z=D.onVnodeBeforeUpdate)&&We(z,b,p,d),N&&St(p,d,b,"beforeUpdate"),b&&xt(b,!0),S&&(!d.dynamicChildren||d.dynamicChildren.length!==S.length)&&(T=0,A=!1,S=null),(O.innerHTML&&D.innerHTML==null||O.textContent&&D.textContent==null)&&a(E,""),S?G(d.dynamicChildren,S,E,b,w,wn(p,x),y):A||re(d,p,E,null,b,w,wn(p,x),y,!1),T>0){if(T&16)ee(E,O,D,b,x);else if(T&2&&O.class!==D.class&&o(E,"class",null,D.class,x),T&4&&o(E,"style",O.style,D.style,x),T&8){const q=p.dynamicProps;for(let ne=0;ne{z&&We(z,b,p,d),N&&St(p,d,b,"updated")},w)},G=(d,p,b,w,x,y,A)=>{for(let E=0;E{if(p!==b){if(p!==ie)for(const y in p)!cs(y)&&!(y in b)&&o(d,y,p[y],null,x,w);for(const y in b){if(cs(y))continue;const A=b[y],E=p[y];A!==E&&y!=="value"&&o(d,y,E,A,x,w)}"value"in b&&o(d,"value",p.value,b.value,x)}},R=(d,p,b,w,x,y,A,E,T)=>{const S=p.el=d?d.el:l(""),N=p.anchor=d?d.anchor:l("");let{patchFlag:O,dynamicChildren:D,slotScopeIds:z}=p;z&&(E=E?E.concat(z):z),d==null?(n(S,b,w),n(N,b,w),Y(p.children||[],b,N,x,y,A,E,T)):O>0&&O&64&&D&&d.dynamicChildren&&d.dynamicChildren.length===D.length?(G(d.dynamicChildren,D,b,x,y,A,E),(p.key!=null||x&&p===x.subTree)&&yi(d,p,!0)):re(d,p,b,N,x,y,A,E,T)},oe=(d,p,b,w,x,y,A,E,T)=>{p.slotScopeIds=E,d==null?p.shapeFlag&512?x.ctx.activate(p,b,w,A,T):fe(p,b,w,x,y,A,T):st(d,p,T)},fe=(d,p,b,w,x,y,A)=>{const E=d.component=Dc(d,w,x);if(un(d)&&(E.ctx.renderer=Xt),kc(E,!1,A),E.asyncDep){if(x&&x.registerDep(E,ge,A),!d.el){const T=E.subTree=se(Te);$(null,T,p,b),d.placeholder=T.el}}else ge(E,d,p,b,x,y,A)},st=(d,p,b)=>{const w=p.component=d.component;if(vc(d,p,b))if(w.asyncDep&&!w.asyncResolved){ue(w,p,b);return}else w.next=p,w.update();else p.el=d.el,w.vnode=p},ge=(d,p,b,w,x,y,A)=>{const E=()=>{if(d.isMounted){let{next:O,bu:D,u:z,parent:q,vnode:ne}=d;{const He=Er(d);if(He){O&&(O.el=ne.el,ue(d,O,A)),He.asyncDep.then(()=>{xe(()=>{d.isUnmounted||S()},x)});return}}let te=O,de;xt(d,!1),O?(O.el=ne.el,ue(d,O,A)):O=ne,D&&zs(D),(de=O.props&&O.props.onVnodeBeforeUpdate)&&We(de,q,O,ne),xt(d,!0);const me=Wi(d),ze=d.subTree;d.subTree=me,_(ze,me,f(ze.el),Is(ze),d,x,y),O.el=me.el,te===null&&_c(d,me.el),z&&xe(z,x),(de=O.props&&O.props.onVnodeUpdated)&&xe(()=>We(de,q,O,ne),x)}else{let O;const{el:D,props:z}=p,{bm:q,m:ne,parent:te,root:de,type:me}=d,ze=ds(p);xt(d,!1),q&&zs(q),!ze&&(O=z&&z.onVnodeBeforeMount)&&We(O,te,p),xt(d,!0);{de.ce&&de.ce._hasShadowRoot()&&de.ce._injectChildStyle(me,d.parent?d.parent.type:void 0);const He=d.subTree=Wi(d);_(null,He,b,w,d,x,y),p.el=He.el}if(ne&&xe(ne,x),!ze&&(O=z&&z.onVnodeMounted)){const He=p;xe(()=>We(O,te,He),x)}(p.shapeFlag&256||te&&ds(te.vnode)&&te.vnode.shapeFlag&256)&&d.a&&xe(d.a,x),d.isMounted=!0,p=b=w=null}};d.scope.on();const T=d.effect=new Po(E);d.scope.off();const S=d.update=T.run.bind(T),N=d.job=T.runIfDirty.bind(T);N.i=d,N.id=d.uid,T.scheduler=()=>hi(N),xt(d,!0),S()},ue=(d,p,b)=>{p.component=d;const w=d.vnode.props;d.vnode=p,d.next=null,yc(d,p.props,w,b),Tc(d,p.children,b),Ze(),Li(d),et()},re=(d,p,b,w,x,y,A,E,T=!1)=>{const S=d&&d.children,N=d?d.shapeFlag:0,O=p.children,{patchFlag:D,shapeFlag:z}=p;if(D>0){if(D&128){As(S,O,b,w,x,y,A,E,T);return}else if(D&256){bt(S,O,b,w,x,y,A,E,T);return}}z&8?(N&16&&Yt(S,x,y),O!==S&&a(b,O)):N&16?z&16?As(S,O,b,w,x,y,A,E,T):Yt(S,x,y,!0):(N&8&&a(b,""),z&16&&Y(O,b,w,x,y,A,E,T))},bt=(d,p,b,w,x,y,A,E,T)=>{d=d||jt,p=p||jt;const S=d.length,N=p.length,O=Math.min(S,N);let D;for(D=0;DN?Yt(d,x,y,!0,!1,O):Y(p,b,w,x,y,A,E,T,O)},As=(d,p,b,w,x,y,A,E,T)=>{let S=0;const N=p.length;let O=d.length-1,D=N-1;for(;S<=O&&S<=D;){const z=d[S],q=p[S]=T?ot(p[S]):Je(p[S]);if(At(z,q))_(z,q,b,null,x,y,A,E,T);else break;S++}for(;S<=O&&S<=D;){const z=d[O],q=p[D]=T?ot(p[D]):Je(p[D]);if(At(z,q))_(z,q,b,null,x,y,A,E,T);else break;O--,D--}if(S>O){if(S<=D){const z=D+1,q=zD)for(;S<=O;)Ve(d[S],x,y,!0),S++;else{const z=S,q=S,ne=new Map;for(S=q;S<=D;S++){const Ae=p[S]=T?ot(p[S]):Je(p[S]);Ae.key!=null&&ne.set(Ae.key,S)}let te,de=0;const me=D-q+1;let ze=!1,He=0;const Qt=new Array(me);for(S=0;S=me){Ve(Ae,x,y,!0);continue}let Be;if(Ae.key!=null)Be=ne.get(Ae.key);else for(te=q;te<=D;te++)if(Qt[te-q]===0&&At(Ae,p[te])){Be=te;break}Be===void 0?Ve(Ae,x,y,!0):(Qt[Be-q]=S+1,Be>=He?He=Be:ze=!0,_(Ae,p[Be],b,null,x,y,A,E,T),de++)}const Ei=ze?Ic(Qt):jt;for(te=Ei.length-1,S=me-1;S>=0;S--){const Ae=q+S,Be=p[Ae],Ai=p[Ae+1],Ii=Ae+1{const{el:y,type:A,transition:E,children:T,shapeFlag:S}=d;if(S&6){yt(d.component.subTree,p,b,w);return}if(S&128){d.suspense.move(p,b,w);return}if(S&64){A.move(d,p,b,Xt);return}if(A===ce){n(y,p,b);for(let O=0;OE.enter(y),x));else{const{leave:O,delayLeave:D,afterLeave:z}=E,q=()=>{d.ctx.isUnmounted?i(y):n(y,p,b)},ne=()=>{const te=y._isLeaving||!!y[$e];y._isLeaving&&y[$e](!0),E.persisted&&!te?q():O(y,()=>{q(),z&&z()})};D?D(y,q,ne):ne()}else n(y,p,b)},Ve=(d,p,b,w=!1,x=!1)=>{const{type:y,props:A,ref:E,children:T,dynamicChildren:S,shapeFlag:N,patchFlag:O,dirs:D,cacheIndex:z,memo:q}=d;if(O===-2&&(x=!1),E!=null&&(Ze(),fs(E,null,b,d,!0),et()),z!=null&&(p.renderCache[z]=void 0),N&256){p.ctx.deactivate(d);return}const ne=N&1&&D,te=!ds(d);let de;if(te&&(de=A&&A.onVnodeBeforeUnmount)&&We(de,p,d),N&6)qr(d.component,b,w);else{if(N&128){d.suspense.unmount(b,w);return}ne&&St(d,null,p,"beforeUnmount"),N&64?d.type.remove(d,p,b,Xt,w):S&&!S.hasOnce&&(y!==ce||O>0&&O&64)?Yt(S,p,b,!1,!0):(y===ce&&O&384||!x&&N&16)&&Yt(T,p,b),w&&Ti(d)}const me=q!=null&&z==null;(te&&(de=A&&A.onVnodeUnmounted)||ne||me)&&xe(()=>{de&&We(de,p,d),ne&&St(d,null,p,"unmounted"),me&&(d.el=null)},b)},Ti=d=>{const{type:p,el:b,anchor:w,transition:x}=d;if(p===ce){Gr(b,w);return}if(p===Tn){P(d);return}const y=()=>{i(b),x&&!x.persisted&&x.afterLeave&&x.afterLeave()};if(d.shapeFlag&1&&x&&!x.persisted){const{leave:A,delayLeave:E}=x,T=()=>A(b,y);E?E(d.el,y,T):T()}else y()},Gr=(d,p)=>{let b;for(;d!==p;)b=h(d),i(d),d=b;i(p)},qr=(d,p,b)=>{const{bum:w,scope:x,job:y,subTree:A,um:E,m:T,a:S}=d;Gi(T),Gi(S),w&&zs(w),x.stop(),y&&(y.flags|=8,Ve(A,d,p,b)),E&&xe(E,p),xe(()=>{d.isUnmounted=!0},p)},Yt=(d,p,b,w=!1,x=!1,y=0)=>{for(let A=y;A{if(d.shapeFlag&6)return Is(d.component.subTree);if(d.shapeFlag&128)return d.suspense.next();const p=h(d.anchor||d.el),b=p&&p[sr];return b?h(b):p};let gn=!1;const Ci=(d,p,b)=>{let w;d==null?p._vnode&&(Ve(p._vnode,null,null,!0),w=p._vnode.component):_(p._vnode||null,d,p,null,null,null,b),p._vnode=d,gn||(gn=!0,Li(w),Xo(),gn=!1)},Xt={p:_,um:Ve,m:yt,r:Ti,mt:fe,mc:Y,pc:re,pbc:G,n:Is,o:e};return{render:Ci,hydrate:void 0,createApp:fc(Ci)}}function wn({type:e,props:t},s){return s==="svg"&&e==="foreignObject"||s==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:s}function xt({effect:e,job:t},s){s?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function Ac(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function yi(e,t,s=!1){const n=e.children,i=t.children;if(k(n)&&k(i))for(let o=0;o>1,e[s[l]]0&&(t[n]=s[o-1]),s[o]=n)}}for(o=s.length,r=s[o-1];o-- >0;)s[o]=r,r=t[r];return s}function Er(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:Er(t)}function Gi(e){if(e)for(let t=0;te.__isSuspense;function Mc(e,t){t&&t.pendingBranch?k(e)?t.effects.push(...e):t.effects.push(e):kl(e)}const ce=Symbol.for("v-fgt"),hn=Symbol.for("v-txt"),Te=Symbol.for("v-cmt"),Tn=Symbol.for("v-stc"),ps=[];let Ie=null;function V(e=!1){ps.push(Ie=e?null:[])}function Oc(){ps.pop(),Ie=ps[ps.length-1]||null}let ys=1;function Js(e,t=!1){ys+=e,e<0&&Ie&&t&&(Ie.hasOnce=!0)}function Mr(e){return e.dynamicChildren=ys>0?Ie||jt:null,Oc(),ys>0&&Ie&&Ie.push(e),e}function H(e,t,s,n,i,o){return Mr(g(e,t,s,n,i,o,!0))}function Or(e,t,s,n,i){return Mr(se(e,t,s,n,i,!0))}function Ys(e){return e?e.__v_isVNode===!0:!1}function At(e,t){return e.type===t.type&&e.key===t.key}const $r=({key:e})=>e??null,Bs=({ref:e,ref_key:t,ref_for:s})=>(typeof e=="number"&&(e=""+e),e!=null?ae(e)||ye(e)||B(e)?{i:Re,r:e,k:t,f:!!s}:e:null);function g(e,t=null,s=null,n=0,i=null,o=e===ce?0:1,r=!1,l=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&$r(t),ref:t&&Bs(t),scopeId:Zo,slotScopeIds:null,children:s,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:o,patchFlag:n,dynamicProps:i,dynamicChildren:null,appContext:null,ctx:Re};return l?(Xs(c,s),o&128&&e.normalize(c)):s&&(c.shapeFlag|=ae(s)?8:16),ys>0&&!r&&Ie&&(c.patchFlag>0||o&6)&&c.patchFlag!==32&&Ie.push(c),c}const se=$c;function $c(e,t=null,s=null,n=0,i=null,o=!1){if((!e||e===nc)&&(e=Te),Ys(e)){const l=_t(e,t,!0);return s&&Xs(l,s),ys>0&&!o&&Ie&&(l.shapeFlag&6?Ie[Ie.indexOf(e)]=l:Ie.push(l)),l.patchFlag=-2,l}if(zc(e)&&(e=e.__vccOpts),t){t=Pc(t);let{class:l,style:c}=t;l&&!ae(l)&&(t.class=_e(l)),Q(c)&&(fi(c)&&!k(c)&&(c=he({},c)),t.style=Bt(c))}const r=ae(e)?1:Ir(e)?128:nr(e)?64:Q(e)?4:B(e)?2:0;return g(e,t,s,n,i,r,o,!0)}function Pc(e){return e?fi(e)||yr(e)?he({},e):e:null}function _t(e,t,s=!1,n=!1){const{props:i,ref:o,patchFlag:r,children:l,transition:c}=e,u=t?Rc(i||{},t):i,a={__v_isVNode:!0,__v_skip:!0,type:e.type,props:u,key:u&&$r(u),ref:t&&t.ref?s&&o?k(o)?o.concat(Bs(t)):[o,Bs(t)]:Bs(t):o,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:l,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==ce?r===-1?16:r|16:r,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:c,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&_t(e.ssContent),ssFallback:e.ssFallback&&_t(e.ssFallback),placeholder:e.placeholder,el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return c&&n&&Pt(a,c.clone(a)),a}function ve(e=" ",t=0){return se(hn,null,e,t)}function Rt(e="",t=!1){return t?(V(),Or(Te,null,e)):se(Te,null,e)}function Je(e){return e==null||typeof e=="boolean"?se(Te):k(e)?se(ce,null,e.slice()):Ys(e)?ot(e):se(hn,null,String(e))}function ot(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:_t(e)}function Xs(e,t){let s=0;const{shapeFlag:n}=e;if(t==null)t=null;else if(k(t))s=16;else if(typeof t=="object")if(n&65){const i=t.default;i&&(i._c&&(i._d=!1),Xs(e,i()),i._c&&(i._d=!0));return}else{s=32;const i=t._;!i&&!yr(t)?t._ctx=Re:i===3&&Re&&(Re.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else if(B(t)){if(n&65){Xs(e,{default:t});return}t={default:t,_ctx:Re},s=32}else t=String(t),n&64?(s=16,t=[ve(t)]):s=8;e.children=t,e.shapeFlag|=s}function Rc(...e){const t={};for(let s=0;sCe||Re;let Qs,Yn;{const e=ln(),t=(s,n)=>{let i;return(i=e[s])||(i=e[s]=[]),i.push(n),o=>{i.length>1?i.forEach(r=>r(o)):i[0](o)}};Qs=t("__VUE_INSTANCE_SETTERS__",s=>Ce=s),Yn=t("__VUE_SSR_SETTERS__",s=>Ss=s)}const Cs=e=>{const t=Ce;return Qs(e),e.scope.on(),()=>{e.scope.off(),Qs(t)}},qi=()=>{Ce&&Ce.scope.off(),Qs(null)};function Pr(e){return e.vnode.shapeFlag&4}let Ss=!1;function kc(e,t=!1,s=!1){t&&Yn(t);const{props:n,children:i}=e.vnode,o=Pr(e);bc(e,n,o,t),wc(e,i,s||t);const r=o?Nc(e,t):void 0;return t&&Yn(!1),r}function Nc(e,t){const s=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,ic);const{setup:n}=s;if(n){Ze();const i=e.setupContext=n.length>1?Vc(e):null,o=Cs(e),r=Ts(n,e,0,[e.props,i]),l=wo(r);if(et(),o(),(l||e.sp)&&!ds(e)&&ar(e),l){if(r.then(qi,qi),t)return r.then(c=>{Ji(e,c)}).catch(c=>{an(c,e,0)});e.asyncDep=r}else Ji(e,r)}else Rr(e)}function Ji(e,t,s){B(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:Q(t)&&(e.setupState=qo(t)),Rr(e)}function Rr(e,t,s){const n=e.type;e.render||(e.render=n.render||Xe);{const i=Cs(e);Ze();try{oc(e)}finally{et(),i()}}}const jc={get(e,t){return be(e,"get",""),e[t]}};function Vc(e){const t=s=>{e.exposed=s||{}};return{attrs:new Proxy(e.attrs,jc),slots:e.slots,emit:e.emit,expose:t}}function pn(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(qo(Uo(e.exposed)),{get(t,s){if(s in t)return t[s];if(s in hs)return hs[s](e)},has(t,s){return s in t||s in hs}})):e.proxy}function zc(e){return B(e)&&"__vccOpts"in e}const tt=(e,t)=>Pl(e,t,Ss);function Hc(e,t,s){try{Js(-1);const n=arguments.length;return n===2?Q(t)&&!k(t)?Ys(t)?se(e,null,[t]):se(e,t):se(e,null,t):(n>3?s=Array.prototype.slice.call(arguments,2):n===3&&Ys(s)&&(s=[s]),se(e,t,s))}finally{Js(1)}}const Bc="3.5.39";/** +* @vue/runtime-dom v3.5.39 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let Xn;const Yi=typeof window<"u"&&window.trustedTypes;if(Yi)try{Xn=Yi.createPolicy("vue",{createHTML:e=>e})}catch{}const Lr=Xn?e=>Xn.createHTML(e):e=>e,Wc="http://www.w3.org/2000/svg",Kc="http://www.w3.org/1998/Math/MathML",it=typeof document<"u"?document:null,Xi=it&&it.createElement("template"),Uc={insert:(e,t,s)=>{t.insertBefore(e,s||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,s,n)=>{const i=t==="svg"?it.createElementNS(Wc,e):t==="mathml"?it.createElementNS(Kc,e):s?it.createElement(e,{is:s}):it.createElement(e);return e==="select"&&n&&n.multiple!=null&&i.setAttribute("multiple",n.multiple),i},createText:e=>it.createTextNode(e),createComment:e=>it.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>it.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,s,n,i,o){const r=s?s.previousSibling:t.lastChild;if(i&&(i===o||i.nextSibling))for(;t.insertBefore(i.cloneNode(!0),s),!(i===o||!(i=i.nextSibling)););else{Xi.innerHTML=Lr(n==="svg"?`${e}`:n==="mathml"?`${e}`:e);const l=Xi.content;if(n==="svg"||n==="mathml"){const c=l.firstChild;for(;c.firstChild;)l.appendChild(c.firstChild);l.removeChild(c)}t.insertBefore(l,s)}return[r?r.nextSibling:t.firstChild,s?s.previousSibling:t.lastChild]}},ft="transition",ts="animation",Kt=Symbol("_vtc"),Fr={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},Dr=he({},or,Fr),Gc=e=>(e.displayName="Transition",e.props=Dr,e),qc=Gc((e,{slots:t})=>Hc(Gl,kr(e),t)),wt=(e,t=[])=>{k(e)?e.forEach(s=>s(...t)):e&&e(...t)},Qi=e=>e?k(e)?e.some(t=>t.length>1):e.length>1:!1;function kr(e){const t={};for(const R in e)R in Fr||(t[R]=e[R]);if(e.css===!1)return t;const{name:s="v",type:n,duration:i,enterFromClass:o=`${s}-enter-from`,enterActiveClass:r=`${s}-enter-active`,enterToClass:l=`${s}-enter-to`,appearFromClass:c=o,appearActiveClass:u=r,appearToClass:a=l,leaveFromClass:f=`${s}-leave-from`,leaveActiveClass:h=`${s}-leave-active`,leaveToClass:v=`${s}-leave-to`}=e,m=Jc(i),_=m&&m[0],I=m&&m[1],{onBeforeEnter:$,onEnter:M,onEnterCancelled:L,onLeave:P,onLeaveCancelled:K,onBeforeAppear:Z=$,onAppear:j=M,onAppearCancelled:Y=L}=t,F=(R,oe,fe,st)=>{R._enterCancelled=st,gt(R,oe?a:l),gt(R,oe?u:r),fe&&fe()},G=(R,oe)=>{R._isLeaving=!1,gt(R,f),gt(R,v),gt(R,h),oe&&oe()},ee=R=>(oe,fe)=>{const st=R?j:M,ge=()=>F(oe,R,fe);wt(st,[oe,ge]),Zi(()=>{gt(oe,R?c:o),Ue(oe,R?a:l),Qi(st)||eo(oe,n,_,ge)})};return he(t,{onBeforeEnter(R){wt($,[R]),Ue(R,o),Ue(R,r)},onBeforeAppear(R){wt(Z,[R]),Ue(R,c),Ue(R,u)},onEnter:ee(!1),onAppear:ee(!0),onLeave(R,oe){R._isLeaving=!0;const fe=()=>G(R,oe);Ue(R,f),R._enterCancelled?(Ue(R,h),Qn(R)):(Qn(R),Ue(R,h)),Zi(()=>{R._isLeaving&&(gt(R,f),Ue(R,v),Qi(P)||eo(R,n,I,fe))}),wt(P,[R,fe])},onEnterCancelled(R){F(R,!1,void 0,!0),wt(L,[R])},onAppearCancelled(R){F(R,!0,void 0,!0),wt(Y,[R])},onLeaveCancelled(R){G(R),wt(K,[R])}})}function Jc(e){if(e==null)return null;if(Q(e))return[Cn(e.enter),Cn(e.leave)];{const t=Cn(e);return[t,t]}}function Cn(e){return Zr(e)}function Ue(e,t){t.split(/\s+/).forEach(s=>s&&e.classList.add(s)),(e[Kt]||(e[Kt]=new Set)).add(t)}function gt(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.remove(n));const s=e[Kt];s&&(s.delete(t),s.size||(e[Kt]=void 0))}function Zi(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let Yc=0;function eo(e,t,s,n){const i=e._endId=++Yc,o=()=>{i===e._endId&&n()};if(s!=null)return setTimeout(o,s);const{type:r,timeout:l,propCount:c}=Nr(e,t);if(!r)return n();const u=r+"end";let a=0;const f=()=>{e.removeEventListener(u,h),o()},h=v=>{v.target===e&&++a>=c&&f()};setTimeout(()=>{a(s[m]||"").split(", "),i=n(`${ft}Delay`),o=n(`${ft}Duration`),r=to(i,o),l=n(`${ts}Delay`),c=n(`${ts}Duration`),u=to(l,c);let a=null,f=0,h=0;t===ft?r>0&&(a=ft,f=r,h=o.length):t===ts?u>0&&(a=ts,f=u,h=c.length):(f=Math.max(r,u),a=f>0?r>u?ft:ts:null,h=a?a===ft?o.length:c.length:0);const v=a===ft&&/\b(?:transform|all)(?:,|$)/.test(n(`${ft}Property`).toString());return{type:a,timeout:f,propCount:h,hasTransform:v}}function to(e,t){for(;e.lengthso(s)+so(e[n])))}function so(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function Qn(e){return(e?e.ownerDocument:document).body.offsetHeight}function Xc(e,t,s){const n=e[Kt];n&&(t=(t?[t,...n]:[...n]).join(" ")),t==null?e.removeAttribute("class"):s?e.setAttribute("class",t):e.className=t}const Zs=Symbol("_vod"),xi=Symbol("_vsh"),En={name:"show",beforeMount(e,{value:t},{transition:s}){e[Zs]=e.style.display==="none"?"":e.style.display,s&&t?s.beforeEnter(e):ss(e,t)},mounted(e,{value:t},{transition:s}){s&&t&&s.enter(e)},updated(e,{value:t,oldValue:s},{transition:n}){!t!=!s&&(n?t?(n.beforeEnter(e),ss(e,!0),n.enter(e)):n.leave(e,()=>{ss(e,!1)}):ss(e,t))},beforeUnmount(e,{value:t}){ss(e,t)}};function ss(e,t){e.style.display=t?e[Zs]:"none",e[xi]=!t}const Qc=Symbol(""),Zc=/(?:^|;)\s*display\s*:/;function ea(e,t,s){const n=e.style,i=ae(s);let o=!1;if(s&&!i){if(t)if(ae(t))for(const r of t.split(";")){const l=r.slice(0,r.indexOf(":")).trim();s[l]==null&&ls(n,l,"")}else for(const r in t)s[r]==null&&ls(n,r,"");for(const r in s){r==="display"&&(o=!0);const l=s[r];l!=null?sa(e,r,!ae(t)&&t?t[r]:void 0,l)||ls(n,r,l):ls(n,r,"")}}else if(i){if(t!==s){const r=n[Qc];r&&(s+=";"+r),n.cssText=s,o=Zc.test(s)}}else t&&e.removeAttribute("style");Zs in e&&(e[Zs]=o?n.display:"",e[xi]&&(n.display="none"))}const no=/\s*!important$/;function ls(e,t,s){if(k(s))s.forEach(n=>ls(e,t,n));else if(s==null&&(s=""),t.startsWith("--"))e.setProperty(t,s);else{const n=ta(e,t);no.test(s)?e.setProperty(Lt(n),s.replace(no,""),"important"):e[n]=s}}const io=["Webkit","Moz","ms"],An={};function ta(e,t){const s=An[t];if(s)return s;let n=ke(t);if(n!=="filter"&&n in e)return An[t]=n;n=Eo(n);for(let i=0;iIn||(ca.then(()=>In=0),In=Date.now());function ua(e,t){const s=n=>{if(!n._vts)n._vts=Date.now();else if(n._vts<=s.attached)return;const i=s.value;if(k(i)){const o=n.stopImmediatePropagation;n.stopImmediatePropagation=()=>{o.call(n),n._stopped=!0};const r=i.slice(),l=[n];for(let c=0;ce.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,fa=(e,t,s,n,i,o)=>{const r=i==="svg";t==="class"?Xc(e,n,r):t==="style"?ea(e,s,n):sn(t)?nn(t)||ia(e,t,s,n,o):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):da(e,t,n,r))?(lo(e,t,n),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&ro(e,t,n,r,o,t!=="value")):e._isVueCE&&(ha(e,t)||e._def.__asyncLoader&&(/[A-Z]/.test(t)||!ae(n)))?lo(e,ke(t),n,o,t):(t==="true-value"?e._trueValue=n:t==="false-value"&&(e._falseValue=n),ro(e,t,n,r))};function da(e,t,s,n){if(n)return!!(t==="innerHTML"||t==="textContent"||t in e&&ao(t)&&B(s));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="autocorrect"||t==="sandbox"&&e.tagName==="IFRAME"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const i=e.tagName;if(i==="IMG"||i==="VIDEO"||i==="CANVAS"||i==="SOURCE")return!1}return ao(t)&&ae(s)?!1:t in e}function ha(e,t){const s=e._def.props;if(!s)return!1;const n=ke(t);return Array.isArray(s)?s.some(i=>ke(i)===n):Object.keys(s).some(i=>ke(i)===n)}const jr=new WeakMap,Vr=new WeakMap,en=Symbol("_moveCb"),uo=Symbol("_enterCb"),pa=e=>(delete e.props.mode,e),ga=pa({name:"TransitionGroup",props:he({},Dr,{tag:String,moveClass:String}),setup(e,{slots:t}){const s=Si(),n=ir();let i,o;return fr(()=>{if(!i.length)return;const r=e.moveClass||`${e.name||"v"}-move`;if(!ya(i[0].el,s.vnode.el,r)){i=[];return}i.forEach(va),i.forEach(_a);const l=i.filter(ba);Qn(s.vnode.el),l.forEach(c=>{const u=c.el,a=u.style;Ue(u,r),a.transform=a.webkitTransform=a.transitionDuration="";const f=u[en]=h=>{h&&h.target!==u||(!h||h.propertyName.endsWith("transform"))&&(u.removeEventListener("transitionend",f),u[en]=null,gt(u,r))};u.addEventListener("transitionend",f)}),i=[]}),()=>{const r=J(e),l=kr(r);let c=r.tag||ce;if(i=[],o)for(let u=0;u{l.split(/\s+/).forEach(c=>c&&n.classList.remove(c))}),s.split(/\s+/).forEach(l=>l&&n.classList.add(l)),n.style.display="none";const o=t.nodeType===1?t:t.parentNode;o.appendChild(n);const{hasTransform:r}=Nr(n);return o.removeChild(n),r}const Ut=e=>{const t=e.props["onUpdate:modelValue"]||!1;return k(t)?s=>zs(t,s):t};function Sa(e){e.target.composing=!0}function fo(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const ct=Symbol("_assign");function ho(e,t,s){return t&&(e=e.trim()),s&&(e=rn(e)),e}const It={created(e,{modifiers:{lazy:t,trim:s,number:n}},i){e[ct]=Ut(i);const o=n||i.props&&i.props.type==="number";vt(e,t?"change":"input",r=>{r.target.composing||e[ct](ho(e.value,s,o))}),(s||o)&&vt(e,"change",()=>{e.value=ho(e.value,s,o)}),t||(vt(e,"compositionstart",Sa),vt(e,"compositionend",fo),vt(e,"change",fo))},mounted(e,{value:t}){e.value=t??""},beforeUpdate(e,{value:t,oldValue:s,modifiers:{lazy:n,trim:i,number:o}},r){if(e[ct]=Ut(r),e.composing)return;const l=(o||e.type==="number")&&!/^0\d/.test(e.value)?rn(e.value):e.value,c=t??"";if(l===c)return;const u=e.getRootNode();(u instanceof Document||u instanceof ShadowRoot)&&u.activeElement===e&&e.type!=="range"&&(n&&t===s||i&&e.value.trim()===c)||(e.value=c)}},xa={deep:!0,created(e,t,s){e[ct]=Ut(s),vt(e,"change",()=>{const n=e._modelValue,i=xs(e),o=e.checked,r=e[ct];if(k(n)){const l=ni(n,i),c=l!==-1;if(o&&!c)r(n.concat(i));else if(!o&&c){const u=[...n];u.splice(l,1),r(u)}}else if(Gt(n)){const l=new Set(n);o?l.add(i):l.delete(i),r(l)}else r(Hr(e,o))})},mounted:po,beforeUpdate(e,t,s){e[ct]=Ut(s),po(e,t,s)}};function po(e,{value:t,oldValue:s},n){e._modelValue=t;let i;if(k(t))i=ni(t,n.props.value)>-1;else if(Gt(t))i=t.has(n.props.value);else{if(t===s)return;i=qt(t,Hr(e,!0))}e.checked!==i&&(e.checked=i)}const wa={deep:!0,created(e,{value:t,modifiers:{number:s}},n){const i=Gt(t);vt(e,"change",()=>{const o=Array.prototype.filter.call(e.options,r=>r.selected).map(r=>s?rn(xs(r)):xs(r));e[ct](e.multiple?i?new Set(o):o:o[0]),e._assigning=!0,di(()=>{e._assigning=!1})}),e[ct]=Ut(n)},mounted(e,{value:t}){go(e,t)},beforeUpdate(e,t,s){e[ct]=Ut(s)},updated(e,{value:t}){e._assigning||go(e,t)}};function go(e,t){const s=e.multiple,n=k(t);if(!(s&&!n&&!Gt(t))){for(let i=0,o=e.options.length;iString(u)===String(l)):r.selected=ni(t,l)>-1}else r.selected=t.has(l);else if(qt(xs(r),t)){e.selectedIndex!==i&&(e.selectedIndex=i);return}}!s&&e.selectedIndex!==-1&&(e.selectedIndex=-1)}}function xs(e){return"_value"in e?e._value:e.value}function Hr(e,t){const s=t?"_trueValue":"_falseValue";return s in e?e[s]:t}const Ta=["ctrl","shift","alt","meta"],Ca={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>Ta.some(s=>e[`${s}Key`]&&!t.includes(s))},Ea=(e,t)=>{if(!e)return e;const s=e._withMods||(e._withMods={}),n=t.join(".");return s[n]||(s[n]=((i,...o)=>{for(let r=0;r{const t=Ia().createApp(...e),{mount:s}=t;return t.mount=n=>{const i=$a(n);if(!i)return;const o=t._component;!B(o)&&!o.render&&!o.template&&(o.template=i.innerHTML),i.nodeType===1&&(i.textContent="");const r=s(i,!1,Oa(i));return i instanceof Element&&(i.removeAttribute("v-cloak"),i.setAttribute("data-v-app","")),r},t});function Oa(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function $a(e){return ae(e)?document.querySelector(e):e}/*! + * pinia v2.3.1 + * (c) 2025 Eduardo San Martin Morote + * @license MIT + */const Pa=Symbol();var vo;(function(e){e.direct="direct",e.patchObject="patch object",e.patchFunction="patch function"})(vo||(vo={}));function Ra(){const e=ll(!0),t=e.run(()=>U({}));let s=[],n=[];const i=Uo({install(o){i._a=o,o.provide(Pa,i),o.config.globalProperties.$pinia=i,n.forEach(r=>s.push(r)),n=[]},use(o){return this._a?s.push(o):n.push(o),this},_p:s,_a:null,_e:e,_s:new Map,state:t});return i}const Mn=U("dark");function Br(){const e=n=>{Mn.value=n,document.body.dataset.theme=n,localStorage.setItem("uiTheme",n)};return{theme:Mn,toggleTheme:()=>{e(Mn.value==="light"?"dark":"light")},initTheme:()=>{var o;const n=localStorage.getItem("uiTheme"),i=(o=window.matchMedia)==null?void 0:o.call(window,"(prefers-color-scheme: light)").matches;e(n||(i?"light":"dark"))}}}const Rs=U([]);let La=0;function Es(){const e=(s,n,i="info",o=4e3)=>{const r=La++,l={id:r,title:s,body:n,type:i,duration:o};Rs.value.push(l),setTimeout(()=>{t(r)},o)},t=s=>{const n=Rs.value.findIndex(i=>i.id===s);n!==-1&&Rs.value.splice(n,1)};return{toasts:Rs,showToast:e,removeToast:t}}const Fa=window.go.main.App,dt=U([]),On=U(null),Tt=U(null),Ls=U(""),Fs=U(""),$n=U(!1);function Ft(){const{showToast:e}=Es(),t=tt(()=>{const u=Fs.value.toLowerCase().trim();return u?dt.value.filter(a=>[a.commodityName,a.commodityId,a.score,a.count].some(f=>String(f??"").toLowerCase().includes(u))):dt.value}),s=tt(()=>dt.value.find(u=>u.commodityId===Tt.value)),n=async(u=!0)=>{$n.value=!0;try{const a=await Fa.LoadProducts(!0);dt.value=Array.isArray(a.products)?a.products:[],On.value=a,Tt.value&&!dt.value.some(f=>f.commodityId===Tt.value)&&o(),u&&e("商品已刷新",`共 ${dt.value.length} 个`,"success")}catch(a){dt.value=[],On.value=null,o(),e("商品刷新失败",a.message,"error")}finally{$n.value=!1}},i=(u,a)=>{Tt.value=u,Ls.value=a,localStorage.setItem("selProd",u),localStorage.setItem("selProdName",a)},o=()=>{Tt.value=null,Ls.value="",localStorage.removeItem("selProd"),localStorage.removeItem("selProdName")};return{products:dt,productInfo:On,selectedProductId:Tt,selectedProductName:Ls,selectedProduct:s,searchQuery:Fs,filteredProducts:t,loading:$n,loadProducts:n,selectProduct:i,clearSelection:o,setSearch:u=>{Fs.value=u.trim()},clearSearch:()=>{Fs.value=""},restoreSelection:()=>{const u=localStorage.getItem("selProd"),a=localStorage.getItem("selProdName");u&&(Tt.value=u,Ls.value=a||"")}}}const Pn=window.go.main.App,ht=U([]),Ee=U(new Set),ns=U({}),Rn=U({});function Jt(){const{showToast:e}=Es(),t=async()=>{const v=await Pn.GetAccounts();ht.value=v||[],Ee.value=new Set([...Ee.value].filter(m=>m>=0&&m{const v=await Pn.ReloadAccounts();await t(),e("账号已刷新",`共 ${v.count} 个账号`,"success")},n=v=>{Ee.value.has(v)?Ee.value.delete(v):Ee.value.add(v),o()},i=()=>{Ee.value.size===ht.value.length?Ee.value.clear():ht.value.forEach((v,m)=>Ee.value.add(m)),o()},o=()=>{localStorage.setItem("selAccs",JSON.stringify([...Ee.value]))};return{accounts:ht,selectedIndices:Ee,statusMap:ns,scoreMap:Rn,loadAccounts:t,reloadAccounts:s,toggleAccount:n,toggleAll:i,restoreSelection:()=>{const v=localStorage.getItem("selAccs");if(v)try{Ee.value=new Set(JSON.parse(v))}catch{}const m=localStorage.getItem("statusMap");if(m)try{ns.value=JSON.parse(m)}catch{}},queryAllScore:async()=>{e("查询积分","正在并发查询...","info");const v=ht.value.map(async m=>{try{const I=(await Pn.QueryScore(m.name)).score??"N/A";Rn.value[m.name]=String(I),localStorage.setItem("accScore_"+m.name,String(I))}catch{}});await Promise.all(v),e("积分查询完成","","success")},getScore:v=>Rn.value[v]||localStorage.getItem("accScore_"+v)||"-",resetStatus:()=>{ns.value={},localStorage.removeItem("statusMap")},setStatus:(v,m)=>{ns.value[v]=m,localStorage.setItem("statusMap",JSON.stringify(ns.value))},selectedAccountNames:()=>[...Ee.value].map(v=>{var m;return(m=ht.value[v])==null?void 0:m.name}).filter(Boolean),buildAccountProducts:v=>{if(Ee.value.size===0)return e("提示","请勾选要抢购的账号","warn"),null;if(!v)return e("提示","请先选择商品","warn"),null;const m={};return Ee.value.forEach(_=>{const I=ht.value[_];I&&(m[I.name]=v)}),Object.keys(m).length===0?(e("提示","没有有效账号可提交","warn"),null):m}}}const Ln=window.go.main.App,Ds=U(!1),Fn=U(0),ks=U(null),_o=U("等待操作");function wi(){const{showToast:e}=Es(),{resetStatus:t,buildAccountProducts:s}=Jt(),{selectedProductId:n}=Ft(),i=h=>{_o.value=h||"等待操作"},o=async()=>{const h=s(n.value||"");if(h){t(),i("立即抢购已提交"),e("抢购中",`${Object.keys(h).length} 个账号正在抢购`,"info",3e3);try{const v=await Ln.StartSeckill(h);i(v.msg||"已提交")}catch(v){i("提交失败"),e("提交失败",v.message,"error")}}},r=async(h,v)=>{const m=s(n.value||"");if(!m)return;if(!h){e("提示","请选择目标时间","warn");return}let _=h;_.split(":").length===2&&(_+=":00");const $=new Intl.DateTimeFormat("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit"}).format(new Date).replace(/\//g,"-")+" "+_;t(),i("定时配置中");try{const M=await Ln.SetSchedule({accountProducts:m,targetTime:$,advance:v});Ds.value=!0,localStorage.setItem("targetTime",_),localStorage.setItem("advance",String(v)),i(`定时已开启,触发 ${M.triggerTime}`),e("定时已开启",`触发时刻: ${M.triggerTime}
剩余时间: ${a(M.remainSecond)}`,"success",5e3),c(M.remainSecond)}catch(M){i("定时设置失败"),e("定时失败",M.message,"error")}},l=async()=>{try{await Ln.CancelSchedule()}catch{}Ds.value=!1,localStorage.removeItem("targetTime"),localStorage.removeItem("advance"),u(),i("定时已停止"),e("定时已停止","抢购任务已取消","warn")},c=h=>{u();const v=Date.now()+h*1e3;ks.value=window.setInterval(()=>{const m=Math.max(0,Math.ceil((v-Date.now())/1e3));Fn.value=m,m<=0&&(Ds.value=!1,i("定时已触发"),u())},500)},u=()=>{ks.value&&(clearInterval(ks.value),ks.value=null),Fn.value=0},a=h=>{const v=Math.floor(h/3600),m=Math.floor(h%3600/60),_=h%60;return`${v}:${String(m).padStart(2,"0")}:${String(_).padStart(2,"0")}`};return{scheduleActive:Ds,countdownSeconds:Fn,runState:_o,setRunState:i,startNow:o,startSchedule:r,cancelSchedule:l,formatRemain:a,restoreSchedule:()=>{const h=localStorage.getItem("targetTime"),v=localStorage.getItem("advance");return{savedTime:h,savedAdv:v?parseInt(v):300}}}}const Dn=window.go.main.App,Ke=U([]),Ns=U({}),js=U(0),Vs=U("");function Zn(){return{logs:Ke,results:Ns,addLocalLog:(o,r="i")=>{const l=new Date,c=l.toLocaleTimeString()+"."+String(l.getMilliseconds()).padStart(3,"0");Ke.value.push({time:c,type:r,message:o,source:"local"}),Ke.value.length>500&&(Ke.value=Ke.value.slice(-300))},fetchServerLogs:async()=>{try{const o=await Dn.GetLogs(js.value);if(!o.success||!Array.isArray(o.logs)||o.logs.length===0)return;o.logs.forEach(r=>{js.value=Math.max(js.value,r.id||0);let l="i";r.level==="success"?l="s":r.level==="error"?l="e":r.level==="warn"?l="w":r.level==="debug"&&(l="d");const c=String(r.message||"").replace(/\[[^\]]+\]\[(info|success|warn|error)\]\s*/i,"");Ke.value.push({time:r.time||"",type:l,message:c,category:r.category,source:"server"})}),Ke.value.length>500&&(Ke.value=Ke.value.slice(-300))}catch{}},checkResults:async()=>{try{const o=await Dn.GetResults(),r=JSON.stringify(o);return r!==Vs.value&&Object.keys(o).length>0?(Vs.value=r,Ns.value=o,!0):!1}catch{return!1}},clearLogs:()=>{Ke.value=[],Ns.value={},Vs.value="",js.value=0},clearResults:async()=>{await Dn.ClearResults(),Ns.value={},Vs.value=""}}}const Da={class:"product-search"},ka=200,Na=Me({__name:"ProductSearch",setup(e){const{searchQuery:t,setSearch:s,clearSearch:n}=Ft(),i=U(t.value);let o=null;$t(i,l=>{o&&clearTimeout(o),o=window.setTimeout(()=>{s(l)},ka)});const r=()=>{i.value="",n()};return(l,c)=>(V(),H("div",Da,[c[1]||(c[1]=g("span",{class:"search-icon"},"⌕",-1)),Pe(g("input",{"onUpdate:modelValue":c[0]||(c[0]=u=>i.value=u),type:"search",placeholder:"搜索商品名 / ID / 积分 / 库存",autocomplete:"off"},null,512),[[It,i.value]]),i.value?(V(),H("button",{key:0,class:"search-clear",type:"button",title:"清空",onClick:r}," × ")):Rt("",!0)]))}}),De=(e,t)=>{const s=e.__vccOpts||e;for(const[n,i]of t)s[n]=i;return s},ja=De(Na,[["__scopeId","data-v-819c56b1"]]);function Va(e,t,s){const n=new Array(e);return new Proxy(n,{get(i,o,r){if(typeof o=="string"){const l=o.charCodeAt(0);if(l>=48&&l<=57){const c=+o;if(Number.isInteger(c)&&c>=0&&cn[a]!==u))&&(n=l,i=t(...l),s!=null&&s.onChange&&!(o&&s.skipInitialOnChange)&&s.onChange(i),o=!1),i}return r.updateDeps=l=>{n=l},r}function bo(e,t){if(e===void 0)throw new Error("Unexpected undefined");return e}const za=(e,t)=>Math.abs(e-t)<1.01,Ha=(e,t,s)=>{let n;return function(...i){e.clearTimeout(n),n=e.setTimeout(()=>t.apply(this,i),s)}};let is;const kn=()=>{if(is!==void 0)return is;if(typeof navigator>"u")return is=!1;if(/iP(hone|od|ad)/.test(navigator.userAgent))return is=!0;const e=navigator.maxTouchPoints;return is=navigator.platform==="MacIntel"&&e!==void 0&&e>0},yo=e=>{const{offsetWidth:t,offsetHeight:s}=e;return{width:t,height:s}},Ba=e=>e,Wa=e=>{const t=Math.max(e.startIndex-e.overscan,0),n=Math.min(e.endIndex+e.overscan,e.count-1)-t+1,i=new Array(n);for(let o=0;o{const s=e.scrollElement;if(!s)return;const n=e.targetWindow;if(!n)return;const i=r=>{const{width:l,height:c}=r;t({width:Math.round(l),height:Math.round(c)})};if(i(yo(s)),!n.ResizeObserver)return()=>{};const o=new n.ResizeObserver(r=>{const l=()=>{const c=r[0];if(c!=null&&c.borderBoxSize){const u=c.borderBoxSize[0];if(u){i({width:u.inlineSize,height:u.blockSize});return}}i(yo(s))};e.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(l):l()});return o.observe(s,{box:"border-box"}),()=>{o.unobserve(s)}},tn={passive:!0},Ua=typeof window>"u"?!0:"onscrollend"in window,Ga=(e,t,s)=>{const n=e.scrollElement;if(!n)return;const i=e.targetWindow;if(!i)return;const o=e.options.useScrollendEvent&&Ua;let r=0;const l=o?null:Ha(i,()=>t(r,!1),e.options.isScrollingResetDelay),c=f=>()=>{r=s(n),l==null||l(),t(r,f)},u=c(!0),a=c(!1);return n.addEventListener("scroll",u,tn),o&&n.addEventListener("scrollend",a,tn),()=>{n.removeEventListener("scroll",u),o&&n.removeEventListener("scrollend",a)}},qa=(e,t)=>Ga(e,t,s=>{const{horizontal:n,isRtl:i}=e.options;return n?s.scrollLeft*(i&&-1||1):s.scrollTop}),Ja=(e,t,s)=>{if(s.options.useCachedMeasurements){const n=s.indexFromElement(e),i=s.options.getItemKey(n);return s.itemSizeCache.get(i)??s.options.estimateSize(n)}if(t!=null&&t.borderBoxSize){const n=t.borderBoxSize[0];if(n)return Math.round(n[s.options.horizontal?"inlineSize":"blockSize"])}if(!t){const n=s.indexFromElement(e),i=s.options.getItemKey(n),o=s.itemSizeCache.get(i);if(o!==void 0)return o}return e[s.options.horizontal?"offsetWidth":"offsetHeight"]},Ya=(e,{adjustments:t=0,behavior:s},n)=>{var i,o;(o=(i=n.scrollElement)==null?void 0:i.scrollTo)==null||o.call(i,{[n.options.horizontal?"left":"top"]:e+t,behavior:s})},Xa=Ya;class Qa{constructor(t){this.unsubs=[],this.scrollElement=null,this.targetWindow=null,this.isScrolling=!1,this.scrollState=null,this.measurementsCache=[],this._flatMeasurements=null,this.itemSizeCache=new Map,this.itemSizeCacheVersion=0,this.laneAssignments=new Map,this.pendingMin=null,this.prevLanes=void 0,this.lanesChangedFlag=!1,this.lanesSettling=!1,this.pendingScrollAnchor=null,this.scrollRect=null,this.scrollOffset=null,this.scrollDirection=null,this.scrollAdjustments=0,this._iosDeferredAdjustment=0,this._iosTouching=!1,this._iosJustTouchEnded=!1,this._iosTouchEndTimerId=null,this._intendedScrollOffset=null,this.elementsCache=new Map,this.now=()=>{var s,n,i;return((i=(n=(s=this.targetWindow)==null?void 0:s.performance)==null?void 0:n.now)==null?void 0:i.call(n))??Date.now()},this.observer=(()=>{let s=null;const n=()=>s||(!this.targetWindow||!this.targetWindow.ResizeObserver?null:s=new this.targetWindow.ResizeObserver(i=>{i.forEach(o=>{const r=()=>{const l=o.target,c=this.indexFromElement(l);if(!l.isConnected){this.observer.unobserve(l);for(const[u,a]of this.elementsCache)if(a===l){this.elementsCache.delete(u);break}return}this.shouldMeasureDuringScroll(c)&&this.resizeItem(c,this.options.measureElement(l,o,this))};this.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(r):r()})}));return{disconnect:()=>{var i;(i=n())==null||i.disconnect(),s=null},observe:i=>{var o;return(o=n())==null?void 0:o.observe(i,{box:"border-box"})},unobserve:i=>{var o;return(o=n())==null?void 0:o.unobserve(i)}}})(),this.range=null,this.setOptions=s=>{var n,i;const o={debug:!1,initialOffset:0,overscan:1,paddingStart:0,paddingEnd:0,scrollPaddingStart:0,scrollPaddingEnd:0,horizontal:!1,getItemKey:Ba,rangeExtractor:Wa,onChange:()=>{},measureElement:Ja,initialRect:{width:0,height:0},scrollMargin:0,gap:0,indexAttribute:"data-index",initialMeasurementsCache:[],lanes:1,anchorTo:"start",followOnAppend:!1,scrollEndThreshold:1,isScrollingResetDelay:150,enabled:!0,isRtl:!1,useScrollendEvent:!1,useAnimationFrameWithResizeObserver:!1,laneAssignmentMode:"estimate",useCachedMeasurements:!1};for(const h in s){const v=s[h];v!==void 0&&(o[h]=v)}const r=this.options;let l=null,c=null,u=!1;if(r!==void 0&&r.enabled&&o.enabled&&o.anchorTo==="end"&&this.scrollElement!==null){const h=r.count,v=o.count,m=this.getMeasurements(),_=h>0?((n=m[0])==null?void 0:n.key)??r.getItemKey(0):null,I=h>0?((i=m[h-1])==null?void 0:i.key)??r.getItemKey(h-1):null;if(v!==h||h>0&&v>0&&(o.getItemKey(0)!==_||o.getItemKey(v-1)!==I)){u=!0;const L=h>0?this.getVirtualItemForOffset(this.getScrollOffset())??m[0]:null;L&&(l=[L.key,this.getScrollOffset()-L.start]);const P=o.followOnAppend===!0?"auto":o.followOnAppend||null;P&&v>h&&this.isAtEnd(r.scrollEndThreshold)&&(h===0||o.getItemKey(v-1)!==I)&&(c=P)}}this.options=o,u&&(this.pendingMin=0,this.itemSizeCacheVersion++);let a=!1,f=0;if(l&&this.scrollOffset!==null){const[h,v]=l,m=this.getMeasurements(),{count:_,getItemKey:I}=this.options;let $=0;for(;$<_&&I($)!==h;)$++;if($<_){const M=m[$];if(M){const L=M.start+v;L!==this.scrollOffset&&(f=L-this.scrollOffset,this.scrollOffset=L,a=!0)}}}(a||c)&&(this.pendingScrollAnchor=[a?l[0]:null,a?l[1]:0,c,f])},this.notify=s=>{var n,i;(i=(n=this.options).onChange)==null||i.call(n,this,s)},this.maybeNotify=kt(()=>(this.calculateRange(),[this.isScrolling,this.range?this.range.startIndex:null,this.range?this.range.endIndex:null]),s=>{this.notify(s)},{key:!1,debug:()=>this.options.debug,initialDeps:[this.isScrolling,this.range?this.range.startIndex:null,this.range?this.range.endIndex:null]}),this.cleanup=()=>{this.unsubs.filter(Boolean).forEach(s=>s()),this.unsubs=[],this.observer.disconnect(),this.rafId!=null&&this.targetWindow&&(this.targetWindow.cancelAnimationFrame(this.rafId),this.rafId=null),this.scrollState=null,this.scrollElement=null,this.targetWindow=null},this._didMount=()=>()=>{this.cleanup()},this._willUpdate=()=>{var s;const n=this.options.enabled?this.options.getScrollElement():null;if(this.scrollElement!==n){if(this.cleanup(),!n){this.maybeNotify();return}if(this.scrollElement=n,this.scrollElement&&"ownerDocument"in this.scrollElement?this.targetWindow=this.scrollElement.ownerDocument.defaultView:this.targetWindow=((s=this.scrollElement)==null?void 0:s.window)??null,this.elementsCache.forEach(o=>{this.observer.observe(o)}),this.unsubs.push(this.options.observeElementRect(this,o=>{this.scrollRect=o,this.maybeNotify()})),this.unsubs.push(this.options.observeElementOffset(this,(o,r)=>{this._intendedScrollOffset!==null&&Math.abs(o-this._intendedScrollOffset)<1.5&&(o=this._intendedScrollOffset),this._intendedScrollOffset=null,this.scrollAdjustments=0,this.scrollDirection=r?this.getScrollOffset(){this._iosTouching=!0,this._iosJustTouchEnded=!1,this._iosTouchEndTimerId!==null&&this.targetWindow!=null&&(this.targetWindow.clearTimeout(this._iosTouchEndTimerId),this._iosTouchEndTimerId=null)},l=()=>{this._iosTouching=!1,!(!kn()||this.targetWindow==null)&&(this._iosJustTouchEnded=!0,this._iosTouchEndTimerId=this.targetWindow.setTimeout(()=>{this._iosJustTouchEnded=!1,this._iosTouchEndTimerId=null,this._flushIosDeferredIfReady()},150))};o.addEventListener("touchstart",r,tn),o.addEventListener("touchend",l,tn),this.unsubs.push(()=>{o.removeEventListener("touchstart",r),o.removeEventListener("touchend",l),this._iosTouchEndTimerId!==null&&this.targetWindow!=null&&(this.targetWindow.clearTimeout(this._iosTouchEndTimerId),this._iosTouchEndTimerId=null)})}this._scrollToOffset(this.getScrollOffset(),{adjustments:void 0,behavior:void 0})}const i=this.pendingScrollAnchor;if(this.pendingScrollAnchor=null,i&&this.scrollElement&&this.options.enabled){const[o,r,l,c]=i;o!==null&&!l&&(kn()&&(this.isScrolling||this._iosTouching||this._iosJustTouchEnded)?c!==0&&(this._iosDeferredAdjustment+=c):this._scrollToOffset(this.getScrollOffset(),{adjustments:void 0,behavior:void 0})),l&&this.scrollToEnd({behavior:l})}},this._flushIosDeferredIfReady=()=>{if(this._iosDeferredAdjustment===0||this.isScrolling||this._iosTouching||this._iosJustTouchEnded)return;const s=this.getScrollOffset(),n=this.getMaxScrollOffset();if(s<0||s>n)return;const i=this._iosDeferredAdjustment;this._iosDeferredAdjustment=0,this._scrollToOffset(s,{adjustments:this.scrollAdjustments+=i,behavior:void 0})},this.rafId=null,this.getSize=()=>this.options.enabled?(this.scrollRect=this.scrollRect??this.options.initialRect,this.scrollRect[this.options.horizontal?"width":"height"]):(this.scrollRect=null,0),this.getScrollOffset=()=>this.options.enabled?(this.scrollOffset=this.scrollOffset??(typeof this.options.initialOffset=="function"?this.options.initialOffset():this.options.initialOffset),this.scrollOffset):(this.scrollOffset=null,0),this.getFurthestMeasurement=(s,n)=>{const i=new Map,o=new Map;for(let r=n-1;r>=0;r--){const l=s[r];if(i.has(l.lane))continue;const c=o.get(l.lane);if(c==null||l.end>c.end?o.set(l.lane,l):l.endr.end===l.end?r.index-l.index:r.end-l.end)[0]:void 0},this.getMeasurementOptions=kt(()=>[this.options.count,this.options.paddingStart,this.options.scrollMargin,this.options.getItemKey,this.options.enabled,this.options.lanes,this.options.laneAssignmentMode],(s,n,i,o,r,l,c)=>(this.prevLanes!==void 0&&this.prevLanes!==l&&(this.lanesChangedFlag=!0),this.prevLanes=l,this.pendingMin=null,{count:s,paddingStart:n,scrollMargin:i,getItemKey:o,enabled:r,lanes:l,laneAssignmentMode:c}),{key:!1}),this.getMeasurements=kt(()=>[this.getMeasurementOptions(),this.itemSizeCacheVersion],({count:s,paddingStart:n,scrollMargin:i,getItemKey:o,enabled:r,lanes:l,laneAssignmentMode:c},u)=>{const a=this.itemSizeCache;if(!r)return this.measurementsCache=[],this.itemSizeCache.clear(),this.laneAssignments.clear(),[];if(this.laneAssignments.size>s)for(const m of this.laneAssignments.keys())m>=s&&this.laneAssignments.delete(m);this.lanesChangedFlag&&(this.lanesChangedFlag=!1,this.lanesSettling=!0,this.measurementsCache=[],this.itemSizeCache.clear(),this.laneAssignments.clear(),this.pendingMin=null),this.measurementsCache.length===0&&!this.lanesSettling&&(this.measurementsCache=this.options.initialMeasurementsCache,this.measurementsCache.forEach(m=>{this.itemSizeCache.set(m.key,m.size)}));const f=this.lanesSettling?0:this.pendingMin??0;if(this.pendingMin=null,this.lanesSettling&&this.measurementsCache.length===s&&(this.lanesSettling=!1),l===1){const m=this.options.gap,_=s*2;let I=this._flatMeasurements;if(!I||I.length<_){const L=new Float64Array(_);I&&f>0&&L.set(I.subarray(0,f*2)),I=L,this._flatMeasurements=I}let $;if(f===0)$=n+i;else{const L=f-1;$=I[L*2]+I[L*2+1]+m}for(let L=f;L1){$=I;const j=v[$],Y=j!==void 0?h[j]:void 0;M=Y?Y.end+this.options.gap:n+i}else{const j=this.options.lanes===1?h[m-1]:this.getFurthestMeasurement(h,m);M=j?j.end+this.options.gap:n+i,$=j?j.lane:m%this.options.lanes,this.options.lanes>1&&L&&this.laneAssignments.set(m,$)}const P=a.get(_),K=typeof P=="number"?P:this.options.estimateSize(m),Z=M+K;h[m]={index:m,start:M,size:K,end:Z,key:_,lane:$},v[$]=m}return this.measurementsCache=h,h},{key:!1,debug:()=>this.options.debug}),this.calculateRange=kt(()=>[this.getMeasurements(),this.getSize(),this.getScrollOffset(),this.options.lanes],(s,n,i,o)=>this.range=s.length>0&&n>0?Za({measurements:s,outerSize:n,scrollOffset:i,lanes:o,flat:o===1&&this._flatMeasurements!=null?this._flatMeasurements:null}):null,{key:!1,debug:()=>this.options.debug}),this.getVirtualIndexes=kt(()=>{let s=null,n=null;const i=this.calculateRange();return i&&(s=i.startIndex,n=i.endIndex),this.maybeNotify.updateDeps([this.isScrolling,s,n]),[this.options.rangeExtractor,this.options.overscan,this.options.count,s,n]},(s,n,i,o,r)=>o===null||r===null?[]:s({startIndex:o,endIndex:r,overscan:n,count:i}),{key:!1,debug:()=>this.options.debug}),this.indexFromElement=s=>{const n=this.options.indexAttribute,i=s.getAttribute(n);return i?parseInt(i,10):(console.warn(`Missing attribute name '${n}={index}' on measured element.`),-1)},this.shouldMeasureDuringScroll=s=>{var n;if(!this.scrollState||this.scrollState.behavior!=="smooth")return!0;const i=this.scrollState.index??((n=this.getVirtualItemForOffset(this.scrollState.lastTargetOffset))==null?void 0:n.index);if(i!==void 0&&this.range){const o=Math.max(this.options.overscan,Math.ceil((this.range.endIndex-this.range.startIndex)/2)),r=Math.max(0,i-o),l=Math.min(this.options.count-1,i+o);return s>=r&&s<=l}return!0},this.measureElement=s=>{if(!s){this.elementsCache.forEach((r,l)=>{r.isConnected||(this.observer.unobserve(r),this.elementsCache.delete(l))});return}const n=this.indexFromElement(s),i=this.options.getItemKey(n),o=this.elementsCache.get(i);o!==s&&(o&&this.observer.unobserve(o),this.observer.observe(s),this.elementsCache.set(i,s)),(!this.isScrolling||this.scrollState)&&this.shouldMeasureDuringScroll(n)&&this.resizeItem(n,this.options.measureElement(s,void 0,this))},this.resizeItem=(s,n)=>{var i,o;if(s<0||s>=this.options.count)return;let r,l,c;const u=this._flatMeasurements;if(this.options.lanes===1&&u!==null)c=this.options.getItemKey(s),l=u[s*2],r=u[s*2+1];else{const h=this.measurementsCache[s];if(!h)return;c=h.key,l=h.start,r=h.size}const a=this.itemSizeCache.get(c)??r,f=n-a;if(f!==0){const h=this.options.anchorTo==="end"&&((i=this.scrollState)==null?void 0:i.behavior)!=="smooth"&&this.getVirtualDistanceFromEnd()<=this.options.scrollEndThreshold,v=h?this.getTotalSize():0,m=((o=this.scrollState)==null?void 0:o.behavior)!=="smooth"&&(this.shouldAdjustScrollPositionOnItemSizeChange!==void 0?this.shouldAdjustScrollPositionOnItemSizeChange(this.measurementsCache[s]??{index:s,key:c,start:l,size:r,end:l+r,lane:0},f,this):l[this.getVirtualIndexes(),this.getMeasurements()],(s,n)=>{const i=[];for(let o=0,r=s.length;othis.options.debug}),this.getVirtualItemForOffset=s=>{const n=this.getMeasurements();if(n.length===0)return;const i=this._flatMeasurements,o=this.options.lanes===1&&i!=null,r=Wr(0,n.length-1,o?l=>i[l*2]:l=>bo(n[l]).start,s);return bo(n[r])},this.getMaxScrollOffset=()=>{if(!this.scrollElement)return 0;if("scrollHeight"in this.scrollElement)return this.options.horizontal?this.scrollElement.scrollWidth-this.scrollElement.clientWidth:this.scrollElement.scrollHeight-this.scrollElement.clientHeight;{const s=this.scrollElement.document.documentElement;return this.options.horizontal?s.scrollWidth-this.scrollElement.innerWidth:s.scrollHeight-this.scrollElement.innerHeight}},this.getVirtualDistanceFromEnd=()=>Math.max(this.getTotalSize()-this.getSize()-this.getScrollOffset(),0),this.getDistanceFromEnd=()=>Math.max(this.getMaxScrollOffset()-this.getScrollOffset(),0),this.isAtEnd=(s=this.options.scrollEndThreshold)=>this.getDistanceFromEnd()<=s,this.getOffsetForAlignment=(s,n,i=0)=>{if(!this.scrollElement)return 0;const o=this.getSize(),r=this.getScrollOffset();n==="auto"&&(n=s>=r+o?"end":"start"),n==="center"?s+=(i-o)/2:n==="end"&&(s-=o);const l=this.getMaxScrollOffset();return Math.max(Math.min(l,s),0)},this.getOffsetForIndex=(s,n="auto")=>{s=Math.max(0,Math.min(s,this.options.count-1));const i=this.getSize(),o=this.getScrollOffset(),r=this.measurementsCache[s];if(!r)return;if(n==="auto")if(r.end>=o+i-this.options.scrollPaddingEnd)n="end";else if(r.start<=o+this.options.scrollPaddingStart)n="start";else return[o,n];if(n==="end"&&s===this.options.count-1)return[this.getMaxScrollOffset(),n];const l=n==="end"?r.end+this.options.scrollPaddingEnd:r.start-this.options.scrollPaddingStart;return[this.getOffsetForAlignment(l,n,r.size),n]},this.scrollToOffset=(s,{align:n="start",behavior:i="auto"}={})=>{const o=this.getOffsetForAlignment(s,n),r=this.now();this.scrollState={index:null,align:n,behavior:i,startedAt:r,lastTargetOffset:o,stableFrames:0},this._scrollToOffset(o,{adjustments:void 0,behavior:i}),this.scheduleScrollReconcile()},this.scrollToIndex=(s,{align:n="auto",behavior:i="auto"}={})=>{s=Math.max(0,Math.min(s,this.options.count-1));const o=this.getOffsetForIndex(s,n);if(!o)return;const[r,l]=o,c=this.now();this.scrollState={index:s,align:l,behavior:i,startedAt:c,lastTargetOffset:r,stableFrames:0},this._scrollToOffset(r,{adjustments:void 0,behavior:i}),this.scheduleScrollReconcile()},this.scrollBy=(s,{behavior:n="auto"}={})=>{const i=this.getScrollOffset()+s,o=this.now();this.scrollState={index:null,align:"start",behavior:n,startedAt:o,lastTargetOffset:i,stableFrames:0},this._scrollToOffset(i,{adjustments:void 0,behavior:n}),this.scheduleScrollReconcile()},this.scrollToEnd=({behavior:s="auto"}={})=>{if(this.options.count>0){this.scrollToIndex(this.options.count-1,{align:"end",behavior:s});return}this.scrollToOffset(Math.max(this.getTotalSize()-this.getSize(),0),{behavior:s})},this.getTotalSize=()=>{var s;const n=this.getMeasurements();let i;if(n.length===0)i=this.options.paddingStart;else if(this.options.lanes===1){const o=n.length-1,r=this._flatMeasurements;r!=null?i=r[o*2]+r[o*2+1]:i=((s=n[o])==null?void 0:s.end)??0}else{const o=Array(this.options.lanes).fill(null);let r=n.length-1;for(;r>=0&&o.some(l=>l===null);){const l=n[r];o[l.lane]===null&&(o[l.lane]=l.end),r--}i=Math.max(...o.filter(l=>l!==null))}return Math.max(i-this.options.scrollMargin+this.options.paddingEnd,0)},this.takeSnapshot=()=>{const s=[];if(this.itemSizeCache.size===0)return s;const n=this.getMeasurements();for(const i of n)i&&this.itemSizeCache.has(i.key)&&s.push({index:i.index,key:i.key,start:i.start,size:i.size,end:i.end,lane:i.lane});return s},this._scrollToOffset=(s,{adjustments:n,behavior:i})=>{this._intendedScrollOffset=s+(n??0),this.options.scrollToFn(s,{behavior:i,adjustments:n},this)},this.measure=()=>{this.pendingMin=null,this.itemSizeCache.clear(),this.laneAssignments.clear(),this.itemSizeCacheVersion++,this.notify(!1)},this.setOptions(t)}applyScrollAdjustment(t,s){t!==0&&(kn()&&(this.isScrolling||this._iosTouching||this._iosJustTouchEnded)?this._iosDeferredAdjustment+=t:this._scrollToOffset(this.getScrollOffset(),{adjustments:this.scrollAdjustments+=t,behavior:s}))}scheduleScrollReconcile(){if(!this.targetWindow){this.scrollState=null;return}this.rafId==null&&(this.rafId=this.targetWindow.requestAnimationFrame(()=>{this.rafId=null,this.reconcileScroll()}))}reconcileScroll(){if(!this.scrollState||!this.scrollElement)return;if(this.now()-this.scrollState.startedAt>5e3){this.scrollState=null;return}const n=this.scrollState.index!=null?this.getOffsetForIndex(this.scrollState.index,this.scrollState.align):void 0,i=n?n[0]:this.scrollState.lastTargetOffset,o=1,r=i!==this.scrollState.lastTargetOffset;if(!r&&za(i,this.getScrollOffset())){if(this.scrollState.stableFrames++,this.scrollState.stableFrames>=o){this.getScrollOffset()!==i&&this._scrollToOffset(i,{adjustments:void 0,behavior:"auto"}),this.scrollState=null;return}}else if(this.scrollState.stableFrames=0,r){const l=this.getSize()||600,c=Math.abs(i-this.getScrollOffset()),u=this.scrollState.behavior==="smooth"&&c>l;this.scrollState.lastTargetOffset=i,u||(this.scrollState.behavior="auto"),this._scrollToOffset(i,{adjustments:void 0,behavior:u?"smooth":"auto"})}this.scheduleScrollReconcile()}}const Wr=(e,t,s,n)=>{for(;e<=t;){const i=(e+t)/2|0,o=s(i);if(on)t=i-1;else return i}return e>0?e-1:0};function Za({measurements:e,outerSize:t,scrollOffset:s,lanes:n,flat:i}){const o=e.length-1,r=i?a=>i[a*2]:a=>e[a].start,l=i?a=>i[a*2]+i[a*2+1]:a=>e[a].end;if(e.length<=n)return{startIndex:0,endIndex:o};let c=Wr(0,o,r,s),u=c;if(n===1)for(;u1){const a=Array(n).fill(0);for(;uh=0&&f.some(h=>h>=s);){const h=e[c];f[h.lane]=h.start,c--}c=Math.max(0,c-c%n),u=Math.min(o,u+(n-1-u%n))}return{startIndex:c,endIndex:u}}function eu(e){const t=new Qa(C(e)),s=Il(t),n=t._didMount();return $t(()=>C(e).getScrollElement(),i=>{i&&t._willUpdate()},{immediate:!0}),$t(()=>C(e),i=>{t.setOptions({...i,onChange:(o,r)=>{var l;Ri(s),(l=i.onChange)==null||l.call(i,o,r)}}),t._willUpdate(),Ri(s)},{immediate:!0}),al(n),s}function Kr(e){return eu(tt(()=>({observeElementRect:Ka,observeElementOffset:qa,scrollToFn:Xa,...C(e)})))}const tu={key:0,class:"empty-state"},su=["onClick"],nu=["src"],iu={class:"pinfo"},ou={class:"pname"},ru={class:"pmeta"},lu={class:"chip chip-score"},cu=Me({__name:"ProductList",setup(e){const{filteredProducts:t,selectedProductId:s,selectProduct:n,searchQuery:i}=Ft(),o=U(null),r=Kr(tt(()=>({count:t.value.length,getScrollElement:()=>o.value,estimateSize:()=>58,overscan:5}))),l=(c,u)=>{n(c,u)};return(c,u)=>(V(),H("div",{ref_key:"parentRef",ref:o,class:"product-list"},[C(t).length===0?(V(),H("div",tu,W(C(i)?`没有匹配"${C(i)}"的商品`:"点击「刷新商品」获取列表"),1)):(V(),H("div",{key:1,class:"product-list-inner",style:Bt({height:`${C(r).getTotalSize()}px`,position:"relative"})},[(V(!0),H(ce,null,bs(C(r).getVirtualItems(),a=>{var f;return V(),H("div",{key:String(a.key),class:_e(["prod-item",{active:C(s)===((f=C(t)[a.index])==null?void 0:f.commodityId)}]),style:Bt({position:"absolute",top:0,left:0,width:"100%",height:`${a.size}px`,transform:`translateY(${a.start}px)`}),onClick:h=>l(C(t)[a.index].commodityId,C(t)[a.index].commodityName)},[g("img",{src:C(t)[a.index].pic,onError:u[0]||(u[0]=h=>h.target.style.display="none")},null,40,nu),g("div",iu,[g("div",ou,W(C(t)[a.index].commodityName),1),g("div",ru,[g("span",lu,W(C(t)[a.index].score)+" 积分",1),g("span",{class:_e(["chip chip-stock",{low:C(t)[a.index].count<500}])}," 库存 "+W(C(t)[a.index].count),3)])])],14,su)}),128))],4))],512))}}),au=De(cu,[["__scopeId","data-v-a05105ef"]]),uu={class:"selected-product-name"},fu={class:"selected-product-meta"},du={class:"chip chip-score"},hu={key:1,class:"chip"},pu={key:2,class:"chip"},gu=Me({__name:"ProductCard",setup(e){const{selectedProductId:t,selectedProductName:s,selectedProduct:n}=Ft();return(i,o)=>(V(),H("div",{class:_e(["selected-product-card",{"has-product":C(t)}])},[o[0]||(o[0]=g("div",{class:"selected-product-label"},"当前商品",-1)),g("div",uu,W(C(s)||"未选"),1),g("div",fu,[C(n)?(V(),H(ce,{key:0},[g("span",du,W(C(n).score)+" 积分",1),g("span",{class:_e(["chip chip-stock",{low:C(n).count<500}])}," 库存 "+W(C(n).count),3)],64)):C(t)?(V(),H("span",hu,"等待刷新")):(V(),H("span",pu,"未绑定任务"))])],2))}}),mu=De(gu,[["__scopeId","data-v-b1ab3b9f"]]),vu={class:"left"},_u={class:"brand"},bu={class:"stat-pill"},yu={class:"left-header"},Su={class:"product-actions"},xu=["disabled"],wu=Me({__name:"LeftSidebar",props:{version:{}},setup(e){const{loadProducts:t,productInfo:s,filteredProducts:n,loading:i}=Ft();return(o,r)=>{var l,c;return V(),H("aside",vu,[g("div",_u,[r[1]||(r[1]=g("div",null,[g("h1",null,"斗鱼抢购"),g("div",{class:"brand-sub"},"实时库存 · 多账号 · 定时触发")],-1)),g("span",bu,"v"+W(e.version),1)]),g("div",yu,[g("div",Su,[g("button",{class:"btn btn-primary",disabled:C(i),onClick:r[0]||(r[0]=u=>C(t)(!0))},W(C(i)?"刷新中...":"刷新商品"),9,xu)]),se(ja),se(mu),g("div",{class:_e(["product-meta",{good:C(s)&&!C(s).stale,warn:(l=C(s))==null?void 0:l.stale}])},[(c=C(s))!=null&&c.fetchedAt?(V(),H(ce,{key:0},[ve(" 实时库存 "+W(C(n).length)+" 个,刷新于 "+W(C(s).fetchedAt),1)],64)):(V(),H(ce,{key:1},[ve("库存未刷新")],64))],2)]),se(au)])}}}),Tu=De(wu,[["__scopeId","data-v-5a20b760"]]),Cu={class:"status-grid"},Eu={class:"metric"},Au={class:"metric-value server"},Iu={class:"metric"},Mu={class:"metric-value"},Ou={class:"metric"},$u={class:"metric-value success-num"},Pu={class:"metric"},Ru={class:"metric-value fail-num"},Lu={class:"metric"},Fu={class:"metric-value"},Du=Me({__name:"StatusGrid",props:{serverTime:{}},setup(e){const{accounts:t,selectedIndices:s,statusMap:n}=Jt(),i=tt(()=>{const o=[...s.value].map(c=>{var u;return(u=t.value[c])==null?void 0:u.name}).filter(Boolean);let r=0,l=0;for(const c of o){const u=n.value[c];u===!0||u&&typeof u=="object"&&u.ok?r++:(u===!1||u&&typeof u=="object"&&u.message)&&l++}return{selected:o.length,total:t.value.length,success:r,fail:l,pending:Math.max(0,o.length-r-l)}});return(o,r)=>(V(),H("div",Cu,[g("div",Eu,[r[0]||(r[0]=g("span",{class:"metric-label"},"服务器",-1)),g("span",Au,W(e.serverTime),1)]),g("div",Iu,[r[2]||(r[2]=g("span",{class:"metric-label"},"账号",-1)),g("span",Mu,[g("span",null,W(i.value.selected),1),r[1]||(r[1]=ve("/",-1)),g("span",null,W(i.value.total),1)])]),g("div",Ou,[r[3]||(r[3]=g("span",{class:"metric-label"},"成功",-1)),g("span",$u,W(i.value.success),1)]),g("div",Pu,[r[4]||(r[4]=g("span",{class:"metric-label"},"异常",-1)),g("span",Ru,W(i.value.fail),1)]),g("div",Lu,[r[5]||(r[5]=g("span",{class:"metric-label"},"待处理",-1)),g("span",Fu,W(i.value.pending),1)])]))}}),ku=De(Du,[["__scopeId","data-v-9217deda"]]),Nu={class:"control-strip"},ju={class:"action-group"},Vu={class:"schedule-bar"},zu={class:"schedule-item"},Hu={class:"schedule-item"},Bu=Me({__name:"ControlStrip",setup(e){const{scheduleActive:t,startNow:s,startSchedule:n,cancelSchedule:i,restoreSchedule:o}=wi(),{reloadAccounts:r,queryAllScore:l}=Jt(),{savedTime:c,savedAdv:u}=o(),a=U(c||"18:00:00"),f=U(u),h=()=>{n(a.value,f.value)};return(v,m)=>(V(),H("div",Nu,[g("div",ju,[g("button",{class:"btn btn-danger",onClick:m[0]||(m[0]=(..._)=>C(s)&&C(s)(..._))},"立即抢购"),C(t)?(V(),H("button",{key:1,class:"btn btn-cancel",onClick:m[1]||(m[1]=(..._)=>C(i)&&C(i)(..._))}," 停止定时 ")):(V(),H("button",{key:0,class:"btn btn-success",onClick:h}," 开启定时 ")),g("button",{class:"btn",onClick:m[2]||(m[2]=(..._)=>C(r)&&C(r)(..._))},"加载账号"),g("button",{class:"btn",onClick:m[3]||(m[3]=(..._)=>C(l)&&C(l)(..._))},"查询积分")]),g("div",Vu,[g("div",zu,[m[6]||(m[6]=g("label",null,"目标",-1)),Pe(g("input",{"onUpdate:modelValue":m[4]||(m[4]=_=>a.value=_),type:"time",step:"1"},null,512),[[It,a.value]])]),g("div",Hu,[m[7]||(m[7]=g("label",null,"提前",-1)),Pe(g("input",{"onUpdate:modelValue":m[5]||(m[5]=_=>f.value=_),type:"number",min:"0",max:"5000",step:"100"},null,512),[[It,f.value,void 0,{number:!0}]]),m[8]||(m[8]=g("span",{style:{color:"var(--muted)","font-size":"11.5px"}},"ms",-1))])])]))}}),Wu=De(Bu,[["__scopeId","data-v-81e7b618"]]),Ku={class:"panel"},Uu={class:"panel-head"},Gu={class:"panel-sub"},qu={class:"stat-pill"},Ju=["checked"],Yu={key:0},Xu={class:"select-cell"},Qu=["onClick"],Zu={key:0},ef={class:"account-name"},tf={class:"account-sub"},sf={key:0,class:"status-badge status-success"},nf={key:1,class:"status-badge status-fail"},of={key:0,class:"prod-tag"},rf={key:1},lf={class:"status-td"},cf=["title"],af=Me({__name:"AccountTable",setup(e){const{accounts:t,selectedIndices:s,statusMap:n,toggleAccount:i,toggleAll:o,getScore:r}=Jt(),{selectedProductName:l}=Ft(),c=U(null),u=tt(()=>t.value.length>0&&s.value.size===t.value.length),a=Kr(tt(()=>({count:t.value.length,getScrollElement:()=>c.value,estimateSize:()=>48,overscan:5}))),f=(v,m)=>{const _=n.value[v];if(_===!0)return{text:"成功",cls:"status-success"};if(_===!1)return{text:"失败",cls:"status-fail"};if(_&&typeof _=="object"){const I=_;if(I.ok)return{text:"成功",cls:"status-success"};const $=String(I.message||"");return $.includes("库存已耗完")?{text:"库存耗尽",cls:"status-warn"}:$.includes("兑换上限")?{text:"已达上限",cls:"status-warn"}:$.includes("未绑定")?{text:"未绑定",cls:"status-fail"}:$.includes("精英手册")?{text:"资格不足",cls:"status-fail"}:{text:m?"未命中":"失败",cls:m?"status-warn":"status-fail"}}return m?{text:"待命",cls:"status-ready"}:{text:"未选择",cls:"status-idle"}},h=v=>{const m=n.value[v];let _="";return m&&typeof m=="object"?_=m.message||"":m===!0?_="成功":m===!1&&(_="失败"),_?_.length>46?_.slice(0,46)+"...":_:"-"};return(v,m)=>(V(),H("div",Ku,[g("div",Uu,[g("div",null,[m[1]||(m[1]=g("span",{class:"panel-title"},"账号作战表",-1)),g("span",Gu,W(C(t).length)+" 个账号,已选 "+W(C(s).size)+" 个",1)]),g("label",qu,[g("input",{type:"checkbox",checked:u.value,onChange:m[0]||(m[0]=(..._)=>C(o)&&C(o)(..._))},null,40,Ju),m[2]||(m[2]=ve(" 全选 ",-1))])]),g("div",{ref_key:"parentRef",ref:c,class:"table-wrap"},[g("table",null,[m[4]||(m[4]=g("thead",null,[g("tr",null,[g("th",{class:"select-cell"}),g("th",null,"账号"),g("th",null,"凭据"),g("th",null,"商品"),g("th",null,"积分"),g("th",{class:"status-col"},"状态"),g("th",null,"最后结果")])],-1)),g("tbody",null,[C(t).length===0?(V(),H("tr",Yu,[...m[3]||(m[3]=[g("td",{colspan:"7",class:"empty-state"},"暂无账号,请加载账号",-1)])])):(V(!0),H(ce,{key:1},bs(C(a).getVirtualItems(),_=>(V(),H("tr",{key:String(_.key),style:Bt({height:`${_.size}px`})},[g("td",Xu,[g("label",{class:"account-check",onClick:I=>C(i)(_.index)},[g("div",{class:_e(["check-box",{checked:C(s).has(_.index)}])},[C(s).has(_.index)?(V(),H("span",Zu,"✓")):Rt("",!0)],2)],8,Qu)]),g("td",null,[g("div",ef,W(C(t)[_.index].name),1),g("div",tf,W(C(s).has(_.index)?"已加入任务":"未选择"),1)]),g("td",null,[C(t)[_.index].cookie?(V(),H("span",sf," 已加载 ")):(V(),H("span",nf,"缺失"))]),g("td",null,[C(l)?(V(),H("span",of,W(C(l)),1)):(V(),H("span",rf,"-"))]),g("td",null,W(C(r)(C(t)[_.index].name)),1),g("td",lf,[g("span",{class:_e(["status-badge",f(C(t)[_.index].name,C(s).has(_.index)).cls])},W(f(C(t)[_.index].name,C(s).has(_.index)).text),3)]),g("td",null,[g("span",{class:"account-sub",title:h(C(t)[_.index].name)},W(h(C(t)[_.index].name)),9,cf)])],4))),128))])])],512)]))}}),uf=De(af,[["__scopeId","data-v-9686f816"]]),ff={class:"panel log-wrap"},df={class:"log-header"},hf={class:"log-tabs"},pf={key:0,class:"log-i"},gf={key:0,class:"log-cat"},mf={class:"log-panel"},vf={key:0,class:"result-empty"},_f={class:"log-panel"},bf={class:"log-result log-s"},yf={class:"log-result log-e"},Sf={class:"log-result log-i"},xf={class:"log-result"},wf=Me({__name:"LogPanel",setup(e){const{logs:t,results:s,clearLogs:n}=Zn(),{accounts:i,selectedIndices:o,statusMap:r}=Jt(),l=U("log"),c=U(null);$t(t,async()=>{await di(),c.value&&(c.value.scrollTop=c.value.scrollHeight)},{deep:!0});const u=tt(()=>{const f=[...o.value].map(m=>{var _;return(_=i.value[m])==null?void 0:_.name}).filter(Boolean);let h=0,v=0;for(const m of f){const _=r.value[m];_===!0||_&&typeof _=="object"&&_.ok?h++:(_===!1||_&&typeof _=="object"&&_.message)&&v++}return{success:h,fail:v,pending:Math.max(0,f.length-h-v),selected:f.length,total:i.value.length}}),a=tt(()=>Object.entries(s.value));return(f,h)=>(V(),H("div",ff,[g("div",df,[g("div",hf,[g("button",{class:_e(["log-tab",{active:l.value==="log"}]),onClick:h[0]||(h[0]=v=>l.value="log")}," 实时日志 ",2),g("button",{class:_e(["log-tab",{active:l.value==="result"}]),onClick:h[1]||(h[1]=v=>l.value="result")}," 抢购结果 ",2),g("button",{class:_e(["log-tab",{active:l.value==="stats"}]),onClick:h[2]||(h[2]=v=>l.value="stats")}," 统计 ",2)]),g("button",{class:"btn btn-compact",onClick:h[3]||(h[3]=(...v)=>C(n)&&C(n)(...v))},"清空")]),Pe(g("div",{ref_key:"logBodyRef",ref:c,class:"log-panel"},[C(t).length===0?(V(),H("div",pf,"[系统] 就绪,等待操作...")):Rt("",!0),(V(!0),H(ce,null,bs(C(t),(v,m)=>(V(),H("div",{key:m,class:_e(`log-${v.type}`)},[v.source==="server"?(V(),H(ce,{key:0},[h[4]||(h[4]=ve(" [后端] ",-1)),v.category?(V(),H("span",gf,W(v.category),1)):Rt("",!0),ve(" "+W(v.message),1)],64)):(V(),H(ce,{key:1},[ve(" ["+W(v.time)+"] "+W(v.message),1)],64))],2))),128))],512),[[En,l.value==="log"]]),Pe(g("div",mf,[a.value.length===0?(V(),H("div",vf,"暂无抢购结果")):(V(),H(ce,{key:1},[h[5]||(h[5]=g("div",{class:"log-i"},"=== 最新结果 ===",-1)),(V(!0),H(ce,null,bs(a.value,([v,m])=>(V(),H("div",{key:v,class:_e(["log-result",m.includes("成功")?"log-s":"log-e"])},[g("b",null,W(v),1),ve(": "+W(m),1)],2))),128))],64))],512),[[En,l.value==="result"]]),Pe(g("div",_f,[g("div",bf,"成功账号: "+W(u.value.success),1),g("div",yf,"异常账号: "+W(u.value.fail),1),g("div",Sf,"待处理账号: "+W(u.value.pending),1),g("div",xf,"已选账号: "+W(u.value.selected)+" / 总账号: "+W(u.value.total),1)],512),[[En,l.value==="stats"]])]))}}),Tf=De(wf,[["__scopeId","data-v-b57afed1"]]),So=window.go.main.App,Nn=U({timeApiUrl:"",traceEnabled:!1,traceMaxBody:0,logLevel:"info",concurrency:80,attempts:1});function Cf(){const{showToast:e}=Es();return{settings:Nn,loadSettings:async()=>{try{const n=await So.GetSettings();Nn.value={timeApiUrl:n.timeApiUrl||"",traceEnabled:!!n.traceEnabled,traceMaxBody:n.traceMaxBody||0,logLevel:n.logLevel||"info",concurrency:n.concurrency||80,attempts:n.attempts||1}}catch(n){e("读取设置失败",n.message,"error")}},saveSettings:async n=>{try{const i=await So.SaveSettings(n);return i.success?(Nn.value={...n},e("设置已保存","配置已生效","success"),!0):(e("保存失败",i.error||"","error"),!1)}catch(i){return e("保存失败",i.message,"error"),!1}}}}const Ef={class:"modal"},Af={class:"modal-body"},If={class:"form-group"},Mf={class:"form-section"},Of={class:"form-group"},$f={class:"toggle-row"},Pf={class:"toggle"},Rf={class:"form-row"},Lf={class:"form-group"},Ff={class:"input-with-unit"},Df={class:"form-group"},kf={class:"form-section"},Nf={class:"form-row"},jf={class:"form-group"},Vf={class:"form-group"},zf=Me({__name:"SettingsModal",setup(e,{expose:t}){const{settings:s,loadSettings:n,saveSettings:i}=Cf(),o=U(!1),r=U({timeApiUrl:"",traceEnabled:!1,traceMaxBody:0,logLevel:"info",concurrency:80,attempts:1}),l=async()=>{await n(),r.value={...s.value},o.value=!0},c=()=>{o.value=!1},u=async()=>{await i(r.value)&&c()};return t({open:l,close:c}),(a,f)=>(V(),Or(Kl,{to:"body"},[se(qc,{name:"modal"},{default:pi(()=>[o.value?(V(),H("div",{key:0,class:"modal-overlay",onClick:Ea(c,["self"])},[g("div",Ef,[g("div",{class:"modal-header"},[f[6]||(f[6]=g("h3",null,"⚙ 设置",-1)),g("button",{class:"modal-close",onClick:c},"×")]),g("div",Af,[g("div",If,[f[7]||(f[7]=g("label",{class:"form-label"},"时间 API 地址",-1)),Pe(g("input",{"onUpdate:modelValue":f[0]||(f[0]=h=>r.value.timeApiUrl=h),class:"form-input",type:"text",placeholder:"留空使用默认地址"},null,512),[[It,r.value.timeApiUrl]]),f[8]||(f[8]=g("div",{class:"form-hint"},"用于获取斗鱼服务端时间,一般不需要修改",-1))]),g("div",Mf,[f[16]||(f[16]=g("div",{class:"form-section-title"},"日志设置",-1)),g("div",Of,[g("div",$f,[f[10]||(f[10]=g("div",null,[g("span",{class:"toggle-label"},"Trace 日志"),g("div",{class:"form-hint"},"开启后会在 logs/ 目录生成 douyu_trace_*.log")],-1)),g("label",Pf,[Pe(g("input",{"onUpdate:modelValue":f[1]||(f[1]=h=>r.value.traceEnabled=h),type:"checkbox"},null,512),[[xa,r.value.traceEnabled]]),f[9]||(f[9]=g("span",{class:"toggle-slider"},null,-1))])])]),g("div",Rf,[g("div",Lf,[f[12]||(f[12]=g("label",{class:"form-label"},"Trace 正文上限",-1)),g("div",Ff,[Pe(g("input",{"onUpdate:modelValue":f[2]||(f[2]=h=>r.value.traceMaxBody=h),class:"form-input",type:"number",min:"0",step:"1024",placeholder:"0"},null,512),[[It,r.value.traceMaxBody,void 0,{number:!0}]]),f[11]||(f[11]=g("span",{class:"input-unit"},"字节",-1))]),f[13]||(f[13]=g("div",{class:"form-hint"},"0 表示不限制",-1))]),g("div",Df,[f[15]||(f[15]=g("label",{class:"form-label"},"日志显示等级",-1)),Pe(g("select",{"onUpdate:modelValue":f[3]||(f[3]=h=>r.value.logLevel=h),class:"form-select"},[...f[14]||(f[14]=[g("option",{value:"debug"},"Debug",-1),g("option",{value:"info"},"Info",-1),g("option",{value:"warn"},"Warn",-1),g("option",{value:"error"},"Error",-1)])],512),[[wa,r.value.logLevel]])])])]),g("div",kf,[f[21]||(f[21]=g("div",{class:"form-section-title"},"抢购设置",-1)),g("div",Nf,[g("div",jf,[f[17]||(f[17]=g("label",{class:"form-label"},"并发数",-1)),Pe(g("input",{"onUpdate:modelValue":f[4]||(f[4]=h=>r.value.concurrency=h),class:"form-input",type:"number",min:"1",max:"500",step:"10"},null,512),[[It,r.value.concurrency,void 0,{number:!0}]]),f[18]||(f[18]=g("div",{class:"form-hint"},"同时发起的请求数量,建议 50-200",-1))]),g("div",Vf,[f[19]||(f[19]=g("label",{class:"form-label"},"尝试包数",-1)),Pe(g("input",{"onUpdate:modelValue":f[5]||(f[5]=h=>r.value.attempts=h),class:"form-input",type:"number",min:"1",max:"10",step:"1"},null,512),[[It,r.value.attempts,void 0,{number:!0}]]),f[20]||(f[20]=g("div",{class:"form-hint"},"每个账号生成几个抢购包,轮询使用",-1))])]),f[22]||(f[22]=g("div",{class:"info-card"},[g("div",{class:"info-title"},"💡 抢购策略说明"),g("ul",{class:"info-list"},[g("li",null,[ve("抢购窗口:"),g("strong",null,"75 秒"),ve(",自动循环重试")]),g("li",null,"前 8 秒高频(180ms),之后逐渐降速"),g("li",null,"尝试包数 > 1 时,每轮使用不同的包")])],-1)),f[23]||(f[23]=g("div",{class:"info-card info-card-warn"},[g("div",{class:"info-title"},"⚠️ 自动停止条件"),g("ul",{class:"info-list"},[g("li",null,[g("strong",null,"成功"),ve(" - 抢到商品")]),g("li",null,[g("strong",null,"库存耗尽"),ve(" - 商品本次活动库存已耗完")]),g("li",null,[g("strong",null,"兑换上限"),ve(" - 该账号已达本次活动兑换上限")]),g("li",null,[g("strong",null,"未绑定"),ve(" - 账号未绑定角色")]),g("li",null,[g("strong",null,"资格不足"),ve(" - 需要开通精英手册")]),g("li",null,[g("strong",null,"超时"),ve(" - 75秒抢购窗口结束")])])],-1))])]),g("div",{class:"modal-footer"},[g("button",{class:"btn btn-ghost",onClick:c},"取消"),g("button",{class:"btn btn-primary",onClick:u},"保存")])])])):Rt("",!0)]),_:1})]))}}),Hf=De(zf,[["__scopeId","data-v-6aaf64c9"]]),Bf={class:"right"},Wf={class:"console-head"},Kf={class:"headline"},Uf={class:"headline-meta"},Gf={key:0,class:"countdown-badge"},qf={class:"top-actions"},Jf=["title","aria-label"],Yf={class:"workspace"},Xf={class:"side-stack"},Qf=Me({__name:"RightConsole",props:{serverTime:{}},setup(e){const{theme:t,toggleTheme:s}=Br(),{runState:n,countdownSeconds:i,formatRemain:o}=wi(),r=U(null),l=()=>{var c;(c=r.value)==null||c.open()};return(c,u)=>(V(),H(ce,null,[g("main",Bf,[g("header",Wf,[g("div",Kf,[g("div",null,[u[1]||(u[1]=g("div",{class:"headline-title"},"抢购控制台",-1)),g("div",Uf,W(C(n)),1)]),C(i)>0?(V(),H("span",Gf,W(C(o)(C(i))),1)):Rt("",!0)]),g("div",qf,[g("button",{class:"btn btn-ghost icon-btn",title:"设置","aria-label":"设置",onClick:l},"⚙"),g("button",{class:"btn btn-ghost icon-btn theme-toggle",title:C(t)==="light"?"切换到暗色":"切换到亮色","aria-label":C(t)==="light"?"切换到暗色":"切换到亮色",onClick:u[0]||(u[0]=(...a)=>C(s)&&C(s)(...a))},W(C(t)==="light"?"☀":"☾"),9,Jf)])]),se(ku,{"server-time":e.serverTime},null,8,["server-time"]),se(Wu),g("section",Yf,[se(uf),g("aside",Xf,[se(Tf)])])]),se(Hf,{ref_key:"settingsModalRef",ref:r},null,512)],64))}}),Zf=De(Qf,[["__scopeId","data-v-0e645076"]]),ed={class:"app-shell"},td=Me({__name:"AppShell",props:{version:{},serverTime:{}},setup(e){return(t,s)=>(V(),H("div",ed,[se(Tu,{version:e.version},null,8,["version"]),se(Zf,{"server-time":e.serverTime},null,8,["server-time"])]))}}),sd=De(td,[["__scopeId","data-v-08a2f527"]]),nd=["onClick"],id={class:"toast-title"},od=["innerHTML"],rd=Me({__name:"ToastContainer",setup(e){const{toasts:t,removeToast:s}=Es();return(n,i)=>(V(),H("div",{class:_e(["toast-container",{show:C(t).length>0}])},[se(ma,{name:"toast"},{default:pi(()=>[(V(!0),H(ce,null,bs(C(t),o=>(V(),H("div",{key:o.id,class:_e(["toast",`toast-${o.type}`]),onClick:r=>C(s)(o.id)},[g("div",id,W(o.title),1),g("div",{class:"toast-body",innerHTML:o.body},null,8,od)],10,nd))),128))]),_:1})],2))}}),ld=De(rd,[["__scopeId","data-v-c5ddc5d1"]]),cd=Me({__name:"App",setup(e){const{initTheme:t}=Br(),{loadProducts:s,restoreSelection:n}=Ft(),{loadAccounts:i,restoreSelection:o}=Jt(),{clearLogs:r,fetchServerLogs:l,checkResults:c}=Zn(),{setRunState:u}=wi(),{clearResults:a}=Zn(),f=U(""),h=U("--");let v=null,m=null,_=null;const I=window.go.main.App,$=async()=>{try{const P=await I.GetTime();h.value=P.serverTime||"--"}catch{}},M=()=>{v=window.setInterval($,1e3),m=window.setInterval(l,2e3),_=window.setInterval(c,2e3)},L=()=>{v&&clearInterval(v),m&&clearInterval(m),_&&clearInterval(_)};return mi(async()=>{t(),n(),o(),r(),u("等待操作"),await i(),await s(!1);try{f.value=await I.GetVersion()}catch{}await a(),$(),M(),l()}),vi(()=>{L()}),(P,K)=>(V(),H(ce,null,[se(sd,{version:f.value,"server-time":h.value},null,8,["version","server-time"]),se(ld)],64))}}),Ur=Ma(cd),ad=Ra();Ur.use(ad);Ur.mount("#app"); diff --git a/frontend/dist/index.html b/frontend/dist/index.html new file mode 100644 index 0000000..51b8a64 --- /dev/null +++ b/frontend/dist/index.html @@ -0,0 +1,13 @@ + + + + + + 斗鱼抢购系统 + + + + +
+ + diff --git a/frontend/index.html b/frontend/index.html index f6d8121..87c5b35 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -1,204 +1,12 @@ - - - 斗鱼抢购系统 - + + + 斗鱼抢购系统 - -
- - - -
- - -
-
-
-
-
抢购控制台
-
等待操作
-
- -
-
- - -
-
- -
-
- 服务器 - -- -
-
- 账号 - 0/0 -
-
- 成功 - 0 -
-
- 异常 - 0 -
-
- 待处理 - 0 -
-
- -
-
- - - - - -
-
-
- - -
-
- - - ms -
-
-
- -
-
-
-
- 账号作战表 - 0 个账号 -
- -
-
- - - - - - - - - - - - - -
账号凭据商品积分状态最后结果
-
-
- - -
-
-
- - +
+ diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 0000000..d729d98 --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,1621 @@ +{ + "name": "douyu-go-frontend", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "douyu-go-frontend", + "version": "1.0.0", + "dependencies": { + "@tanstack/vue-virtual": "^3.11.2", + "pinia": "^2.3.0", + "vue": "^3.5.13" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.2.1", + "typescript": "~5.7.0", + "vite": "^6.0.5", + "vue-tsc": "^2.2.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", + "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz", + "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz", + "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz", + "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz", + "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz", + "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz", + "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz", + "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz", + "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz", + "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz", + "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz", + "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz", + "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz", + "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz", + "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz", + "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz", + "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz", + "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz", + "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz", + "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz", + "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz", + "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz", + "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz", + "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz", + "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tanstack/virtual-core": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.17.1.tgz", + "integrity": "sha512-VZyW2Uiml5tmBZwPGrSD3Sz73OxzljQMCmzYHsUTPEuTsERf5xwa+uWb01xEzkz3ZSYTjj8NEb/mKHvgKxyZdA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/vue-virtual": { + "version": "3.13.29", + "resolved": "https://registry.npmjs.org/@tanstack/vue-virtual/-/vue-virtual-3.13.29.tgz", + "integrity": "sha512-MWb9tNHjpar3sP34b8+3A4I5j9akveoPXIYqqp7/ipyWd49a/kso+1S1LqEmAVR/+g/k1WWTJC4ktvdCGWgXYQ==", + "license": "MIT", + "dependencies": { + "@tanstack/virtual-core": "3.17.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "vue": "^2.7.0 || ^3.0.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", + "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.15.tgz", + "integrity": "sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.15" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.15.tgz", + "integrity": "sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.15.tgz", + "integrity": "sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.15", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.39", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.39.tgz", + "integrity": "sha512-16KBTEXAJCpDr0mwlw+AZyhu8iyC7R3S2vBwsI7QnWJU6X3WKc9VKeNEZpiMdZ569qWhz9574L3vV55qRL0Vtw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@vue/shared": "3.5.39", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.39", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.39.tgz", + "integrity": "sha512-oQPigALqYbNxTNPvNgSOe+czwVExfbVF02lz8jP0S3AXJiu3jxYDygNUiqSep4ezzW8XgnubqH63My2A7JR/vg==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.39", + "@vue/shared": "3.5.39" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.39", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.39.tgz", + "integrity": "sha512-d0ki86iOyN8LoZPBmk5SJWNwHP19CnDDCfuo//+2WJa2g5Ke0Jay983PIBIcSSzldC68I8DrD5GrHV3OSDfodg==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@vue/compiler-core": "3.5.39", + "@vue/compiler-dom": "3.5.39", + "@vue/compiler-ssr": "3.5.39", + "@vue/shared": "3.5.39", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.15", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.39", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.39.tgz", + "integrity": "sha512-Ce7/wvwMHai74bdszfXExdazFigYnlF9zgCmEQUcM1j0fOymlouZ7XilTYNo8oUjhlnjYOZbGrcYKuqjz89Ucw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.39", + "@vue/shared": "3.5.39" + } + }, + "node_modules/@vue/compiler-vue2": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", + "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", + "dev": true, + "license": "MIT", + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/@vue/language-core": { + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.2.12.tgz", + "integrity": "sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.15", + "@vue/compiler-dom": "^3.5.0", + "@vue/compiler-vue2": "^2.7.16", + "@vue/shared": "^3.5.0", + "alien-signals": "^1.0.3", + "minimatch": "^9.0.3", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.39", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.39.tgz", + "integrity": "sha512-TpsuBJ9gGlZa5d23XcM2y8EXanz9dZeVDQBXRwzy46ItgvM+rWpzs+UVM0wcRLxGvcav0HE5jz2gNL53xlRAog==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.39" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.39", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.39.tgz", + "integrity": "sha512-9GLtNyRvPAUMbX+7ono0RC2j0guo2LXVi8LvcmAooImACUKm0oFf0jjwbX8/H0AE/t1nxhAkn8RSl9PMCzzxZw==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.39", + "@vue/shared": "3.5.39" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.39", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.39.tgz", + "integrity": "sha512-7Y6aAGboKcXAZ3ECuUy7RrS5yy2r47dhTp2SKaJmYxjopImaVFaNa5Ne66NwGovsrxVAl5S5rwc7m22UG7Lmww==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.39", + "@vue/runtime-core": "3.5.39", + "@vue/shared": "3.5.39", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.39", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.39.tgz", + "integrity": "sha512-yZSakiAGw85rZfG7UM8akMnIF+FmeiNk47uvHf2nVBBSe+dIKUhZuZq9+XgJhbV3nS5Z4ALH23/MpXofW+mbcw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.39", + "@vue/shared": "3.5.39" + }, + "peerDependencies": { + "vue": "3.5.39" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.39", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.39.tgz", + "integrity": "sha512-l1rrBtBfTnmxvtsvdQDXltUUy8S1Y+ZaqdfUzmAnJkTd8Z8rv5v/ytW+TKiqEOWyHPoqtPlNFSs0lhRmYVSHVA==", + "license": "MIT" + }, + "node_modules/alien-signals": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-1.0.13.tgz", + "integrity": "sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.15", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz", + "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pinia": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.3.1.tgz", + "integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.3", + "vue-demi": "^0.14.10" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "typescript": ">=4.4.4", + "vue": "^2.7.0 || ^3.5.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/postcss": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rollup": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz", + "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.62.2", + "@rollup/rollup-android-arm64": "4.62.2", + "@rollup/rollup-darwin-arm64": "4.62.2", + "@rollup/rollup-darwin-x64": "4.62.2", + "@rollup/rollup-freebsd-arm64": "4.62.2", + "@rollup/rollup-freebsd-x64": "4.62.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", + "@rollup/rollup-linux-arm-musleabihf": "4.62.2", + "@rollup/rollup-linux-arm64-gnu": "4.62.2", + "@rollup/rollup-linux-arm64-musl": "4.62.2", + "@rollup/rollup-linux-loong64-gnu": "4.62.2", + "@rollup/rollup-linux-loong64-musl": "4.62.2", + "@rollup/rollup-linux-ppc64-gnu": "4.62.2", + "@rollup/rollup-linux-ppc64-musl": "4.62.2", + "@rollup/rollup-linux-riscv64-gnu": "4.62.2", + "@rollup/rollup-linux-riscv64-musl": "4.62.2", + "@rollup/rollup-linux-s390x-gnu": "4.62.2", + "@rollup/rollup-linux-x64-gnu": "4.62.2", + "@rollup/rollup-linux-x64-musl": "4.62.2", + "@rollup/rollup-openbsd-x64": "4.62.2", + "@rollup/rollup-openharmony-arm64": "4.62.2", + "@rollup/rollup-win32-arm64-msvc": "4.62.2", + "@rollup/rollup-win32-ia32-msvc": "4.62.2", + "@rollup/rollup-win32-x64-gnu": "4.62.2", + "@rollup/rollup-win32-x64-msvc": "4.62.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/typescript": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/vite": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.3.tgz", + "integrity": "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.39", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.39.tgz", + "integrity": "sha512-xmZCYabFGcirU8r0fTuvl/LICc1OU620rnqepaJDL/a141ZigkG7AyaxQLdqJ02ZRYzWe6YPaDHeQx7MfknQfA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.39", + "@vue/compiler-sfc": "3.5.39", + "@vue/runtime-dom": "3.5.39", + "@vue/server-renderer": "3.5.39", + "@vue/shared": "3.5.39" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/vue-tsc": { + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.2.12.tgz", + "integrity": "sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "2.4.15", + "@vue/language-core": "2.2.12" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + } + } +} diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000..85d8a87 --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,23 @@ +{ + "name": "douyu-go-frontend", + "private": true, + "version": "1.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vue-tsc --noEmit && vite build", + "preview": "vite preview", + "type-check": "vue-tsc --noEmit" + }, + "dependencies": { + "vue": "^3.5.13", + "pinia": "^2.3.0", + "@tanstack/vue-virtual": "^3.11.2" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.2.1", + "typescript": "~5.7.0", + "vite": "^6.0.5", + "vue-tsc": "^2.2.0" + } +} diff --git a/frontend/package.json.md5 b/frontend/package.json.md5 new file mode 100755 index 0000000..de351dc --- /dev/null +++ b/frontend/package.json.md5 @@ -0,0 +1 @@ +6ead8f3487bf170694573d8c0420d83c \ No newline at end of file diff --git a/frontend/src/App.vue b/frontend/src/App.vue new file mode 100644 index 0000000..2f9b584 --- /dev/null +++ b/frontend/src/App.vue @@ -0,0 +1,93 @@ + + + + + diff --git a/frontend/src/components/ToastContainer.vue b/frontend/src/components/ToastContainer.vue new file mode 100644 index 0000000..391724b --- /dev/null +++ b/frontend/src/components/ToastContainer.vue @@ -0,0 +1,114 @@ + + + + + diff --git a/frontend/src/components/account/AccountTable.vue b/frontend/src/components/account/AccountTable.vue new file mode 100644 index 0000000..af0db30 --- /dev/null +++ b/frontend/src/components/account/AccountTable.vue @@ -0,0 +1,309 @@ + + + + + diff --git a/frontend/src/components/console/ControlStrip.vue b/frontend/src/components/console/ControlStrip.vue new file mode 100644 index 0000000..359692b --- /dev/null +++ b/frontend/src/components/console/ControlStrip.vue @@ -0,0 +1,141 @@ + + + + + diff --git a/frontend/src/components/console/StatusGrid.vue b/frontend/src/components/console/StatusGrid.vue new file mode 100644 index 0000000..2034b68 --- /dev/null +++ b/frontend/src/components/console/StatusGrid.vue @@ -0,0 +1,115 @@ + + + + + diff --git a/frontend/src/components/layout/AppShell.vue b/frontend/src/components/layout/AppShell.vue new file mode 100644 index 0000000..ba3e31c --- /dev/null +++ b/frontend/src/components/layout/AppShell.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/frontend/src/components/layout/LeftSidebar.vue b/frontend/src/components/layout/LeftSidebar.vue new file mode 100644 index 0000000..863bf81 --- /dev/null +++ b/frontend/src/components/layout/LeftSidebar.vue @@ -0,0 +1,128 @@ + + + + + diff --git a/frontend/src/components/layout/RightConsole.vue b/frontend/src/components/layout/RightConsole.vue new file mode 100644 index 0000000..50bcd78 --- /dev/null +++ b/frontend/src/components/layout/RightConsole.vue @@ -0,0 +1,158 @@ + + + + + diff --git a/frontend/src/components/log/LogPanel.vue b/frontend/src/components/log/LogPanel.vue new file mode 100644 index 0000000..4ee613d --- /dev/null +++ b/frontend/src/components/log/LogPanel.vue @@ -0,0 +1,257 @@ + + + + + diff --git a/frontend/src/components/modal/SettingsModal.vue b/frontend/src/components/modal/SettingsModal.vue new file mode 100644 index 0000000..1ed09aa --- /dev/null +++ b/frontend/src/components/modal/SettingsModal.vue @@ -0,0 +1,445 @@ + + + + + diff --git a/frontend/src/components/product/ProductCard.vue b/frontend/src/components/product/ProductCard.vue new file mode 100644 index 0000000..b0dec0f --- /dev/null +++ b/frontend/src/components/product/ProductCard.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/frontend/src/components/product/ProductList.vue b/frontend/src/components/product/ProductList.vue new file mode 100644 index 0000000..2153a47 --- /dev/null +++ b/frontend/src/components/product/ProductList.vue @@ -0,0 +1,140 @@ + + + + + diff --git a/frontend/src/components/product/ProductSearch.vue b/frontend/src/components/product/ProductSearch.vue new file mode 100644 index 0000000..323b89a --- /dev/null +++ b/frontend/src/components/product/ProductSearch.vue @@ -0,0 +1,100 @@ + + + + + diff --git a/frontend/src/composables/useAccounts.ts b/frontend/src/composables/useAccounts.ts new file mode 100644 index 0000000..37f5189 --- /dev/null +++ b/frontend/src/composables/useAccounts.ts @@ -0,0 +1,155 @@ +import { ref } from 'vue' +import { useToast } from './useToast' + +export interface Account { + index: number + name: string + cookie: string +} + +export interface AccountStatus { + ok?: boolean + message?: string +} + +const App = window.go.main.App + +const accounts = ref([]) +const selectedIndices = ref>(new Set()) +const statusMap = ref>({}) +const scoreMap = ref>({}) + +export function useAccounts() { + const { showToast } = useToast() + + const loadAccounts = async () => { + const data = await App.GetAccounts() + accounts.value = data || [] + + // 清理无效选择 + selectedIndices.value = new Set( + [...selectedIndices.value].filter(i => i >= 0 && i < accounts.value.length) + ) + saveSelection() + } + + const reloadAccounts = async () => { + const data = await App.ReloadAccounts() + await loadAccounts() + showToast('账号已刷新', `共 ${data.count} 个账号`, 'success') + } + + const toggleAccount = (index: number) => { + if (selectedIndices.value.has(index)) { + selectedIndices.value.delete(index) + } else { + selectedIndices.value.add(index) + } + saveSelection() + } + + const toggleAll = () => { + if (selectedIndices.value.size === accounts.value.length) { + selectedIndices.value.clear() + } else { + accounts.value.forEach((_, i) => selectedIndices.value.add(i)) + } + saveSelection() + } + + const saveSelection = () => { + localStorage.setItem('selAccs', JSON.stringify([...selectedIndices.value])) + } + + const restoreSelection = () => { + const saved = localStorage.getItem('selAccs') + if (saved) { + try { + selectedIndices.value = new Set(JSON.parse(saved)) + } catch {} + } + const savedStatus = localStorage.getItem('statusMap') + if (savedStatus) { + try { + statusMap.value = JSON.parse(savedStatus) + } catch {} + } + } + + const queryAllScore = async () => { + showToast('查询积分', '正在并发查询...', 'info') + const tasks = accounts.value.map(async (a) => { + try { + const d = await App.QueryScore(a.name) + const score = d.score ?? 'N/A' + scoreMap.value[a.name] = String(score) + localStorage.setItem('accScore_' + a.name, String(score)) + } catch {} + }) + await Promise.all(tasks) + showToast('积分查询完成', '', 'success') + } + + const getScore = (name: string): string => { + return scoreMap.value[name] || localStorage.getItem('accScore_' + name) || '-' + } + + const resetStatus = () => { + statusMap.value = {} + localStorage.removeItem('statusMap') + } + + const setStatus = (name: string, status: AccountStatus | boolean) => { + statusMap.value[name] = status + localStorage.setItem('statusMap', JSON.stringify(statusMap.value)) + } + + const selectedAccountNames = (): string[] => { + return [...selectedIndices.value] + .map(i => accounts.value[i]?.name) + .filter(Boolean) as string[] + } + + const buildAccountProducts = (productId: string): Record | null => { + if (selectedIndices.value.size === 0) { + showToast('提示', '请勾选要抢购的账号', 'warn') + return null + } + if (!productId) { + showToast('提示', '请先选择商品', 'warn') + return null + } + + const ap: Record = {} + selectedIndices.value.forEach(i => { + const account = accounts.value[i] + if (account) { + ap[account.name] = productId + } + }) + + if (Object.keys(ap).length === 0) { + showToast('提示', '没有有效账号可提交', 'warn') + return null + } + return ap + } + + return { + accounts, + selectedIndices, + statusMap, + scoreMap, + loadAccounts, + reloadAccounts, + toggleAccount, + toggleAll, + restoreSelection, + queryAllScore, + getScore, + resetStatus, + setStatus, + selectedAccountNames, + buildAccountProducts + } +} diff --git a/frontend/src/composables/useLogs.ts b/frontend/src/composables/useLogs.ts new file mode 100644 index 0000000..6b89124 --- /dev/null +++ b/frontend/src/composables/useLogs.ts @@ -0,0 +1,113 @@ +import { ref } from 'vue' + +export interface LogEntry { + id: number + time: string + level: string + category: string + message: string +} + +export interface LogMessage { + time: string + type: 's' | 'e' | 'i' | 'w' | 'd' + message: string + category?: string + source: 'local' | 'server' +} + +const App = window.go.main.App + +const logs = ref([]) +const results = ref>({}) +const lastLogId = ref(0) +const lastResultsJson = ref('') + +export function useLogs() { + const addLocalLog = (message: string, type: LogMessage['type'] = 'i') => { + const now = new Date() + const timeStr = now.toLocaleTimeString() + '.' + String(now.getMilliseconds()).padStart(3, '0') + logs.value.push({ + time: timeStr, + type, + message, + source: 'local' + }) + // 限制日志数量 + if (logs.value.length > 500) { + logs.value = logs.value.slice(-300) + } + } + + const fetchServerLogs = async () => { + try { + const d = await App.GetLogs(lastLogId.value) + if (!d.success || !Array.isArray(d.logs) || d.logs.length === 0) return + + d.logs.forEach((item: LogEntry) => { + lastLogId.value = Math.max(lastLogId.value, item.id || 0) + + let type: LogMessage['type'] = 'i' + if (item.level === 'success') type = 's' + else if (item.level === 'error') type = 'e' + else if (item.level === 'warn') type = 'w' + else if (item.level === 'debug') type = 'd' + + // 清理日志前缀 + const cleanMsg = String(item.message || '').replace(/\[[^\]]+\]\[(info|success|warn|error)\]\s*/i, '') + + logs.value.push({ + time: item.time || '', + type, + message: cleanMsg, + category: item.category, + source: 'server' + }) + }) + + // 限制日志数量 + if (logs.value.length > 500) { + logs.value = logs.value.slice(-300) + } + } catch {} + } + + const checkResults = async () => { + try { + const d = await App.GetResults() + const json = JSON.stringify(d) + + if (json !== lastResultsJson.value && Object.keys(d).length > 0) { + lastResultsJson.value = json + results.value = d + return true + } + return false + } catch { + return false + } + } + + const clearLogs = () => { + logs.value = [] + results.value = {} + lastResultsJson.value = '' + lastLogId.value = 0 + } + + const clearResults = async () => { + await App.ClearResults() + results.value = {} + lastResultsJson.value = '' + } + + return { + logs, + results, + addLocalLog, + fetchServerLogs, + checkResults, + clearLogs, + clearResults + } +} diff --git a/frontend/src/composables/useProducts.ts b/frontend/src/composables/useProducts.ts new file mode 100644 index 0000000..08f2194 --- /dev/null +++ b/frontend/src/composables/useProducts.ts @@ -0,0 +1,126 @@ +import { ref, computed } from 'vue' +import { useToast } from './useToast' + +export interface Product { + commodityId: string + commodityName: string + score: number + count: number + pic: string + status: number + openStatus: number + storeStatus: number + timeLimited: number + countLimited: number + eliteLimited: number +} + +export interface ProductPayload { + success: boolean + source: string + products: Product[] + count: number + fetchedAt: string + ageSecond: number + stale: boolean +} + +const App = window.go.main.App + +const products = ref([]) +const productInfo = ref(null) +const selectedProductId = ref(null) +const selectedProductName = ref('') +const searchQuery = ref('') +const loading = ref(false) + +export function useProducts() { + const { showToast } = useToast() + + const filteredProducts = computed(() => { + const keyword = searchQuery.value.toLowerCase().trim() + if (!keyword) return products.value + return products.value.filter(p => + [p.commodityName, p.commodityId, p.score, p.count].some( + v => String(v ?? '').toLowerCase().includes(keyword) + ) + ) + }) + + const selectedProduct = computed(() => + products.value.find(p => p.commodityId === selectedProductId.value) + ) + + const loadProducts = async (showToastMsg = true) => { + loading.value = true + try { + const data = await App.LoadProducts(true) + products.value = Array.isArray(data.products) ? data.products : [] + productInfo.value = data + + // 如果选中的商品不存在了,清空选择 + if (selectedProductId.value && !products.value.some(p => p.commodityId === selectedProductId.value)) { + clearSelection() + } + + if (showToastMsg) { + showToast('商品已刷新', `共 ${products.value.length} 个`, 'success') + } + } catch (e: any) { + products.value = [] + productInfo.value = null + clearSelection() + showToast('商品刷新失败', e.message, 'error') + } finally { + loading.value = false + } + } + + const selectProduct = (id: string, name: string) => { + selectedProductId.value = id + selectedProductName.value = name + localStorage.setItem('selProd', id) + localStorage.setItem('selProdName', name) + } + + const clearSelection = () => { + selectedProductId.value = null + selectedProductName.value = '' + localStorage.removeItem('selProd') + localStorage.removeItem('selProdName') + } + + const setSearch = (query: string) => { + searchQuery.value = query.trim() + } + + const clearSearch = () => { + searchQuery.value = '' + } + + const restoreSelection = () => { + const savedId = localStorage.getItem('selProd') + const savedName = localStorage.getItem('selProdName') + if (savedId) { + selectedProductId.value = savedId + selectedProductName.value = savedName || '' + } + } + + return { + products, + productInfo, + selectedProductId, + selectedProductName, + selectedProduct, + searchQuery, + filteredProducts, + loading, + loadProducts, + selectProduct, + clearSelection, + setSearch, + clearSearch, + restoreSelection + } +} diff --git a/frontend/src/composables/useScheduler.ts b/frontend/src/composables/useScheduler.ts new file mode 100644 index 0000000..dc54e26 --- /dev/null +++ b/frontend/src/composables/useScheduler.ts @@ -0,0 +1,149 @@ +import { ref } from 'vue' +import { useToast } from './useToast' +import { useAccounts } from './useAccounts' +import { useProducts } from './useProducts' + +const App = window.go.main.App + +const scheduleActive = ref(false) +const countdownSeconds = ref(0) +const countdownTimer = ref(null) +const runState = ref('等待操作') + +export function useScheduler() { + const { showToast } = useToast() + const { resetStatus, buildAccountProducts } = useAccounts() + const { selectedProductId, selectedProductName } = useProducts() + + const setRunState = (text: string) => { + runState.value = text || '等待操作' + } + + const startNow = async () => { + const ap = buildAccountProducts(selectedProductId.value || '') + if (!ap) return + + resetStatus() + setRunState('立即抢购已提交') + showToast('抢购中', `${Object.keys(ap).length} 个账号正在抢购`, 'info', 3000) + + try { + const d = await App.StartSeckill(ap) + setRunState(d.msg || '已提交') + } catch (e: any) { + setRunState('提交失败') + showToast('提交失败', e.message, 'error') + } + } + + const startSchedule = async (targetTime: string, advance: number) => { + const ap = buildAccountProducts(selectedProductId.value || '') + if (!ap) return + + if (!targetTime) { + showToast('提示', '请选择目标时间', 'warn') + return + } + + // 格式化时间 + let timeStr = targetTime + if (timeStr.split(':').length === 2) timeStr += ':00' + + const today = new Intl.DateTimeFormat('zh-CN', { + year: 'numeric', + month: '2-digit', + day: '2-digit' + }).format(new Date()).replace(/\//g, '-') + + const fullTime = today + ' ' + timeStr + + resetStatus() + setRunState('定时配置中') + + try { + const d = await App.SetSchedule({ + accountProducts: ap, + targetTime: fullTime, + advance + }) + + scheduleActive.value = true + localStorage.setItem('targetTime', timeStr) + localStorage.setItem('advance', String(advance)) + + setRunState(`定时已开启,触发 ${d.triggerTime}`) + showToast( + '定时已开启', + `触发时刻: ${d.triggerTime}
剩余时间: ${formatRemain(d.remainSecond)}`, + 'success', + 5000 + ) + startCountdown(d.remainSecond) + } catch (e: any) { + setRunState('定时设置失败') + showToast('定时失败', e.message, 'error') + } + } + + const cancelSchedule = async () => { + try { + await App.CancelSchedule() + } catch {} + + scheduleActive.value = false + localStorage.removeItem('targetTime') + localStorage.removeItem('advance') + stopCountdown() + setRunState('定时已停止') + showToast('定时已停止', '抢购任务已取消', 'warn') + } + + const startCountdown = (sec: number) => { + stopCountdown() + const endTime = Date.now() + sec * 1000 + + countdownTimer.value = window.setInterval(() => { + const remain = Math.max(0, Math.ceil((endTime - Date.now()) / 1000)) + countdownSeconds.value = remain + + if (remain <= 0) { + scheduleActive.value = false + setRunState('定时已触发') + stopCountdown() + } + }, 500) + } + + const stopCountdown = () => { + if (countdownTimer.value) { + clearInterval(countdownTimer.value) + countdownTimer.value = null + } + countdownSeconds.value = 0 + } + + const formatRemain = (sec: number): string => { + const h = Math.floor(sec / 3600) + const m = Math.floor((sec % 3600) / 60) + const s = sec % 60 + return `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}` + } + + const restoreSchedule = () => { + const savedTime = localStorage.getItem('targetTime') + const savedAdv = localStorage.getItem('advance') + return { savedTime, savedAdv: savedAdv ? parseInt(savedAdv) : 300 } + } + + return { + scheduleActive, + countdownSeconds, + runState, + setRunState, + startNow, + startSchedule, + cancelSchedule, + formatRemain, + restoreSchedule + } +} diff --git a/frontend/src/composables/useSettings.ts b/frontend/src/composables/useSettings.ts new file mode 100644 index 0000000..5338c11 --- /dev/null +++ b/frontend/src/composables/useSettings.ts @@ -0,0 +1,65 @@ +import { ref } from 'vue' +import { useToast } from './useToast' + +export interface Settings { + timeApiUrl: string + traceEnabled: boolean + traceMaxBody: number + logLevel: string + concurrency: number + attempts: number +} + +const App = window.go.main.App + +const settings = ref({ + timeApiUrl: '', + traceEnabled: false, + traceMaxBody: 0, + logLevel: 'info', + concurrency: 80, + attempts: 1 +}) + +export function useSettings() { + const { showToast } = useToast() + + const loadSettings = async () => { + try { + const cfg = await App.GetSettings() + settings.value = { + timeApiUrl: cfg.timeApiUrl || '', + traceEnabled: !!cfg.traceEnabled, + traceMaxBody: cfg.traceMaxBody || 0, + logLevel: cfg.logLevel || 'info', + concurrency: cfg.concurrency || 80, + attempts: cfg.attempts || 1 + } + } catch (e: any) { + showToast('读取设置失败', e.message, 'error') + } + } + + const saveSettings = async (newSettings: Settings) => { + try { + const d = await App.SaveSettings(newSettings) + if (d.success) { + settings.value = { ...newSettings } + showToast('设置已保存', '配置已生效', 'success') + return true + } else { + showToast('保存失败', d.error || '', 'error') + return false + } + } catch (e: any) { + showToast('保存失败', e.message, 'error') + return false + } + } + + return { + settings, + loadSettings, + saveSettings + } +} diff --git a/frontend/src/composables/useTheme.ts b/frontend/src/composables/useTheme.ts new file mode 100644 index 0000000..19266b0 --- /dev/null +++ b/frontend/src/composables/useTheme.ts @@ -0,0 +1,29 @@ +import { ref, watch, onMounted } from 'vue' + +export type Theme = 'dark' | 'light' + +const theme = ref('dark') + +export function useTheme() { + const applyTheme = (t: Theme) => { + theme.value = t + document.body.dataset.theme = t + localStorage.setItem('uiTheme', t) + } + + const toggleTheme = () => { + applyTheme(theme.value === 'light' ? 'dark' : 'light') + } + + const initTheme = () => { + const saved = localStorage.getItem('uiTheme') as Theme | null + const prefersLight = window.matchMedia?.('(prefers-color-scheme: light)').matches + applyTheme(saved || (prefersLight ? 'light' : 'dark')) + } + + return { + theme, + toggleTheme, + initTheme + } +} diff --git a/frontend/src/composables/useToast.ts b/frontend/src/composables/useToast.ts new file mode 100644 index 0000000..6aa65ce --- /dev/null +++ b/frontend/src/composables/useToast.ts @@ -0,0 +1,38 @@ +import { ref, reactive } from 'vue' + +export interface Toast { + id: number + title: string + body: string + type: 'success' | 'error' | 'warn' | 'info' + duration: number +} + +const toasts = ref([]) +let nextId = 0 + +export function useToast() { + const showToast = (title: string, body: string, type: Toast['type'] = 'info', duration = 4000) => { + const id = nextId++ + const toast: Toast = { id, title, body, type, duration } + toasts.value.push(toast) + + // 自动移除 + setTimeout(() => { + removeToast(id) + }, duration) + } + + const removeToast = (id: number) => { + const index = toasts.value.findIndex(t => t.id === id) + if (index !== -1) { + toasts.value.splice(index, 1) + } + } + + return { + toasts, + showToast, + removeToast + } +} diff --git a/frontend/src/env.d.ts b/frontend/src/env.d.ts new file mode 100644 index 0000000..cccfe2b --- /dev/null +++ b/frontend/src/env.d.ts @@ -0,0 +1,31 @@ +/// + +declare module '*.vue' { + import type { DefineComponent } from 'vue' + const component: DefineComponent<{}, {}, any> + export default component +} + +// Wails Go 绑定类型声明 +interface Window { + go: { + main: { + App: { + LoadProducts: (refresh: boolean) => Promise + GetAccounts: () => Promise + ReloadAccounts: () => Promise + StartSeckill: (accountProducts: Record) => Promise + SetSchedule: (req: any) => Promise + CancelSchedule: () => Promise + GetResults: () => Promise> + GetLogs: (since: number) => Promise + GetTime: () => Promise + ClearResults: () => Promise + QueryScore: (accountName: string) => Promise + GetVersion: () => Promise + GetSettings: () => Promise + SaveSettings: (cfg: any) => Promise + } + } + } +} diff --git a/frontend/src/main.ts b/frontend/src/main.ts new file mode 100644 index 0000000..764d958 --- /dev/null +++ b/frontend/src/main.ts @@ -0,0 +1,9 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) +const pinia = createPinia() + +app.use(pinia) +app.mount('#app') diff --git a/frontend/src/styles/common.css b/frontend/src/styles/common.css new file mode 100644 index 0000000..faf03dc --- /dev/null +++ b/frontend/src/styles/common.css @@ -0,0 +1,211 @@ +/* ============ 按钮 ============ */ +.btn { + height: 30px; + padding: 0 12px; + border: 1px solid var(--line); + border-radius: var(--radius-sm); + background: var(--surface-2); + color: var(--text); + cursor: pointer; + font-size: 12.5px; + font-weight: 500; + white-space: nowrap; + transition: .12s; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 6px; +} + +.btn:hover { + background: var(--surface-3); + border-color: var(--line-strong); +} + +.btn:focus-visible { + outline: 0; + box-shadow: var(--focus); +} + +.btn:disabled { + opacity: .55; + cursor: not-allowed; +} + +.btn-primary { + background: var(--accent); + border-color: var(--accent); + color: #fff; +} + +.btn-primary:hover { + filter: brightness(1.08); +} + +.btn-danger { + background: var(--danger); + border-color: var(--danger); + color: #fff; +} + +.btn-danger:hover { + filter: brightness(1.08); +} + +.btn-success { + background: var(--success); + border-color: var(--success); + color: #fff; +} + +.btn-success:hover { + filter: brightness(1.08); +} + +.btn-cancel { + background: transparent; + color: var(--danger); + border-color: var(--danger); +} + +.btn-cancel:hover { + background: var(--danger-soft); +} + +.btn-ghost { + background: transparent; + border-color: transparent; + color: var(--muted); +} + +.btn-ghost:hover { + color: var(--text-strong); + background: var(--surface-2); + border-color: var(--line); +} + +.icon-btn { + width: 36px; + height: 36px; + padding: 0; + font-size: 18px; +} + +.btn-compact { + height: 26px; + font-size: 11.5px; + padding: 0 10px; +} + +/* ============ 状态标签 ============ */ +.stat-pill { + display: inline-flex; + align-items: center; + gap: 6px; + height: 24px; + padding: 0 10px; + border: 1px solid var(--line); + border-radius: 999px; + background: var(--surface-2); + color: var(--muted); + font-size: 11.5px; + font-variant-numeric: tabular-nums; +} + +/* ============ 芯片 ============ */ +.chip { + display: inline-flex; + align-items: center; + gap: 3px; + padding: 1px 7px; + border-radius: 999px; + background: var(--surface-3); + font-size: 11px; + font-weight: 500; + white-space: nowrap; + color: var(--muted); +} + +.chip-score { + color: var(--warning); + background: var(--warning-soft); +} + +.chip-stock { + color: var(--success); + background: var(--success-soft); +} + +.chip-stock.low { + color: var(--danger); + background: var(--danger-soft); +} + +/* ============ 状态徽章 ============ */ +.status-badge { + display: inline-flex; + align-items: center; + padding: 2px 8px; + border-radius: 999px; + border: 1px solid var(--line); + background: var(--surface-2); + font-size: 11px; + font-weight: 500; + white-space: nowrap; +} + +.status-idle { + color: var(--muted); +} + +.status-ready { + color: var(--accent); + background: var(--accent-soft); + border-color: var(--accent-border); +} + +.status-success { + color: var(--success); + background: var(--success-soft); + border-color: var(--success); +} + +.status-fail { + color: var(--danger); + background: var(--danger-soft); + border-color: var(--danger); +} + +.status-warn { + color: var(--warning); + background: var(--warning-soft); + border-color: var(--warning); +} + +/* ============ 表单 ============ */ +.form-input, .form-select { + width: 100%; + height: 32px; + padding: 0 10px; + background: var(--field); + color: var(--text-strong); + border: 1px solid var(--line); + border-radius: var(--radius-sm); + font-size: 12.5px; + transition: .15s; +} + +.form-input:focus, .form-select:focus { + outline: 0; + border-color: var(--accent); + box-shadow: var(--focus); +} + +/* ============ 空状态 ============ */ +.empty-state { + text-align: center; + color: var(--muted); + padding: 48px 16px; + font-size: 12px; + line-height: 1.7; +} diff --git a/frontend/src/styles/variables.css b/frontend/src/styles/variables.css new file mode 100644 index 0000000..e956219 --- /dev/null +++ b/frontend/src/styles/variables.css @@ -0,0 +1,108 @@ +/* ============ CSS 变量系统 ============ */ +:root { + color-scheme: dark; + --bg: #0f1419; + --surface: #161b22; + --surface-2: #1c232c; + --surface-3: #232b36; + --field: #0d1117; + --text: #c9d1d9; + --text-strong: #f0f6fc; + --muted: #8b949e; + --muted-2: #6e7681; + --line: #21262d; + --line-strong: #30363d; + --accent: #388bfd; + --accent-soft: rgba(56, 139, 253, .12); + --accent-border: rgba(56, 139, 253, .35); + --danger: #f85149; + --danger-soft: rgba(248, 81, 73, .12); + --success: #3fb950; + --success-soft: rgba(63, 185, 80, .12); + --warning: #d29922; + --warning-soft: rgba(210, 153, 34, .12); + --orange: #f78166; + --orange-soft: rgba(247, 129, 102, .12); + --shadow: 0 1px 0 rgba(0, 0, 0, .04), 0 8px 24px rgba(0, 0, 0, .18); + --radius: 8px; + --radius-sm: 6px; + --focus: 0 0 0 3px rgba(56, 139, 253, .3); +} + +body[data-theme="light"] { + color-scheme: light; + --bg: #f6f8fa; + --surface: #ffffff; + --surface-2: #f6f8fa; + --surface-3: #eaeef2; + --field: #ffffff; + --text: #1f2328; + --text-strong: #0d1117; + --muted: #656d76; + --muted-2: #8c959f; + --line: #d0d7de; + --line-strong: #afb8c1; + --accent: #0969da; + --accent-soft: rgba(9, 105, 218, .08); + --accent-border: rgba(9, 105, 218, .3); + --danger: #cf222e; + --danger-soft: rgba(207, 34, 46, .08); + --success: #1a7f37; + --success-soft: rgba(26, 127, 55, .08); + --warning: #9a6700; + --warning-soft: rgba(154, 103, 0, .1); + --orange: #bc4c00; + --orange-soft: rgba(188, 76, 0, .08); + --shadow: 0 1px 0 rgba(31, 35, 40, .04), 0 8px 24px rgba(140, 149, 159, .15); + --focus: 0 0 0 3px rgba(9, 105, 218, .3); +} + +/* ============ 全局重置 ============ */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html, body { + height: 100vh; + overflow: hidden; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif; + background: var(--bg); + color: var(--text); + font-size: 13px; + line-height: 1.5; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +button, input, select { + font: inherit; + color: inherit; +} + +::selection { + background: var(--accent-soft); + color: var(--text-strong); +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-track { + background: transparent; +} + +::-webkit-scrollbar-thumb { + background: var(--line-strong); + border-radius: 999px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--muted-2); +} diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json new file mode 100644 index 0000000..9d38e6f --- /dev/null +++ b/frontend/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "preserve", + "strict": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noFallthroughCasesInSwitch": true, + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "wailsjs/**/*.ts"] +} diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts new file mode 100644 index 0000000..3f42d84 --- /dev/null +++ b/frontend/vite.config.ts @@ -0,0 +1,20 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import { resolve } from 'path' + +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: { + '@': resolve(__dirname, 'src') + } + }, + build: { + outDir: 'dist', + emptyOutDir: true, + sourcemap: false + }, + server: { + strictPort: true + } +}) diff --git a/frontend_backup/app.js b/frontend_backup/app.js new file mode 100644 index 0000000..9d88824 --- /dev/null +++ b/frontend_backup/app.js @@ -0,0 +1,722 @@ +let accounts=[], products=[], productInfo=null, selProdId=null, selProdName='', selAccs=new Set(); +let productSearch=''; +let scheduleActive=false, countdownTimer=null, lastResults={}; +let lastLogId=0; +let statusMap={}; // ← 加这行 + +// applyTheme 应用亮色/暗色主题,并把选择保存到本地。 +function applyTheme(theme) { + let nextTheme = theme === 'light' ? 'light' : 'dark'; + document.body.dataset.theme = nextTheme; + localStorage.setItem('uiTheme', nextTheme); + let btn = document.getElementById('btnTheme'); + if (btn) { + btn.textContent = nextTheme === 'light' ? '☀' : '☾'; + btn.title = nextTheme === 'light' ? '切换到暗色' : '切换到亮色'; + btn.setAttribute('aria-label', btn.title); + } +} + +// toggleTheme 在亮色和暗色之间切换。 +function toggleTheme() { + applyTheme(document.body.dataset.theme === 'light' ? 'dark' : 'light'); +} + +// init 初始化页面状态:恢复本地缓存、加载账号和商品、启动时间与结果轮询。 +async function init(){ + let savedTheme=localStorage.getItem('uiTheme') || (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'); + applyTheme(savedTheme); + // 恢复缓存的选择 + let savedAccs=localStorage.getItem('selAccs'); + let savedProd=localStorage.getItem('selProd'); + let savedProdName=localStorage.getItem('selProdName'); + let savedTime=localStorage.getItem('targetTime'); + let savedAdv=localStorage.getItem('advance'); + let savedStatus=localStorage.getItem('statusMap'); // ← 提前读取 + let savedProductSearch=localStorage.getItem('productSearch'); + + clearLegacyProductBindings(); + if(savedAccs) selAccs=new Set(JSON.parse(savedAccs)); + if(savedProd){ selProdId=savedProd; selProdName=savedProdName||''; } + if(savedTime) document.getElementById('targetTime').value=savedTime; + if(savedAdv) document.getElementById('advance').value=savedAdv; + if(savedStatus) statusMap=JSON.parse(savedStatus); // ← 提前恢复 + if(savedProductSearch) { + productSearch=savedProductSearch; + document.getElementById('productSearch').value=productSearch; + } + updateSelectedProductCard(); + updateDashboardStats(); + + + await loadAccounts(); + + await loadProducts(false); + + updateTime(); + + clearLog(); // ← 加这行,启动时清空日志区 + + + //localStorage.removeItem('statusMap'); // ← 加这行 + // statusMap={}; // ← 加这行 这两行删除就保存成功失败得状态 + + // 清空后端旧结果 + await App.ClearResults(); + + App.GetVersion().then(v => { document.getElementById('versionTag').textContent = 'v' + v; }).catch(()=>{}); + + setInterval(updateTime,1000); + setInterval(checkResults,2000); + setInterval(fetchServerLogs,2000); + fetchServerLogs(); +} + +// setProductSearch 更新商品搜索词,并即时过滤左侧商品列表。 +function setProductSearch(value) { + productSearch = String(value || '').trim(); + if (productSearch) localStorage.setItem('productSearch', productSearch); + else localStorage.removeItem('productSearch'); + renderProducts(); + renderProductMeta(); +} + +// clearProductSearch 清空商品搜索词。 +function clearProductSearch() { + productSearch = ''; + localStorage.removeItem('productSearch'); + document.getElementById('productSearch').value = ''; + renderProducts(); + renderProductMeta(); +} + +// filteredProducts 根据搜索词过滤商品,支持名称、ID、积分和库存。 +function filteredProducts() { + let keyword = productSearch.toLowerCase(); + if (!keyword) return products; + return products.filter(p => [ + p.commodityName, + p.commodityId, + p.score, + p.count + ].some(v => String(v ?? '').toLowerCase().includes(keyword))); +} + +// updateTime 从后端获取斗鱼服务端时间,并刷新顶部时间展示。 +function updateTime(){ + App.GetTime().then(d=>{ + document.getElementById('svrTime').textContent=d.serverTime||'--'; + }).catch(()=>{}); +} + +// apiJSON 统一处理 Wails 绑定调用,失败时抛出后端返回的错误文案。 +async function apiJSON(fn) { + let data = await fn(); + if (data && data.success === false && data.error) { + throw new Error(data.error); + } + return data; +} + +// Wails 绑定快捷引用 +const App = window.go.main.App; + +// reloadAccounts 通知后端重新读取 user.txt,然后刷新前端账号表格。 +async function reloadAccounts(){ + let d=await App.ReloadAccounts(); + await loadAccounts(); + toast('账号已刷新',`共 ${d.count} 个账号`,'success'); +} + +// queryAllScore 并发查询所有账号积分,并把积分按账号名缓存到 localStorage。 +async function queryAllScore() { + addLog('正在并发查询积分...', 'i'); + let tasks = []; + for (let i = 0; i < accounts.length; i++) { + tasks.push((async (idx) => { + let a = accounts[idx]; + try { + let d = await App.QueryScore(a.name); + let score = (d.score !== undefined && d.score !== null && d.score !== '') ? d.score : 'N/A'; + localStorage.setItem('accScore_' + a.name, score); + let el = document.getElementById('score_' + idx); + if (el) el.textContent = score; + } catch (e) { } + })(i)); + } + await Promise.all(tasks); + addLog('积分查询完成', 's'); + toast('积分查询完成', '', 'success'); +} + + +// ==================== Toast提示 ==================== +// toast 创建右侧滑入提示,按类型控制颜色,并在指定时间后自动移除。 +function toast(title, body, type, duration){ + type=type||'info'; duration=duration||4000; + let container=document.getElementById('toastContainer'); + let div=document.createElement('div'); + div.className='toast toast-'+type; + div.innerHTML=`
${title}
${body}
`; + container.appendChild(div); + // 短延迟回调用于触发 CSS 过渡,让提示从右侧滑入。 + setTimeout(()=>container.classList.add('show'),10); + // 外层回调控制停留时长,内层回调等待淡出动画结束后移除节点。 + setTimeout(()=>{ + div.style.opacity='0'; + div.style.transition='opacity .3s'; + setTimeout(()=>{div.remove();if(container.children.length===0)container.classList.remove('show');},300); + },duration); +} + +// ==================== 商品 ==================== +// loadProducts 从后端实时刷新斗鱼商品;失败时不读取旧缓存,避免库存误判。 +async function loadProducts(showToast = true){ + let btn = document.getElementById('btnLoadProducts'); + let meta = document.getElementById('productMeta'); + btn.disabled = true; + btn.textContent = '刷新中...'; + meta.className = 'product-meta'; + meta.textContent = '正在请求斗鱼商品接口'; + addLog('正在实时刷新商品...','i'); + try{ + let d = await App.LoadProducts(true); + products = Array.isArray(d.products) ? d.products : []; + productInfo = d; + if (selProdId && !products.some(p => p.commodityId === selProdId)) { + clearSelectedProduct(); + } + renderProducts(); + renderProductMeta(); + renderAccounts(); + addLog(`商品刷新完成,共 ${products.length} 个,库存时间 ${d.fetchedAt || '--'}`,'s'); + if (showToast) toast('商品已刷新',`共 ${products.length} 个,库存时间 ${d.fetchedAt || '--'}`,'success'); + }catch(e){ + products = []; + productInfo = null; + clearSelectedProduct(); + renderProducts(); + renderProductMeta(e.message); + addLog('商品刷新失败: ' + e.message,'e'); + toast('商品刷新失败', e.message || '请检查网络连接','error'); + }finally{ + btn.disabled = false; + btn.textContent = '刷新商品'; + } +} +// renderProducts 根据当前商品数组绘制左侧商品列表,并标记已选商品。 +function renderProducts(){ + let h=''; + let list = filteredProducts(); + document.getElementById('btnClearProductSearch').style.display = productSearch ? 'block' : 'none'; + // 遍历商品缓存,生成每个商品的点击项和库存、积分信息。 + list.forEach(p=>{ + h+=`
+ +
${escHtml(p.commodityName)}
+
${p.score} 积分库存 ${p.count}
+
`; + }); + let emptyText = productSearch ? `没有匹配“${escHtml(productSearch)}”的商品` : '暂无实时商品数据'; + document.getElementById('prodList').innerHTML=h||`
${emptyText}
`; + updateSelectedProductCard(); +} +// renderProductMeta 显示库存来源和刷新时间,避免把旧库存当实时库存。 +function renderProductMeta(errorMsg) { + let meta = document.getElementById('productMeta'); + if (errorMsg) { + meta.className = 'product-meta warn'; + meta.textContent = '刷新失败,未使用旧库存'; + return; + } + if (!productInfo || !productInfo.fetchedAt) { + meta.className = 'product-meta'; + meta.textContent = '库存未刷新'; + return; + } + meta.className = 'product-meta ' + (productInfo.stale ? 'warn' : 'good'); + if (productSearch) { + meta.textContent = `实时库存 ${filteredProducts().length}/${productInfo.count} 个,刷新于 ${productInfo.fetchedAt}`; + } else { + meta.textContent = `实时库存 ${productInfo.count} 个,刷新于 ${productInfo.fetchedAt}`; + } +} + +// selProduct 记录当前选择的商品,提交时会应用到所有已勾选账号。 +function selProduct(id, name) { + selProdId = id; + selProdName = name; + localStorage.setItem('selProd', id); + localStorage.setItem('selProdName', name); + renderProducts(); + renderAccounts(); + updateSelectedProductCard(); + updateDashboardStats(); +} + +// clearSelectedProduct 清理已经不存在的商品选择。 +function clearSelectedProduct() { + selProdId = null; + selProdName = ''; + localStorage.removeItem('selProd'); + localStorage.removeItem('selProdName'); + updateSelectedProductCard(); + updateDashboardStats(); +} + +// ==================== 账号 ==================== + +// loadAccounts 从后端获取账号列表,清理无效本地缓存后重新渲染账号表格。 +async function loadAccounts() { + accounts = await App.GetAccounts(); + selAccs = new Set([...selAccs].filter(i => i >= 0 && i < accounts.length)); + localStorage.setItem('selAccs', JSON.stringify([...selAccs])); + + // map 回调抽取账号名,用于判断 localStorage 中的旧积分缓存是否仍然有效。 + let validNames = new Set(accounts.map(a => a.name)); + + for (let key in localStorage) { + // 只清理积分缓存,商品选择改为全局当前商品。 + if (key.startsWith('accScore_')) { + let name = key.substring(key.indexOf('_') + 1); + if (!validNames.has(name)) { + localStorage.removeItem(key); + } + } + } + renderAccounts(); +} + + +// renderAccounts 根据账号、选择状态、商品绑定、积分和抢购结果绘制账号表格。 +function renderAccounts() { + document.getElementById('accCnt').textContent = accounts.length; + document.getElementById('selectedCnt').textContent = selAccs.size; + document.getElementById('accountPanelSub').textContent = `${accounts.length} 个账号,已选 ${selAccs.size} 个`; + let chkAll = document.getElementById('chkAll'); + if (chkAll) chkAll.checked = accounts.length > 0 && selAccs.size === accounts.length; + // 将账号数组映射为表格行 HTML,行内状态从 localStorage 和 statusMap 读取。 + let h = accounts.map((a, i) => { + let isSel = selAccs.has(i); + // 商品列展示当前选中商品,提交时会应用到所有勾选账号。 + let prodTag = selProdName ? `${escHtml(selProdName)}` : '-'; + let scoreVal = localStorage.getItem('accScore_' + a.name) || '-'; // ← 改成 a.name + let st = statusMap[a.name]; // ← 已经是 a.name,保持 + let status = statusInfo(st, isSel); + let credential = a.cookie ? '已加载' : '缺失'; + let lastMessage = resultMessage(st); + return ` + + + + + ${credential} + ${prodTag} + ${scoreVal} + ${status.text} + ${lastMessage} + `; + }); + document.getElementById('accTable').innerHTML = h.join(''); + updateDashboardStats(); +} + + +// toggleAll 根据表头复选框批量选择或取消所有账号,并持久化选择结果。 +function toggleAll(){ + let ck=document.getElementById('chkAll').checked; + // 批量选择时的回调把每个账号下标加入选择集合。 + if(ck) accounts.forEach((_,i)=>selAccs.add(i)); + else selAccs.clear(); + + localStorage.setItem('selAccs',JSON.stringify([...selAccs])); + + renderAccounts(); + updateDashboardStats(); +} +// togAcc 切换单个账号的选择状态,并同步更新 localStorage。 +function togAcc(i){ + if(selAccs.has(i)) selAccs.delete(i); else selAccs.add(i); + localStorage.setItem('selAccs',JSON.stringify([...selAccs])); + renderAccounts(); + updateDashboardStats(); +} + +// ==================== 立即抢购(不弹窗) ==================== +// startNow 构建账号商品映射后,调用后端立即启动抢购。 +async function startNow(){ + let ap=buildAP(); + if(!ap) return; + resetRunResults(); + setRunState('立即抢购已提交'); + addLog(`立即抢购: ${Object.keys(ap).length}个账号 → ${selProdName}`,'i'); + toast('抢购中',`${Object.keys(ap).length} 个账号正在抢购 ${selProdName}`,'info',3000); + try { + let d=await App.StartSeckill(ap); + addLog(d.msg||'已提交','i'); + } catch(e) { + setRunState('提交失败'); + addLog('提交失败: '+e.message,'e'); + toast('提交失败',e.message,'error'); + } +} + +// ==================== 定时抢购 ==================== +// startSchedule 构建定时参数并提交给后端,由后端按服务端时间安排抢购。 +async function startSchedule(){ + let ap=buildAP(); + if(!ap) return; + resetRunResults(); + let timeStr=document.getElementById('targetTime').value.trim(); + if(!timeStr){ toast('提示','请选择目标时间','warn'); return; } + if(timeStr.split(':').length===2) timeStr+=':00'; + let today=new Intl.DateTimeFormat('zh-CN',{year:'numeric',month:'2-digit',day:'2-digit'}) + .format(new Date()).replace(/\//g,'-'); + let fullTime=today+' '+timeStr; + let adv=parseInt(document.getElementById('advance').value)||300; + + setRunState('定时配置中'); + addLog(`设置定时: ${fullTime}, 提前=${adv}ms`,'i'); + try { + let d=await App.SetSchedule({accountProducts:ap,targetTime:fullTime,advance:adv}); + scheduleActive=true; + // 保存定时信息 + localStorage.setItem('targetTime',timeStr); + localStorage.setItem('advance',adv); + + // 锁定:关闭自动,固定当前值 + document.getElementById('btnSchedule').style.display='none'; + document.getElementById('btnCancel').style.display='inline-block'; + setRunState(`定时已开启,触发 ${d.triggerTime}`); + addLog(`定时已开启: 触发 ${d.triggerTime},剩余 ${d.remainSecond} 秒`,'s'); + toast('定时已开启',`触发时刻: ${d.triggerTime}
剩余时间: ${formatRemain(d.remainSecond)}
商品: ${selProdName}
账号: ${Object.keys(ap).length} 个`,'success',5000); + startCountdown(d.remainSecond); + } catch(e) { + setRunState('定时设置失败'); + addLog('设置失败: '+e.message,'e'); + toast('定时失败',e.message,'error'); + } +} +// cancelSchedule 调用后端取消尚未触发的定时任务,并恢复前端按钮状态。 +async function cancelSchedule(){ + try{ + await App.CancelSchedule(); + }catch(e){} + scheduleActive=false; + // 清除缓存的定时 + localStorage.removeItem('targetTime'); + localStorage.removeItem('advance'); + + // 恢复自动 + document.getElementById('btnSchedule').style.display='inline-block'; + document.getElementById('btnCancel').style.display='none'; + stopCountdown(); + setRunState('定时已停止'); + addLog('定时已手动停止','w'); + toast('定时已停止','抢购任务已取消','warn'); +} + +// startCountdown 启动前端倒计时徽标,用后端返回的剩余秒数做展示。 +function startCountdown(sec) { + stopCountdown(); + let badge = document.getElementById('cdBadge'); + badge.style.display = 'inline-block'; + let startTime = Date.now(); + let endTime = startTime + sec * 1000; + + // 每 500ms 刷新一次显示,确保用户能看到接近触发时的状态变化。 + countdownTimer = setInterval(() => { + let now = Date.now(); + let remain = Math.max(0, Math.ceil((endTime - now) / 1000)); + if (remain <= 0) { + badge.textContent = '触发中'; + clearInterval(countdownTimer); + countdownTimer = null; + scheduleActive = false; + document.getElementById('btnSchedule').style.display = 'inline-block'; + document.getElementById('btnCancel').style.display = 'none'; + setRunState('定时已触发'); + // 延迟回调让“触发中”状态短暂停留,避免用户看不到最终状态。 + setTimeout(() => badge.style.display = 'none', 5000); + } else { + badge.textContent = formatRemain(remain); + } + }, 500); +} + + +// stopCountdown 停止倒计时定时器,并隐藏倒计时徽标。 +function stopCountdown(){ + clearInterval(countdownTimer); + document.getElementById('cdBadge').style.display='none'; +} +// formatRemain 把秒数格式化为 h:mm:ss,供定时提示和倒计时徽标使用。 +function formatRemain(sec){ + let h=Math.floor(sec/3600),m=Math.floor((sec%3600)/60),s=sec%60; + return `${h}:${String(m).padStart(2,'0')}:${String(s).padStart(2,'0')}`; +} + +// setRunState 更新顶部运行状态。 +function setRunState(text) { + let el = document.getElementById('runStateText'); + if (el) el.textContent = text || '等待操作'; +} + +// switchLogTab 切换右侧日志/结果/统计面板。 +function switchLogTab(id) { + document.querySelectorAll('.log-tab').forEach(btn => btn.classList.toggle('active', btn.dataset.logTab === id)); + document.querySelectorAll('.log-panel').forEach(panel => panel.classList.toggle('active', panel.id === id)); +} + +// updateSelectedProductCard 刷新左侧当前商品卡片。 +function updateSelectedProductCard() { + let card = document.getElementById('selectedProductCard'); + let nameEl = document.getElementById('selectedProductName'); + let metaEl = document.getElementById('selectedProductMeta'); + if (!nameEl || !metaEl) return; + let product = products.find(p => p.commodityId === selProdId); + nameEl.textContent = selProdName || '未选'; + if (card) card.classList.toggle('has-product', !!selProdId); + if (!product) { + metaEl.innerHTML = selProdId ? '等待刷新' : '未绑定任务'; + return; + } + metaEl.innerHTML = `${product.score} 积分库存 ${product.count}`; +} + +// statusInfo 将后端结果转换为账号状态标签。 +function statusInfo(st, selected) { + if (st === true) return {text:'成功', cls:'status-success'}; + if (st === false) return {text:'失败', cls:'status-fail'}; + if (st && typeof st === 'object') { + if (st.ok) return {text:'成功', cls:'status-success'}; + let msg = String(st.message || ''); + if (msg.includes('库存已耗完')) return {text:'库存耗尽', cls:'status-warn'}; + if (msg.includes('兑换上限')) return {text:'已达上限', cls:'status-warn'}; + if (msg.includes('未绑定')) return {text:'未绑定', cls:'status-fail'}; + if (msg.includes('精英手册')) return {text:'资格不足', cls:'status-fail'}; + return {text:selected ? '未命中' : '失败', cls:selected ? 'status-warn' : 'status-fail'}; + } + return selected ? {text:'待命', cls:'status-ready'} : {text:'未选择', cls:'status-idle'}; +} + +// resultMessage 返回账号最后一次结果摘要。 +function resultMessage(st) { + let msg = ''; + if (st && typeof st === 'object') msg = st.message || ''; + else if (st === true) msg = '成功'; + else if (st === false) msg = '失败'; + if (!msg) return ''; + let short = msg.length > 46 ? msg.slice(0, 46) + '...' : msg; + return ``; +} + +// updateDashboardStats 刷新顶部统计指标。 +function updateDashboardStats() { + let selectedNames = new Set([...selAccs].map(i => accounts[i]?.name).filter(Boolean)); + let success = 0, fail = 0; + for (let name of selectedNames) { + let st = statusMap[name]; + if (st === true || (st && typeof st === 'object' && st.ok)) success++; + else if (st === false || (st && typeof st === 'object' && st.message)) fail++; + } + let pending = Math.max(0, selectedNames.size - success - fail); + setText('selectedCnt', selectedNames.size); + setText('successCnt', success); + setText('failCnt', fail); + setText('pendingCnt', pending); + let stats = document.getElementById('statsBody'); + if (stats) { + stats.innerHTML = `
成功账号: ${success}
+
异常账号: ${fail}
+
待处理账号: ${pending}
+
已选账号: ${selectedNames.size} / 总账号: ${accounts.length}
`; + } +} + +function setText(id, value) { + let el = document.getElementById(id); + if (el) el.textContent = value; +} + +// resetRunResults 清理上一轮前端结果,避免新任务被旧状态干扰。 +function resetRunResults() { + lastResults = {}; + statusMap = {}; + localStorage.removeItem('statusMap'); + let resultEl = document.getElementById('resultBody'); + if (resultEl) resultEl.innerHTML = '
暂无抢购结果
'; + renderAccounts(); + updateDashboardStats(); +} + +// ==================== 结果刷新 ==================== +// checkResults 轮询后端抢购结果,更新日志区、账号状态和本地状态缓存。 +async function checkResults() { + try { + let d = await App.GetResults(); + if (JSON.stringify(d) !== JSON.stringify(lastResults) && Object.keys(d).length > 0) { + lastResults = d; + let newStatusMap = {}; + let h = '
=== 最新结果 ===
'; + for (let [k, v] of Object.entries(d)) { + let cls = v.includes('成功') ? 'log-s' : 'log-e'; + h += `
${k}: ${v}
`; + let name = k.split('_')[0]; + if (!(name in newStatusMap)) newStatusMap[name] = {ok:false,message:v}; + if (v.includes('成功')) newStatusMap[name] = {ok:true,message:v}; + } + statusMap = newStatusMap; + localStorage.setItem('statusMap', JSON.stringify(statusMap)); + renderAccounts(); + let resultEl = document.getElementById('resultBody'); + resultEl.innerHTML = h; + resultEl.scrollTop = resultEl.scrollHeight; + updateDashboardStats(); + } + } catch (e) { } +} + + +// fetchServerLogs 增量拉取后端日志,把真实接口链路日志显示到前端日志区。 +async function fetchServerLogs() { + try { + let d = await App.GetLogs(lastLogId); + if (!d.success || !Array.isArray(d.logs) || d.logs.length === 0) return; + d.logs.forEach(item => { + lastLogId = Math.max(lastLogId, item.id || 0); + let type = 'i'; + if (item.level === 'success') type = 's'; + else if (item.level === 'error') type = 'e'; + else if (item.level === 'warn') type = 'w'; + else if (item.level === 'debug') type = 'd'; + addServerLog(item.message, type, item.category); + }); + } catch (e) { } +} + +// addServerLog 追加一条后端日志,和本地操作日志共用同一个日志区域。 +function addServerLog(msg, type = 'i', category = '') { + let el = document.getElementById('logBody'); + let cat = category ? `${escHtml(category)}` : ''; + el.innerHTML += `
[后端] ${cat}${escHtml(cleanServerLogMessage(msg))}
`; + el.scrollTop = el.scrollHeight; +} + +// cleanServerLogMessage 去掉后端结构化日志前缀,分类由单独标签展示。 +function cleanServerLogMessage(msg) { + return String(msg ?? '').replace(/\[[^\]]+\]\[(info|success|warn|error)\]\s*/i, ''); +} + + +// ==================== 设置 ==================== +// openSettings 打开设置弹窗,从后端读取当前配置填充表单。 +async function openSettings() { + try { + let cfg = await App.GetSettings(); + document.getElementById('setTraceEnabled').checked = !!cfg.traceEnabled; + document.getElementById('setTraceMaxBody').value = cfg.traceMaxBody || 0; + document.getElementById('setLogLevel').value = cfg.logLevel || 'info'; + document.getElementById('setConcurrency').value = cfg.concurrency || 80; + document.getElementById('setAttempts').value = cfg.attempts || 1; + } catch(e) { + toast('读取设置失败', e.message, 'error'); + } + document.getElementById('settingsModal').classList.add('show'); +} + +// closeSettings 关闭设置弹窗。 +function closeSettings() { + document.getElementById('settingsModal').classList.remove('show'); +} + +// saveSettings 收集表单数据,提交给后端保存。 +async function saveSettings() { + let cfg = { + traceEnabled: document.getElementById('setTraceEnabled').checked, + traceMaxBody: parseInt(document.getElementById('setTraceMaxBody').value) || 0, + logLevel: document.getElementById('setLogLevel').value, + concurrency: parseInt(document.getElementById('setConcurrency').value) || 80, + attempts: parseInt(document.getElementById('setAttempts').value) || 1, + }; + try { + let d = await App.SaveSettings(cfg); + if (d.success) { + toast('设置已保存', '配置已生效', 'success'); + closeSettings(); + } else { + toast('保存失败', d.error || '', 'error'); + } + } catch(e) { + toast('保存失败', e.message, 'error'); + } +} + +// buildAP 根据已勾选账号和账号绑定商品,生成后端需要的账号到商品 ID 映射。 +function buildAP() { + if (selAccs.size === 0) { + toast('提示', '请勾选要抢购的账号', 'warn'); + return null; + } + if (!selProdId) { + toast('提示', '请先选择商品', 'warn'); + return null; + } + if (!productInfo || !products.some(p => p.commodityId === selProdId)) { + toast('提示', '请先刷新商品,确认库存是实时数据', 'warn'); + return null; + } + let ap = {}; + // 遍历已选账号,把当前选中商品应用到每个账号。 + selAccs.forEach(i => { + let account = accounts[i]; + if (account) { + ap[account.name] = selProdId; + } + }); + if (Object.keys(ap).length === 0) { + toast('提示', '没有有效账号可提交', 'warn'); + return null; + } + return ap; +} + +// clearLegacyProductBindings 删除旧版按账号保存商品的缓存,避免残留旧商品误导界面。 +function clearLegacyProductBindings() { + for (let key in localStorage) { + if (key.startsWith('accProd_') || key.startsWith('accProdName_')) { + localStorage.removeItem(key); + } + } +} + + +// addLog 向底部日志区追加一条带毫秒时间戳的运行日志。 +function addLog(msg, type = 'i') { + let el = document.getElementById('logBody'); + let now = new Date(); + let timeStr = now.toLocaleTimeString() + '.' + String(now.getMilliseconds()).padStart(3, '0'); + el.innerHTML += `
[${timeStr}] ${msg}
`; + el.scrollTop = el.scrollHeight; +} + + +// clearLog 清空前端日志显示,并重置最近一次结果快照。 +function clearLog(){ + document.getElementById('logBody').innerHTML='
[系统] 就绪,等待操作...
'; + document.getElementById('resultBody').innerHTML='
暂无抢购结果
'; + lastResults={}; + setRunState('等待操作'); + updateDashboardStats(); +} + +// escHtml 转义 HTML 特殊字符,避免接口数据破坏页面结构。 +function escHtml(s){ return String(s ?? '').replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"').replace(/'/g,'''); } +// jsAttr 转义写入 onclick 字符串参数的数据。 +function jsAttr(s){ return escHtml(String(s ?? '').replace(/\\/g,'\\\\').replace(/'/g,"\\'").replace(/\n/g,' ')); } + +init(); diff --git a/frontend_backup/index.html b/frontend_backup/index.html new file mode 100644 index 0000000..f6d8121 --- /dev/null +++ b/frontend_backup/index.html @@ -0,0 +1,204 @@ + + + + + + 斗鱼抢购系统 + + + + +
+ + + +
+ + +
+
+
+
+
抢购控制台
+
等待操作
+
+ +
+
+ + +
+
+ +
+
+ 服务器 + -- +
+
+ 账号 + 0/0 +
+
+ 成功 + 0 +
+
+ 异常 + 0 +
+
+ 待处理 + 0 +
+
+ +
+
+ + + + + +
+
+
+ + +
+
+ + + ms +
+
+
+ +
+
+
+
+ 账号作战表 + 0 个账号 +
+ +
+
+ + + + + + + + + + + + + +
账号凭据商品积分状态最后结果
+
+
+ + +
+
+
+ + + + diff --git a/frontend_backup/styles.css b/frontend_backup/styles.css new file mode 100644 index 0000000..de2a70b --- /dev/null +++ b/frontend_backup/styles.css @@ -0,0 +1,801 @@ +*{margin:0;padding:0;box-sizing:border-box} +:root{ + color-scheme:dark; + --bg:#0f1419; + --surface:#161b22; + --surface-2:#1c232c; + --surface-3:#232b36; + --field:#0d1117; + --text:#c9d1d9; + --text-strong:#f0f6fc; + --muted:#8b949e; + --muted-2:#6e7681; + --line:#21262d; + --line-strong:#30363d; + --accent:#388bfd; + --accent-soft:rgba(56,139,253,.12); + --accent-border:rgba(56,139,253,.35); + --danger:#f85149; + --danger-soft:rgba(248,81,73,.12); + --success:#3fb950; + --success-soft:rgba(63,185,80,.12); + --warning:#d29922; + --warning-soft:rgba(210,153,34,.12); + --orange:#f78166; + --orange-soft:rgba(247,129,102,.12); + --shadow:0 1px 0 rgba(0,0,0,.04),0 8px 24px rgba(0,0,0,.18); + --radius:8px; + --radius-sm:6px; + --focus:0 0 0 3px rgba(56,139,253,.3); +} +body[data-theme="light"]{ + color-scheme:light; + --bg:#f6f8fa; + --surface:#ffffff; + --surface-2:#f6f8fa; + --surface-3:#eaeef2; + --field:#ffffff; + --text:#1f2328; + --text-strong:#0d1117; + --muted:#656d76; + --muted-2:#8c959f; + --line:#d0d7de; + --line-strong:#afb8c1; + --accent:#0969da; + --accent-soft:rgba(9,105,218,.08); + --accent-border:rgba(9,105,218,.3); + --danger:#cf222e; + --danger-soft:rgba(207,34,46,.08); + --success:#1a7f37; + --success-soft:rgba(26,127,55,.08); + --warning:#9a6700; + --warning-soft:rgba(154,103,0,.1); + --orange:#bc4c00; + --orange-soft:rgba(188,76,0,.08); + --shadow:0 1px 0 rgba(31,35,40,.04),0 8px 24px rgba(140,149,159,.15); + --focus:0 0 0 3px rgba(9,105,218,.3); +} + +html,body{height:100vh;overflow:hidden} +body{ + font-family:-apple-system,BlinkMacSystemFont,'Segoe UI','PingFang SC','Microsoft YaHei',sans-serif; + background:var(--bg); + color:var(--text); + font-size:13px; + line-height:1.5; + -webkit-font-smoothing:antialiased; + -moz-osx-font-smoothing:grayscale; +} +button,input,select{font:inherit;color:inherit} +::selection{background:var(--accent-soft);color:var(--text-strong)} +::-webkit-scrollbar{width:8px;height:8px} +::-webkit-scrollbar-track{background:transparent} +::-webkit-scrollbar-thumb{background:var(--line-strong);border-radius:999px} +::-webkit-scrollbar-thumb:hover{background:var(--muted-2)} + +/* ============ 主布局 ============ */ +.app-shell{ + display:grid; + grid-template-columns:300px minmax(0,1fr); + height:100vh; + min-width:1080px; + overflow:hidden; +} +.left{ + background:var(--surface); + border-right:1px solid var(--line); + display:flex; + flex-direction:column; + min-width:0; + min-height:0; + overflow:hidden; +} +.right{ + display:flex; + flex-direction:column; + min-width:0; + min-height:0; + overflow:hidden; +} + +/* ============ 品牌区 ============ */ +.brand{ + display:flex; + align-items:center; + justify-content:space-between; + gap:12px; + padding:16px 18px; + border-bottom:1px solid var(--line); +} +.brand h1{ + font-size:15px; + font-weight:600; + color:var(--text-strong); + letter-spacing:-.01em; +} +.brand-sub{ + font-size:11px; + color:var(--muted); + margin-top:3px; + letter-spacing:.02em; +} + +/* ============ 商品侧栏 ============ */ +.left-header{ + padding:14px 16px; + border-bottom:1px solid var(--line); + display:flex; + flex-direction:column; + gap:10px; +} +.product-actions{display:flex;gap:6px;align-items:center} +.product-actions .btn-primary{flex:1} +.product-search{ + display:flex; + align-items:center; + gap:8px; + background:var(--field); + border:1px solid var(--line); + border-radius:var(--radius-sm); + padding:0 10px; + transition:.15s; +} +.product-search:focus-within{border-color:var(--accent);box-shadow:var(--focus)} +.product-search input{ + flex:1; + min-width:0; + height:32px; + border:0; + outline:0; + background:transparent; + font-size:13px; +} +.product-search input::placeholder{color:var(--muted-2)} +.search-icon{color:var(--muted-2);font-size:13px} +.product-search .search-clear{ + width:20px;height:20px; + border:0;border-radius:4px; + background:transparent;color:var(--muted); + cursor:pointer;font-size:14px; + display:none; + align-items:center;justify-content:center; +} +.product-search .search-clear:hover{background:var(--surface-3);color:var(--text-strong)} + +.selected-product-card{ + padding:12px; + border:1px solid var(--line); + border-radius:var(--radius); + background:var(--surface-2); +} +.selected-product-card.has-product{ + border-color:var(--accent-border); + background:var(--accent-soft); +} +.selected-product-label{ + font-size:10px; + color:var(--muted); + font-weight:600; + text-transform:uppercase; + letter-spacing:.08em; + margin-bottom:6px; +} +.selected-product-name{ + font-size:13px; + color:var(--text-strong); + font-weight:600; + line-height:1.4; + word-break:break-all; +} +.selected-product-meta{ + display:flex; + gap:6px; + flex-wrap:wrap; + margin-top:8px; +} + +.product-meta{ + font-size:11px; + color:var(--muted); + padding:0 2px; +} +.product-meta.good{color:var(--success)} +.product-meta.warn{color:var(--warning)} + +.left-list{ + flex:1; + overflow-y:auto; + padding:6px 8px 12px; +} +.prod-item{ + display:grid; + grid-template-columns:40px minmax(0,1fr); + gap:10px; + padding:8px 10px; + margin:2px 0; + border-radius:var(--radius-sm); + cursor:pointer; + border:1px solid transparent; + transition:.12s; + position:relative; +} +.prod-item:hover{background:var(--surface-2)} +.prod-item.active{ + background:var(--accent-soft); + border-color:var(--accent-border); +} +.prod-item img{ + width:40px;height:40px; + border-radius:var(--radius-sm); + object-fit:cover; + background:var(--field); + border:1px solid var(--line); +} +.pinfo{min-width:0;display:flex;flex-direction:column;justify-content:center;gap:4px} +.pname{ + font-size:12.5px; + font-weight:500; + color:var(--text-strong); + white-space:nowrap; + overflow:hidden; + text-overflow:ellipsis; + line-height:1.3; +} +.pmeta{ + font-size:11px; + color:var(--muted); + display:flex; + gap:6px; + flex-wrap:wrap; +} +.chip{ + display:inline-flex; + align-items:center; + gap:3px; + padding:1px 7px; + border-radius:999px; + background:var(--surface-3); + font-size:11px; + font-weight:500; + white-space:nowrap; + color:var(--muted); +} +.chip-score{color:var(--warning);background:var(--warning-soft)} +.chip-stock{color:var(--success);background:var(--success-soft)} +.chip-stock.low{color:var(--danger);background:var(--danger-soft)} +.empty-state{ + text-align:center; + color:var(--muted); + padding:48px 16px; + font-size:12px; + line-height:1.7; +} + +/* ============ 顶部控制台 ============ */ +.console-head{ + padding:14px 20px; + border-bottom:1px solid var(--line); + background:var(--surface); + display:flex; + align-items:center; + justify-content:space-between; + gap:16px; +} +.headline{display:flex;align-items:center;gap:14px;min-width:0} +.headline-title{ + font-size:15px; + font-weight:600; + color:var(--text-strong); + letter-spacing:-.01em; +} +.headline-meta{ + font-size:12px; + color:var(--muted); + margin-top:2px; +} +.top-actions{display:flex;align-items:center;gap:6px} +.countdown-badge{ + display:inline-flex; + align-items:center; + padding:4px 10px; + border-radius:999px; + background:var(--danger-soft); + color:var(--danger); + border:1px solid var(--danger); + font-weight:600; + font-size:12px; + font-variant-numeric:tabular-nums; +} + +/* ============ 状态指标条 ============ */ +.status-grid{ + display:flex; + gap:24px; + padding:12px 20px; + background:var(--surface); + border-bottom:1px solid var(--line); + align-items:center; +} +.metric{ + display:flex; + align-items:baseline; + gap:6px; + min-width:0; +} +.metric-label{ + font-size:11px; + color:var(--muted); + text-transform:uppercase; + letter-spacing:.06em; + font-weight:500; +} +.metric-value{ + color:var(--text-strong); + font-weight:600; + font-size:14px; + font-variant-numeric:tabular-nums; +} +.metric-value.server{color:var(--accent)} +.metric-value.success-num{color:var(--success)} +.metric-value.fail-num{color:var(--danger)} + +/* ============ 操作条 ============ */ +.control-strip{ + padding:12px 20px; + background:var(--surface); + border-bottom:1px solid var(--line); + display:flex; + align-items:center; + justify-content:space-between; + gap:16px; + flex-wrap:wrap; +} +.action-group{display:flex;gap:6px;align-items:center;flex-wrap:wrap} +.schedule-bar{display:flex;gap:8px;align-items:center;flex-wrap:wrap} +.schedule-item{ + display:flex; + align-items:center; + gap:6px; +} +.schedule-bar label{ + color:var(--muted); + font-size:12px; + white-space:nowrap; +} +.schedule-bar input{ + height:30px; + padding:0 10px; + background:var(--field); + color:var(--text-strong); + border:1px solid var(--line); + border-radius:var(--radius-sm); + font-size:12.5px; + font-variant-numeric:tabular-nums; + transition:.15s; +} +.schedule-bar input:focus{outline:0;border-color:var(--accent);box-shadow:var(--focus)} +.schedule-bar input#targetTime{width:108px;text-align:center} +.schedule-bar input#advance{width:72px;text-align:center} + +/* ============ 按钮 ============ */ +.btn{ + height:30px; + padding:0 12px; + border:1px solid var(--line); + border-radius:var(--radius-sm); + background:var(--surface-2); + color:var(--text); + cursor:pointer; + font-size:12.5px; + font-weight:500; + white-space:nowrap; + transition:.12s; + display:inline-flex; + align-items:center; + justify-content:center; + gap:6px; +} +.btn:hover{background:var(--surface-3);border-color:var(--line-strong)} +.btn:focus-visible{outline:0;box-shadow:var(--focus)} +.btn:disabled{opacity:.55;cursor:not-allowed} +.btn-primary{ + background:var(--accent); + border-color:var(--accent); + color:#fff; +} +.btn-primary:hover{filter:brightness(1.08);background:var(--accent)} +.btn-danger{ + background:var(--danger); + border-color:var(--danger); + color:#fff; +} +.btn-danger:hover{filter:brightness(1.08);background:var(--danger)} +.btn-success{ + background:var(--success); + border-color:var(--success); + color:#fff; +} +.btn-success:hover{filter:brightness(1.08);background:var(--success)} +.btn-cancel{ + background:transparent; + color:var(--danger); + border-color:var(--danger); +} +.btn-cancel:hover{background:var(--danger-soft)} +.btn-ghost{background:transparent;border-color:transparent;color:var(--muted)} +.btn-ghost:hover{color:var(--text-strong);background:var(--surface-2);border-color:var(--line)} +.icon-btn{width:30px;padding:0;font-size:14px} +.btn-compact{height:26px;font-size:11.5px;padding:0 10px} + +.stat-pill{ + display:inline-flex; + align-items:center; + gap:6px; + height:24px; + padding:0 10px; + border:1px solid var(--line); + border-radius:999px; + background:var(--surface-2); + color:var(--muted); + font-size:11.5px; + font-variant-numeric:tabular-nums; +} + +/* ============ 工作区 ============ */ +.workspace{ + display:grid; + grid-template-columns:minmax(0,1fr) 380px; + gap:14px; + padding:14px 20px 20px; + align-items:stretch; + flex:1; + min-height:0; + overflow:hidden; +} +.panel{ + background:var(--surface); + border:1px solid var(--line); + border-radius:var(--radius); + min-width:0; + min-height:0; + display:flex; + flex-direction:column; + overflow:hidden; + height:100%; +} +.panel-head{ + padding:10px 14px; + border-bottom:1px solid var(--line); + display:flex; + align-items:center; + justify-content:space-between; + gap:10px; + background:var(--surface); +} +.panel-title{ + font-size:13px; + font-weight:600; + color:var(--text-strong); +} +.panel-sub{ + font-size:11.5px; + color:var(--muted); + margin-left:8px; + font-weight:400; +} +.panel-head label.stat-pill{cursor:pointer} +.panel-head label.stat-pill input{margin:0;cursor:pointer} + +/* ============ 账号表 ============ */ +.table-wrap{flex:1;overflow:auto;min-height:0} +table{width:100%;border-collapse:separate;border-spacing:0;font-size:12.5px} +th{ + background:var(--surface-2); + padding:8px 12px; + text-align:left; + border-bottom:1px solid var(--line); + position:sticky; + top:0; + z-index:1; + color:var(--muted); + font-size:11px; + font-weight:600; + text-transform:uppercase; + letter-spacing:.04em; + white-space:nowrap; +} +td{padding:9px 12px;border-bottom:1px solid var(--line);vertical-align:middle} +tbody tr:last-child td{border-bottom:0} +tbody tr{transition:.1s} +tbody tr:hover{background:var(--surface-2)} +.select-cell{width:36px} +.status-col{width:96px} +.account-name{font-weight:500;color:var(--text-strong)} +.account-sub{font-size:11px;color:var(--muted);margin-top:2px} +.account-check{display:inline-flex;align-items:center;cursor:pointer} +.check-box{ + width:16px;height:16px; + border-radius:4px; + border:1.5px solid var(--line-strong); + background:transparent; + display:flex;align-items:center;justify-content:center; + transition:.15s; + color:#fff; + font-size:10px; + font-weight:700; +} +.check-box.checked{ + border-color:var(--accent); + background:var(--accent); +} +.prod-tag{ + display:inline-flex; + max-width:200px; + overflow:hidden; + text-overflow:ellipsis; + white-space:nowrap; + background:var(--surface-2); + color:var(--text); + border:1px solid var(--line); + padding:2px 8px; + border-radius:999px; + font-size:11.5px; +} +.status-badge{ + display:inline-flex; + align-items:center; + padding:2px 8px; + border-radius:999px; + border:1px solid var(--line); + background:var(--surface-2); + font-size:11px; + font-weight:500; + white-space:nowrap; +} +.status-idle{color:var(--muted)} +.status-ready{color:var(--accent);background:var(--accent-soft);border-color:var(--accent-border)} +.status-success{color:var(--success);background:var(--success-soft);border-color:var(--success)} +.status-fail{color:var(--danger);background:var(--danger-soft);border-color:var(--danger)} +.status-warn{color:var(--warning);background:var(--warning-soft);border-color:var(--warning)} +.cred-ok{color:var(--success)} +.cred-miss{color:var(--danger)} + +/* ============ 日志区 ============ */ +.side-stack{ + display:flex; + flex-direction:column; + gap:14px; + min-height:0; + height:100%; +} +.log-wrap{flex:1;min-height:0} +.log-header{ + padding:8px 12px; + border-bottom:1px solid var(--line); + display:flex; + justify-content:space-between; + align-items:center; + gap:8px; + background:var(--surface); +} +.log-tabs{display:flex;gap:2px;align-items:center} +.log-tab{ + height:26px; + padding:0 10px; + border-radius:var(--radius-sm); + border:0; + background:transparent; + color:var(--muted); + cursor:pointer; + font-size:11.5px; + font-weight:500; + transition:.12s; +} +.log-tab:hover{color:var(--text-strong);background:var(--surface-2)} +.log-tab.active{ + background:var(--accent-soft); + color:var(--accent); +} +.log-panel{ + display:none; + flex:1; + min-height:0; + overflow:auto; + padding:10px 12px; + font-family:'SF Mono','Monaco','Consolas','Courier New',monospace; + font-size:11.5px; + line-height:1.7; + background:var(--field); +} +.log-panel.active{display:block} +.log-s{color:var(--success)} +.log-e{color:var(--danger)} +.log-i{color:var(--accent)} +.log-w{color:var(--warning)} +.log-d{color:var(--muted-2)} +.log-result{ + background:var(--surface); + padding:6px 9px; + margin:4px 0; + border-radius:var(--radius-sm); + word-break:break-all; + border:1px solid var(--line); +} +.log-cat{ + display:inline-block; + min-width:32px; + text-align:center; + margin-right:6px; + padding:0 5px; + border:1px solid var(--line); + border-radius:3px; + color:var(--muted); + font-size:10px; + line-height:1.5; + background:var(--surface); +} +.result-empty{color:var(--muted);padding:14px 4px;font-style:italic} + +/* ============ Toast ============ */ +.toast-container{ + position:fixed; + top:20px; + right:-420px; + z-index:9999; + transition:right .35s cubic-bezier(.16,1,.3,1); +} +.toast-container.show{right:20px} +.toast{ + background:var(--surface); + border:1px solid var(--line); + border-left-width:3px; + border-radius:var(--radius); + padding:12px 14px; + margin-bottom:8px; + min-width:300px; + max-width:380px; + box-shadow:var(--shadow); +} +.toast-title{ + font-size:12.5px; + font-weight:600; + margin-bottom:3px; + color:var(--text-strong); +} +.toast-body{ + font-size:12px; + color:var(--muted); + line-height:1.6; +} +.toast-success{border-left-color:var(--success)} +.toast-success .toast-title{color:var(--success)} +.toast-info{border-left-color:var(--accent)} +.toast-info .toast-title{color:var(--accent)} +.toast-warn{border-left-color:var(--warning)} +.toast-warn .toast-title{color:var(--warning)} +.toast-error{border-left-color:var(--danger)} +.toast-error .toast-title{color:var(--danger)} + +/* ============ Modal ============ */ +.modal-overlay{ + position:fixed; + inset:0; + background:rgba(0,0,0,.5); + z-index:9000; + display:none; + align-items:center; + justify-content:center; + backdrop-filter:blur(4px); +} +.modal-overlay.show{display:flex} +.modal{ + background:var(--surface); + border:1px solid var(--line); + border-radius:var(--radius); + width:480px; + max-width:92vw; + max-height:85vh; + overflow-y:auto; + box-shadow:var(--shadow); +} +.modal-header{ + display:flex; + align-items:center; + justify-content:space-between; + padding:14px 18px; + border-bottom:1px solid var(--line); +} +.modal-header h3{ + font-size:14px; + font-weight:600; + color:var(--text-strong); +} +.modal-close{ + width:28px;height:28px; + border:0;border-radius:var(--radius-sm); + background:transparent;color:var(--muted); + cursor:pointer;font-size:18px; + display:flex;align-items:center;justify-content:center; +} +.modal-close:hover{background:var(--surface-2);color:var(--text-strong)} +.modal-body{padding:18px} +.form-group{margin-bottom:14px} +.form-group:last-child{margin-bottom:0} +.form-label{ + display:block; + font-size:12px; + font-weight:500; + color:var(--text); + margin-bottom:6px; +} +.form-hint{ + font-size:11px; + color:var(--muted); + margin-top:4px; + line-height:1.5; +} +.form-row{display:flex;gap:12px} +.form-row .form-group{flex:1} +.form-input,.form-select{ + width:100%; + height:32px; + padding:0 10px; + background:var(--field); + color:var(--text-strong); + border:1px solid var(--line); + border-radius:var(--radius-sm); + font-size:12.5px; + transition:.15s; +} +.form-input:focus,.form-select:focus{outline:0;border-color:var(--accent);box-shadow:var(--focus)} +.toggle-row{ + display:flex; + align-items:center; + justify-content:space-between; + padding:6px 0; +} +.toggle-label{font-size:12.5px;color:var(--text-strong);font-weight:500} +.toggle{position:relative;width:36px;height:20px;cursor:pointer} +.toggle input{opacity:0;width:0;height:0} +.toggle-slider{ + position:absolute;inset:0; + background:var(--line-strong); + border-radius:999px; + transition:.2s; +} +.toggle-slider::before{ + content:""; + position:absolute; + left:2px;top:2px; + width:16px;height:16px; + background:#fff; + border-radius:50%; + transition:.2s; +} +.toggle input:checked+.toggle-slider{background:var(--accent)} +.toggle input:checked+.toggle-slider::before{transform:translateX(16px)} +.modal-footer{ + padding:12px 18px; + border-top:1px solid var(--line); + display:flex; + justify-content:flex-end; + gap:8px; +} + +/* ============ 响应式 ============ */ +@media (max-width: 1180px){ + html,body{height:auto;overflow:auto} + .app-shell{display:block;min-width:0;height:auto;overflow:visible} + .left{height:auto;overflow:visible;border-right:0;border-bottom:1px solid var(--line)} + .left-list{max-height:280px} + .right{overflow:visible;min-height:auto} + .status-grid{flex-wrap:wrap;gap:14px 24px} + .control-strip{flex-direction:column;align-items:stretch} + .schedule-bar{justify-content:flex-end} + .workspace{grid-template-columns:1fr;padding:14px;overflow:visible} + .table-wrap{max-height:520px} + .log-wrap{height:360px} + .toast-container{left:12px;right:12px;top:12px} + .toast-container.show{right:12px} + .toast{min-width:0;width:100%;max-width:none} +} diff --git a/wails.json b/wails.json index 76bee0e..6975c36 100644 --- a/wails.json +++ b/wails.json @@ -2,12 +2,12 @@ "$schema": "https://wails.io/schemas/config.v2.json", "name": "douyu_go", "outputfilename": "douyu_go", - "version": "0.0.3", + "version": "0.0.4", "frontend:dir": "frontend", - "frontend:install": "", - "frontend:build": "", - "frontend:dev:watcher": "", - "frontend:dev:serverUrl": "", + "frontend:install": "npm install", + "frontend:build": "npm run build", + "frontend:dev:watcher": "npm run dev", + "frontend:dev:serverUrl": "auto", "wailsjsdir": "frontend", "author": { "name": "yml",