perf: optimize polling, stats cache, and frontend chunk splitting

This commit is contained in:
2026-02-07 11:41:49 +08:00
parent 21c537da10
commit 04b94d7fb2
73 changed files with 516 additions and 203 deletions
+38 -5
View File
@@ -405,18 +405,51 @@ async function refreshAll(options = {}) {
}
}
const REPORT_POLL_ACTIVE_MS = 5000
const REPORT_POLL_HIDDEN_MS = 20000
let refreshTimer = null
function isPageHidden() {
if (typeof document === 'undefined') return false
return document.visibilityState === 'hidden'
}
function currentRefreshDelay() {
return isPageHidden() ? REPORT_POLL_HIDDEN_MS : REPORT_POLL_ACTIVE_MS
}
function stopRefreshLoop() {
if (!refreshTimer) return
clearTimeout(refreshTimer)
refreshTimer = null
}
function scheduleRefreshLoop() {
stopRefreshLoop()
refreshTimer = window.setTimeout(async () => {
refreshTimer = null
await refreshAll({ showLoading: false }).catch(() => {})
scheduleRefreshLoop()
}, currentRefreshDelay())
}
function onVisibilityChange() {
scheduleRefreshLoop()
}
onMounted(() => {
refreshAll({ showLoading: false })
refreshTimer = setInterval(() => refreshAll({ showLoading: false }), 5000)
.catch(() => {})
.finally(() => {
scheduleRefreshLoop()
})
window.addEventListener('visibilitychange', onVisibilityChange)
})
onUnmounted(() => {
if (refreshTimer) {
clearInterval(refreshTimer)
refreshTimer = null
}
stopRefreshLoop()
window.removeEventListener('visibilitychange', onVisibilityChange)
})
</script>
+13
View File
@@ -8,5 +8,18 @@ export default defineConfig({
outDir: '../static/admin',
emptyOutDir: true,
manifest: true,
cssCodeSplit: true,
chunkSizeWarningLimit: 800,
rollupOptions: {
output: {
manualChunks(id) {
if (!id.includes('node_modules')) return
if (id.includes('/vue/') || id.includes('/vue-router/')) return 'vendor-vue'
if (id.includes('/element-plus/') || id.includes('/@element-plus/')) return 'vendor-element'
if (id.includes('/axios/')) return 'vendor-axios'
return 'vendor'
},
},
},
},
})
+59 -9
View File
@@ -532,6 +532,17 @@ function bindSocket() {
let unbindSocket = null
let statsTimer = null
let kdocsStatusTimer = null
const STATS_POLL_ACTIVE_MS = 10_000
const STATS_POLL_HIDDEN_MS = 30_000
const KDOCS_STATUS_POLL_ACTIVE_MS = 60_000
const KDOCS_STATUS_POLL_HIDDEN_MS = 180_000
function isPageHidden() {
if (typeof document === 'undefined') return false
return document.visibilityState === 'hidden'
}
const shouldPollStats = computed(() => {
// 仅在“真正执行中”才轮询(排队中不轮询,避免空转导致页面闪烁)
@@ -543,15 +554,27 @@ const shouldPollStats = computed(() => {
})
})
function currentStatsPollDelay() {
return isPageHidden() ? STATS_POLL_HIDDEN_MS : STATS_POLL_ACTIVE_MS
}
function stopStatsPolling() {
if (!statsTimer) return
window.clearInterval(statsTimer)
window.clearTimeout(statsTimer)
statsTimer = null
}
function scheduleStatsPolling() {
if (statsTimer || !shouldPollStats.value) return
statsTimer = window.setTimeout(async () => {
statsTimer = null
await refreshStats({ silent: true }).catch(() => {})
scheduleStatsPolling()
}, currentStatsPollDelay())
}
function startStatsPolling() {
if (statsTimer) return
statsTimer = window.setInterval(() => refreshStats({ silent: true }), 10_000)
scheduleStatsPolling()
}
function syncStatsPolling(prevRunning = null) {
@@ -564,11 +587,37 @@ function syncStatsPolling(prevRunning = null) {
else stopStatsPolling()
}
watch(shouldPollStats, (running, prevRunning) => {
watch(shouldPollStats, (_running, prevRunning) => {
syncStatsPolling(prevRunning)
})
let kdocsStatusTimer = null
function currentKdocsStatusPollDelay() {
return isPageHidden() ? KDOCS_STATUS_POLL_HIDDEN_MS : KDOCS_STATUS_POLL_ACTIVE_MS
}
function stopKdocsStatusPolling() {
if (!kdocsStatusTimer) return
window.clearTimeout(kdocsStatusTimer)
kdocsStatusTimer = null
}
function scheduleKdocsStatusPolling() {
if (kdocsStatusTimer) return
kdocsStatusTimer = window.setTimeout(async () => {
kdocsStatusTimer = null
await loadKdocsStatus().catch(() => {})
scheduleKdocsStatusPolling()
}, currentKdocsStatusPollDelay())
}
function restartTimedPollingOnVisibilityChange() {
if (shouldPollStats.value) {
stopStatsPolling()
startStatsPolling()
}
stopKdocsStatusPolling()
scheduleKdocsStatusPolling()
}
onMounted(async () => {
if (!userStore.vipInfo) {
@@ -583,16 +632,17 @@ onMounted(async () => {
await loadKdocsSettings()
await loadKdocsStatus()
await refreshStats()
syncStatsPolling()
// 每60秒刷新 KDocs 状态
kdocsStatusTimer = window.setInterval(() => loadKdocsStatus(), 60_000)
syncStatsPolling()
scheduleKdocsStatusPolling()
window.addEventListener('visibilitychange', restartTimedPollingOnVisibilityChange)
})
onBeforeUnmount(() => {
if (unbindSocket) unbindSocket()
stopStatsPolling()
if (kdocsStatusTimer) window.clearInterval(kdocsStatusTimer)
stopKdocsStatusPolling()
window.removeEventListener('visibilitychange', restartTimedPollingOnVisibilityChange)
})
</script>
+14 -1
View File
@@ -8,6 +8,19 @@ export default defineConfig({
outDir: '../static/app',
emptyOutDir: true,
manifest: true,
cssCodeSplit: true,
chunkSizeWarningLimit: 800,
rollupOptions: {
output: {
manualChunks(id) {
if (!id.includes('node_modules')) return
if (id.includes('/vue/') || id.includes('/vue-router/') || id.includes('/pinia/')) return 'vendor-vue'
if (id.includes('/element-plus/') || id.includes('/@element-plus/')) return 'vendor-element'
if (id.includes('/socket.io-client/')) return 'vendor-socket'
if (id.includes('/axios/')) return 'vendor-axios'
return 'vendor'
},
},
},
},
})
+28 -29
View File
@@ -190,41 +190,40 @@ def get_system_stats() -> dict:
with db_pool.get_db() as conn:
cursor = conn.cursor()
total_users = _count_scalar(cursor, "SELECT COUNT(*) as count FROM users")
approved_users = _count_scalar(cursor, "SELECT COUNT(*) as count FROM users WHERE status = 'approved'")
new_users_today = _count_scalar(
cursor,
cursor.execute(
"""
SELECT COUNT(*) as count
FROM users
WHERE date(created_at) = date('now', 'localtime')
""",
)
new_users_7d = _count_scalar(
cursor,
"""
SELECT COUNT(*) as count
FROM users
WHERE datetime(created_at) >= datetime('now', 'localtime', '-7 days')
""",
)
total_accounts = _count_scalar(cursor, "SELECT COUNT(*) as count FROM accounts")
vip_users = _count_scalar(
cursor,
"""
SELECT COUNT(*) as count FROM users
WHERE vip_expire_time IS NOT NULL
SELECT
COUNT(*) AS total_users,
SUM(CASE WHEN status = 'approved' THEN 1 ELSE 0 END) AS approved_users,
SUM(CASE WHEN date(created_at) = date('now', 'localtime') THEN 1 ELSE 0 END) AS new_users_today,
SUM(CASE WHEN datetime(created_at) >= datetime('now', 'localtime', '-7 days') THEN 1 ELSE 0 END) AS new_users_7d,
SUM(
CASE
WHEN vip_expire_time IS NOT NULL
AND datetime(vip_expire_time) > datetime('now', 'localtime')
""",
THEN 1 ELSE 0
END
) AS vip_users
FROM users
"""
)
user_stats = cursor.fetchone() or {}
def _to_int(key: str) -> int:
try:
return int(user_stats[key] or 0)
except Exception:
return 0
total_accounts = _count_scalar(cursor, "SELECT COUNT(*) as count FROM accounts")
return {
"total_users": total_users,
"approved_users": approved_users,
"new_users_today": new_users_today,
"new_users_7d": new_users_7d,
"total_users": _to_int("total_users"),
"approved_users": _to_int("approved_users"),
"new_users_today": _to_int("new_users_today"),
"new_users_7d": _to_int("new_users_7d"),
"total_accounts": total_accounts,
"vip_users": vip_users,
"vip_users": _to_int("vip_users"),
}
+1 -1
View File
@@ -68,7 +68,7 @@ services:
# 健康检查(可选)
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:51233 || exit 1"]
interval: 5m
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
+38 -1
View File
@@ -4,6 +4,7 @@ from __future__ import annotations
import os
import socket
import threading
import time
from datetime import datetime
@@ -16,12 +17,37 @@ from services.time_utils import BEIJING_TZ, get_beijing_now
logger = get_logger("app")
_ADMIN_STATS_CACHE_TTL = max(1.0, float(os.environ.get("ADMIN_STATS_CACHE_TTL_SECONDS", "5")))
_admin_stats_cache: dict[str, object] = {"expires_at_monotonic": 0.0, "data": None}
_admin_stats_cache_lock = threading.Lock()
_DOCKER_STATS_CACHE_TTL = max(2.0, float(os.environ.get("ADMIN_DOCKER_STATS_CACHE_TTL_SECONDS", "5")))
_docker_stats_cache: dict[str, object] = {"expires_at_monotonic": 0.0, "data": None}
_docker_stats_cache_lock = threading.Lock()
def _get_system_stats_cached() -> dict:
now = time.monotonic()
with _admin_stats_cache_lock:
expires_at = float(_admin_stats_cache.get("expires_at_monotonic") or 0.0)
cached_data = _admin_stats_cache.get("data")
if isinstance(cached_data, dict) and now < expires_at:
return dict(cached_data)
fresh_data = database.get_system_stats() or {}
with _admin_stats_cache_lock:
_admin_stats_cache["data"] = dict(fresh_data)
_admin_stats_cache["expires_at_monotonic"] = now + _ADMIN_STATS_CACHE_TTL
return dict(fresh_data)
@admin_api_bp.route("/stats", methods=["GET"])
@admin_required
def get_system_stats():
"""获取系统统计"""
stats = database.get_system_stats()
stats = _get_system_stats_cached()
stats["admin_username"] = session.get("admin_username", "admin")
return jsonify(stats)
@@ -132,6 +158,13 @@ def _fill_host_service_stats(docker_status: dict) -> None:
@admin_required
def get_docker_stats():
"""获取容器运行状态(非容器部署时返回当前服务进程状态)"""
now = time.monotonic()
with _docker_stats_cache_lock:
expires_at = float(_docker_stats_cache.get("expires_at_monotonic") or 0.0)
cached_data = _docker_stats_cache.get("data")
if isinstance(cached_data, dict) and now < expires_at:
return jsonify(dict(cached_data))
docker_status = {
"running": False,
"container_name": "N/A",
@@ -245,4 +278,8 @@ def get_docker_stats():
logger.exception(f"获取容器/服务状态失败: {e}")
docker_status["status"] = f"Error: {e}"
with _docker_stats_cache_lock:
_docker_stats_cache["data"] = dict(docker_status)
_docker_stats_cache["expires_at_monotonic"] = now + _DOCKER_STATS_CACHE_TTL
return jsonify(docker_status)
+114 -40
View File
@@ -1,9 +1,10 @@
{
"_MetricGrid-CgcBn9pb.js": {
"file": "assets/MetricGrid-CgcBn9pb.js",
"_MetricGrid-Cbhb9OGV.js": {
"file": "assets/MetricGrid-Cbhb9OGV.js",
"name": "MetricGrid",
"imports": [
"index.html"
"index.html",
"_vendor-sLgkZK1v.js"
],
"css": [
"assets/MetricGrid-yP_dkP6X.css"
@@ -13,39 +14,76 @@
"file": "assets/MetricGrid-yP_dkP6X.css",
"src": "_MetricGrid-yP_dkP6X.css"
},
"_email-CVq2PrUv.js": {
"file": "assets/email-CVq2PrUv.js",
"_email-CqsrP_Ts.js": {
"file": "assets/email-CqsrP_Ts.js",
"name": "email",
"imports": [
"index.html"
]
},
"_system-DC-mm2Aw.js": {
"file": "assets/system-DC-mm2Aw.js",
"_system-In7Gh8x7.js": {
"file": "assets/system-In7Gh8x7.js",
"name": "system",
"imports": [
"index.html"
]
},
"_tasks-7DYyQLMx.js": {
"file": "assets/tasks-7DYyQLMx.js",
"_tasks-DZnsc1fC.js": {
"file": "assets/tasks-DZnsc1fC.js",
"name": "tasks",
"imports": [
"index.html"
]
},
"_users-UHxQPBbl.js": {
"file": "assets/users-UHxQPBbl.js",
"_users-CTuo5Ynz.js": {
"file": "assets/users-CTuo5Ynz.js",
"name": "users",
"imports": [
"index.html"
]
},
"_vendor-axios-B9ygI19o.js": {
"file": "assets/vendor-axios-B9ygI19o.js",
"name": "vendor-axios"
},
"_vendor-element-C68yOrAy.css": {
"file": "assets/vendor-element-C68yOrAy.css",
"src": "_vendor-element-C68yOrAy.css"
},
"_vendor-element-CJoVtPsD.js": {
"file": "assets/vendor-element-CJoVtPsD.js",
"name": "vendor-element",
"imports": [
"_vendor-sLgkZK1v.js",
"_vendor-vue-CWkOjFoA.js"
],
"css": [
"assets/vendor-element-C68yOrAy.css"
]
},
"_vendor-sLgkZK1v.js": {
"file": "assets/vendor-sLgkZK1v.js",
"name": "vendor"
},
"_vendor-vue-CWkOjFoA.js": {
"file": "assets/vendor-vue-CWkOjFoA.js",
"name": "vendor-vue",
"imports": [
"_vendor-sLgkZK1v.js",
"_vendor-element-CJoVtPsD.js"
]
},
"index.html": {
"file": "assets/index-Cg-w8G7A.js",
"file": "assets/index-D8t2quK2.js",
"name": "index",
"src": "index.html",
"isEntry": true,
"imports": [
"_vendor-sLgkZK1v.js",
"_vendor-vue-CWkOjFoA.js",
"_vendor-element-CJoVtPsD.js",
"_vendor-axios-B9ygI19o.js"
],
"dynamicImports": [
"src/pages/ReportPage.vue",
"src/pages/UsersPage.vue",
@@ -58,124 +96,160 @@
"src/pages/SettingsPage.vue"
],
"css": [
"assets/index-DRsk2q1y.css"
"assets/index-Tk47UJAg.css"
]
},
"src/pages/AnnouncementsPage.vue": {
"file": "assets/AnnouncementsPage-Xjvdn6OS.js",
"file": "assets/AnnouncementsPage-CaSWhmIw.js",
"name": "AnnouncementsPage",
"src": "src/pages/AnnouncementsPage.vue",
"isDynamicEntry": true,
"imports": [
"index.html"
"_vendor-element-CJoVtPsD.js",
"index.html",
"_vendor-sLgkZK1v.js",
"_vendor-vue-CWkOjFoA.js",
"_vendor-axios-B9ygI19o.js"
],
"css": [
"assets/AnnouncementsPage-DOwZaaOu.css"
]
},
"src/pages/EmailPage.vue": {
"file": "assets/EmailPage-CB0pDhEa.js",
"file": "assets/EmailPage-DlOkUKzK.js",
"name": "EmailPage",
"src": "src/pages/EmailPage.vue",
"isDynamicEntry": true,
"imports": [
"_email-CVq2PrUv.js",
"_email-CqsrP_Ts.js",
"index.html",
"_MetricGrid-CgcBn9pb.js"
"_MetricGrid-Cbhb9OGV.js",
"_vendor-element-CJoVtPsD.js",
"_vendor-sLgkZK1v.js",
"_vendor-vue-CWkOjFoA.js",
"_vendor-axios-B9ygI19o.js"
],
"css": [
"assets/EmailPage-BmPCDPYC.css"
]
},
"src/pages/FeedbacksPage.vue": {
"file": "assets/FeedbacksPage-Cek35_AN.js",
"file": "assets/FeedbacksPage-B8rr6rHD.js",
"name": "FeedbacksPage",
"src": "src/pages/FeedbacksPage.vue",
"isDynamicEntry": true,
"imports": [
"index.html",
"_MetricGrid-CgcBn9pb.js"
"_MetricGrid-Cbhb9OGV.js",
"_vendor-element-CJoVtPsD.js",
"_vendor-sLgkZK1v.js",
"_vendor-vue-CWkOjFoA.js",
"_vendor-axios-B9ygI19o.js"
],
"css": [
"assets/FeedbacksPage-mrXjCiV2.css"
]
},
"src/pages/LogsPage.vue": {
"file": "assets/LogsPage-DlgiquJf.js",
"file": "assets/LogsPage-WfvkzS-6.js",
"name": "LogsPage",
"src": "src/pages/LogsPage.vue",
"isDynamicEntry": true,
"imports": [
"_users-UHxQPBbl.js",
"_tasks-7DYyQLMx.js",
"index.html"
"_users-CTuo5Ynz.js",
"_tasks-DZnsc1fC.js",
"index.html",
"_vendor-element-CJoVtPsD.js",
"_vendor-sLgkZK1v.js",
"_vendor-vue-CWkOjFoA.js",
"_vendor-axios-B9ygI19o.js"
],
"css": [
"assets/LogsPage-D1bozCEo.css"
]
},
"src/pages/ReportPage.vue": {
"file": "assets/ReportPage-Bowqk0qw.js",
"file": "assets/ReportPage-GPt5J1Db.js",
"name": "ReportPage",
"src": "src/pages/ReportPage.vue",
"isDynamicEntry": true,
"imports": [
"_vendor-element-CJoVtPsD.js",
"index.html",
"_email-CVq2PrUv.js",
"_tasks-7DYyQLMx.js",
"_system-DC-mm2Aw.js",
"_MetricGrid-CgcBn9pb.js"
"_email-CqsrP_Ts.js",
"_tasks-DZnsc1fC.js",
"_system-In7Gh8x7.js",
"_MetricGrid-Cbhb9OGV.js",
"_vendor-sLgkZK1v.js",
"_vendor-vue-CWkOjFoA.js",
"_vendor-axios-B9ygI19o.js"
],
"css": [
"assets/ReportPage-BUAmM22W.css"
"assets/ReportPage-CnNjCmpq.css"
]
},
"src/pages/SecurityPage.vue": {
"file": "assets/SecurityPage-ZwNpU8eS.js",
"file": "assets/SecurityPage-BWFFA3z9.js",
"name": "SecurityPage",
"src": "src/pages/SecurityPage.vue",
"isDynamicEntry": true,
"imports": [
"index.html",
"_MetricGrid-CgcBn9pb.js"
"_MetricGrid-Cbhb9OGV.js",
"_vendor-element-CJoVtPsD.js",
"_vendor-sLgkZK1v.js",
"_vendor-vue-CWkOjFoA.js",
"_vendor-axios-B9ygI19o.js"
],
"css": [
"assets/SecurityPage-DN76ndc_.css"
]
},
"src/pages/SettingsPage.vue": {
"file": "assets/SettingsPage-CoSYWzHG.js",
"file": "assets/SettingsPage-3cNfdgGx.js",
"name": "SettingsPage",
"src": "src/pages/SettingsPage.vue",
"isDynamicEntry": true,
"imports": [
"index.html"
"index.html",
"_vendor-element-CJoVtPsD.js",
"_vendor-sLgkZK1v.js",
"_vendor-vue-CWkOjFoA.js",
"_vendor-axios-B9ygI19o.js"
],
"css": [
"assets/SettingsPage-DaB8PeRL.css"
]
},
"src/pages/SystemPage.vue": {
"file": "assets/SystemPage-Dg22nmv0.js",
"file": "assets/SystemPage-CJ2F6_EU.js",
"name": "SystemPage",
"src": "src/pages/SystemPage.vue",
"isDynamicEntry": true,
"imports": [
"_system-DC-mm2Aw.js",
"index.html"
"_system-In7Gh8x7.js",
"index.html",
"_vendor-element-CJoVtPsD.js",
"_vendor-sLgkZK1v.js",
"_vendor-vue-CWkOjFoA.js",
"_vendor-axios-B9ygI19o.js"
],
"css": [
"assets/SystemPage-DMyNBO3N.css"
]
},
"src/pages/UsersPage.vue": {
"file": "assets/UsersPage-BBavbhFt.js",
"file": "assets/UsersPage-KZ5WSZrO.js",
"name": "UsersPage",
"src": "src/pages/UsersPage.vue",
"isDynamicEntry": true,
"imports": [
"_users-UHxQPBbl.js",
"index.html"
"_users-CTuo5Ynz.js",
"index.html",
"_vendor-element-CJoVtPsD.js",
"_vendor-sLgkZK1v.js",
"_vendor-vue-CWkOjFoA.js",
"_vendor-axios-B9ygI19o.js"
],
"css": [
"assets/UsersPage-Cow_LicY.css"
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
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
@@ -0,0 +1 @@
import{_}from"./index-D8t2quK2.js";import{aW as c,z as s,A as t,R as r,ak as u,E as p,B as o,N as l,S as y,L as h,K as i,O as k,Q as n,P as v,D as f}from"./vendor-sLgkZK1v.js";const b={class:"metric-top"},x={key:0,class:"metric-icon"},B={class:"metric-label"},N={class:"metric-value"},g={key:0,class:"metric-hint app-muted"},C={__name:"MetricGrid",props:{items:{type:Array,default:()=>[]},loading:{type:Boolean,default:!1},minWidth:{type:Number,default:180}},setup(a){return(V,z)=>{const d=c("el-icon"),m=c("el-skeleton");return t(),s("div",{class:"metric-grid",style:f({"--metric-min":`${a.minWidth}px`})},[(t(!0),s(r,null,u(a.items,e=>(t(),s("div",{key:e?.key||e?.label,class:p(["metric-card",`metric-tone--${e?.tone||"blue"}`])},[o("div",b,[e?.icon?(t(),s("div",x,[y(d,null,{default:h(()=>[(t(),i(k(e.icon)))]),_:2},1024)])):l("",!0),o("div",B,n(e?.label||"-"),1)]),o("div",N,[a.loading?(t(),i(m,{key:0,rows:1,animated:""})):(t(),s(r,{key:1},[v(n(e?.value??0),1)],64))]),e?.hint||e?.sub?(t(),s("div",g,n(e?.hint||e?.sub),1)):l("",!0)],2))),128))],4)}}},S=_(C,[["__scopeId","data-v-00e217d4"]]);export{S as M};
@@ -1 +0,0 @@
import{_ as m,f as c,g as s,h as t,F as l,q as u,y as p,j as o,n as r,m as y,x as h,w as i,O as v,p as n,B as k,P as f}from"./index-Cg-w8G7A.js";const b={class:"metric-top"},x={key:0,class:"metric-icon"},g={class:"metric-label"},B={class:"metric-value"},C={key:0,class:"metric-hint app-muted"},N={__name:"MetricGrid",props:{items:{type:Array,default:()=>[]},loading:{type:Boolean,default:!1},minWidth:{type:Number,default:180}},setup(a){return(V,w)=>{const d=c("el-icon"),_=c("el-skeleton");return t(),s("div",{class:"metric-grid",style:f({"--metric-min":`${a.minWidth}px`})},[(t(!0),s(l,null,u(a.items,e=>(t(),s("div",{key:e?.key||e?.label,class:p(["metric-card",`metric-tone--${e?.tone||"blue"}`])},[o("div",b,[e?.icon?(t(),s("div",x,[y(d,null,{default:h(()=>[(t(),i(v(e.icon)))]),_:2},1024)])):r("",!0),o("div",g,n(e?.label||"-"),1)]),o("div",B,[a.loading?(t(),i(_,{key:0,rows:1,animated:""})):(t(),s(l,{key:1},[k(n(e?.value??0),1)],64))]),e?.hint||e?.sub?(t(),s("div",C,n(e?.hint||e?.sub),1)):r("",!0)],2))),128))],4)}}},z=m(N,[["__scopeId","data-v-00e217d4"]]);export{z as M};
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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
import{a as m,_ as h}from"./index-D8t2quK2.js";import{f as u,E as x}from"./vendor-element-CJoVtPsD.js";import{r as p,aW as i,z as T,A as P,B as r,S as a,L as o,P as b}from"./vendor-sLgkZK1v.js";import"./vendor-vue-CWkOjFoA.js";import"./vendor-axios-B9ygI19o.js";async function S(l){const{data:s}=await m.put("/admin/username",{new_username:l});return s}async function A(l){const{data:s}=await m.put("/admin/password",{new_password:l});return s}async function C(){const{data:l}=await m.post("/logout");return l}const E={class:"page-stack"},U={__name:"SettingsPage",setup(l){const s=p(""),d=p(""),n=p(!1);function k(t){const e=String(t||"");return e.length<8?{ok:!1,message:"密码长度至少8位"}:e.length>128?{ok:!1,message:"密码长度不能超过128个字符"}:!/[a-zA-Z]/.test(e)||!/\d/.test(e)?{ok:!1,message:"密码必须包含字母和数字"}:{ok:!0,message:""}}async function f(){try{await C()}catch{}finally{window.location.href="/yuyx"}}async function B(){const t=s.value.trim();if(!t){u.error("请输入新用户名");return}try{await x.confirm(`确定将管理员用户名修改为「${t}」吗?修改后需要重新登录。`,"修改用户名",{confirmButtonText:"确认修改",cancelButtonText:"取消",type:"warning"})}catch{return}n.value=!0;try{await S(t),u.success("用户名修改成功,请重新登录"),s.value="",setTimeout(f,1200)}catch{}finally{n.value=!1}}async function V(){const t=d.value;if(!t){u.error("请输入新密码");return}const e=k(t);if(!e.ok){u.error(e.message);return}try{await x.confirm("确定修改管理员密码吗?修改后需要重新登录。","修改密码",{confirmButtonText:"确认修改",cancelButtonText:"取消",type:"warning"})}catch{return}n.value=!0;try{await A(t),u.success("密码修改成功,请重新登录"),d.value="",setTimeout(f,1200)}catch{}finally{n.value=!1}}return(t,e)=>{const g=i("el-input"),v=i("el-form-item"),w=i("el-form"),y=i("el-button"),_=i("el-card");return P(),T("div",E,[e[7]||(e[7]=r("div",{class:"app-page-title"},[r("h2",null,"设置"),r("span",{class:"app-muted"},"管理员账号设置")],-1)),a(_,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:o(()=>[e[3]||(e[3]=r("h3",{class:"section-title"},"修改管理员用户名",-1)),a(w,{"label-width":"120px"},{default:o(()=>[a(v,{label:"新用户名"},{default:o(()=>[a(g,{modelValue:s.value,"onUpdate:modelValue":e[0]||(e[0]=c=>s.value=c),placeholder:"输入新用户名",disabled:n.value},null,8,["modelValue","disabled"])]),_:1})]),_:1}),a(y,{type:"primary",loading:n.value,onClick:B},{default:o(()=>[...e[2]||(e[2]=[b("保存用户名",-1)])]),_:1},8,["loading"])]),_:1}),a(_,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:o(()=>[e[5]||(e[5]=r("h3",{class:"section-title"},"修改管理员密码",-1)),a(w,{"label-width":"120px"},{default:o(()=>[a(v,{label:"新密码"},{default:o(()=>[a(g,{modelValue:d.value,"onUpdate:modelValue":e[1]||(e[1]=c=>d.value=c),type:"password","show-password":"",placeholder:"输入新密码",disabled:n.value},null,8,["modelValue","disabled"])]),_:1})]),_:1}),a(y,{type:"primary",loading:n.value,onClick:V},{default:o(()=>[...e[4]||(e[4]=[b("保存密码",-1)])]),_:1},8,["loading"]),e[6]||(e[6]=r("div",{class:"help"},"建议使用更强密码(至少8位且包含字母与数字)。",-1))]),_:1})])}}},W=h(U,[["__scopeId","data-v-83d3840a"]]);export{W as default};
@@ -1 +0,0 @@
import{a as m,_ as h,r as p,f as u,g as T,h as C,j as r,m as a,x as l,B as x,C as i,E as b}from"./index-Cg-w8G7A.js";async function P(o){const{data:s}=await m.put("/admin/username",{new_username:o});return s}async function E(o){const{data:s}=await m.put("/admin/password",{new_password:o});return s}async function S(){const{data:o}=await m.post("/logout");return o}const U={class:"page-stack"},A={__name:"SettingsPage",setup(o){const s=p(""),d=p(""),n=p(!1);function k(t){const e=String(t||"");return e.length<8?{ok:!1,message:"密码长度至少8位"}:e.length>128?{ok:!1,message:"密码长度不能超过128个字符"}:!/[a-zA-Z]/.test(e)||!/\d/.test(e)?{ok:!1,message:"密码必须包含字母和数字"}:{ok:!0,message:""}}async function f(){try{await S()}catch{}finally{window.location.href="/yuyx"}}async function B(){const t=s.value.trim();if(!t){i.error("请输入新用户名");return}try{await b.confirm(`确定将管理员用户名修改为「${t}」吗?修改后需要重新登录。`,"修改用户名",{confirmButtonText:"确认修改",cancelButtonText:"取消",type:"warning"})}catch{return}n.value=!0;try{await P(t),i.success("用户名修改成功,请重新登录"),s.value="",setTimeout(f,1200)}catch{}finally{n.value=!1}}async function V(){const t=d.value;if(!t){i.error("请输入新密码");return}const e=k(t);if(!e.ok){i.error(e.message);return}try{await b.confirm("确定修改管理员密码吗?修改后需要重新登录。","修改密码",{confirmButtonText:"确认修改",cancelButtonText:"取消",type:"warning"})}catch{return}n.value=!0;try{await E(t),i.success("密码修改成功,请重新登录"),d.value="",setTimeout(f,1200)}catch{}finally{n.value=!1}}return(t,e)=>{const g=u("el-input"),v=u("el-form-item"),w=u("el-form"),y=u("el-button"),_=u("el-card");return C(),T("div",U,[e[7]||(e[7]=r("div",{class:"app-page-title"},[r("h2",null,"设置"),r("span",{class:"app-muted"},"管理员账号设置")],-1)),a(_,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:l(()=>[e[3]||(e[3]=r("h3",{class:"section-title"},"修改管理员用户名",-1)),a(w,{"label-width":"120px"},{default:l(()=>[a(v,{label:"新用户名"},{default:l(()=>[a(g,{modelValue:s.value,"onUpdate:modelValue":e[0]||(e[0]=c=>s.value=c),placeholder:"输入新用户名",disabled:n.value},null,8,["modelValue","disabled"])]),_:1})]),_:1}),a(y,{type:"primary",loading:n.value,onClick:B},{default:l(()=>[...e[2]||(e[2]=[x("保存用户名",-1)])]),_:1},8,["loading"])]),_:1}),a(_,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:l(()=>[e[5]||(e[5]=r("h3",{class:"section-title"},"修改管理员密码",-1)),a(w,{"label-width":"120px"},{default:l(()=>[a(v,{label:"新密码"},{default:l(()=>[a(g,{modelValue:d.value,"onUpdate:modelValue":e[1]||(e[1]=c=>d.value=c),type:"password","show-password":"",placeholder:"输入新密码",disabled:n.value},null,8,["modelValue","disabled"])]),_:1})]),_:1}),a(y,{type:"primary",loading:n.value,onClick:V},{default:l(()=>[...e[4]||(e[4]=[x("保存密码",-1)])]),_:1},8,["loading"]),e[6]||(e[6]=r("div",{class:"help"},"建议使用更强密码(至少8位且包含字母与数字)。",-1))]),_:1})])}}},M=h(A,[["__scopeId","data-v-83d3840a"]]);export{M 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
@@ -1 +1 @@
import{a as n}from"./index-Cg-w8G7A.js";async function i(){const{data:a}=await n.get("/email/settings");return a}async function e(a){const{data:t}=await n.post("/email/settings",a);return t}async function c(){const{data:a}=await n.get("/email/stats");return a}async function o(a){const{data:t}=await n.get("/email/logs",{params:a});return t}async function l(a){const{data:t}=await n.post("/email/logs/cleanup",{days:a});return t}export{o as a,i as b,l as c,c as f,e as u};
import{a as n}from"./index-D8t2quK2.js";async function i(){const{data:a}=await n.get("/email/settings");return a}async function e(a){const{data:t}=await n.post("/email/settings",a);return t}async function c(){const{data:a}=await n.get("/email/stats");return a}async function o(a){const{data:t}=await n.get("/email/logs",{params:a});return t}async function l(a){const{data:t}=await n.post("/email/logs/cleanup",{days:a});return t}export{o as a,i as b,l as c,c as f,e as u};
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
@@ -1 +1 @@
import{a}from"./index-Cg-w8G7A.js";async function o(){const{data:t}=await a.get("/system/config");return t}async function e(t){const{data:n}=await a.post("/system/config",t);return n}export{o as f,e as u};
import{a}from"./index-D8t2quK2.js";async function o(){const{data:t}=await a.get("/system/config");return t}async function e(t){const{data:n}=await a.post("/system/config",t);return n}export{o as f,e as u};
@@ -1 +1 @@
import{a}from"./index-Cg-w8G7A.js";async function c(){const{data:t}=await a.get("/server/info");return t}async function e(){const{data:t}=await a.get("/docker_stats");return t}async function o(){const{data:t}=await a.get("/task/stats");return t}async function r(){const{data:t}=await a.get("/task/running");return t}async function i(t){const{data:s}=await a.get("/task/logs",{params:t});return s}async function f(t){const{data:s}=await a.post("/task/logs/clear",{days:t});return s}export{r as a,c as b,e as c,i as d,f as e,o as f};
import{a}from"./index-D8t2quK2.js";async function c(){const{data:t}=await a.get("/server/info");return t}async function e(){const{data:t}=await a.get("/docker_stats");return t}async function o(){const{data:t}=await a.get("/task/stats");return t}async function r(){const{data:t}=await a.get("/task/running");return t}async function i(t){const{data:s}=await a.get("/task/logs",{params:t});return s}async function f(t){const{data:s}=await a.post("/task/logs/clear",{days:t});return s}export{r as a,c as b,e as c,i as d,f as e,o as f};
@@ -1 +1 @@
import{a as t}from"./index-Cg-w8G7A.js";async function n(){const{data:s}=await t.get("/users");return s}async function o(s){const{data:a}=await t.post(`/users/${s}/approve`);return a}async function c(s){const{data:a}=await t.post(`/users/${s}/reject`);return a}async function i(s){const{data:a}=await t.delete(`/users/${s}`);return a}async function u(s,a){const{data:e}=await t.post(`/users/${s}/vip`,{days:a});return e}async function p(s){const{data:a}=await t.delete(`/users/${s}/vip`);return a}async function d(s,a){const{data:e}=await t.post(`/users/${s}/reset_password`,{new_password:a});return e}export{o as a,p as b,d as c,i as d,n as f,c as r,u as s};
import{a as t}from"./index-D8t2quK2.js";async function n(){const{data:s}=await t.get("/users");return s}async function o(s){const{data:a}=await t.post(`/users/${s}/approve`);return a}async function c(s){const{data:a}=await t.post(`/users/${s}/reject`);return a}async function i(s){const{data:a}=await t.delete(`/users/${s}`);return a}async function u(s,a){const{data:e}=await t.post(`/users/${s}/vip`,{days:a});return e}async function p(s){const{data:a}=await t.delete(`/users/${s}/vip`);return a}async function d(s,a){const{data:e}=await t.post(`/users/${s}/reset_password`,{new_password:a});return e}export{o as a,p as b,d as c,i as d,n as f,c as r,u as s};
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
File diff suppressed because one or more lines are too long
+7 -2
View File
@@ -5,8 +5,13 @@
<link rel="icon" type="image/svg+xml" href="./vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>后台管理 - 知识管理平台</title>
<script type="module" crossorigin src="./assets/index-Cg-w8G7A.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-DRsk2q1y.css">
<script type="module" crossorigin src="./assets/index-D8t2quK2.js"></script>
<link rel="modulepreload" crossorigin href="./assets/vendor-sLgkZK1v.js">
<link rel="modulepreload" crossorigin href="./assets/vendor-element-CJoVtPsD.js">
<link rel="modulepreload" crossorigin href="./assets/vendor-vue-CWkOjFoA.js">
<link rel="modulepreload" crossorigin href="./assets/vendor-axios-B9ygI19o.js">
<link rel="stylesheet" crossorigin href="./assets/vendor-element-C68yOrAy.css">
<link rel="stylesheet" crossorigin href="./assets/index-Tk47UJAg.css">
</head>
<body>
<div id="app"></div>
+96 -23
View File
@@ -1,23 +1,67 @@
{
"_accounts-D0u3_DmH.js": {
"file": "assets/accounts-D0u3_DmH.js",
"_accounts-DpRp0y7G.js": {
"file": "assets/accounts-DpRp0y7G.js",
"name": "accounts",
"imports": [
"index.html"
]
},
"_auth-BbAHBKrj.js": {
"file": "assets/auth-BbAHBKrj.js",
"_auth-CtTBVBJk.js": {
"file": "assets/auth-CtTBVBJk.js",
"name": "auth",
"imports": [
"index.html"
]
},
"_vendor-DR-vtVVc.js": {
"file": "assets/vendor-DR-vtVVc.js",
"name": "vendor"
},
"_vendor-axios-B9ygI19o.js": {
"file": "assets/vendor-axios-B9ygI19o.js",
"name": "vendor-axios"
},
"_vendor-element-BaI2aKL6.css": {
"file": "assets/vendor-element-BaI2aKL6.css",
"src": "_vendor-element-BaI2aKL6.css"
},
"_vendor-element-D5SbqSD5.js": {
"file": "assets/vendor-element-D5SbqSD5.js",
"name": "vendor-element",
"imports": [
"_vendor-DR-vtVVc.js",
"_vendor-vue-l2lnRGj2.js"
],
"css": [
"assets/vendor-element-BaI2aKL6.css"
]
},
"_vendor-socket-ciQGyZ7q.js": {
"file": "assets/vendor-socket-ciQGyZ7q.js",
"name": "vendor-socket",
"imports": [
"_vendor-DR-vtVVc.js"
]
},
"_vendor-vue-l2lnRGj2.js": {
"file": "assets/vendor-vue-l2lnRGj2.js",
"name": "vendor-vue",
"imports": [
"_vendor-DR-vtVVc.js",
"_vendor-element-D5SbqSD5.js"
]
},
"index.html": {
"file": "assets/index-B_BXzkJV.js",
"file": "assets/index-C4rfJ09l.js",
"name": "index",
"src": "index.html",
"isEntry": true,
"imports": [
"_vendor-DR-vtVVc.js",
"_vendor-vue-l2lnRGj2.js",
"_vendor-element-D5SbqSD5.js",
"_vendor-axios-B9ygI19o.js"
],
"dynamicImports": [
"src/pages/LoginPage.vue",
"src/pages/RegisterPage.vue",
@@ -28,93 +72,122 @@
"src/pages/ScreenshotsPage.vue"
],
"css": [
"assets/index-BVjJVlht.css"
"assets/index-BJUdh4ps.css"
]
},
"src/pages/AccountsPage.vue": {
"file": "assets/AccountsPage-CnrKgJXQ.js",
"file": "assets/AccountsPage-Cj2MTk-l.js",
"name": "AccountsPage",
"src": "src/pages/AccountsPage.vue",
"isDynamicEntry": true,
"imports": [
"_accounts-D0u3_DmH.js",
"index.html"
"_accounts-DpRp0y7G.js",
"index.html",
"_vendor-socket-ciQGyZ7q.js",
"_vendor-element-D5SbqSD5.js",
"_vendor-DR-vtVVc.js",
"_vendor-vue-l2lnRGj2.js",
"_vendor-axios-B9ygI19o.js"
],
"css": [
"assets/AccountsPage-tARhOk5s.css"
"assets/AccountsPage-CRlBbogn.css"
]
},
"src/pages/LoginPage.vue": {
"file": "assets/LoginPage-Ba8KKzJb.js",
"file": "assets/LoginPage-B4Cm3mBQ.js",
"name": "LoginPage",
"src": "src/pages/LoginPage.vue",
"isDynamicEntry": true,
"imports": [
"_vendor-DR-vtVVc.js",
"_vendor-vue-l2lnRGj2.js",
"_auth-CtTBVBJk.js",
"index.html",
"_auth-BbAHBKrj.js"
"_vendor-element-D5SbqSD5.js",
"_vendor-axios-B9ygI19o.js"
],
"css": [
"assets/LoginPage-DKpbim43.css"
]
},
"src/pages/RegisterPage.vue": {
"file": "assets/RegisterPage-CNLEXFa0.js",
"file": "assets/RegisterPage-DDkEhw5Z.js",
"name": "RegisterPage",
"src": "src/pages/RegisterPage.vue",
"isDynamicEntry": true,
"imports": [
"_vendor-DR-vtVVc.js",
"_vendor-vue-l2lnRGj2.js",
"_auth-CtTBVBJk.js",
"index.html",
"_auth-BbAHBKrj.js"
"_vendor-element-D5SbqSD5.js",
"_vendor-axios-B9ygI19o.js"
],
"css": [
"assets/RegisterPage-BOcNcW5D.css"
]
},
"src/pages/ResetPasswordPage.vue": {
"file": "assets/ResetPasswordPage-BaGrQ8Bf.js",
"file": "assets/ResetPasswordPage-DTBT5Kre.js",
"name": "ResetPasswordPage",
"src": "src/pages/ResetPasswordPage.vue",
"isDynamicEntry": true,
"imports": [
"_vendor-DR-vtVVc.js",
"_vendor-vue-l2lnRGj2.js",
"_auth-CtTBVBJk.js",
"index.html",
"_auth-BbAHBKrj.js"
"_vendor-element-D5SbqSD5.js",
"_vendor-axios-B9ygI19o.js"
],
"css": [
"assets/ResetPasswordPage-DybfLMAw.css"
]
},
"src/pages/SchedulesPage.vue": {
"file": "assets/SchedulesPage-CRyac5iz.js",
"file": "assets/SchedulesPage-DtRro62b.js",
"name": "SchedulesPage",
"src": "src/pages/SchedulesPage.vue",
"isDynamicEntry": true,
"imports": [
"_accounts-D0u3_DmH.js",
"index.html"
"_accounts-DpRp0y7G.js",
"index.html",
"_vendor-element-D5SbqSD5.js",
"_vendor-DR-vtVVc.js",
"_vendor-vue-l2lnRGj2.js",
"_vendor-axios-B9ygI19o.js"
],
"css": [
"assets/SchedulesPage-DwfusXou.css"
]
},
"src/pages/ScreenshotsPage.vue": {
"file": "assets/ScreenshotsPage-Bv6MAoM4.js",
"file": "assets/ScreenshotsPage-BMPLt3Or.js",
"name": "ScreenshotsPage",
"src": "src/pages/ScreenshotsPage.vue",
"isDynamicEntry": true,
"imports": [
"index.html"
"index.html",
"_vendor-element-D5SbqSD5.js",
"_vendor-DR-vtVVc.js",
"_vendor-vue-l2lnRGj2.js",
"_vendor-axios-B9ygI19o.js"
],
"css": [
"assets/ScreenshotsPage-ByqUbmUI.css"
]
},
"src/pages/VerifyResultPage.vue": {
"file": "assets/VerifyResultPage-7PFmI380.js",
"file": "assets/VerifyResultPage-CdTQeWQk.js",
"name": "VerifyResultPage",
"src": "src/pages/VerifyResultPage.vue",
"isDynamicEntry": true,
"imports": [
"index.html"
"_vendor-vue-l2lnRGj2.js",
"index.html",
"_vendor-DR-vtVVc.js",
"_vendor-element-D5SbqSD5.js",
"_vendor-axios-B9ygI19o.js"
],
"css": [
"assets/VerifyResultPage-CG6ZYNrm.css"
@@ -0,0 +1 @@
.page[data-v-a3d05837]{display:flex;flex-direction:column;gap:12px}.stat-card[data-v-a3d05837],.panel[data-v-a3d05837]{border-radius:var(--app-radius);border:1px solid var(--app-border)}.stat-label[data-v-a3d05837]{font-size:12px}.stat-value[data-v-a3d05837]{margin-top:6px;font-size:22px;font-weight:900;letter-spacing:.2px}.stat-suffix[data-v-a3d05837]{margin-left:6px;font-size:12px;font-weight:600}.upgrade-banner[data-v-a3d05837]{border-radius:var(--app-radius);border:1px solid var(--app-border)}.upgrade-actions[data-v-a3d05837]{margin-top:10px}.panel-head[data-v-a3d05837]{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:10px;flex-wrap:wrap}.panel-title[data-v-a3d05837]{font-size:16px;font-weight:900}.panel-actions[data-v-a3d05837]{display:flex;gap:10px;flex-wrap:wrap;justify-content:flex-end}.toolbar[data-v-a3d05837]{display:flex;flex-wrap:wrap;align-items:center;gap:12px;padding:10px;border:1px dashed rgba(17,24,39,.14);border-radius:12px;background:#f6f7fb99}.toolbar-left[data-v-a3d05837],.toolbar-middle[data-v-a3d05837],.toolbar-right[data-v-a3d05837]{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.toolbar-right[data-v-a3d05837]{margin-left:auto;justify-content:flex-end}.grid[data-v-a3d05837]{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:12px;align-items:start}.account-card[data-v-a3d05837]{border-radius:14px;border:1px solid var(--app-border)}.card-top[data-v-a3d05837]{display:flex;gap:10px}.card-check[data-v-a3d05837]{padding-top:2px}.card-main[data-v-a3d05837]{min-width:0;flex:1}.card-title[data-v-a3d05837]{display:flex;align-items:center;justify-content:space-between;gap:10px}.card-name[data-v-a3d05837]{font-size:14px;font-weight:900;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.card-sub[data-v-a3d05837]{margin-top:6px;font-size:12px;line-height:1.4;word-break:break-word}.progress[data-v-a3d05837]{margin-top:12px}.progress-meta[data-v-a3d05837]{margin-top:6px;display:flex;justify-content:space-between;gap:10px;font-size:12px}.card-controls[data-v-a3d05837]{margin-top:12px;display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.card-buttons[data-v-a3d05837]{display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:flex-end}.vip-body[data-v-a3d05837]{padding:12px 0 0}.vip-tip[data-v-a3d05837]{margin-top:10px;font-size:13px;line-height:1.6}@media(max-width:480px){.grid[data-v-a3d05837]{grid-template-columns:1fr}}@media(max-width:768px){.panel-actions[data-v-a3d05837]{width:100%;justify-content:flex-end}.toolbar-left[data-v-a3d05837],.toolbar-middle[data-v-a3d05837],.toolbar-right[data-v-a3d05837]{width:100%}.toolbar-right[data-v-a3d05837]{margin-left:0;justify-content:flex-end}}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
.page[data-v-961c6960]{display:flex;flex-direction:column;gap:12px}.stat-card[data-v-961c6960],.panel[data-v-961c6960]{border-radius:var(--app-radius);border:1px solid var(--app-border)}.stat-label[data-v-961c6960]{font-size:12px}.stat-value[data-v-961c6960]{margin-top:6px;font-size:22px;font-weight:900;letter-spacing:.2px}.stat-suffix[data-v-961c6960]{margin-left:6px;font-size:12px;font-weight:600}.upgrade-banner[data-v-961c6960]{border-radius:var(--app-radius);border:1px solid var(--app-border)}.upgrade-actions[data-v-961c6960]{margin-top:10px}.panel-head[data-v-961c6960]{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:10px;flex-wrap:wrap}.panel-title[data-v-961c6960]{font-size:16px;font-weight:900}.panel-actions[data-v-961c6960]{display:flex;gap:10px;flex-wrap:wrap;justify-content:flex-end}.toolbar[data-v-961c6960]{display:flex;flex-wrap:wrap;align-items:center;gap:12px;padding:10px;border:1px dashed rgba(17,24,39,.14);border-radius:12px;background:#f6f7fb99}.toolbar-left[data-v-961c6960],.toolbar-middle[data-v-961c6960],.toolbar-right[data-v-961c6960]{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.toolbar-right[data-v-961c6960]{margin-left:auto;justify-content:flex-end}.grid[data-v-961c6960]{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:12px;align-items:start}.account-card[data-v-961c6960]{border-radius:14px;border:1px solid var(--app-border)}.card-top[data-v-961c6960]{display:flex;gap:10px}.card-check[data-v-961c6960]{padding-top:2px}.card-main[data-v-961c6960]{min-width:0;flex:1}.card-title[data-v-961c6960]{display:flex;align-items:center;justify-content:space-between;gap:10px}.card-name[data-v-961c6960]{font-size:14px;font-weight:900;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.card-sub[data-v-961c6960]{margin-top:6px;font-size:12px;line-height:1.4;word-break:break-word}.progress[data-v-961c6960]{margin-top:12px}.progress-meta[data-v-961c6960]{margin-top:6px;display:flex;justify-content:space-between;gap:10px;font-size:12px}.card-controls[data-v-961c6960]{margin-top:12px;display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.card-buttons[data-v-961c6960]{display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:flex-end}.vip-body[data-v-961c6960]{padding:12px 0 0}.vip-tip[data-v-961c6960]{margin-top:10px;font-size:13px;line-height:1.6}@media(max-width:480px){.grid[data-v-961c6960]{grid-template-columns:1fr}}@media(max-width:768px){.panel-actions[data-v-961c6960]{width:100%;justify-content:flex-end}.toolbar-left[data-v-961c6960],.toolbar-middle[data-v-961c6960],.toolbar-right[data-v-961c6960]{width:100%}.toolbar-right[data-v-961c6960]{margin-left:0;justify-content:flex-end}}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
import{_ as M,r as j,a as d,c as B,o as A,b as U,e as t,i as o,g as v,u as H,j as b,d as n,k as N,f as E,h as P,t as q,l as S,E as c,v as z}from"./index-B_BXzkJV.js";import{g as F,f as G,b as J}from"./auth-BbAHBKrj.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),l=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(){l.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){l.value="用户名至少3个字符",c.error(l.value);return}const p=z(e);if(!p.ok){l.value=p.message||"密码格式不正确",c.error(l.value);return}if(e!==g){l.value="两次输入的密码不一致",c.error(l.value);return}if(f.value&&!s){l.value="请填写邮箱地址用于账号验证",c.error(l.value);return}if(s&&!s.includes("@")){l.value="邮箱格式不正确",c.error(l.value);return}if(!i){l.value="请输入验证码",c.error(l.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;l.value=x?.error||"注册失败",c.error(l.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,[t(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)),l.value?(b(),N(g,{key:0,type:"error",closable:!1,title:l.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),t(m,{"label-position":"top"},{default:o(()=>[t(i,{label:"用户名 *"},{default:o(()=>[t(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}),t(i,{label:"密码 *"},{default:o(()=>[t(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}),t(i,{label:"确认密码 *"},{default:o(()=>[t(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}),t(i,{label:K.value},{default:o(()=>[t(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"]),t(i,{label:"验证码 *"},{default:o(()=>[n("div",W,[t(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),t(p,{onClick:y},{default:o(()=>[...e[7]||(e[7]=[S("刷新",-1)])]),_:1})])]),_:1})]),_:1}),t(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)),t(p,{link:"",type:"primary",onClick:L},{default:o(()=>[...e[9]||(e[9]=[S("立即登录",-1)])]),_:1})])]),_:1})])}}},le=M(Z,[["__scopeId","data-v-a9d7804f"]]);export{le as default};
@@ -0,0 +1 @@
import{a1 as A,r as d,c as S,v as M,z as N,Q as l,J as o,aY as v,A as b,B as n,I as U,L as B,aD as P,O as z,N as E}from"./vendor-DR-vtVVc.js";import{p as H}from"./vendor-vue-l2lnRGj2.js";import{g as J,f as O,b as Q}from"./auth-CtTBVBJk.js";import{_ as Y,v as j}from"./index-C4rfJ09l.js";import{E as c}from"./vendor-element-D5SbqSD5.js";import"./vendor-axios-B9ygI19o.js";const q={class:"auth-wrap"},F={class:"hint app-muted"},G={class:"captcha-row"},W=["src"],X={class:"actions"},Z={__name:"RegisterPage",setup($){const T=H(),a=A({username:"",password:"",confirm_password:"",email:"",captcha:""}),f=d(!1),w=d(""),h=d(""),V=d(!1),t=d(""),_=d(""),k=d(""),D=S(()=>f.value?"邮箱 *":"邮箱(可选)"),I=S(()=>f.value?"必填,用于账号验证":"选填,用于找回密码和接收通知");async function y(){try{const u=await J();h.value=u?.session_id||"",w.value=u?.captcha_image||"",a.captcha=""}catch{h.value="",w.value=""}}async function K(){try{const u=await O();f.value=!!u?.register_verify_enabled}catch{f.value=!1}}function L(){t.value="",_.value="",k.value=""}async function C(){L();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=j(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 Q({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 R(){T.push("/login")}return M(async()=>{await y(),await K()}),(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(),N("div",q,[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(),U(g,{key:0,type:"error",closable:!1,title:t.value,"show-icon":"",class:"alert"},null,8,["title"])):B("",!0),_.value?(b(),U(g,{key:1,type:"success",closable:!1,title:_.value,description:k.value,"show-icon":"",class:"alert"},null,8,["title","description"])):B("",!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:D.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",F,z(I.value),1)]),_:1},8,["label"]),l(i,{label:"验证码 *"},{default:o(()=>[n("div",G,[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(),N("img",{key:0,class:"captcha-img",src:w.value,alt:"验证码",title:"点击刷新",onClick:y},null,8,W)):B("",!0),l(p,{onClick:y},{default:o(()=>[...e[7]||(e[7]=[E("刷新",-1)])]),_:1})])]),_:1})]),_:1}),l(p,{type:"primary",class:"submit-btn",loading:V.value,onClick:C},{default:o(()=>[...e[8]||(e[8]=[E("注册",-1)])]),_:1},8,["loading"]),n("div",X,[e[10]||(e[10]=n("span",{class:"app-muted"},"已有账号?",-1)),l(p,{link:"",type:"primary",onClick:R},{default:o(()=>[...e[9]||(e[9]=[E("立即登录",-1)])]),_:1})])]),_:1})])}}},re=Y(Z,[["__scopeId","data-v-a9d7804f"]]);export{re as default};
@@ -1 +0,0 @@
import{_ as L,a as n,m as M,r as U,c as j,o as F,n as K,b as v,e as s,i as a,g as l,u as D,j as m,d as w,F as T,l as k,k as q,f as x,h as z,t as G,v as H,E as y}from"./index-B_BXzkJV.js";import{c as J}from"./auth-BbAHBKrj.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 m(),v("div",O,[s(E,{shadow:"never",class:"auth-card","body-style":{padding:"22px"}},{default:a(()=>[e[5]||(e[5]=w("div",{class:"brand"},[w("div",{class:"brand-title"},"知识管理平台"),w("div",{class:"brand-sub app-muted"},"重置密码")],-1)),i.value?(m(),v(T,{key:1},[_.value?(m(),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"]),w("div",W,[s(p,{link:"",type:"primary",onClick:S},{default:a(()=>[...e[4]||(e[4]=[k("返回登录",-1)])]),_:1}),d.value>0?(m(),v("span",X,G(d.value)+" 秒后自动跳转…",1)):x("",!0)])],64)):(m(),v(T,{key:0},[s(c,{type:"error",closable:!1,title:"链接已失效",description:b.value,"show-icon":""},null,8,["description"]),w("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};
@@ -0,0 +1 @@
import{r as n,a1 as L,c as M,v as U,a0 as D,z as v,Q as s,J as a,aY as l,A as m,B as w,P as h,N as k,I as K,L as B,aD as j,O as z}from"./vendor-DR-vtVVc.js";import{u as F,p as J}from"./vendor-vue-l2lnRGj2.js";import{c as O}from"./auth-CtTBVBJk.js";import{_ as Q,v as Y}from"./index-C4rfJ09l.js";import{E as y}from"./vendor-element-D5SbqSD5.js";import"./vendor-axios-B9ygI19o.js";const q={class:"auth-wrap"},G={class:"actions"},H={class:"actions"},W={key:0,class:"app-muted"},X={__name:"ResetPasswordPage",setup(Z){const x=F(),A=J(),r=n(String(x.params.token||"")),i=n(!0),b=n(""),t=L({newPassword:"",confirmPassword:""}),P=n(!1),f=n(""),d=n(0);let u=null;function N(){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=M(()=>!!(i.value&&r.value&&!f.value));function S(){A.push("/login")}function C(){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=Y(o);if(!c.ok){y.error(c.message);return}if(o!==e){y.error("两次输入的密码不一致");return}P.value=!0;try{await O({token:r.value,new_password:o}),f.value="密码重置成功!3秒后跳转到登录页面...",y.success("密码重置成功"),C()}catch(p){const _=p?.response?.data;y.error(_?.error||"重置失败")}finally{P.value=!1}}return U(()=>{const o=N();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="重置链接无效或已过期,请重新申请密码重置")}),D(()=>{u&&window.clearInterval(u)}),(o,e)=>{const c=l("el-alert"),p=l("el-button"),_=l("el-input"),T=l("el-form-item"),R=l("el-form"),E=l("el-card");return m(),v("div",q,[s(E,{shadow:"never",class:"auth-card","body-style":{padding:"22px"}},{default:a(()=>[e[5]||(e[5]=w("div",{class:"brand"},[w("div",{class:"brand-title"},"知识管理平台"),w("div",{class:"brand-sub app-muted"},"重置密码")],-1)),i.value?(m(),v(h,{key:1},[f.value?(m(),K(c,{key:0,type:"success",closable:!1,title:"重置成功",description:f.value,"show-icon":"",class:"alert"},null,8,["description"])):B("",!0),s(R,{"label-position":"top"},{default:a(()=>[s(T,{label:"新密码(至少8位且包含字母和数字)"},{default:a(()=>[s(_,{modelValue:t.newPassword,"onUpdate:modelValue":e[0]||(e[0]=g=>t.newPassword=g),type:"password","show-password":"",placeholder:"请输入新密码",autocomplete:"new-password"},null,8,["modelValue"])]),_:1}),s(T,{label:"确认密码"},{default:a(()=>[s(_,{modelValue:t.confirmPassword,"onUpdate:modelValue":e[1]||(e[1]=g=>t.confirmPassword=g),type:"password","show-password":"",placeholder:"请再次输入新密码",autocomplete:"new-password",onKeyup:j(V,["enter"])},null,8,["modelValue"])]),_:1})]),_:1}),s(p,{type:"primary",class:"submit-btn",loading:P.value,disabled:!I.value,onClick:V},{default:a(()=>[...e[3]||(e[3]=[k(" 确认重置 ",-1)])]),_:1},8,["loading","disabled"]),w("div",H,[s(p,{link:"",type:"primary",onClick:S},{default:a(()=>[...e[4]||(e[4]=[k("返回登录",-1)])]),_:1}),d.value>0?(m(),v("span",W,z(d.value)+" 秒后自动跳转…",1)):B("",!0)])],64)):(m(),v(h,{key:0},[s(c,{type:"error",closable:!1,title:"链接已失效",description:b.value,"show-icon":""},null,8,["description"]),w("div",G,[s(p,{type:"primary",onClick:S},{default:a(()=>[...e[2]||(e[2]=[k("返回登录",-1)])]),_:1})])],64))]),_:1})])}}},ne=Q(X,[["__scopeId","data-v-0bbb511c"]]);export{ne 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
@@ -1 +0,0 @@
import{_ as U,a as o,c as I,o as E,n as R,b as k,e as i,i as s,g as d,u as j,j as _,d as l,f as B,k as W,l as T,t as v}from"./index-B_BXzkJV.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};
@@ -0,0 +1 @@
import{p as U}from"./vendor-vue-l2lnRGj2.js";import{_ as E}from"./index-C4rfJ09l.js";import{r as o,c as h,v as R,a0 as z,z as B,Q as i,J as s,aY as d,A as _,B as l,L as k,I as W,N,O as v}from"./vendor-DR-vtVVc.js";import"./vendor-element-D5SbqSD5.js";import"./vendor-axios-B9ygI19o.js";const $={class:"auth-wrap"},j={class:"actions"},D={key:0,class:"countdown app-muted"},J={__name:"VerifyResultPage",setup(M){const T=U(),p=o(!1),f=o(""),m=o(""),w=o(""),y=o(""),r=o(""),u=o(""),c=o(""),n=o(0);let a=null;function x(){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 A(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 C=h(()=>!!(r.value&&u.value)),b=h(()=>!!(c.value&&n.value>0));async function g(e){if(e){if(e.startsWith("http://")||e.startsWith("https://")){window.location.href=e;return}await T.push(e)}}function L(){b.value&&(a=window.setInterval(()=>{n.value-=1,n.value<=0&&(window.clearInterval(a),a=null,window.location.href=c.value)},1e3))}return R(()=>{const e=x();A(e),L()}),z(()=>{a&&window.clearInterval(a)}),(e,t)=>{const I=d("el-button"),P=d("el-result"),V=d("el-card");return _(),B("div",$,[i(V,{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(P,{icon:p.value?"success":"error",title:f.value,"sub-title":m.value,class:"result"},{extra:s(()=>[l("div",j,[i(I,{type:"primary",onClick:t[0]||(t[0]=S=>g(y.value))},{default:s(()=>[N(v(w.value),1)]),_:1}),C.value?(_(),W(I,{key:0,onClick:t[1]||(t[1]=S=>g(u.value))},{default:s(()=>[N(v(r.value),1)]),_:1})):k("",!0)]),b.value?(_(),B("div",D,v(n.value)+" 秒后自动跳转... ",1)):k("",!0)]),_:1},8,["icon","title","sub-title"])]),_:1})])}}},G=E(J,[["__scopeId","data-v-1fc6b081"]]);export{G as default};
@@ -1 +1 @@
import{p as c}from"./index-B_BXzkJV.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-C4rfJ09l.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};
@@ -1 +1 @@
import{p as s}from"./index-B_BXzkJV.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-C4rfJ09l.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};
+1
View File
@@ -0,0 +1 @@
.layout-root[data-v-7ce33baa]{height:100%}.layout-aside[data-v-7ce33baa]{background:#fff;border-right:1px solid var(--app-border)}.brand[data-v-7ce33baa],.drawer-brand[data-v-7ce33baa]{padding:18px 16px 10px}.brand-title[data-v-7ce33baa]{font-size:15px;font-weight:800;letter-spacing:.2px}.brand-sub[data-v-7ce33baa]{margin-top:2px;font-size:12px}.aside-menu[data-v-7ce33baa]{border-right:none}.layout-header[data-v-7ce33baa]{display:flex;align-items:center;justify-content:space-between;gap:12px;background:#f6f7fb99;-webkit-backdrop-filter:saturate(180%) blur(10px);backdrop-filter:saturate(180%) blur(10px);border-bottom:1px solid var(--app-border)}.header-left[data-v-7ce33baa]{display:flex;align-items:center;gap:10px;min-width:0}.header-title[data-v-7ce33baa]{font-size:14px;font-weight:800;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.header-menu-btn[data-v-7ce33baa]{padding-left:0;padding-right:0}.header-right[data-v-7ce33baa]{display:flex;align-items:center;gap:12px}.user-meta[data-v-7ce33baa]{display:flex;align-items:center;gap:8px;min-width:0}.user-name[data-v-7ce33baa]{font-size:13px;font-weight:700;max-width:180px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.vip-warn[data-v-7ce33baa]{font-size:12px;color:var(--app-muted);white-space:nowrap}.layout-main[data-v-7ce33baa]{padding:16px}.drawer-user[data-v-7ce33baa]{padding:0 16px 10px;display:flex;align-items:center;gap:8px}.drawer-actions[data-v-7ce33baa]{padding:12px 16px 4px;border-top:1px solid var(--app-border)}.announcement-body[data-v-7ce33baa]{min-height:80px}.announcement-content[data-v-7ce33baa]{white-space:pre-wrap;line-height:1.6;font-size:14px}.announcement-image[data-v-7ce33baa]{margin-top:12px;display:flex;justify-content:center}.announcement-image img[data-v-7ce33baa]{max-width:100%;max-height:320px;border-radius:10px;border:1px solid var(--app-border);object-fit:contain}.feedback-title[data-v-7ce33baa]{display:flex;align-items:center;gap:10px;width:100%;min-width:0}.feedback-title-text[data-v-7ce33baa]{font-weight:800;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.feedback-time[data-v-7ce33baa]{margin-left:auto;font-size:12px;white-space:nowrap}.feedback-body[data-v-7ce33baa]{padding:6px 0 2px}.feedback-section+.feedback-section[data-v-7ce33baa]{margin-top:12px}.feedback-label[data-v-7ce33baa]{font-size:12px;margin-bottom:6px}.feedback-text[data-v-7ce33baa]{white-space:pre-wrap;line-height:1.6;font-size:13px}.settings-section[data-v-7ce33baa]{padding:6px 2px 2px}.settings-alert[data-v-7ce33baa]{margin-bottom:12px}.email-row[data-v-7ce33baa]{display:flex;align-items:center;justify-content:space-between;gap:12px}.email-value[data-v-7ce33baa]{font-weight:800;min-width:0;overflow:hidden;text-overflow:ellipsis}.notify-row[data-v-7ce33baa]{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.notify-title[data-v-7ce33baa]{font-weight:800}.notify-desc[data-v-7ce33baa]{margin-top:4px;font-size:12px}.settings-hint[data-v-7ce33baa]{margin-top:10px}.vip-info[data-v-7ce33baa]{margin-top:12px;display:grid;gap:10px}.vip-line[data-v-7ce33baa]{display:flex;align-items:center;justify-content:space-between;gap:12px}@media(max-width:768px){.layout-header[data-v-7ce33baa]{flex-wrap:wrap;height:auto;padding-top:10px;padding-bottom:10px}.header-right[data-v-7ce33baa]{width:100%;justify-content:flex-end}.layout-main[data-v-7ce33baa]{padding:12px}.user-name[data-v-7ce33baa]{max-width:120px}}:root{--app-bg: #f6f7fb;--app-text: #111827;--app-muted: #6b7280;--app-border: rgba(17, 24, 39, .08);--app-radius: 12px;--app-shadow: 0 8px 24px rgba(17, 24, 39, .06);--el-switch-off-color: var(--el-border-color-darker);--el-switch-border-color: var(--el-border-color-darker);font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,Hiragino Sans GB,Microsoft YaHei,Arial,sans-serif;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}html,body,#app{height:100%}body{margin:0;background:var(--app-bg);color:var(--app-text)}a{color:inherit;text-decoration:none}.app-muted{color:var(--app-muted)}.el-switch:not(.is-checked) .el-switch__core .el-switch__inner .is-icon,.el-switch:not(.is-checked) .el-switch__core .el-switch__inner .is-text{color:var(--el-text-color-regular)}.el-switch.is-disabled{opacity:1}@media(max-width:768px){.el-dialog{max-width:92vw}.el-form-item{flex-direction:column;align-items:stretch}.el-form-item__label{width:auto!important;justify-content:flex-start!important;padding:0 0 6px!important;line-height:1.4;text-align:left!important}.el-form-item__content{margin-left:0!important;width:100%}}
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
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
File diff suppressed because one or more lines are too long
+7 -2
View File
@@ -4,8 +4,13 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<title>知识管理平台</title>
<script type="module" crossorigin src="./assets/index-B_BXzkJV.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-BVjJVlht.css">
<script type="module" crossorigin src="./assets/index-C4rfJ09l.js"></script>
<link rel="modulepreload" crossorigin href="./assets/vendor-DR-vtVVc.js">
<link rel="modulepreload" crossorigin href="./assets/vendor-element-D5SbqSD5.js">
<link rel="modulepreload" crossorigin href="./assets/vendor-vue-l2lnRGj2.js">
<link rel="modulepreload" crossorigin href="./assets/vendor-axios-B9ygI19o.js">
<link rel="stylesheet" crossorigin href="./assets/vendor-element-BaI2aKL6.css">
<link rel="stylesheet" crossorigin href="./assets/index-BJUdh4ps.css">
</head>
<body>
<noscript>该页面需要启用 JavaScript 才能使用。</noscript>