feat: unify login UI and improve kdocs defaults

This commit is contained in:
2026-02-07 01:27:00 +08:00
parent bf29ac1924
commit 9991834ccd
22 changed files with 358 additions and 114 deletions

View File

@@ -240,31 +240,49 @@ onMounted(async () => {
</script> </script>
<template> <template>
<div class="auth-wrap"> <div class="login-page">
<el-card shadow="never" class="auth-card" :body-style="{ padding: '22px' }"> <div class="login-container">
<div class="brand"> <div class="login-header">
<div class="brand-title">知识管理平台</div> <span class="login-badge">用户登录</span>
<div class="brand-sub app-muted">用户登录</div> <h1>用户登录系统</h1>
<p>知识管理平台</p>
</div> </div>
<el-form label-position="top"> <div class="form-group">
<el-form-item label="用户名"> <label for="username">用户账号</label>
<el-input v-model="form.username" placeholder="请输入用户名" autocomplete="username" />
</el-form-item>
<el-form-item label="密码">
<el-input <el-input
id="username"
v-model="form.username"
class="login-input"
placeholder="请输入用户名"
autocomplete="username"
/>
</div>
<div class="form-group">
<label for="password">密码</label>
<el-input
id="password"
v-model="form.password" v-model="form.password"
class="login-input"
type="password" type="password"
show-password show-password
placeholder="请输入密码" placeholder="请输入密码"
autocomplete="current-password" autocomplete="current-password"
@keyup.enter="onSubmit" @keyup.enter="onSubmit"
/> />
</el-form-item> </div>
<el-form-item v-if="needCaptcha" label="验证码"> <div v-if="needCaptcha" class="form-group">
<label for="captcha">验证码</label>
<div class="captcha-row"> <div class="captcha-row">
<el-input v-model="form.captcha" placeholder="请输入验证码" @keyup.enter="onSubmit" /> <el-input
id="captcha"
v-model="form.captcha"
class="login-input captcha-input"
placeholder="请输入验证码"
@keyup.enter="onSubmit"
/>
<img <img
v-if="captchaImage" v-if="captchaImage"
class="captcha-img" class="captcha-img"
@@ -273,23 +291,29 @@ onMounted(async () => {
title="点击刷新" title="点击刷新"
@click="refreshLoginCaptcha" @click="refreshLoginCaptcha"
/> />
<el-button @click="refreshLoginCaptcha">刷新</el-button> <button type="button" class="captcha-refresh" @click="refreshLoginCaptcha">刷新</button>
</div> </div>
</el-form-item>
</el-form>
<div class="links">
<el-button text type="primary" @click="openForgot">忘记密码</el-button>
<el-button v-if="showResendLink" text type="primary" @click="openResend">重发验证邮件</el-button>
</div> </div>
<el-button type="primary" class="submit-btn" :loading="loading" @click="onSubmit">登录</el-button> <button type="button" class="btn-login" :disabled="loading" @click="onSubmit">
{{ loading ? '登录中...' : '登录系统' }}
</button>
<div class="foot"> <div class="action-links">
<span class="app-muted">还没有账号</span> <button type="button" class="link-btn" @click="openForgot">忘记密码</button>
<el-button link type="primary" @click="goRegister">立即注册</el-button> <button v-if="showResendLink" type="button" class="link-btn" @click="openResend">重发验证邮件</button>
</div>
<div class="register-row">
<span>还没有账号</span>
<button type="button" class="link-btn" @click="goRegister">立即注册</button>
</div>
<div class="back-link">
<span>管理员请前往</span>
<a href="/yuyx">后台登录</a>
</div>
</div> </div>
</el-card>
<el-dialog v-model="forgotOpen" title="找回密码" width="min(560px, 92vw)"> <el-dialog v-model="forgotOpen" title="找回密码" width="min(560px, 92vw)">
<el-alert <el-alert
@@ -376,61 +400,181 @@ onMounted(async () => {
</template> </template>
<style scoped> <style scoped>
.auth-wrap { .login-page {
min-height: 100vh; min-height: 100vh;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 20px; padding: 20px;
position: relative;
background: linear-gradient(135deg, #eef2ff 0%, #f6f7fb 45%, #ecfeff 100%);
} }
.auth-card { .login-page::before {
content: '';
position: fixed;
inset: 0;
background:
radial-gradient(800px 500px at 15% 20%, rgba(59, 130, 246, 0.18), transparent 60%),
radial-gradient(700px 420px at 85% 70%, rgba(124, 58, 237, 0.16), transparent 55%);
pointer-events: none;
}
.login-container {
width: 100%; width: 100%;
max-width: 420px; max-width: 420px;
border-radius: var(--app-radius); background: #fff;
border: 1px solid var(--app-border); border-radius: 16px;
box-shadow: var(--app-shadow); box-shadow: 0 18px 60px rgba(17, 24, 39, 0.15);
border: 1px solid rgba(17, 24, 39, 0.08);
padding: 38px 34px;
position: relative;
z-index: 1;
} }
.brand { .login-header {
text-align: center;
margin-bottom: 28px;
}
.login-badge {
display: inline-block;
background: rgba(59, 130, 246, 0.1);
color: #1d4ed8;
padding: 6px 14px;
border-radius: 999px;
font-size: 12px;
font-weight: 700;
margin-bottom: 14px; margin-bottom: 14px;
} }
.brand-title { .login-header h1 {
font-size: 18px; font-size: 24px;
font-weight: 900; color: #111827;
margin: 0 0 10px;
letter-spacing: 0.2px;
} }
.brand-sub { .login-header p {
margin-top: 4px; margin: 0;
font-size: 12px; color: #6b7280;
font-size: 14px;
} }
.links { .form-group {
display: flex; margin-bottom: 20px;
align-items: center;
justify-content: space-between;
gap: 10px;
margin: 2px 0 10px;
flex-wrap: wrap;
} }
.submit-btn { .form-group label {
display: block;
margin-bottom: 8px;
color: #111827;
font-weight: 700;
font-size: 13px;
}
.login-input :deep(.el-input__wrapper) {
border-radius: 10px;
min-height: 44px;
background: rgba(255, 255, 255, 0.9);
box-shadow: 0 0 0 1px rgba(17, 24, 39, 0.14) inset;
transition: box-shadow 0.2s;
}
.login-input :deep(.el-input__wrapper.is-focus) {
box-shadow: 0 0 0 1px rgba(59, 130, 246, 0.7) inset, 0 0 0 4px rgba(59, 130, 246, 0.16);
}
.login-input :deep(.el-input__inner) {
font-size: 14px;
}
.btn-login {
width: 100%; width: 100%;
padding: 12px;
border: none;
border-radius: 10px;
background: linear-gradient(135deg, #2563eb 0%, #7c3aed 100%);
color: #fff;
font-size: 16px;
font-weight: 800;
cursor: pointer;
transition: transform 0.15s, filter 0.15s;
} }
.foot { .btn-login:hover:not(:disabled) {
transform: translateY(-2px);
filter: brightness(1.02);
}
.btn-login:active:not(:disabled) {
transform: translateY(0);
}
.btn-login:disabled {
cursor: not-allowed;
opacity: 0.8;
}
.action-links {
margin-top: 14px; margin-top: 14px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
gap: 8px;
flex-wrap: wrap;
}
.link-btn {
border: none;
background: none;
color: #2563eb;
font-size: 13px;
font-weight: 700;
cursor: pointer;
padding: 0;
}
.link-btn:hover {
text-decoration: underline;
}
.register-row {
margin-top: 16px;
display: flex;
justify-content: center; justify-content: center;
gap: 6px; align-items: center;
gap: 8px;
color: #6b7280;
font-size: 13px;
}
.back-link {
text-align: center;
margin-top: 18px;
color: #6b7280;
font-size: 13px;
}
.back-link a {
margin-left: 6px;
color: #2563eb;
text-decoration: none;
font-weight: 700;
}
.back-link a:hover {
text-decoration: underline;
} }
.dialog-form { .dialog-form {
margin-top: 10px; margin-top: 10px;
} }
.alert {
margin-top: 12px;
}
.captcha-row { .captcha-row {
display: flex; display: flex;
align-items: center; align-items: center;
@@ -438,17 +582,62 @@ onMounted(async () => {
width: 100%; width: 100%;
} }
.captcha-input {
flex: 1;
min-width: 0;
}
.captcha-img { .captcha-img {
height: 40px; height: 46px;
border: 1px solid var(--app-border); border: 1px solid rgba(17, 24, 39, 0.14);
border-radius: 8px; border-radius: 8px;
cursor: pointer; cursor: pointer;
user-select: none; user-select: none;
} }
.captcha-refresh {
height: 44px;
padding: 0 14px;
border: 1px solid rgba(17, 24, 39, 0.14);
border-radius: 10px;
background: #f8fafc;
color: #111827;
font-size: 13px;
cursor: pointer;
}
.captcha-refresh:hover {
background: #f1f5f9;
}
@media (max-width: 480px) { @media (max-width: 480px) {
.login-page {
align-items: flex-start;
padding: 20px 12px 12px;
}
.login-container {
max-width: 100%;
padding: 28px 20px;
border-radius: 14px;
}
.login-header h1 {
font-size: 22px;
}
.btn-login {
padding: 13px;
font-size: 15px;
}
.captcha-img { .captcha-img {
height: 38px; height: 42px;
}
.captcha-refresh {
height: 42px;
padding: 0 12px;
} }
} }
</style> </style>

View File

@@ -59,7 +59,10 @@ def get_kdocs_status_api():
uploader = get_kdocs_uploader() uploader = get_kdocs_uploader()
status = uploader.get_status() status = uploader.get_status()
live = str(request.args.get("live", "")).lower() in ("1", "true", "yes") live = str(request.args.get("live", "")).lower() in ("1", "true", "yes")
if live:
# 重启后首次查询时last_login_ok is None自动做一次实时状态校验
should_live_check = live or status.get("last_login_ok") is None
if should_live_check:
live_status = uploader.refresh_login_status() live_status = uploader.refresh_login_status()
if live_status.get("success"): if live_status.get("success"):
logged_in = bool(live_status.get("logged_in")) logged_in = bool(live_status.get("logged_in"))

View File

@@ -234,10 +234,12 @@ def get_user_email():
@login_required @login_required
def get_user_kdocs_settings(): def get_user_kdocs_settings():
"""获取当前用户的金山文档设置""" """获取当前用户的金山文档设置"""
settings = database.get_user_kdocs_settings(current_user.id) settings = database.get_user_kdocs_settings(current_user.id) or {}
if not settings: cfg = database.get_system_config() or {}
return jsonify({"kdocs_unit": "", "kdocs_auto_upload": 0}) default_unit = (cfg.get("kdocs_default_unit") or "").strip() or "道县"
return jsonify(settings) kdocs_unit = (settings.get("kdocs_unit") or "").strip() or default_unit
kdocs_auto_upload = 1 if int(settings.get("kdocs_auto_upload", 0) or 0) == 1 else 0
return jsonify({"kdocs_unit": kdocs_unit, "kdocs_auto_upload": kdocs_auto_upload})
@api_user_bp.route("/api/user/kdocs", methods=["POST"]) @api_user_bp.route("/api/user/kdocs", methods=["POST"])
@@ -265,8 +267,14 @@ def update_user_kdocs_settings():
): ):
return jsonify({"error": "更新失败"}), 400 return jsonify({"error": "更新失败"}), 400
settings = database.get_user_kdocs_settings(current_user.id) or {"kdocs_unit": "", "kdocs_auto_upload": 0} settings = database.get_user_kdocs_settings(current_user.id) or {}
return jsonify({"success": True, "settings": settings}) cfg = database.get_system_config() or {}
default_unit = (cfg.get("kdocs_default_unit") or "").strip() or "道县"
response_settings = {
"kdocs_unit": (settings.get("kdocs_unit") or "").strip() or default_unit,
"kdocs_auto_upload": 1 if int(settings.get("kdocs_auto_upload", 0) or 0) == 1 else 0,
}
return jsonify({"success": True, "settings": response_settings})
@api_user_bp.route("/api/user/bind-email", methods=["POST"]) @api_user_bp.route("/api/user/bind-email", methods=["POST"])
@@ -405,6 +413,14 @@ def get_kdocs_status_for_user():
login_required_flag = status.get("login_required", False) login_required_flag = status.get("login_required", False)
last_login_ok = status.get("last_login_ok") last_login_ok = status.get("last_login_ok")
# 重启后首次查询时,状态可能还是 None这里做一次轻量实时校验
if last_login_ok is None:
live_status = kdocs.refresh_login_status()
if live_status.get("success"):
logged_in = bool(live_status.get("logged_in"))
login_required_flag = not logged_in
last_login_ok = logged_in
# 判断是否在线 # 判断是否在线
is_online = not login_required_flag and last_login_ok is True is_online = not login_required_flag and last_login_ok is True

View File

@@ -3,6 +3,7 @@
from __future__ import annotations from __future__ import annotations
import os import os
import re
import shutil import shutil
import subprocess import subprocess
import time import time
@@ -13,7 +14,6 @@ import email_service
from api_browser import APIBrowser, get_cookie_jar_path, is_cookie_jar_fresh from api_browser import APIBrowser, get_cookie_jar_path, is_cookie_jar_fresh
from app_config import get_config from app_config import get_config
from app_logger import get_logger from app_logger import get_logger
from app_security import sanitize_filename
from browser_pool_worker import get_browser_worker_pool from browser_pool_worker import get_browser_worker_pool
from services.client_log import log_to_client from services.client_log import log_to_client
from services.runtime import get_socketio from services.runtime import get_socketio
@@ -264,12 +264,46 @@ def _build_screenshot_targets(browse_type: str) -> tuple[str, str, str]:
return index_url, target_url, run_script return index_url, target_url, run_script
def _normalize_screenshot_name(value: str, *, fallback: str = "账号") -> str:
"""规范化截图文件名中的账号名,尽量保留中文。"""
label = str(value or "").strip() or fallback
label = label.replace("/", "_").replace("\\", "_")
label = re.sub(r"\s+", "", label)
label = re.sub(r"[^0-9A-Za-z_\-.一-鿿]", "_", label)
label = re.sub(r"_+", "_", label).strip("._-")
return label or fallback
def _next_screenshot_sequence(username_prefix: str, account_label: str, date_str: str) -> int:
"""按“用户+账号+日期”计算下一个截图序号。"""
pattern = re.compile(
rf"^{re.escape(username_prefix)}_{re.escape(account_label)}_{date_str}_(\d{{3}})\.jpg$",
re.IGNORECASE,
)
max_seq = 0
try:
with os.scandir(SCREENSHOTS_DIR) as entries:
for entry in entries:
if not entry.is_file():
continue
matched = pattern.match(entry.name)
if not matched:
continue
max_seq = max(max_seq, int(matched.group(1)))
except FileNotFoundError:
pass
return max_seq + 1
def _build_screenshot_output_path(username_prefix: str, account, browse_type: str) -> tuple[str, str]: def _build_screenshot_output_path(username_prefix: str, account, browse_type: str) -> tuple[str, str]:
"""构建截图输出文件名与路径。""" """构建截图输出文件名与路径(账号备注 + 日期 + 序号)"""
timestamp = get_beijing_now().strftime("%Y%m%d_%H%M%S") del browse_type
login_account = account.remark if account.remark else account.username date_str = get_beijing_now().strftime("%Y%m%d")
raw_filename = f"{username_prefix}_{login_account}_{browse_type}_{timestamp}.jpg" account_label = _normalize_screenshot_name(account.remark or account.username, fallback=account.username)
screenshot_filename = sanitize_filename(raw_filename) seq = _next_screenshot_sequence(username_prefix, account_label, date_str)
screenshot_filename = f"{username_prefix}_{account_label}_{date_str}_{seq:03d}.jpg"
return screenshot_filename, os.path.join(SCREENSHOTS_DIR, screenshot_filename) return screenshot_filename, os.path.join(SCREENSHOTS_DIR, screenshot_filename)
@@ -379,11 +413,13 @@ def _enqueue_kdocs_upload_if_needed(user_id: int, account_id: str, account, scre
if int(user_cfg.get("kdocs_auto_upload", 0) or 0) != 1: if int(user_cfg.get("kdocs_auto_upload", 0) or 0) != 1:
return return
unit = (user_cfg.get("kdocs_unit") or cfg.get("kdocs_default_unit") or "").strip() user_unit = (user_cfg.get("kdocs_unit") or "").strip()
default_unit = (cfg.get("kdocs_default_unit") or "").strip() or "道县"
unit = user_unit or default_unit
if not user_unit:
log_to_client(f"未配置县区,使用默认县区: {unit}", user_id, account_id)
name = (account.remark or "").strip() name = (account.remark or "").strip()
if not unit:
log_to_client("表格上传跳过: 未配置县区", user_id, account_id)
return
if not name: if not name:
log_to_client("表格上传跳过: 账号备注为空", user_id, account_id) log_to_client("表格上传跳过: 账号备注为空", user_id, account_id)
return return

View File

@@ -1,20 +1,20 @@
{ {
"_accounts-Bta9cdL5.js": { "_accounts-Cq6KNxFR.js": {
"file": "assets/accounts-Bta9cdL5.js", "file": "assets/accounts-Cq6KNxFR.js",
"name": "accounts", "name": "accounts",
"imports": [ "imports": [
"index.html" "index.html"
] ]
}, },
"_auth--ytvFYf6.js": { "_auth-CjQgMKAl.js": {
"file": "assets/auth--ytvFYf6.js", "file": "assets/auth-CjQgMKAl.js",
"name": "auth", "name": "auth",
"imports": [ "imports": [
"index.html" "index.html"
] ]
}, },
"index.html": { "index.html": {
"file": "assets/index-CPwwGffH.js", "file": "assets/index-DMtbRy1f.js",
"name": "index", "name": "index",
"src": "index.html", "src": "index.html",
"isEntry": true, "isEntry": true,
@@ -32,12 +32,12 @@
] ]
}, },
"src/pages/AccountsPage.vue": { "src/pages/AccountsPage.vue": {
"file": "assets/AccountsPage-D3MJyXUD.js", "file": "assets/AccountsPage-xwYY9lse.js",
"name": "AccountsPage", "name": "AccountsPage",
"src": "src/pages/AccountsPage.vue", "src": "src/pages/AccountsPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"_accounts-Bta9cdL5.js", "_accounts-Cq6KNxFR.js",
"index.html" "index.html"
], ],
"css": [ "css": [
@@ -45,51 +45,51 @@
] ]
}, },
"src/pages/LoginPage.vue": { "src/pages/LoginPage.vue": {
"file": "assets/LoginPage-Cz6slTnR.js", "file": "assets/LoginPage-BchU6qog.js",
"name": "LoginPage", "name": "LoginPage",
"src": "src/pages/LoginPage.vue", "src": "src/pages/LoginPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"index.html", "index.html",
"_auth--ytvFYf6.js" "_auth-CjQgMKAl.js"
], ],
"css": [ "css": [
"assets/LoginPage-CnwOLKJz.css" "assets/LoginPage-Dra3USJu.css"
] ]
}, },
"src/pages/RegisterPage.vue": { "src/pages/RegisterPage.vue": {
"file": "assets/RegisterPage-D46uldFj.js", "file": "assets/RegisterPage-CwVejO-I.js",
"name": "RegisterPage", "name": "RegisterPage",
"src": "src/pages/RegisterPage.vue", "src": "src/pages/RegisterPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"index.html", "index.html",
"_auth--ytvFYf6.js" "_auth-CjQgMKAl.js"
], ],
"css": [ "css": [
"assets/RegisterPage-BOcNcW5D.css" "assets/RegisterPage-BOcNcW5D.css"
] ]
}, },
"src/pages/ResetPasswordPage.vue": { "src/pages/ResetPasswordPage.vue": {
"file": "assets/ResetPasswordPage-CO1hZug-.js", "file": "assets/ResetPasswordPage-Cp3rzSEn.js",
"name": "ResetPasswordPage", "name": "ResetPasswordPage",
"src": "src/pages/ResetPasswordPage.vue", "src": "src/pages/ResetPasswordPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"index.html", "index.html",
"_auth--ytvFYf6.js" "_auth-CjQgMKAl.js"
], ],
"css": [ "css": [
"assets/ResetPasswordPage-DybfLMAw.css" "assets/ResetPasswordPage-DybfLMAw.css"
] ]
}, },
"src/pages/SchedulesPage.vue": { "src/pages/SchedulesPage.vue": {
"file": "assets/SchedulesPage-CliP1bMU.js", "file": "assets/SchedulesPage-BebL6WA6.js",
"name": "SchedulesPage", "name": "SchedulesPage",
"src": "src/pages/SchedulesPage.vue", "src": "src/pages/SchedulesPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"_accounts-Bta9cdL5.js", "_accounts-Cq6KNxFR.js",
"index.html" "index.html"
], ],
"css": [ "css": [
@@ -97,7 +97,7 @@
] ]
}, },
"src/pages/ScreenshotsPage.vue": { "src/pages/ScreenshotsPage.vue": {
"file": "assets/ScreenshotsPage-CqETBpbn.js", "file": "assets/ScreenshotsPage-M4eRrqBg.js",
"name": "ScreenshotsPage", "name": "ScreenshotsPage",
"src": "src/pages/ScreenshotsPage.vue", "src": "src/pages/ScreenshotsPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
@@ -109,7 +109,7 @@
] ]
}, },
"src/pages/VerifyResultPage.vue": { "src/pages/VerifyResultPage.vue": {
"file": "assets/VerifyResultPage-XFuV1ie5.js", "file": "assets/VerifyResultPage-D9tJlwTO.js",
"name": "VerifyResultPage", "name": "VerifyResultPage",
"src": "src/pages/VerifyResultPage.vue", "src": "src/pages/VerifyResultPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
.auth-wrap[data-v-9eb557e5]{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px}.auth-card[data-v-9eb557e5]{width:100%;max-width:420px;border-radius:var(--app-radius);border:1px solid var(--app-border);box-shadow:var(--app-shadow)}.brand[data-v-9eb557e5]{margin-bottom:14px}.brand-title[data-v-9eb557e5]{font-size:18px;font-weight:900}.brand-sub[data-v-9eb557e5]{margin-top:4px;font-size:12px}.links[data-v-9eb557e5]{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:2px 0 10px;flex-wrap:wrap}.submit-btn[data-v-9eb557e5]{width:100%}.foot[data-v-9eb557e5]{margin-top:14px;display:flex;align-items:center;justify-content:center;gap:6px}.dialog-form[data-v-9eb557e5]{margin-top:10px}.captcha-row[data-v-9eb557e5]{display:flex;align-items:center;gap:10px;width:100%}.captcha-img[data-v-9eb557e5]{height:40px;border:1px solid var(--app-border);border-radius:8px;cursor:pointer;-webkit-user-select:none;user-select:none}@media(max-width:480px){.captcha-img[data-v-9eb557e5]{height:38px}}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
.login-page[data-v-60947b3b]{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px;position:relative;background:linear-gradient(135deg,#eef2ff,#f6f7fb 45%,#ecfeff)}.login-page[data-v-60947b3b]:before{content:"";position:fixed;inset:0;background:radial-gradient(800px 500px at 15% 20%,rgba(59,130,246,.18),transparent 60%),radial-gradient(700px 420px at 85% 70%,rgba(124,58,237,.16),transparent 55%);pointer-events:none}.login-container[data-v-60947b3b]{width:100%;max-width:420px;background:#fff;border-radius:16px;box-shadow:0 18px 60px #11182726;border:1px solid rgba(17,24,39,.08);padding:38px 34px;position:relative;z-index:1}.login-header[data-v-60947b3b]{text-align:center;margin-bottom:28px}.login-badge[data-v-60947b3b]{display:inline-block;background:#3b82f61a;color:#1d4ed8;padding:6px 14px;border-radius:999px;font-size:12px;font-weight:700;margin-bottom:14px}.login-header h1[data-v-60947b3b]{font-size:24px;color:#111827;margin:0 0 10px;letter-spacing:.2px}.login-header p[data-v-60947b3b]{margin:0;color:#6b7280;font-size:14px}.form-group[data-v-60947b3b]{margin-bottom:20px}.form-group label[data-v-60947b3b]{display:block;margin-bottom:8px;color:#111827;font-weight:700;font-size:13px}.login-input[data-v-60947b3b] .el-input__wrapper{border-radius:10px;min-height:44px;background:#ffffffe6;box-shadow:0 0 0 1px #11182724 inset;transition:box-shadow .2s}.login-input[data-v-60947b3b] .el-input__wrapper.is-focus{box-shadow:0 0 0 1px #3b82f6b3 inset,0 0 0 4px #3b82f629}.login-input[data-v-60947b3b] .el-input__inner{font-size:14px}.btn-login[data-v-60947b3b]{width:100%;padding:12px;border:none;border-radius:10px;background:linear-gradient(135deg,#2563eb,#7c3aed);color:#fff;font-size:16px;font-weight:800;cursor:pointer;transition:transform .15s,filter .15s}.btn-login[data-v-60947b3b]:hover:not(:disabled){transform:translateY(-2px);filter:brightness(1.02)}.btn-login[data-v-60947b3b]:active:not(:disabled){transform:translateY(0)}.btn-login[data-v-60947b3b]:disabled{cursor:not-allowed;opacity:.8}.action-links[data-v-60947b3b]{margin-top:14px;display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap}.link-btn[data-v-60947b3b]{border:none;background:none;color:#2563eb;font-size:13px;font-weight:700;cursor:pointer;padding:0}.link-btn[data-v-60947b3b]:hover{text-decoration:underline}.register-row[data-v-60947b3b]{margin-top:16px;display:flex;justify-content:center;align-items:center;gap:8px;color:#6b7280;font-size:13px}.back-link[data-v-60947b3b]{text-align:center;margin-top:18px;color:#6b7280;font-size:13px}.back-link a[data-v-60947b3b]{margin-left:6px;color:#2563eb;text-decoration:none;font-weight:700}.back-link a[data-v-60947b3b]:hover{text-decoration:underline}.dialog-form[data-v-60947b3b]{margin-top:10px}.alert[data-v-60947b3b]{margin-top:12px}.captcha-row[data-v-60947b3b]{display:flex;align-items:center;gap:10px;width:100%}.captcha-input[data-v-60947b3b]{flex:1;min-width:0}.captcha-img[data-v-60947b3b]{height:46px;border:1px solid rgba(17,24,39,.14);border-radius:8px;cursor:pointer;-webkit-user-select:none;user-select:none}.captcha-refresh[data-v-60947b3b]{height:44px;padding:0 14px;border:1px solid rgba(17,24,39,.14);border-radius:10px;background:#f8fafc;color:#111827;font-size:13px;cursor:pointer}.captcha-refresh[data-v-60947b3b]:hover{background:#f1f5f9}@media(max-width:480px){.login-page[data-v-60947b3b]{align-items:flex-start;padding:20px 12px 12px}.login-container[data-v-60947b3b]{max-width:100%;padding:28px 20px;border-radius:14px}.login-header h1[data-v-60947b3b]{font-size:22px}.btn-login[data-v-60947b3b]{padding:13px;font-size:15px}.captcha-img[data-v-60947b3b]{height:42px}.captcha-refresh[data-v-60947b3b]{height:42px;padding:0 12px}}

View File

@@ -1 +1 @@
import{_ as M,r as j,a as d,c as B,o as A,b as U,d as l,w as o,e as v,u as H,f as b,g as n,h as N,i as E,j as P,t as q,k as S,E as c,v as z}from"./index-CPwwGffH.js";import{g as F,f as G,b as J}from"./auth--ytvFYf6.js";const O={class:"auth-wrap"},Q={class:"hint app-muted"},W={class:"captcha-row"},X=["src"],Y={class:"actions"},Z={__name:"RegisterPage",setup($){const T=H(),a=j({username:"",password:"",confirm_password:"",email:"",captcha:""}),f=d(!1),w=d(""),h=d(""),V=d(!1),t=d(""),_=d(""),k=d(""),K=B(()=>f.value?"邮箱 *":"邮箱(可选)"),R=B(()=>f.value?"必填,用于账号验证":"选填,用于找回密码和接收通知");async function y(){try{const u=await F();h.value=u?.session_id||"",w.value=u?.captcha_image||"",a.captcha=""}catch{h.value="",w.value=""}}async function D(){try{const u=await G();f.value=!!u?.register_verify_enabled}catch{f.value=!1}}function I(){t.value="",_.value="",k.value=""}async function C(){I();const u=a.username.trim(),e=a.password,g=a.confirm_password,s=a.email.trim(),i=a.captcha.trim();if(u.length<3){t.value="用户名至少3个字符",c.error(t.value);return}const p=z(e);if(!p.ok){t.value=p.message||"密码格式不正确",c.error(t.value);return}if(e!==g){t.value="两次输入的密码不一致",c.error(t.value);return}if(f.value&&!s){t.value="请填写邮箱地址用于账号验证",c.error(t.value);return}if(s&&!s.includes("@")){t.value="邮箱格式不正确",c.error(t.value);return}if(!i){t.value="请输入验证码",c.error(t.value);return}V.value=!0;try{const m=await J({username:u,password:e,email:s,captcha_session:h.value,captcha:i});_.value=m?.message||"注册成功",k.value=m?.need_verify?"请检查您的邮箱(包括垃圾邮件文件夹)":"",c.success("注册成功"),a.username="",a.password="",a.confirm_password="",a.email="",a.captcha="",setTimeout(()=>{window.location.href="/login"},3e3)}catch(m){const x=m?.response?.data;t.value=x?.error||"注册失败",c.error(t.value),await y()}finally{V.value=!1}}function L(){T.push("/login")}return A(async()=>{await y(),await D()}),(u,e)=>{const g=v("el-alert"),s=v("el-input"),i=v("el-form-item"),p=v("el-button"),m=v("el-form"),x=v("el-card");return b(),U("div",O,[l(x,{shadow:"never",class:"auth-card","body-style":{padding:"22px"}},{default:o(()=>[e[11]||(e[11]=n("div",{class:"brand"},[n("div",{class:"brand-title"},"知识管理平台"),n("div",{class:"brand-sub app-muted"},"用户注册")],-1)),t.value?(b(),N(g,{key:0,type:"error",closable:!1,title:t.value,"show-icon":"",class:"alert"},null,8,["title"])):E("",!0),_.value?(b(),N(g,{key:1,type:"success",closable:!1,title:_.value,description:k.value,"show-icon":"",class:"alert"},null,8,["title","description"])):E("",!0),l(m,{"label-position":"top"},{default:o(()=>[l(i,{label:"用户名 *"},{default:o(()=>[l(s,{modelValue:a.username,"onUpdate:modelValue":e[0]||(e[0]=r=>a.username=r),placeholder:"至少3个字符",autocomplete:"username"},null,8,["modelValue"]),e[5]||(e[5]=n("div",{class:"hint app-muted"},"至少3个字符",-1))]),_:1}),l(i,{label:"密码 *"},{default:o(()=>[l(s,{modelValue:a.password,"onUpdate:modelValue":e[1]||(e[1]=r=>a.password=r),type:"password","show-password":"",placeholder:"至少8位且包含字母和数字",autocomplete:"new-password"},null,8,["modelValue"]),e[6]||(e[6]=n("div",{class:"hint app-muted"},"至少8位且包含字母和数字",-1))]),_:1}),l(i,{label:"确认密码 *"},{default:o(()=>[l(s,{modelValue:a.confirm_password,"onUpdate:modelValue":e[2]||(e[2]=r=>a.confirm_password=r),type:"password","show-password":"",placeholder:"请再次输入密码",autocomplete:"new-password",onKeyup:P(C,["enter"])},null,8,["modelValue"])]),_:1}),l(i,{label:K.value},{default:o(()=>[l(s,{modelValue:a.email,"onUpdate:modelValue":e[3]||(e[3]=r=>a.email=r),placeholder:"name@example.com",autocomplete:"email"},null,8,["modelValue"]),n("div",Q,q(R.value),1)]),_:1},8,["label"]),l(i,{label:"验证码 *"},{default:o(()=>[n("div",W,[l(s,{modelValue:a.captcha,"onUpdate:modelValue":e[4]||(e[4]=r=>a.captcha=r),placeholder:"请输入验证码",onKeyup:P(C,["enter"])},null,8,["modelValue"]),w.value?(b(),U("img",{key:0,class:"captcha-img",src:w.value,alt:"验证码",title:"点击刷新",onClick:y},null,8,X)):E("",!0),l(p,{onClick:y},{default:o(()=>[...e[7]||(e[7]=[S("刷新",-1)])]),_:1})])]),_:1})]),_:1}),l(p,{type:"primary",class:"submit-btn",loading:V.value,onClick:C},{default:o(()=>[...e[8]||(e[8]=[S("注册",-1)])]),_:1},8,["loading"]),n("div",Y,[e[10]||(e[10]=n("span",{class:"app-muted"},"已有账号?",-1)),l(p,{link:"",type:"primary",onClick:L},{default:o(()=>[...e[9]||(e[9]=[S("立即登录",-1)])]),_:1})])]),_:1})])}}},te=M(Z,[["__scopeId","data-v-a9d7804f"]]);export{te as default}; import{_ as M,r as j,a as d,c as B,o as A,b as U,e as l,h as o,g as v,u as H,i as b,d as n,j as N,f as E,w as P,t as q,k as S,E as c,v as z}from"./index-DMtbRy1f.js";import{g as F,f as G,b as J}from"./auth-CjQgMKAl.js";const O={class:"auth-wrap"},Q={class:"hint app-muted"},W={class:"captcha-row"},X=["src"],Y={class:"actions"},Z={__name:"RegisterPage",setup($){const T=H(),a=j({username:"",password:"",confirm_password:"",email:"",captcha:""}),f=d(!1),w=d(""),h=d(""),V=d(!1),t=d(""),_=d(""),k=d(""),K=B(()=>f.value?"邮箱 *":"邮箱(可选)"),R=B(()=>f.value?"必填,用于账号验证":"选填,用于找回密码和接收通知");async function y(){try{const u=await F();h.value=u?.session_id||"",w.value=u?.captcha_image||"",a.captcha=""}catch{h.value="",w.value=""}}async function D(){try{const u=await G();f.value=!!u?.register_verify_enabled}catch{f.value=!1}}function I(){t.value="",_.value="",k.value=""}async function C(){I();const u=a.username.trim(),e=a.password,g=a.confirm_password,s=a.email.trim(),i=a.captcha.trim();if(u.length<3){t.value="用户名至少3个字符",c.error(t.value);return}const p=z(e);if(!p.ok){t.value=p.message||"密码格式不正确",c.error(t.value);return}if(e!==g){t.value="两次输入的密码不一致",c.error(t.value);return}if(f.value&&!s){t.value="请填写邮箱地址用于账号验证",c.error(t.value);return}if(s&&!s.includes("@")){t.value="邮箱格式不正确",c.error(t.value);return}if(!i){t.value="请输入验证码",c.error(t.value);return}V.value=!0;try{const m=await J({username:u,password:e,email:s,captcha_session:h.value,captcha:i});_.value=m?.message||"注册成功",k.value=m?.need_verify?"请检查您的邮箱(包括垃圾邮件文件夹)":"",c.success("注册成功"),a.username="",a.password="",a.confirm_password="",a.email="",a.captcha="",setTimeout(()=>{window.location.href="/login"},3e3)}catch(m){const x=m?.response?.data;t.value=x?.error||"注册失败",c.error(t.value),await y()}finally{V.value=!1}}function L(){T.push("/login")}return A(async()=>{await y(),await D()}),(u,e)=>{const g=v("el-alert"),s=v("el-input"),i=v("el-form-item"),p=v("el-button"),m=v("el-form"),x=v("el-card");return b(),U("div",O,[l(x,{shadow:"never",class:"auth-card","body-style":{padding:"22px"}},{default:o(()=>[e[11]||(e[11]=n("div",{class:"brand"},[n("div",{class:"brand-title"},"知识管理平台"),n("div",{class:"brand-sub app-muted"},"用户注册")],-1)),t.value?(b(),N(g,{key:0,type:"error",closable:!1,title:t.value,"show-icon":"",class:"alert"},null,8,["title"])):E("",!0),_.value?(b(),N(g,{key:1,type:"success",closable:!1,title:_.value,description:k.value,"show-icon":"",class:"alert"},null,8,["title","description"])):E("",!0),l(m,{"label-position":"top"},{default:o(()=>[l(i,{label:"用户名 *"},{default:o(()=>[l(s,{modelValue:a.username,"onUpdate:modelValue":e[0]||(e[0]=r=>a.username=r),placeholder:"至少3个字符",autocomplete:"username"},null,8,["modelValue"]),e[5]||(e[5]=n("div",{class:"hint app-muted"},"至少3个字符",-1))]),_:1}),l(i,{label:"密码 *"},{default:o(()=>[l(s,{modelValue:a.password,"onUpdate:modelValue":e[1]||(e[1]=r=>a.password=r),type:"password","show-password":"",placeholder:"至少8位且包含字母和数字",autocomplete:"new-password"},null,8,["modelValue"]),e[6]||(e[6]=n("div",{class:"hint app-muted"},"至少8位且包含字母和数字",-1))]),_:1}),l(i,{label:"确认密码 *"},{default:o(()=>[l(s,{modelValue:a.confirm_password,"onUpdate:modelValue":e[2]||(e[2]=r=>a.confirm_password=r),type:"password","show-password":"",placeholder:"请再次输入密码",autocomplete:"new-password",onKeyup:P(C,["enter"])},null,8,["modelValue"])]),_:1}),l(i,{label:K.value},{default:o(()=>[l(s,{modelValue:a.email,"onUpdate:modelValue":e[3]||(e[3]=r=>a.email=r),placeholder:"name@example.com",autocomplete:"email"},null,8,["modelValue"]),n("div",Q,q(R.value),1)]),_:1},8,["label"]),l(i,{label:"验证码 *"},{default:o(()=>[n("div",W,[l(s,{modelValue:a.captcha,"onUpdate:modelValue":e[4]||(e[4]=r=>a.captcha=r),placeholder:"请输入验证码",onKeyup:P(C,["enter"])},null,8,["modelValue"]),w.value?(b(),U("img",{key:0,class:"captcha-img",src:w.value,alt:"验证码",title:"点击刷新",onClick:y},null,8,X)):E("",!0),l(p,{onClick:y},{default:o(()=>[...e[7]||(e[7]=[S("刷新",-1)])]),_:1})])]),_:1})]),_:1}),l(p,{type:"primary",class:"submit-btn",loading:V.value,onClick:C},{default:o(()=>[...e[8]||(e[8]=[S("注册",-1)])]),_:1},8,["loading"]),n("div",Y,[e[10]||(e[10]=n("span",{class:"app-muted"},"已有账号?",-1)),l(p,{link:"",type:"primary",onClick:L},{default:o(()=>[...e[9]||(e[9]=[S("立即登录",-1)])]),_:1})])]),_:1})])}}},te=M(Z,[["__scopeId","data-v-a9d7804f"]]);export{te as default};

View File

@@ -1 +1 @@
import{_ as L,a as n,l as M,r as U,c as j,o as F,m as K,b as v,d as s,w as a,e as l,u as D,f as w,g as m,F as T,k,h as q,i as x,j as z,t as G,v as H,E as y}from"./index-CPwwGffH.js";import{c as J}from"./auth--ytvFYf6.js";const O={class:"auth-wrap"},Q={class:"actions"},W={class:"actions"},X={key:0,class:"app-muted"},Y={__name:"ResetPasswordPage",setup(Z){const B=M(),A=D(),r=n(String(B.params.token||"")),i=n(!0),b=n(""),t=U({newPassword:"",confirmPassword:""}),g=n(!1),_=n(""),d=n(0);let u=null;function C(){if(typeof window>"u")return null;const o=window.__APP_INITIAL_STATE__;return!o||typeof o!="object"?null:(window.__APP_INITIAL_STATE__=null,o)}const I=j(()=>!!(i.value&&r.value&&!_.value));function S(){A.push("/login")}function N(){d.value=3,u=window.setInterval(()=>{d.value-=1,d.value<=0&&(window.clearInterval(u),u=null,window.location.href="/login")},1e3)}async function V(){if(!I.value)return;const o=t.newPassword,e=t.confirmPassword,c=H(o);if(!c.ok){y.error(c.message);return}if(o!==e){y.error("两次输入的密码不一致");return}g.value=!0;try{await J({token:r.value,new_password:o}),_.value="密码重置成功3秒后跳转到登录页面...",y.success("密码重置成功"),N()}catch(p){const f=p?.response?.data;y.error(f?.error||"重置失败")}finally{g.value=!1}}return F(()=>{const o=C();o?.page==="reset_password"?(r.value=String(o?.token||r.value||""),i.value=!!o?.valid,b.value=o?.error_message||(i.value?"":"重置链接无效或已过期,请重新申请密码重置")):r.value||(i.value=!1,b.value="重置链接无效或已过期,请重新申请密码重置")}),K(()=>{u&&window.clearInterval(u)}),(o,e)=>{const c=l("el-alert"),p=l("el-button"),f=l("el-input"),h=l("el-form-item"),R=l("el-form"),E=l("el-card");return w(),v("div",O,[s(E,{shadow:"never",class:"auth-card","body-style":{padding:"22px"}},{default:a(()=>[e[5]||(e[5]=m("div",{class:"brand"},[m("div",{class:"brand-title"},"知识管理平台"),m("div",{class:"brand-sub app-muted"},"重置密码")],-1)),i.value?(w(),v(T,{key:1},[_.value?(w(),q(c,{key:0,type:"success",closable:!1,title:"重置成功",description:_.value,"show-icon":"",class:"alert"},null,8,["description"])):x("",!0),s(R,{"label-position":"top"},{default:a(()=>[s(h,{label:"新密码至少8位且包含字母和数字"},{default:a(()=>[s(f,{modelValue:t.newPassword,"onUpdate:modelValue":e[0]||(e[0]=P=>t.newPassword=P),type:"password","show-password":"",placeholder:"请输入新密码",autocomplete:"new-password"},null,8,["modelValue"])]),_:1}),s(h,{label:"确认密码"},{default:a(()=>[s(f,{modelValue:t.confirmPassword,"onUpdate:modelValue":e[1]||(e[1]=P=>t.confirmPassword=P),type:"password","show-password":"",placeholder:"请再次输入新密码",autocomplete:"new-password",onKeyup:z(V,["enter"])},null,8,["modelValue"])]),_:1})]),_:1}),s(p,{type:"primary",class:"submit-btn",loading:g.value,disabled:!I.value,onClick:V},{default:a(()=>[...e[3]||(e[3]=[k(" 确认重置 ",-1)])]),_:1},8,["loading","disabled"]),m("div",W,[s(p,{link:"",type:"primary",onClick:S},{default:a(()=>[...e[4]||(e[4]=[k("返回登录",-1)])]),_:1}),d.value>0?(w(),v("span",X,G(d.value)+" 秒后自动跳转…",1)):x("",!0)])],64)):(w(),v(T,{key:0},[s(c,{type:"error",closable:!1,title:"链接已失效",description:b.value,"show-icon":""},null,8,["description"]),m("div",Q,[s(p,{type:"primary",onClick:S},{default:a(()=>[...e[2]||(e[2]=[k("返回登录",-1)])]),_:1})])],64))]),_:1})])}}},oe=L(Y,[["__scopeId","data-v-0bbb511c"]]);export{oe as default}; import{_ as L,a as n,l as M,r as U,c as j,o as F,m as K,b as v,e as s,h as a,g as l,u as D,i as w,d as m,F as T,k,j as q,f as x,w as z,t as G,v as H,E as y}from"./index-DMtbRy1f.js";import{c as J}from"./auth-CjQgMKAl.js";const O={class:"auth-wrap"},Q={class:"actions"},W={class:"actions"},X={key:0,class:"app-muted"},Y={__name:"ResetPasswordPage",setup(Z){const B=M(),A=D(),r=n(String(B.params.token||"")),i=n(!0),b=n(""),t=U({newPassword:"",confirmPassword:""}),g=n(!1),_=n(""),d=n(0);let u=null;function C(){if(typeof window>"u")return null;const o=window.__APP_INITIAL_STATE__;return!o||typeof o!="object"?null:(window.__APP_INITIAL_STATE__=null,o)}const I=j(()=>!!(i.value&&r.value&&!_.value));function S(){A.push("/login")}function N(){d.value=3,u=window.setInterval(()=>{d.value-=1,d.value<=0&&(window.clearInterval(u),u=null,window.location.href="/login")},1e3)}async function V(){if(!I.value)return;const o=t.newPassword,e=t.confirmPassword,c=H(o);if(!c.ok){y.error(c.message);return}if(o!==e){y.error("两次输入的密码不一致");return}g.value=!0;try{await J({token:r.value,new_password:o}),_.value="密码重置成功3秒后跳转到登录页面...",y.success("密码重置成功"),N()}catch(p){const f=p?.response?.data;y.error(f?.error||"重置失败")}finally{g.value=!1}}return F(()=>{const o=C();o?.page==="reset_password"?(r.value=String(o?.token||r.value||""),i.value=!!o?.valid,b.value=o?.error_message||(i.value?"":"重置链接无效或已过期,请重新申请密码重置")):r.value||(i.value=!1,b.value="重置链接无效或已过期,请重新申请密码重置")}),K(()=>{u&&window.clearInterval(u)}),(o,e)=>{const c=l("el-alert"),p=l("el-button"),f=l("el-input"),h=l("el-form-item"),R=l("el-form"),E=l("el-card");return w(),v("div",O,[s(E,{shadow:"never",class:"auth-card","body-style":{padding:"22px"}},{default:a(()=>[e[5]||(e[5]=m("div",{class:"brand"},[m("div",{class:"brand-title"},"知识管理平台"),m("div",{class:"brand-sub app-muted"},"重置密码")],-1)),i.value?(w(),v(T,{key:1},[_.value?(w(),q(c,{key:0,type:"success",closable:!1,title:"重置成功",description:_.value,"show-icon":"",class:"alert"},null,8,["description"])):x("",!0),s(R,{"label-position":"top"},{default:a(()=>[s(h,{label:"新密码至少8位且包含字母和数字"},{default:a(()=>[s(f,{modelValue:t.newPassword,"onUpdate:modelValue":e[0]||(e[0]=P=>t.newPassword=P),type:"password","show-password":"",placeholder:"请输入新密码",autocomplete:"new-password"},null,8,["modelValue"])]),_:1}),s(h,{label:"确认密码"},{default:a(()=>[s(f,{modelValue:t.confirmPassword,"onUpdate:modelValue":e[1]||(e[1]=P=>t.confirmPassword=P),type:"password","show-password":"",placeholder:"请再次输入新密码",autocomplete:"new-password",onKeyup:z(V,["enter"])},null,8,["modelValue"])]),_:1})]),_:1}),s(p,{type:"primary",class:"submit-btn",loading:g.value,disabled:!I.value,onClick:V},{default:a(()=>[...e[3]||(e[3]=[k(" 确认重置 ",-1)])]),_:1},8,["loading","disabled"]),m("div",W,[s(p,{link:"",type:"primary",onClick:S},{default:a(()=>[...e[4]||(e[4]=[k("返回登录",-1)])]),_:1}),d.value>0?(w(),v("span",X,G(d.value)+" 秒后自动跳转…",1)):x("",!0)])],64)):(w(),v(T,{key:0},[s(c,{type:"error",closable:!1,title:"链接已失效",description:b.value,"show-icon":""},null,8,["description"]),m("div",Q,[s(p,{type:"primary",onClick:S},{default:a(()=>[...e[2]||(e[2]=[k("返回登录",-1)])]),_:1})])],64))]),_:1})])}}},oe=L(Y,[["__scopeId","data-v-0bbb511c"]]);export{oe as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
import{_ as U,a as o,c as I,o as E,m as R,b as k,d as i,w as s,e as d,u as W,f as _,g as l,i as B,h as $,k as T,t as v}from"./index-CPwwGffH.js";const j={class:"auth-wrap"},z={class:"actions"},D={key:0,class:"countdown app-muted"},M={__name:"VerifyResultPage",setup(q){const x=W(),p=o(!1),f=o(""),m=o(""),w=o(""),y=o(""),r=o(""),u=o(""),c=o(""),n=o(0);let a=null;function C(){if(typeof window>"u")return null;const e=window.__APP_INITIAL_STATE__;return!e||typeof e!="object"?null:(window.__APP_INITIAL_STATE__=null,e)}function N(e){const t=!!e?.success;p.value=t,f.value=e?.title||(t?"验证成功":"验证失败"),m.value=e?.message||e?.error_message||(t?"操作已完成,现在可以继续使用系统。":"操作失败,请稍后重试。"),w.value=e?.primary_label||(t?"立即登录":"重新注册"),y.value=e?.primary_url||(t?"/login":"/register"),r.value=e?.secondary_label||(t?"":"返回登录"),u.value=e?.secondary_url||(t?"":"/login"),c.value=e?.redirect_url||(t?"/login":""),n.value=Number(e?.redirect_seconds||(t?5:0))||0}const A=I(()=>!!(r.value&&u.value)),b=I(()=>!!(c.value&&n.value>0));async function g(e){if(e){if(e.startsWith("http://")||e.startsWith("https://")){window.location.href=e;return}await x.push(e)}}function P(){b.value&&(a=window.setInterval(()=>{n.value-=1,n.value<=0&&(window.clearInterval(a),a=null,window.location.href=c.value)},1e3))}return E(()=>{const e=C();N(e),P()}),R(()=>{a&&window.clearInterval(a)}),(e,t)=>{const h=d("el-button"),V=d("el-result"),L=d("el-card");return _(),k("div",j,[i(L,{shadow:"never",class:"auth-card","body-style":{padding:"22px"}},{default:s(()=>[t[2]||(t[2]=l("div",{class:"brand"},[l("div",{class:"brand-title"},"知识管理平台"),l("div",{class:"brand-sub app-muted"},"验证结果")],-1)),i(V,{icon:p.value?"success":"error",title:f.value,"sub-title":m.value,class:"result"},{extra:s(()=>[l("div",z,[i(h,{type:"primary",onClick:t[0]||(t[0]=S=>g(y.value))},{default:s(()=>[T(v(w.value),1)]),_:1}),A.value?(_(),$(h,{key:0,onClick:t[1]||(t[1]=S=>g(u.value))},{default:s(()=>[T(v(r.value),1)]),_:1})):B("",!0)]),b.value?(_(),k("div",D,v(n.value)+" 秒后自动跳转... ",1)):B("",!0)]),_:1},8,["icon","title","sub-title"])]),_:1})])}}},G=U(M,[["__scopeId","data-v-1fc6b081"]]);export{G as default}; import{_ as U,a as o,c as I,o as E,m as R,b as k,e as i,h as s,g as d,u as j,i as _,d as l,f as B,j as W,k as T,t as v}from"./index-DMtbRy1f.js";const $={class:"auth-wrap"},z={class:"actions"},D={key:0,class:"countdown app-muted"},M={__name:"VerifyResultPage",setup(q){const x=j(),p=o(!1),f=o(""),m=o(""),w=o(""),y=o(""),r=o(""),u=o(""),c=o(""),n=o(0);let a=null;function C(){if(typeof window>"u")return null;const e=window.__APP_INITIAL_STATE__;return!e||typeof e!="object"?null:(window.__APP_INITIAL_STATE__=null,e)}function N(e){const t=!!e?.success;p.value=t,f.value=e?.title||(t?"验证成功":"验证失败"),m.value=e?.message||e?.error_message||(t?"操作已完成,现在可以继续使用系统。":"操作失败,请稍后重试。"),w.value=e?.primary_label||(t?"立即登录":"重新注册"),y.value=e?.primary_url||(t?"/login":"/register"),r.value=e?.secondary_label||(t?"":"返回登录"),u.value=e?.secondary_url||(t?"":"/login"),c.value=e?.redirect_url||(t?"/login":""),n.value=Number(e?.redirect_seconds||(t?5:0))||0}const A=I(()=>!!(r.value&&u.value)),b=I(()=>!!(c.value&&n.value>0));async function g(e){if(e){if(e.startsWith("http://")||e.startsWith("https://")){window.location.href=e;return}await x.push(e)}}function P(){b.value&&(a=window.setInterval(()=>{n.value-=1,n.value<=0&&(window.clearInterval(a),a=null,window.location.href=c.value)},1e3))}return E(()=>{const e=C();N(e),P()}),R(()=>{a&&window.clearInterval(a)}),(e,t)=>{const h=d("el-button"),V=d("el-result"),L=d("el-card");return _(),k("div",$,[i(L,{shadow:"never",class:"auth-card","body-style":{padding:"22px"}},{default:s(()=>[t[2]||(t[2]=l("div",{class:"brand"},[l("div",{class:"brand-title"},"知识管理平台"),l("div",{class:"brand-sub app-muted"},"验证结果")],-1)),i(V,{icon:p.value?"success":"error",title:f.value,"sub-title":m.value,class:"result"},{extra:s(()=>[l("div",z,[i(h,{type:"primary",onClick:t[0]||(t[0]=S=>g(y.value))},{default:s(()=>[T(v(w.value),1)]),_:1}),A.value?(_(),W(h,{key:0,onClick:t[1]||(t[1]=S=>g(u.value))},{default:s(()=>[T(v(r.value),1)]),_:1})):B("",!0)]),b.value?(_(),k("div",D,v(n.value)+" 秒后自动跳转... ",1)):B("",!0)]),_:1},8,["icon","title","sub-title"])]),_:1})])}}},G=U(M,[["__scopeId","data-v-1fc6b081"]]);export{G as default};

View File

@@ -1 +1 @@
import{p as c}from"./index-CPwwGffH.js";async function o(t={}){const{data:a}=await c.get("/accounts",{params:t});return a}async function u(t){const{data:a}=await c.post("/accounts",t);return a}async function r(t,a){const{data:n}=await c.put(`/accounts/${t}`,a);return n}async function e(t){const{data:a}=await c.delete(`/accounts/${t}`);return a}async function i(t,a){const{data:n}=await c.put(`/accounts/${t}/remark`,a);return n}async function p(t,a){const{data:n}=await c.post(`/accounts/${t}/start`,a);return n}async function d(t){const{data:a}=await c.post(`/accounts/${t}/stop`,{});return a}async function f(t){const{data:a}=await c.post("/accounts/batch/start",t);return a}async function w(t){const{data:a}=await c.post("/accounts/batch/stop",t);return a}async function y(){const{data:t}=await c.post("/accounts/clear",{});return t}async function A(t,a={}){const{data:n}=await c.post(`/accounts/${t}/screenshot`,a);return n}export{w as a,f as b,y as c,d,e,o as f,u as g,i as h,p as s,A as t,r as u}; import{p as c}from"./index-DMtbRy1f.js";async function o(t={}){const{data:a}=await c.get("/accounts",{params:t});return a}async function u(t){const{data:a}=await c.post("/accounts",t);return a}async function r(t,a){const{data:n}=await c.put(`/accounts/${t}`,a);return n}async function e(t){const{data:a}=await c.delete(`/accounts/${t}`);return a}async function i(t,a){const{data:n}=await c.put(`/accounts/${t}/remark`,a);return n}async function p(t,a){const{data:n}=await c.post(`/accounts/${t}/start`,a);return n}async function d(t){const{data:a}=await c.post(`/accounts/${t}/stop`,{});return a}async function f(t){const{data:a}=await c.post("/accounts/batch/start",t);return a}async function w(t){const{data:a}=await c.post("/accounts/batch/stop",t);return a}async function y(){const{data:t}=await c.post("/accounts/clear",{});return t}async function A(t,a={}){const{data:n}=await c.post(`/accounts/${t}/screenshot`,a);return n}export{w as a,f as b,y as c,d,e,o as f,u as g,i as h,p as s,A as t,r as u};

View File

@@ -1 +1 @@
import{p as s}from"./index-CPwwGffH.js";async function r(){const{data:a}=await s.get("/email/verify-status");return a}async function o(){const{data:a}=await s.post("/generate_captcha",{});return a}async function e(a){const{data:t}=await s.post("/login",a);return t}async function i(a){const{data:t}=await s.post("/register",a);return t}async function c(a){const{data:t}=await s.post("/resend-verify-email",a);return t}async function f(a){const{data:t}=await s.post("/forgot-password",a);return t}async function u(a){const{data:t}=await s.post("/reset-password-confirm",a);return t}export{f as a,i as b,u as c,r as f,o as g,e as l,c as r}; import{p as s}from"./index-DMtbRy1f.js";async function r(){const{data:a}=await s.get("/email/verify-status");return a}async function o(){const{data:a}=await s.post("/generate_captcha",{});return a}async function e(a){const{data:t}=await s.post("/login",a);return t}async function i(a){const{data:t}=await s.post("/register",a);return t}async function c(a){const{data:t}=await s.post("/resend-verify-email",a);return t}async function f(a){const{data:t}=await s.post("/forgot-password",a);return t}async function u(a){const{data:t}=await s.post("/reset-password-confirm",a);return t}export{f as a,i as b,u as c,r as f,o as g,e as l,c as r};

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<title>知识管理平台</title> <title>知识管理平台</title>
<script type="module" crossorigin src="./assets/index-CPwwGffH.js"></script> <script type="module" crossorigin src="./assets/index-DMtbRy1f.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-BVjJVlht.css"> <link rel="stylesheet" crossorigin href="./assets/index-BVjJVlht.css">
</head> </head>
<body> <body>