Force KDocs QR fetch and improve login detection

This commit is contained in:
2026-01-07 13:07:57 +08:00
parent 28e86b1147
commit 6b416dc5f1
22 changed files with 112 additions and 65 deletions

View File

@@ -5,8 +5,9 @@ export async function fetchKdocsStatus() {
return data return data
} }
export async function fetchKdocsQr() { export async function fetchKdocsQr(payload = {}) {
const { data } = await api.post('/kdocs/qr', {}) const body = { force: true, ...payload }
const { data } = await api.post('/kdocs/qr', body)
return data return data
} }

View File

@@ -258,13 +258,13 @@ async function refreshKdocsStatus() {
async function onFetchKdocsQr() { async function onFetchKdocsQr() {
try { try {
const res = await fetchKdocsQr() const res = await fetchKdocsQr()
kdocsQrImage.value = res?.qr_image || ''
if (!kdocsQrImage.value) {
if (res?.logged_in) { if (res?.logged_in) {
ElMessage.success('当前已登录,无需扫码') ElMessage.success('当前已登录,无需扫码')
await refreshKdocsStatus() await refreshKdocsStatus()
return return
} }
kdocsQrImage.value = res?.qr_image || ''
if (!kdocsQrImage.value) {
ElMessage.warning('未获取到二维码') ElMessage.warning('未获取到二维码')
return return
} }

View File

@@ -863,7 +863,11 @@ def get_kdocs_qr_api():
from services.kdocs_uploader import get_kdocs_uploader from services.kdocs_uploader import get_kdocs_uploader
uploader = get_kdocs_uploader() uploader = get_kdocs_uploader()
result = uploader.request_qr() data = request.get_json(silent=True) or {}
force = bool(data.get("force"))
if not force:
force = str(request.args.get("force", "")).lower() in ("1", "true", "yes")
result = uploader.request_qr(force=force)
if not result.get("success"): if not result.get("success"):
return jsonify({"error": result.get("error", "获取二维码失败")}), 400 return jsonify({"error": result.get("error", "获取二维码失败")}), 400
return jsonify(result) return jsonify(result)

View File

@@ -91,8 +91,8 @@ class KDocsUploader:
self._last_error = "上传队列已满" self._last_error = "上传队列已满"
return False return False
def request_qr(self, timeout: int = 30) -> Dict[str, Any]: def request_qr(self, timeout: int = 30, *, force: bool = False) -> Dict[str, Any]:
return self._submit_command("qr", timeout=timeout) return self._submit_command("qr", timeout=timeout, payload={"force": force})
def clear_login(self, timeout: int = 20) -> Dict[str, Any]: def clear_login(self, timeout: int = 20) -> Dict[str, Any]:
return self._submit_command("clear_login", timeout=timeout) return self._submit_command("clear_login", timeout=timeout)
@@ -100,11 +100,16 @@ class KDocsUploader:
def refresh_login_status(self, timeout: int = 20) -> Dict[str, Any]: def refresh_login_status(self, timeout: int = 20) -> Dict[str, Any]:
return self._submit_command("status", timeout=timeout) return self._submit_command("status", timeout=timeout)
def _submit_command(self, action: str, timeout: int = 30) -> Dict[str, Any]: def _submit_command(
self,
action: str,
timeout: int = 30,
payload: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
if not self._running: if not self._running:
self.start() self.start()
resp_queue: queue.Queue = queue.Queue(maxsize=1) resp_queue: queue.Queue = queue.Queue(maxsize=1)
self._queue.put({"action": action, "response": resp_queue}) self._queue.put({"action": action, "response": resp_queue, "payload": payload or {}})
try: try:
return resp_queue.get(timeout=timeout) return resp_queue.get(timeout=timeout)
except queue.Empty: except queue.Empty:
@@ -122,7 +127,7 @@ class KDocsUploader:
if action == "upload": if action == "upload":
self._handle_upload(task.get("payload") or {}) self._handle_upload(task.get("payload") or {})
elif action == "qr": elif action == "qr":
result = self._handle_qr() result = self._handle_qr(task.get("payload") or {})
task.get("response").put(result) task.get("response").put(result)
elif action == "clear_login": elif action == "clear_login":
result = self._handle_clear_login() result = self._handle_clear_login()
@@ -138,7 +143,7 @@ class KDocsUploader:
def _load_system_config(self) -> Dict[str, Any]: def _load_system_config(self) -> Dict[str, Any]:
return database.get_system_config() or {} return database.get_system_config() or {}
def _ensure_playwright(self) -> bool: def _ensure_playwright(self, *, use_storage_state: bool = True) -> bool:
if sync_playwright is None: if sync_playwright is None:
self._last_error = "playwright 未安装" self._last_error = "playwright 未安装"
return False return False
@@ -150,7 +155,7 @@ class KDocsUploader:
self._browser = self._playwright.chromium.launch(headless=headless) self._browser = self._playwright.chromium.launch(headless=headless)
if self._context is None: if self._context is None:
storage_state = getattr(config, "KDOCS_LOGIN_STATE_FILE", "data/kdocs_login_state.json") storage_state = getattr(config, "KDOCS_LOGIN_STATE_FILE", "data/kdocs_login_state.json")
if os.path.exists(storage_state): if use_storage_state and os.path.exists(storage_state):
self._context = self._browser.new_context(storage_state=storage_state) self._context = self._browser.new_context(storage_state=storage_state)
else: else:
self._context = self._browser.new_context() self._context = self._browser.new_context()
@@ -205,6 +210,24 @@ class KDocsUploader:
return False return False
except Exception: except Exception:
return False return False
try:
login_btn = self._page.get_by_role("button", name="登录")
if login_btn.is_visible(timeout=1200):
return False
except Exception:
pass
try:
login_link = self._page.get_by_role("link", name="登录")
if login_link.is_visible(timeout=1200):
return False
except Exception:
pass
try:
wechat_btn = self._page.get_by_role("button", name="微信登录")
if wechat_btn.is_visible(timeout=1200):
return False
except Exception:
pass
return True return True
def _has_saved_login_state(self) -> bool: def _has_saved_login_state(self) -> bool:
@@ -220,6 +243,22 @@ class KDocsUploader:
except Exception: except Exception:
pass pass
try:
login_btn = self._page.get_by_role("button", name="登录")
if login_btn.is_visible(timeout=1500):
login_btn.click()
time.sleep(1)
except Exception:
pass
try:
login_link = self._page.get_by_role("link", name="登录")
if login_link.is_visible(timeout=1500):
login_link.click()
time.sleep(1)
except Exception:
pass
try: try:
wechat_btn = self._page.get_by_role("button", name="微信登录") wechat_btn = self._page.get_by_role("button", name="微信登录")
if wechat_btn.is_visible(timeout=3000): if wechat_btn.is_visible(timeout=3000):
@@ -258,17 +297,20 @@ class KDocsUploader:
except Exception as e: except Exception as e:
logger.warning(f"[KDocs] 保存登录态失败: {e}") logger.warning(f"[KDocs] 保存登录态失败: {e}")
def _handle_qr(self) -> Dict[str, Any]: def _handle_qr(self, payload: Dict[str, Any]) -> Dict[str, Any]:
cfg = self._load_system_config() cfg = self._load_system_config()
doc_url = (cfg.get("kdocs_doc_url") or "").strip() doc_url = (cfg.get("kdocs_doc_url") or "").strip()
if not doc_url: if not doc_url:
return {"success": False, "error": "未配置金山文档链接"} return {"success": False, "error": "未配置金山文档链接"}
if not self._ensure_playwright(): force = bool(payload.get("force"))
if force:
self._handle_clear_login()
if not self._ensure_playwright(use_storage_state=not force):
return {"success": False, "error": self._last_error or "浏览器不可用"} return {"success": False, "error": self._last_error or "浏览器不可用"}
if not self._open_document(doc_url): if not self._open_document(doc_url):
return {"success": False, "error": self._last_error or "打开文档失败"} return {"success": False, "error": self._last_error or "打开文档失败"}
if self._has_saved_login_state() and self._is_logged_in(): if not force and self._has_saved_login_state() and self._is_logged_in():
self._login_required = False self._login_required = False
self._last_login_ok = True self._last_login_ok = True
self._save_login_state() self._save_login_state()

View File

@@ -1,34 +1,34 @@
{ {
"_email-B1605y-H.js": { "_email-BKzLhLgA.js": {
"file": "assets/email-B1605y-H.js", "file": "assets/email-BKzLhLgA.js",
"name": "email", "name": "email",
"imports": [ "imports": [
"index.html" "index.html"
] ]
}, },
"_system-C--cT22w.js": { "_system-znscrp81.js": {
"file": "assets/system-C--cT22w.js", "file": "assets/system-znscrp81.js",
"name": "system", "name": "system",
"imports": [ "imports": [
"index.html" "index.html"
] ]
}, },
"_tasks-BNEjyFS7.js": { "_tasks-BsWiVPgX.js": {
"file": "assets/tasks-BNEjyFS7.js", "file": "assets/tasks-BsWiVPgX.js",
"name": "tasks", "name": "tasks",
"imports": [ "imports": [
"index.html" "index.html"
] ]
}, },
"_users-Z6zennED.js": { "_users-DOjL610a.js": {
"file": "assets/users-Z6zennED.js", "file": "assets/users-DOjL610a.js",
"name": "users", "name": "users",
"imports": [ "imports": [
"index.html" "index.html"
] ]
}, },
"index.html": { "index.html": {
"file": "assets/index-a8w3mx3g.js", "file": "assets/index-BfJ_SeqK.js",
"name": "index", "name": "index",
"src": "index.html", "src": "index.html",
"isEntry": true, "isEntry": true,
@@ -48,7 +48,7 @@
] ]
}, },
"src/pages/AnnouncementsPage.vue": { "src/pages/AnnouncementsPage.vue": {
"file": "assets/AnnouncementsPage-B4NSG18W.js", "file": "assets/AnnouncementsPage-D-szjsrj.js",
"name": "AnnouncementsPage", "name": "AnnouncementsPage",
"src": "src/pages/AnnouncementsPage.vue", "src": "src/pages/AnnouncementsPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
@@ -60,12 +60,12 @@
] ]
}, },
"src/pages/EmailPage.vue": { "src/pages/EmailPage.vue": {
"file": "assets/EmailPage-bnS2lxdA.js", "file": "assets/EmailPage-CPSyBOlI.js",
"name": "EmailPage", "name": "EmailPage",
"src": "src/pages/EmailPage.vue", "src": "src/pages/EmailPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"_email-B1605y-H.js", "_email-BKzLhLgA.js",
"index.html" "index.html"
], ],
"css": [ "css": [
@@ -73,7 +73,7 @@
] ]
}, },
"src/pages/FeedbacksPage.vue": { "src/pages/FeedbacksPage.vue": {
"file": "assets/FeedbacksPage-VbmcQLrX.js", "file": "assets/FeedbacksPage-C4y9Uk8C.js",
"name": "FeedbacksPage", "name": "FeedbacksPage",
"src": "src/pages/FeedbacksPage.vue", "src": "src/pages/FeedbacksPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
@@ -85,13 +85,13 @@
] ]
}, },
"src/pages/LogsPage.vue": { "src/pages/LogsPage.vue": {
"file": "assets/LogsPage-CYxgYYkM.js", "file": "assets/LogsPage-D1mKNpoI.js",
"name": "LogsPage", "name": "LogsPage",
"src": "src/pages/LogsPage.vue", "src": "src/pages/LogsPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"_users-Z6zennED.js", "_users-DOjL610a.js",
"_tasks-BNEjyFS7.js", "_tasks-BsWiVPgX.js",
"index.html" "index.html"
], ],
"css": [ "css": [
@@ -99,22 +99,22 @@
] ]
}, },
"src/pages/ReportPage.vue": { "src/pages/ReportPage.vue": {
"file": "assets/ReportPage-CWobMgMS.js", "file": "assets/ReportPage-CLdZ2ItD.js",
"name": "ReportPage", "name": "ReportPage",
"src": "src/pages/ReportPage.vue", "src": "src/pages/ReportPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"index.html", "index.html",
"_email-B1605y-H.js", "_email-BKzLhLgA.js",
"_tasks-BNEjyFS7.js", "_tasks-BsWiVPgX.js",
"_system-C--cT22w.js" "_system-znscrp81.js"
], ],
"css": [ "css": [
"assets/ReportPage-Q8rCsG8A.css" "assets/ReportPage-Q8rCsG8A.css"
] ]
}, },
"src/pages/SecurityPage.vue": { "src/pages/SecurityPage.vue": {
"file": "assets/SecurityPage-CBvaqgN-.js", "file": "assets/SecurityPage-CSg6vQJS.js",
"name": "SecurityPage", "name": "SecurityPage",
"src": "src/pages/SecurityPage.vue", "src": "src/pages/SecurityPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
@@ -126,7 +126,7 @@
] ]
}, },
"src/pages/SettingsPage.vue": { "src/pages/SettingsPage.vue": {
"file": "assets/SettingsPage-DTIxDo9J.js", "file": "assets/SettingsPage-B6H7yFj0.js",
"name": "SettingsPage", "name": "SettingsPage",
"src": "src/pages/SettingsPage.vue", "src": "src/pages/SettingsPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
@@ -138,25 +138,25 @@
] ]
}, },
"src/pages/SystemPage.vue": { "src/pages/SystemPage.vue": {
"file": "assets/SystemPage-C7s6uqSA.js", "file": "assets/SystemPage-B5EipiDb.js",
"name": "SystemPage", "name": "SystemPage",
"src": "src/pages/SystemPage.vue", "src": "src/pages/SystemPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"_system-C--cT22w.js", "_system-znscrp81.js",
"index.html" "index.html"
], ],
"css": [ "css": [
"assets/SystemPage-H89YK9Pc.css" "assets/SystemPage-Ju_Dzsyt.css"
] ]
}, },
"src/pages/UsersPage.vue": { "src/pages/UsersPage.vue": {
"file": "assets/UsersPage-CIttj4S8.js", "file": "assets/UsersPage-D0MdPL73.js",
"name": "UsersPage", "name": "UsersPage",
"src": "src/pages/UsersPage.vue", "src": "src/pages/UsersPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"_users-Z6zennED.js", "_users-DOjL610a.js",
"index.html" "index.html"
], ],
"css": [ "css": [

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{a as m,_ as B,r as p,f as u,g as T,h as P,j as r,m as a,w as l,q as x,L as i,K as b}from"./index-a8w3mx3g.js";async function C(o){const{data:s}=await m.put("/admin/username",{new_username:o});return s}async function S(o){const{data:s}=await m.put("/admin/password",{new_password:o});return s}async function U(){const{data:o}=await m.post("/logout");return o}const A={class:"page-stack"},E={__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 U()}catch{}finally{window.location.href="/yuyx"}}async function V(){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 C(t),i.success("用户名修改成功,请重新登录"),s.value="",setTimeout(f,1200)}catch{}finally{n.value=!1}}async function h(){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 S(t),i.success("密码修改成功,请重新登录"),d.value="",setTimeout(f,1200)}catch{}finally{n.value=!1}}return(t,e)=>{const g=u("el-input"),w=u("el-form-item"),v=u("el-form"),y=u("el-button"),_=u("el-card");return P(),T("div",A,[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(v,{"label-width":"120px"},{default:l(()=>[a(w,{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:V},{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(v,{"label-width":"120px"},{default:l(()=>[a(w,{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:h},{default:l(()=>[...e[4]||(e[4]=[x("保存密码",-1)])]),_:1},8,["loading"]),e[6]||(e[6]=r("div",{class:"help"},"建议使用更强密码至少8位且包含字母与数字。",-1))]),_:1})])}}},M=B(E,[["__scopeId","data-v-12a26d11"]]);export{M as default}; import{a as m,_ as B,r as p,f as u,g as T,h as P,j as r,m as a,w as l,q as x,L as i,K as b}from"./index-BfJ_SeqK.js";async function C(o){const{data:s}=await m.put("/admin/username",{new_username:o});return s}async function S(o){const{data:s}=await m.put("/admin/password",{new_password:o});return s}async function U(){const{data:o}=await m.post("/logout");return o}const A={class:"page-stack"},E={__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 U()}catch{}finally{window.location.href="/yuyx"}}async function V(){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 C(t),i.success("用户名修改成功,请重新登录"),s.value="",setTimeout(f,1200)}catch{}finally{n.value=!1}}async function h(){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 S(t),i.success("密码修改成功,请重新登录"),d.value="",setTimeout(f,1200)}catch{}finally{n.value=!1}}return(t,e)=>{const g=u("el-input"),w=u("el-form-item"),v=u("el-form"),y=u("el-button"),_=u("el-card");return P(),T("div",A,[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(v,{"label-width":"120px"},{default:l(()=>[a(w,{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:V},{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(v,{"label-width":"120px"},{default:l(()=>[a(w,{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:h},{default:l(()=>[...e[4]||(e[4]=[x("保存密码",-1)])]),_:1},8,["loading"]),e[6]||(e[6]=r("div",{class:"help"},"建议使用更强密码至少8位且包含字母与数字。",-1))]),_:1})])}}},M=B(E,[["__scopeId","data-v-12a26d11"]]);export{M as default};

View File

@@ -1 +0,0 @@
.page-stack[data-v-965e79dd]{display:flex;flex-direction:column;gap:12px}.card[data-v-965e79dd]{border-radius:var(--app-radius);border:1px solid var(--app-border)}.section-title[data-v-965e79dd]{margin:0 0 12px;font-size:14px;font-weight:800}.kdocs-qr[data-v-965e79dd]{display:flex;flex-direction:column;align-items:center;gap:12px}.kdocs-qr img[data-v-965e79dd]{width:260px;max-width:100%;border:1px solid var(--app-border);border-radius:8px;padding:8px;background:#fff}.help[data-v-965e79dd]{margin-top:6px;font-size:12px;color:var(--app-muted)}.row-actions[data-v-965e79dd]{display:flex;flex-wrap:wrap;gap:10px}

View File

@@ -0,0 +1 @@
.page-stack[data-v-7b6c1dc3]{display:flex;flex-direction:column;gap:12px}.card[data-v-7b6c1dc3]{border-radius:var(--app-radius);border:1px solid var(--app-border)}.section-title[data-v-7b6c1dc3]{margin:0 0 12px;font-size:14px;font-weight:800}.kdocs-qr[data-v-7b6c1dc3]{display:flex;flex-direction:column;align-items:center;gap:12px}.kdocs-qr img[data-v-7b6c1dc3]{width:260px;max-width:100%;border:1px solid var(--app-border);border-radius:8px;padding:8px;background:#fff}.help[data-v-7b6c1dc3]{margin-top:6px;font-size:12px;color:var(--app-muted)}.row-actions[data-v-7b6c1dc3]{display:flex;flex-wrap:wrap;gap:10px}

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
import{a as n}from"./index-a8w3mx3g.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-BfJ_SeqK.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

View File

@@ -1 +1 @@
import{a}from"./index-a8w3mx3g.js";async function s(){const{data:t}=await a.get("/system/config");return t}async function c(t){const{data:e}=await a.post("/system/config",t);return e}async function o(){const{data:t}=await a.post("/schedule/execute",{});return t}export{o as e,s as f,c as u}; import{a}from"./index-BfJ_SeqK.js";async function s(){const{data:t}=await a.get("/system/config");return t}async function c(t){const{data:e}=await a.post("/system/config",t);return e}async function o(){const{data:t}=await a.post("/schedule/execute",{});return t}export{o as e,s as f,c as u};

View File

@@ -1 +1 @@
import{a}from"./index-a8w3mx3g.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-BfJ_SeqK.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};

View File

@@ -1 +1 @@
import{a as t}from"./index-a8w3mx3g.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-BfJ_SeqK.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};

View File

@@ -5,7 +5,7 @@
<link rel="icon" type="image/svg+xml" href="./vite.svg" /> <link rel="icon" type="image/svg+xml" href="./vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>后台管理 - 知识管理平台</title> <title>后台管理 - 知识管理平台</title>
<script type="module" crossorigin src="./assets/index-a8w3mx3g.js"></script> <script type="module" crossorigin src="./assets/index-BfJ_SeqK.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-DxTKnDeo.css"> <link rel="stylesheet" crossorigin href="./assets/index-DxTKnDeo.css">
</head> </head>
<body> <body>