2 lines
14 KiB
JavaScript
2 lines
14 KiB
JavaScript
import{f as X,g as n,h as Ee,i as Le,j as l,k as s,l as u,n as ae,t as g,w,v as k,m as se,p as Re,q as oe,o as c}from"./vendor-vue-WbiK4TmU.js";import{S as Ve}from"./SocialLoginButtons-BlVSr6Mm.js";import{_ as Ne}from"./style-CEbARg1o.js";import"./base-xgxQQEpV.js";import"./el-overlay-hge8bsIn.js";import"./aria-DLpFpzDe.js";import"./http-BoPYlvwK.js";import"./vendor-axios-B9ygI19o.js";import"./index-CoYtSGUZ.js";import"./auth-B5cl_nsV.js";const Ie={class:"login-page"},$e={class:"login-container"},Be={class:"form-group"},Ke={class:"form-group"},De={key:1,class:"form-group"},ze={class:"captcha-row"},He=["src"],je=["disabled"],qe=["disabled"],Fe={key:2,class:"social-login-area"},Je={class:"action-links"},We={class:"modal-card"},Me={class:"modal-head"},Ge={key:0,class:"modal-tip warn"},Xe={key:1,class:"modal-tip error"},Qe={class:"form-group"},Ye={class:"form-group"},Ze={class:"captcha-row"},et=["src"],tt={class:"modal-actions"},at=["disabled"],st={class:"modal-card"},ot={class:"modal-head"},nt={key:0,class:"modal-tip error"},rt={class:"form-group"},it={class:"form-group"},lt={class:"captcha-row"},ct=["src"],ut={class:"modal-actions"},dt=["disabled"],pt={__name:"LoginPage",setup(mt){const i=X({username:"",password:"",captcha:""}),_=n(!1),A=n(""),H=n(""),U=n(!1),E=n(!1),C=n(!1),j=n(!1),q=n(""),L=n(""),S=n(!1),P=n(!1),p=X({username:"",captcha:""}),R=n(""),F=n(""),V=n(!1),T=n(""),y=n(""),m=X({email:"",captcha:""}),N=n(""),J=n(""),I=n(!1),h=n(""),ne=Ee(()=>!0),Q=n(!1),$=n({enabled:!1,providers:[]}),B=n(!1),K={token:"zsglpt_social_pending_bind_token",provider:"zsglpt_social_pending_bind_provider",nickname:"zsglpt_social_pending_bind_nickname",avatar:"zsglpt_social_pending_bind_avatar_url"};function re(t){const e=String(t).replace(/([.*+?^${}()|[\]\\])/g,"\\$1"),a=document.cookie.match(new RegExp(`(?:^|; )${e}=([^;]*)`));return a?decodeURIComponent(a[1]):""}class ie extends Error{constructor(e,a,o){super(e||"请求失败"),this.name="ApiError",this.response={status:Number(a||0),data:o||{}}}}async function f(t,e={}){const a=String(e.method||"GET").toUpperCase(),o={...e.headers||{}},v=Object.prototype.hasOwnProperty.call(e,"body");if(v&&!o["Content-Type"]&&(o["Content-Type"]="application/json"),!["GET","HEAD","OPTIONS"].includes(a)){const te=re("csrf_token");te&&(o["X-CSRF-Token"]=te)}const b=await fetch(`/api${t}`,{method:a,headers:o,credentials:"include",body:v?JSON.stringify(e.body??{}):void 0});let d={};try{d=await b.json()}catch{d={}}if(!b.ok)throw new ie(d?.error||d?.message||`请求失败 (${b.status})`,b.status,d);return d}const le=()=>f("/email/verify-status"),W=()=>f("/generate_captcha",{method:"POST",body:{}}),ce=t=>f("/login",{method:"POST",body:t||{}}),ue=t=>f("/passkeys/login/options",{method:"POST",body:t||{}}),de=t=>f("/passkeys/login/verify",{method:"POST",body:t||{}}),pe=t=>f("/resend-verify-email",{method:"POST",body:t||{}}),me=t=>f("/forgot-password",{method:"POST",body:t||{}}),fe=()=>f("/auth/social/config"),ve=t=>f("/auth/social/callback",{method:"POST",body:t||{}});function Y(t){const e=String(t||""),a="=".repeat((4-e.length%4)%4),o=(e+a).replace(/-/g,"+").replace(/_/g,"/"),v=window.atob(o),b=new Uint8Array(v.length);for(let d=0;d<v.length;d+=1)b[d]=v.charCodeAt(d);return b}function O(t){const e=t instanceof ArrayBuffer?new Uint8Array(t):new Uint8Array(t||[]);let a="";for(let o=0;o<e.length;o+=1)a+=String.fromCharCode(e[o]);return window.btoa(a).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function ge(t){if(!t||typeof t!="object")throw new Error("Passkey参数无效");return t.publicKey&&typeof t.publicKey=="object"?t.publicKey:t}function ye(t){const e=ge(t),a={...e,challenge:Y(e.challenge)};return Array.isArray(e.allowCredentials)&&(a.allowCredentials=e.allowCredentials.map(o=>({...o,id:Y(o.id)}))),a}function he(t){const e=t?.response||{},a={id:t?.id,rawId:O(t?.rawId),type:t?.type,authenticatorAttachment:t?.authenticatorAttachment||void 0,response:{}};return e.clientDataJSON&&(a.response.clientDataJSON=O(e.clientDataJSON)),e.authenticatorData&&(a.response.authenticatorData=O(e.authenticatorData)),e.signature&&(a.response.signature=O(e.signature)),e.userHandle?a.response.userHandle=O(e.userHandle):a.response.userHandle=null,a}function be(){return typeof window<"u"&&window.isSecureContext&&!!window.PublicKeyCredential&&!!navigator.credentials}async function we(t){const e=ye(t),a=await navigator.credentials.get({publicKey:e});return he(a)}async function Z(){if(!Q.value)try{const t=await le();C.value=!!t?.email_enabled,j.value=!!t?.register_verify_enabled}catch{C.value=!1,j.value=!1}finally{Q.value=!0}}function r(t,e){q.value=String(t||""),L.value=String(e||"")}function ee(){q.value="",L.value=""}async function x(){try{const t=await W();H.value=t?.session_id||"",A.value=t?.captcha_image||"",i.captcha=""}catch{H.value="",A.value=""}}async function D(){try{const t=await W();F.value=t?.session_id||"",R.value=t?.captcha_image||"",p.captcha=""}catch{F.value="",R.value=""}}async function z(){try{const t=await W();J.value=t?.session_id||"",N.value=t?.captcha_image||"",m.captcha=""}catch{J.value="",N.value=""}}function M(){const t=new URLSearchParams(window.location.search||""),e=String(t.get("next")||"").trim(),a=e&&e.startsWith("/")&&!e.startsWith("//")&&!e.startsWith("/\\")?e:"";window.setTimeout(()=>{window.location.href=a||"/app"},300)}function ke(){const t=new URL(window.location.href);return t.pathname="/login",t.search="",t.hash="",t.toString()}async function _e(){try{const t=await fe();$.value={enabled:!!t?.enabled,providers:Array.isArray(t?.providers)?t.providers:[]}}catch{$.value={enabled:!1,providers:[]}}}function Ce(t){try{window.sessionStorage.setItem(K.token,t?.bind_token||""),window.sessionStorage.setItem(K.provider,t?.provider||""),window.sessionStorage.setItem(K.nickname,t?.nickname||""),window.sessionStorage.setItem(K.avatar,t?.avatar_url||"")}catch{}}async function Se(){const t=new URLSearchParams(window.location.search||""),e=String(t.get("provider")||t.get("type")||"").trim(),a=String(t.get("code")||"").trim();if(!e||!a)return!1;B.value=!0,r("success","正在完成快捷登录...");try{const o=await ve({provider:e,code:a,mode:"login"});if(o?.requires_register&&o?.bind_token)return Ce(o),r("success","请完成注册后继续"),window.setTimeout(()=>{window.location.href="/register"},500),!0;if(o?.success||o?.bound)return r("success","快捷登录成功,正在跳转..."),M(),!0;r("error","快捷登录失败")}catch(o){const v=o?.response?.data;r("error",v?.error||v?.message||"快捷登录失败")}finally{B.value=!1}return!0}async function G(){if(ee(),!i.username.trim()||!i.password.trim()){r("error","用户名和密码不能为空");return}if(_.value&&!i.captcha.trim()){r("error","请输入验证码");return}U.value=!0;try{const t=i.username.trim();await ce({username:t,password:i.password,captcha_session:H.value,captcha:i.captcha.trim(),need_captcha:_.value}),r("success","登录成功,正在跳转..."),M()}catch(t){const e=t?.response?.status,a=t?.response?.data,o=a?.error||a?.message||"登录失败";r("error",o),a?.need_captcha?(_.value=!0,await x()):_.value&&e===400&&await x()}finally{U.value=!1}}async function Pe(){ee();const t=i.username.trim();if(!be()){r("error","当前浏览器或环境不支持Passkey(需 HTTPS)");return}E.value=!0;try{const e=await ue(t?{username:t}:{}),a=await we(e?.publicKey||{});await de(t?{username:t,credential:a}:{credential:a}),r("success","Passkey 登录成功,正在跳转..."),M()}catch(e){const o=e?.response?.data?.error||(e?.name==="NotAllowedError"?"Passkey验证未完成(可能取消、超时或设备未响应)":e?.message||"Passkey登录失败");r("error",o)}finally{E.value=!1}}async function Te(){await Z(),S.value=!0,T.value="",y.value="",p.username="",p.captcha="",await D()}async function Oe(){if(y.value="",T.value="",!C.value){y.value="邮件功能未启用,请联系管理员重置密码。";return}const t=p.username.trim();if(!t){y.value="请输入用户名";return}if(!p.captcha.trim()){y.value="请输入验证码";return}V.value=!0;try{const e=await me({username:t,captcha_session:F.value,captcha:p.captcha.trim()});r("success",e?.message||"已发送重置邮件"),S.value=!1}catch(e){const a=e?.response?.data,o=a?.error||"发送失败";a?.code==="email_not_bound"?T.value=o:y.value=o,await D()}finally{V.value=!1}}async function xe(){if(await Z(),!j.value){r("error","当前未启用注册邮箱验证,无需重发验证邮件。");return}P.value=!0,m.email="",m.captcha="",h.value="",await z()}async function Ae(){h.value="";const t=m.email.trim();if(!t){h.value="请输入邮箱";return}if(!m.captcha.trim()){h.value="请输入验证码";return}I.value=!0;try{const e=await pe({email:t,captcha_session:J.value,captcha:m.captcha.trim()});r("success",e?.message||"验证邮件已发送,请查收"),P.value=!1}catch(e){const a=e?.response?.data;h.value=a?.error||"发送失败",await z()}finally{I.value=!1}}function Ue(){window.location.href="/register"}return Le(async()=>{await _e(),await Se(),_.value&&await x()}),(t,e)=>(c(),l("div",Ie,[s("div",$e,[e[19]||(e[19]=s("div",{class:"login-header"},[s("span",{class:"login-badge"},"用户登录"),s("h1",null,"用户登录系统"),s("p",null,"知识管理平台")],-1)),L.value?(c(),l("div",{key:0,class:ae(["notice",q.value==="success"?"is-success":"is-error"])},g(L.value),3)):u("",!0),s("div",Be,[e[14]||(e[14]=s("label",{for:"username"},"用户账号",-1)),w(s("input",{id:"username","onUpdate:modelValue":e[0]||(e[0]=a=>i.username=a),class:"text-input",placeholder:"请输入用户名",autocomplete:"username"},null,512),[[k,i.username]])]),s("div",Ke,[e[15]||(e[15]=s("label",{for:"password"},"密码",-1)),w(s("input",{id:"password","onUpdate:modelValue":e[1]||(e[1]=a=>i.password=a),class:"text-input",type:"password",placeholder:"请输入密码",autocomplete:"current-password",onKeyup:se(G,["enter"])},null,544),[[k,i.password]])]),_.value?(c(),l("div",De,[e[16]||(e[16]=s("label",{for:"captcha"},"验证码",-1)),s("div",ze,[w(s("input",{id:"captcha","onUpdate:modelValue":e[2]||(e[2]=a=>i.captcha=a),class:"text-input captcha-input",placeholder:"请输入验证码",onKeyup:se(G,["enter"])},null,544),[[k,i.captcha]]),A.value?(c(),l("img",{key:0,class:"captcha-img",src:A.value,alt:"验证码",title:"点击刷新",onClick:x},null,8,He)):u("",!0),s("button",{type:"button",class:"captcha-refresh",onClick:x},"刷新")])])):u("",!0),s("button",{type:"button",class:"btn-login",disabled:U.value||B.value,onClick:G},g(U.value||B.value?"登录中...":"登录系统"),9,je),s("button",{type:"button",class:"btn-passkey",disabled:E.value,onClick:Pe},g(E.value?"Passkey验证中...":"使用 Passkey 登录"),9,qe),$.value.enabled?(c(),l("div",Fe,[e[17]||(e[17]=s("div",{class:"divider"},[s("span",null,"快捷登录")],-1)),Re(Ve,{providers:$.value.providers,mode:"login","redirect-uri":ke(),block:"",onError:e[3]||(e[3]=a=>r("error",a))},null,8,["providers","redirect-uri"])])):u("",!0),s("div",Je,[s("button",{type:"button",class:"link-btn",onClick:Te},"忘记密码?"),ne.value?(c(),l("button",{key:0,type:"button",class:"link-btn",onClick:xe},"重发验证邮件")):u("",!0)]),s("div",{class:"register-row"},[e[18]||(e[18]=s("span",null,"还没有账号?",-1)),s("button",{type:"button",class:"link-btn",onClick:Ue},"立即注册")])]),S.value?(c(),l("div",{key:0,class:"modal-mask",onClick:e[8]||(e[8]=oe(a=>S.value=!1,["self"]))},[s("section",We,[s("div",Me,[e[20]||(e[20]=s("h3",null,"找回密码",-1)),s("button",{type:"button",class:"modal-close",onClick:e[4]||(e[4]=a=>S.value=!1)},"关闭")]),s("p",{class:ae(["modal-tip",{warn:!C.value}])},g(C.value?"输入用户名并完成验证码,我们将向该账号绑定的邮箱发送重置链接。":"邮件功能未启用,无法通过邮箱找回密码。"),3),T.value?(c(),l("p",Ge,g(T.value),1)):u("",!0),y.value?(c(),l("p",Xe,g(y.value),1)):u("",!0),s("div",Qe,[e[21]||(e[21]=s("label",{for:"forgot-username"},"用户名",-1)),w(s("input",{id:"forgot-username","onUpdate:modelValue":e[5]||(e[5]=a=>p.username=a),class:"text-input",placeholder:"请输入用户名"},null,512),[[k,p.username]])]),s("div",Ye,[e[22]||(e[22]=s("label",{for:"forgot-captcha"},"验证码",-1)),s("div",Ze,[w(s("input",{id:"forgot-captcha","onUpdate:modelValue":e[6]||(e[6]=a=>p.captcha=a),class:"text-input captcha-input",placeholder:"请输入验证码"},null,512),[[k,p.captcha]]),R.value?(c(),l("img",{key:0,class:"captcha-img",src:R.value,alt:"验证码",title:"点击刷新",onClick:D},null,8,et)):u("",!0),s("button",{type:"button",class:"captcha-refresh",onClick:D},"刷新")])]),s("div",tt,[s("button",{type:"button",class:"btn-ghost",onClick:e[7]||(e[7]=a=>S.value=!1)},"取消"),s("button",{type:"button",class:"btn-login",disabled:V.value||!C.value,onClick:Oe},g(V.value?"发送中...":"发送重置邮件"),9,at)])])])):u("",!0),P.value?(c(),l("div",{key:1,class:"modal-mask",onClick:e[13]||(e[13]=oe(a=>P.value=!1,["self"]))},[s("section",st,[s("div",ot,[e[23]||(e[23]=s("h3",null,"重发验证邮件",-1)),s("button",{type:"button",class:"modal-close",onClick:e[9]||(e[9]=a=>P.value=!1)},"关闭")]),e[26]||(e[26]=s("p",{class:"modal-tip"},"用于注册邮箱验证:请输入邮箱并完成验证码。",-1)),h.value?(c(),l("p",nt,g(h.value),1)):u("",!0),s("div",rt,[e[24]||(e[24]=s("label",{for:"resend-email"},"邮箱",-1)),w(s("input",{id:"resend-email","onUpdate:modelValue":e[10]||(e[10]=a=>m.email=a),class:"text-input",placeholder:"name@example.com"},null,512),[[k,m.email]])]),s("div",it,[e[25]||(e[25]=s("label",{for:"resend-captcha"},"验证码",-1)),s("div",lt,[w(s("input",{id:"resend-captcha","onUpdate:modelValue":e[11]||(e[11]=a=>m.captcha=a),class:"text-input captcha-input",placeholder:"请输入验证码"},null,512),[[k,m.captcha]]),N.value?(c(),l("img",{key:0,class:"captcha-img",src:N.value,alt:"验证码",title:"点击刷新",onClick:z},null,8,ct)):u("",!0),s("button",{type:"button",class:"captcha-refresh",onClick:z},"刷新")])]),s("div",ut,[s("button",{type:"button",class:"btn-ghost",onClick:e[12]||(e[12]=a=>P.value=!1)},"取消"),s("button",{type:"button",class:"btn-login",disabled:I.value,onClick:Ae},g(I.value?"发送中...":"发送"),9,dt)])])])):u("",!0)]))}},St=Ne(pt,[["__scopeId","data-v-870324c7"]]);export{St as default};
|