Files
zsglpt/static/admin/assets/SettingsPage-BbHyIZsy.js
2026-05-27 21:24:48 +08:00

2 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import{ad as be}from"./vendor-misc-DszMq72k.js";import{f as he,a as ke,u as Pe,b as xe,c as ne,d as Ae,r as Se,e as Ce,g as Be,h as Ve,l as Te,p as Ee}from"./admin-VsbfHbbH.js";import{_ as Ue}from"./index-6ynv0Z9Y.js";import{a as u,E as q}from"./vendor-element-CIudPaVX.js";import{r as c,c as De,o as Oe,R as Me,aj as m,ap as Ne,n as P,q as f,t as v,L as s,E as i,I as x,F as se,D as w,G as le,K as qe,a3 as $e,y as Re,J as $}from"./vendor-vue-CVxSw_oJ.js";import"./vendor-axios-B9ygI19o.js";function ze(n){if(!n||typeof n!="object")throw new Error("Passkey参数无效");return n.publicKey&&typeof n.publicKey=="object"?n.publicKey:n}function H(n){const t=String(n||""),l="=".repeat((4-t.length%4)%4),d=(t+l).replace(/-/g,"+").replace(/_/g,"/"),_=window.atob(d),y=new Uint8Array(_.length);for(let b=0;b<_.length;b+=1)y[b]=_.charCodeAt(b);return y}function C(n){const t=n instanceof ArrayBuffer?new Uint8Array(n):new Uint8Array(n||[]);let l="";for(let d=0;d<t.length;d+=1)l+=String.fromCharCode(t[d]);return window.btoa(l).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function Ke(n){const t=ze(n),l={...t,challenge:H(t.challenge),user:{...t.user,id:H(t.user?.id)}};return Array.isArray(t.excludeCredentials)&&(l.excludeCredentials=t.excludeCredentials.map(d=>({...d,id:H(d.id)}))),l}function Ie(n){if(!n)return null;const t=n.response||{},l={id:n.id,rawId:C(n.rawId),type:n.type,authenticatorAttachment:n.authenticatorAttachment||void 0,response:{}};return t.clientDataJSON&&(l.response.clientDataJSON=C(t.clientDataJSON)),t.attestationObject&&(l.response.attestationObject=C(t.attestationObject)),t.authenticatorData&&(l.response.authenticatorData=C(t.authenticatorData)),t.signature&&(l.response.signature=C(t.signature)),t.userHandle?l.response.userHandle=C(t.userHandle):l.response.userHandle=null,typeof t.getTransports=="function"&&(l.response.transports=t.getTransports()||[]),l}function Le(){return typeof window<"u"&&window.isSecureContext&&!!window.PublicKeyCredential&&!!navigator.credentials}function Qe(){const n=String(window?.navigator?.userAgent||"");return/MiuiBrowser|XiaoMi\/MiuiBrowser/i.test(n)}function He(n,t="Passkey操作"){const l=String(n?.name||"").trim(),d=String(n?.message||"").trim();return l==="NotAllowedError"?`${t}未完成(可能已取消、超时或设备未响应)`:l==="NotReadableError"?/credential manager/i.test(d)&&Qe()?"当前小米浏览器与系统凭据管理器兼容性较差,请改用系统 Chrome 或 Edge 后重试。":/credential manager/i.test(d)?"系统凭据管理器返回异常,请确认已设置系统锁屏并改用系统 Chrome/Edge 后重试。":d||`${t}失败(设备读取异常)`:l==="SecurityError"?"当前环境安全策略不满足 Passkey 要求,请确认使用 HTTPS 且证书有效。":d||`${t}失败`}async function je(n){const t=Ke(n),l=await navigator.credentials.create({publicKey:t});return Ie(l)}const Je={class:"page-stack"},Fe={class:"section-head"},Ge={key:1,class:"social-list"},Xe={class:"social-provider"},Ye={class:"social-info"},Ze={key:0},We={key:1},ea={class:"social-actions"},aa={class:"social-qr-box"},ta={class:"social-qr-prompt"},na=24e4,sa={__name:"SettingsPage",setup(n){const t=c(""),l=c(""),d=c(""),_=c(""),y=c(!1),b=c(!1),R=c(!1),E=c(""),S=c([]),h=c(null),A=c(0),z=c(!1),U=c(""),K=c([]),B=c(!1),D=c(!1),O=c(""),I=c("wx");let V=null,j=0;const J={qq:"QQ",wx:"微信",alipay:"支付宝"},F=De(()=>K.value.filter(a=>J[a.provider]));function re(a){const e=String(a||"");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 G(){try{await Te()}catch{}finally{window.location.href="/yuyx"}}async function oe(){const a=t.value.trim();if(!a){u.error("请输入新用户名");return}try{await q.confirm(`确定将管理员用户名修改为「${a}」吗?修改后需要重新登录。`,"修改用户名",{confirmButtonText:"确认修改",cancelButtonText:"取消",type:"warning"})}catch{return}y.value=!0;try{await Pe(a),u.success("用户名修改成功,请重新登录"),t.value="",setTimeout(G,1200)}catch{}finally{y.value=!1}}async function ie(){const a=l.value,e=d.value,r=_.value;if(!a){u.error("请输入当前密码");return}if(!e){u.error("请输入新密码");return}const p=re(e);if(!p.ok){u.error(p.message);return}if(e!==r){u.error("两次输入的新密码不一致");return}try{await q.confirm("确定修改管理员密码吗?修改后需要重新登录。","修改密码",{confirmButtonText:"确认修改",cancelButtonText:"取消",type:"warning"})}catch{return}y.value=!0;try{await xe({currentPassword:a,newPassword:e}),u.success("密码修改成功,请重新登录"),l.value="",d.value="",_.value="",setTimeout(G,1200)}catch{}finally{y.value=!1}}async function L(){b.value=!0;try{const a=await he();S.value=Array.isArray(a?.items)?a.items:[],S.value.length<3?await X():(h.value=null,A.value=0)}catch{S.value=[],h.value=null,A.value=0}finally{b.value=!1}}function ue(){return!h.value||Date.now()-Number(A.value||0)>na?null:h.value}async function X(){try{const a=await ne({});h.value=a,A.value=Date.now()}catch{h.value=null,A.value=0}}async function de(){if(!Le()){u.error("当前浏览器或环境不支持Passkey需 HTTPS");return}if(S.value.length>=3){u.error("最多可绑定3台设备");return}R.value=!0;try{let a=ue();a||(a=await ne({}));const e=await je(a?.publicKey||{});await Ae({credential:e,device_name:E.value.trim()}),h.value=null,A.value=0,E.value="",u.success("Passkey设备添加成功"),await L()}catch(a){try{await Se({stage:"register",source:"admin-settings",name:a?.name||"",message:a?.message||"",code:a?.code||"",user_agent:navigator.userAgent||""})}catch{}h.value=null,A.value=0,await X();const r=a?.response?.data?.error||He(a,"Passkey注册");u.error(r)}finally{R.value=!1}}async function ce(a){try{await q.confirm(`确定删除设备「${a?.device_name||"未命名设备"}」吗?`,"删除Passkey设备",{confirmButtonText:"删除",cancelButtonText:"取消",type:"warning"})}catch{return}try{await Ce(a.id),u.success("设备已删除"),await L()}catch(e){const r=e?.response?.data;u.error(r?.error||"删除失败")}}function pe(){const a=new URL(window.location.href);return a.pathname="/yuyx/admin-social-bind-callback",a.search="",a.hash="",a.toString()}function fe(a){return a==="wx"?"微":a==="qq"?"Q":"支"}function ve(a){return a==="wx"?"请使用微信扫描二维码完成绑定":a==="qq"?"请使用 QQ 扫描二维码完成绑定":"请使用支付宝扫描二维码完成绑定"}function Q(){V&&(window.clearTimeout(V),V=null)}function M(){Q(),D.value=!1,O.value=""}function ye(a,e,r){Q(),j=Date.now();const p=async()=>{if(Date.now()-j>300*1e3){M(),u.warning("二维码已过期,请重新获取");return}try{const g=await Ee({provider:a,state:e});if(g?.status==="authorized"&&g?.url){M(),window.location.assign(g.url);return}V=window.setTimeout(p,Math.max(Number(r||2),2)*1e3)}catch(g){M();const k=g?.response?.data;u.error(k?.error||"扫码状态获取失败,请重新尝试")}};V=window.setTimeout(p,Math.max(Number(r),2)*1e3)}async function Y(){z.value=!0;try{const a=await ke();B.value=!!a?.enabled,K.value=Array.isArray(a?.items)?a.items:[]}catch{B.value=!1,K.value=[]}finally{z.value=!1}}async function me(a){const e=String(a?.provider||"").trim();if(!(!e||U.value)){U.value=e;try{const r=await Ve({provider:e,redirect_uri:pe()});if(e!=="wx"){window.location.assign(r.url);return}const p=r.scan_url||r.qrcode||r.url;if(!p||!r.scan_state){u.error("微信二维码获取失败");return}I.value=e,O.value=p,D.value=!0,ye(e,r.scan_state,r.scan_poll_interval||2)}catch(r){const p=r?.response?.data;u.error(p?.error||"获取聚合登录地址失败")}finally{U.value=""}}}async function ge(a){try{await q.confirm(`确定解绑${a?.provider_label||"快捷登录"}吗?`,"解绑快捷登录",{confirmButtonText:"解绑",cancelButtonText:"取消",type:"warning"})}catch{return}try{await Be(a.provider),u.success("已解绑"),await Y()}catch(e){const r=e?.response?.data;u.error(r?.error||"解绑失败")}}return Oe(()=>{L(),Y()}),Me(()=>{Q()}),(a,e)=>{const r=m("el-input"),p=m("el-form-item"),g=m("el-form"),k=m("el-button"),N=m("el-card"),Z=m("el-alert"),W=m("el-empty"),T=m("el-table-column"),we=m("el-table"),ee=m("el-tag"),_e=m("el-dialog"),ae=Ne("loading");return f(),P("div",Je,[e[19]||(e[19]=v("div",{class:"app-page-title"},[v("h2",null,"设置"),v("span",{class:"app-muted"},"管理员账号设置")],-1)),s(N,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:i(()=>[e[7]||(e[7]=v("h3",{class:"section-title"},"修改管理员用户名",-1)),s(g,{"label-width":"120px"},{default:i(()=>[s(p,{label:"新用户名"},{default:i(()=>[s(r,{modelValue:t.value,"onUpdate:modelValue":e[0]||(e[0]=o=>t.value=o),placeholder:"输入新用户名",disabled:y.value},null,8,["modelValue","disabled"])]),_:1})]),_:1}),s(k,{type:"primary",loading:y.value,onClick:oe},{default:i(()=>[...e[6]||(e[6]=[x("保存用户名",-1)])]),_:1},8,["loading"])]),_:1}),s(N,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:i(()=>[e[9]||(e[9]=v("h3",{class:"section-title"},"修改管理员密码",-1)),s(g,{"label-width":"120px"},{default:i(()=>[s(p,{label:"当前密码"},{default:i(()=>[s(r,{modelValue:l.value,"onUpdate:modelValue":e[1]||(e[1]=o=>l.value=o),type:"password","show-password":"",placeholder:"输入当前密码",disabled:y.value},null,8,["modelValue","disabled"])]),_:1}),s(p,{label:"新密码"},{default:i(()=>[s(r,{modelValue:d.value,"onUpdate:modelValue":e[2]||(e[2]=o=>d.value=o),type:"password","show-password":"",placeholder:"输入新密码",disabled:y.value},null,8,["modelValue","disabled"])]),_:1}),s(p,{label:"确认新密码"},{default:i(()=>[s(r,{modelValue:_.value,"onUpdate:modelValue":e[3]||(e[3]=o=>_.value=o),type:"password","show-password":"",placeholder:"再次输入新密码",disabled:y.value},null,8,["modelValue","disabled"])]),_:1})]),_:1}),s(k,{type:"primary",loading:y.value,onClick:ie},{default:i(()=>[...e[8]||(e[8]=[x("保存密码",-1)])]),_:1},8,["loading"]),e[10]||(e[10]=v("div",{class:"help"},"建议使用更强密码至少8位且包含字母与数字。",-1))]),_:1}),s(N,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:i(()=>[e[13]||(e[13]=v("h3",{class:"section-title"},"Passkey设备",-1)),s(Z,{type:"info",closable:!1,title:"最多可绑定3台设备可用于管理员无密码登录。","show-icon":"",class:"help-alert"}),s(g,{inline:""},{default:i(()=>[s(p,{label:"设备备注"},{default:i(()=>[s(r,{modelValue:E.value,"onUpdate:modelValue":e[4]||(e[4]=o=>E.value=o),placeholder:"例如值班iPhone / 办公Mac",maxlength:"40","show-word-limit":""},null,8,["modelValue"])]),_:1}),s(p,null,{default:i(()=>[s(k,{type:"primary",loading:R.value,onClick:de},{default:i(()=>[...e[11]||(e[11]=[x("添加Passkey设备",-1)])]),_:1},8,["loading"])]),_:1})]),_:1}),se((f(),P("div",null,[S.value.length===0?(f(),w(W,{key:0,description:"暂无Passkey设备"})):(f(),w(we,{key:1,data:S.value,size:"small",style:{width:"100%"}},{default:i(()=>[s(T,{prop:"device_name",label:"设备备注","min-width":"160"}),s(T,{prop:"credential_id_preview",label:"凭据ID","min-width":"180"}),s(T,{prop:"last_used_at",label:"最近使用","min-width":"140"}),s(T,{prop:"created_at",label:"创建时间","min-width":"140"}),s(T,{label:"操作",width:"100",fixed:"right"},{default:i(({row:o})=>[s(k,{type:"danger",text:"",onClick:te=>ce(o)},{default:i(()=>[...e[12]||(e[12]=[x("删除",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"]))])),[[ae,b.value]])]),_:1}),s(N,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:i(()=>[v("div",Fe,[e[16]||(e[16]=v("h3",{class:"section-title"},"快捷登录绑定",-1)),B.value?(f(),w(ee,{key:0,size:"small",type:"success"},{default:i(()=>[...e[14]||(e[14]=[x("已启用",-1)])]),_:1})):(f(),w(ee,{key:1,size:"small",type:"info"},{default:i(()=>[...e[15]||(e[15]=[x("未启用",-1)])]),_:1}))]),B.value?le("",!0):(f(),w(Z,{key:0,type:"warning",closable:!1,title:"聚合登录未启用,请先在系统配置中填写并启用 Space 聚合登录。","show-icon":"",class:"help-alert"})),se((f(),P("div",null,[F.value.length===0?(f(),w(W,{key:0,description:"暂无可绑定的快捷登录方式"})):(f(),P("div",Ge,[(f(!0),P(qe,null,$e(F.value,o=>(f(),P("div",{key:o.provider,class:"social-row"},[v("div",Xe,[v("span",{class:Re(["social-icon",`provider-${o.provider}`])},$(fe(o.provider)),3),v("div",Ye,[v("strong",null,$(o.provider_label),1),o.bound?(f(),P("span",Ze,$(o.nickname||"已绑定"),1)):(f(),P("span",We,"未绑定"))])]),v("div",ea,[o.bound?(f(),w(k,{key:0,type:"danger",text:"",onClick:te=>ge(o)},{default:i(()=>[...e[17]||(e[17]=[x(" 解绑 ",-1)])]),_:1},8,["onClick"])):(f(),w(k,{key:1,type:"primary",plain:"",disabled:!B.value,loading:U.value===o.provider,onClick:te=>me(o)},{default:i(()=>[...e[18]||(e[18]=[x(" 绑定 ",-1)])]),_:1},8,["disabled","loading","onClick"]))])]))),128))]))])),[[ae,z.value]]),s(_e,{modelValue:D.value,"onUpdate:modelValue":e[5]||(e[5]=o=>D.value=o),title:`${J[I.value]}绑定`,width:"min(340px, 92vw)",onClose:M},{default:i(()=>[v("div",aa,[O.value?(f(),w(be,{key:0,value:O.value,size:220,level:"M"},null,8,["value"])):le("",!0),v("div",ta,$(ve(I.value)),1)])]),_:1},8,["modelValue","title"])]),_:1})])}}},ca=Ue(sa,[["__scopeId","data-v-e6d9cfda"]]);export{ca as default};