Files
zsglpt/static/admin/assets/SecurityPage-BtFrxpZs.js
yuyx 7007f5f6f5 feat: 完成 Passkey 能力与前后台加载优化
更新说明:\n1. 新增用户端与管理员端 Passkey 登录/注册/设备管理(最多3台,支持设备备注、删除设备)。\n2. 修复 Passkey 注册与登录流程中的浏览器/证书/CSRF相关问题,增强错误提示。\n3. 前台登录页改为独立入口,首屏仅加载必要资源,其他页面按需加载。\n4. 系统配置页改为静默获取金山文档状态,避免首屏阻塞,并优化状态展示为“检测中/已登录/未登录/异常”。\n5. 补充后端接口与页面渲染适配,修复多入口下样式依赖注入问题。\n6. 同步更新前后台构建产物与相关静态资源。
2026-02-15 23:51:46 +08:00

6 lines
18 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{a as g,_ as qe}from"./index-BMIn4N2u.js";import{M as Ee}from"./MetricGrid-R-_JZS_i.js";import{E as ee,a as w}from"./vendor-element-B5S5pUKo.js";import{r as d,c as oe,o as ze,aj as v,ap as Ae,n as P,q as c,t as p,L as a,E as l,I as i,K as Ge,a3 as Ke,D as b,F as te,J as f,G as ue}from"./vendor-vue-CVxSw_oJ.js";import"./vendor-axios-B9ygI19o.js";import"./vendor-misc-BeoNyvBp.js";async function Oe(){const{data:u}=await g.get("/admin/security/dashboard");return u}async function He(u){const{data:m}=await g.get("/admin/security/threats",{params:u});return m}async function Je(){const{data:u}=await g.get("/admin/security/banned-ips");return u}async function Qe(){const{data:u}=await g.get("/admin/security/banned-users");return u}async function We(u){const{data:m}=await g.post("/admin/security/ban-ip",u);return m}async function Xe(u){const{data:m}=await g.post("/admin/security/unban-ip",{ip:u});return m}async function Ye(u){const{data:m}=await g.post("/admin/security/ban-user",u);return m}async function Ze(u){const{data:m}=await g.post("/admin/security/unban-user",{user_id:u});return m}async function et(u){const m=encodeURIComponent(String(u||"").trim()),{data:V}=await g.get(`/admin/security/ip-risk/${m}`);return V}async function tt(u){const{data:m}=await g.post("/admin/security/ip-risk/clear",{ip:u});return m}async function at(u){const m=encodeURIComponent(String(u||"").trim()),{data:V}=await g.get(`/admin/security/user-risk/${m}`);return V}async function lt(){const{data:u}=await g.post("/admin/security/cleanup",{});return u}const nt={class:"page-stack"},it={class:"app-page-title"},st={class:"toolbar"},ot={class:"filters"},ut={class:"table-wrap"},rt={key:1},dt={key:1},pt={class:"mono ellipsis"},ct={class:"ellipsis"},ft={class:"pagination"},mt={class:"page-hint app-muted"},vt={class:"toolbar"},_t={class:"table-wrap"},yt={class:"table-wrap"},bt={class:"filters"},gt={class:"filters"},kt={class:"risk-head"},ht={class:"risk-title"},wt={key:0},It={key:1},Vt={class:"toolbar"},xt={class:"table-wrap"},Ct={class:"mono ellipsis"},St={class:"ellipsis"},Tt={class:"dialog-actions"},re=20,Pt={__name:"SecurityPage",setup(u){const m=d("threats"),V=d(!1),L=d(null),ae=d(!1),q=d([]),E=d(0),C=d(1),U=d(""),B=d(""),$=d(!1),de=d([]),pe=d([]),ce=d("ips"),S=d(!1),R=d(!1),o=d({kind:"ip",ip:"",user_id:"",reason:"",duration_hours:24,permanent:!1}),z=d("ip"),k=d(!1),A=d(""),G=d(""),_=d(null),h=d(""),Ie=["sql_injection","xss","path_traversal","command_injection","ssrf","scanner","bruteforce","csrf","xxe","file_upload"];function le(n){const e=Number(n);return Number.isFinite(e)?e:0}function D(n){const e=Number(n||0);return e>=80?{label:"高",type:"danger"}:e>=50?{label:"中",type:"warning"}:{label:"低",type:"success"}}function fe(n){const e=String(n||"").trim();return e||"永久"}function me(n){const e=[];return n?.field_name&&e.push(`字段: ${n.field_name}`),n?.rule&&e.push(`规则: ${n.rule}`),n?.matched&&e.push(`匹配: ${n.matched}`),n?.value_preview&&e.push(`值: ${n.value_preview}`),e.length?e.join(" · "):"-"}function K(n){const e=String(n?.request_method||"").trim(),s=String(n?.request_path||"").trim();return`${e} ${s}`.trim()||"-"}const Ve=oe(()=>{const n=new Set(Ie),e=L.value?.recent_threat_events||[];for(const s of e){const y=String(s?.threat_type||"").trim();y&&n.add(y)}for(const s of q.value||[]){const y=String(s?.threat_type||"").trim();y&&n.add(y)}return Array.from(n).sort((s,y)=>s.localeCompare(y)).map(s=>({label:s,value:s}))}),xe=oe(()=>{const n=L.value||{};return[{key:"threat_events_24h",label:"最近24小时威胁事件",value:le(n.threat_events_24h),tone:"red",hint:"用于衡量当前攻击面活跃度"},{key:"banned_ip_count",label:"当前封禁 IP 数",value:le(n.banned_ip_count),tone:"orange",hint:"自动与人工封禁总量"},{key:"banned_user_count",label:"当前封禁用户数",value:le(n.banned_user_count),tone:"purple",hint:"高风险账户拦截情况"}]}),Ce=oe(()=>Math.max(1,Math.ceil((E.value||0)/re)));async function N(){V.value=!0;try{L.value=await Oe()}catch{L.value=null}finally{V.value=!1}}async function O(){ae.value=!0;try{const n={page:C.value,per_page:re};U.value&&(n.event_type=U.value),B.value&&(n.severity=B.value);const e=await He(n);q.value=e?.items||[],E.value=e?.total||0}catch{q.value=[],E.value=0}finally{ae.value=!1}}async function F(){if(!$.value){$.value=!0;try{const[n,e]=await Promise.allSettled([Je(),Qe()]);de.value=n.status==="fulfilled"?n.value?.items||[]:[],pe.value=e.status==="fulfilled"?e.value?.items||[]:[]}finally{$.value=!1}}}async function ve(){await Promise.allSettled([N(),O(),F()])}function Se(){C.value=1,O()}function Te(){U.value="",B.value="",C.value=1,O()}function _e(){o.value={kind:"ip",ip:"",user_id:"",reason:"",duration_hours:24,permanent:!1}}function H(n="ip",e={}){_e(),o.value.kind=n==="user"?"user":"ip",o.value.kind==="ip"?o.value.ip=String(e.ip||"").trim():o.value.user_id=String(e.user_id||"").trim(),e.reason&&(o.value.reason=String(e.reason||"").trim()),S.value=!0}async function Pe(){const n=o.value.kind,e=String(o.value.reason||"").trim(),s=!!o.value.permanent,y=Number(o.value.duration_hours||24);if(!e){w.error("原因不能为空");return}if(n==="ip"){const I=String(o.value.ip||"").trim();if(!I){w.error("IP不能为空");return}R.value=!0;try{await We({ip:I,reason:e,duration_hours:y,permanent:s}),w.success("IP已封禁"),S.value=!1,await Promise.allSettled([N(),F()])}catch{}finally{R.value=!1}return}const Q=String(o.value.user_id||"").trim(),r=Number.parseInt(Q,10);if(!Number.isFinite(r)){w.error("用户ID无效");return}R.value=!0;try{await Ye({user_id:r,reason:e,duration_hours:y,permanent:s}),w.success("用户已封禁"),S.value=!1,await Promise.allSettled([N(),F()])}catch{}finally{R.value=!1}}async function ye(n){const e=String(n||"").trim();if(e){try{await ee.confirm(`确定解除对 IP ${e} 的封禁吗?`,"解除封禁",{confirmButtonText:"解除",cancelButtonText:"取消",type:"warning"})}catch{return}try{await Xe(e),w.success("已解除IP封禁"),await Promise.allSettled([N(),F()])}catch{}}}async function be(n){const e=Number.parseInt(String(n||"").trim(),10);if(Number.isFinite(e)){try{await ee.confirm(`确定解除对 用户ID ${e} 的封禁吗?`,"解除封禁",{confirmButtonText:"解除",cancelButtonText:"取消",type:"warning"})}catch{return}try{await Ze(e),w.success("已解除用户封禁"),await Promise.allSettled([N(),F()])}catch{}}}function ge(n){const e=String(n||"").trim();e&&(m.value="risk",z.value="ip",A.value=e,J())}function ke(n){const e=String(n||"").trim();e&&(m.value="risk",z.value="user",G.value=e,ne())}async function J(){const n=String(A.value||"").trim();if(!n){w.error("请输入IP");return}k.value=!0;try{_.value=await et(n),h.value="ip"}catch{_.value=null,h.value=""}finally{k.value=!1}}async function ne(){const n=String(G.value||"").trim(),e=Number.parseInt(n,10);if(!Number.isFinite(e)){w.error("请输入有效的用户ID");return}k.value=!0;try{_.value=await at(e),h.value="user"}catch{_.value=null,h.value=""}finally{k.value=!1}}function Ue(){!_.value||!h.value||(h.value==="ip"?H("ip",{ip:_.value?.ip,reason:"风险查询手动封禁"}):H("user",{user_id:_.value?.user_id,reason:"风险查询手动封禁"}))}async function Be(){!_.value||!h.value||(h.value==="ip"?(await ye(_.value?.ip),await J()):(await be(_.value?.user_id),await ne()))}async function $e(){if(h.value!=="ip")return;const n=String(_.value?.ip||"").trim();if(n){try{await ee.confirm(`确定清除 IP ${n} 的风险分吗?
清除风险分不会删除威胁历史,也不会解除封禁。`,"清除风险分",{confirmButtonText:"清除",cancelButtonText:"取消",type:"warning"})}catch{return}if(!k.value){k.value=!0;try{await tt(n),w.success("IP风险分已清零")}catch{}finally{k.value=!1}await J()}}}const ie=d(!1);async function Re(){try{await ee.confirm(`确定清理过期封禁记录,并衰减风险分吗?
该操作不会影响仍在有效期内的封禁。`,"清理过期记录",{confirmButtonText:"清理",cancelButtonText:"取消",type:"warning"})}catch{return}ie.value=!0;try{await lt(),w.success("清理完成"),await ve()}catch{}finally{ie.value=!1}}return ze(async()=>{await ve()}),(n,e)=>{const s=v("el-button"),y=v("el-option"),Q=v("el-select"),r=v("el-table-column"),I=v("el-tag"),W=v("el-link"),X=v("el-tooltip"),Y=v("el-table"),De=v("el-pagination"),x=v("el-tab-pane"),se=v("el-tabs"),M=v("el-input"),he=v("el-card"),we=v("el-radio-button"),Ne=v("el-radio-group"),T=v("el-form-item"),Fe=v("el-switch"),Me=v("el-input-number"),je=v("el-form"),Le=v("el-dialog"),Z=Ae("loading");return c(),P("div",nt,[p("div",it,[e[20]||(e[20]=p("h2",null,"安全防护",-1)),p("div",st,[a(s,{type:"warning",plain:"",loading:ie.value,onClick:Re},{default:l(()=>[...e[18]||(e[18]=[i("清理过期记录",-1)])]),_:1},8,["loading"]),a(s,{type:"primary",onClick:e[0]||(e[0]=t=>H())},{default:l(()=>[...e[19]||(e[19]=[i("手动封禁",-1)])]),_:1})])]),a(Ee,{items:xe.value,loading:V.value,"min-width":220},null,8,["items","loading"]),a(he,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:l(()=>[a(se,{modelValue:m.value,"onUpdate:modelValue":e[9]||(e[9]=t=>m.value=t)},{default:l(()=>[a(x,{label:"威胁事件",name:"threats"},{default:l(()=>[p("div",ot,[a(Q,{modelValue:U.value,"onUpdate:modelValue":e[1]||(e[1]=t=>U.value=t),placeholder:"类型",style:{width:"220px"},filterable:"",clearable:"","allow-create":"","default-first-option":""},{default:l(()=>[a(y,{label:"全部",value:""}),(c(!0),P(Ge,null,Ke(Ve.value,t=>(c(),b(y,{key:t.value,label:t.label,value:t.value},null,8,["label","value"]))),128))]),_:1},8,["modelValue"]),a(Q,{modelValue:B.value,"onUpdate:modelValue":e[2]||(e[2]=t=>B.value=t),placeholder:"严重程度",style:{width:"200px"},clearable:""},{default:l(()=>[a(y,{label:"全部",value:""}),a(y,{label:"高风险(>=80)",value:"high"}),a(y,{label:"中风险(50-79)",value:"medium"}),a(y,{label:"低风险(<50)",value:"low"})]),_:1},8,["modelValue"]),a(s,{type:"primary",onClick:Se},{default:l(()=>[...e[21]||(e[21]=[i("筛选",-1)])]),_:1}),a(s,{onClick:Te},{default:l(()=>[...e[22]||(e[22]=[i("重置",-1)])]),_:1})]),p("div",ut,[te((c(),b(Y,{data:q.value,style:{width:"100%"}},{default:l(()=>[a(r,{prop:"created_at",label:"时间",width:"180"}),a(r,{label:"类型",width:"170"},{default:l(({row:t})=>[a(I,{effect:"light",type:"info"},{default:l(()=>[i(f(t.threat_type||"unknown"),1)]),_:2},1024)]),_:1}),a(r,{label:"严重程度",width:"120"},{default:l(({row:t})=>[a(I,{type:D(t.score).type,effect:"light"},{default:l(()=>[i(f(D(t.score).label)+" ("+f(t.score??0)+") ",1)]),_:2},1032,["type"])]),_:1}),a(r,{label:"IP",width:"150"},{default:l(({row:t})=>[t.ip?(c(),b(W,{key:0,type:"primary",underline:!1,onClick:j=>ge(t.ip)},{default:l(()=>[i(f(t.ip),1)]),_:2},1032,["onClick"])):(c(),P("span",rt,"-"))]),_:1}),a(r,{label:"用户",width:"120"},{default:l(({row:t})=>[t.user_id!==null&&t.user_id!==void 0?(c(),b(W,{key:0,type:"primary",underline:!1,onClick:j=>ke(t.user_id)},{default:l(()=>[i(f(t.user_id),1)]),_:2},1032,["onClick"])):(c(),P("span",dt,"-"))]),_:1}),a(r,{label:"操作路径","min-width":"220"},{default:l(({row:t})=>[a(X,{content:K(t),placement:"top","show-after":300},{default:l(()=>[p("span",pt,f(K(t)),1)]),_:2},1032,["content"])]),_:1}),a(r,{label:"Payload预览","min-width":"240"},{default:l(({row:t})=>[a(X,{content:me(t),placement:"top","show-after":300},{default:l(()=>[p("span",ct,f(t.value_preview||"-"),1)]),_:2},1032,["content"])]),_:1})]),_:1},8,["data"])),[[Z,ae.value]])]),p("div",ft,[a(De,{"current-page":C.value,"onUpdate:currentPage":e[3]||(e[3]=t=>C.value=t),"page-size":re,total:E.value,layout:"prev, pager, next, jumper, ->, total",onCurrentChange:O},null,8,["current-page","total"]),p("div",mt,"第 "+f(C.value)+" / "+f(Ce.value)+" 页",1)])]),_:1}),a(x,{label:"封禁管理",name:"bans"},{default:l(()=>[p("div",vt,[a(s,{type:"primary",onClick:e[4]||(e[4]=t=>H())},{default:l(()=>[...e[23]||(e[23]=[i("手动封禁",-1)])]),_:1})]),a(se,{modelValue:ce.value,"onUpdate:modelValue":e[5]||(e[5]=t=>ce.value=t),class:"inner-tabs"},{default:l(()=>[a(x,{label:"IP黑名单",name:"ips"},{default:l(()=>[p("div",_t,[te((c(),b(Y,{data:de.value,style:{width:"100%"}},{default:l(()=>[a(r,{label:"IP",width:"180"},{default:l(({row:t})=>[a(W,{type:"primary",underline:!1,onClick:j=>ge(t.ip)},{default:l(()=>[i(f(t.ip||"-"),1)]),_:2},1032,["onClick"])]),_:1}),a(r,{prop:"reason",label:"原因","min-width":"260"}),a(r,{label:"过期时间",width:"190"},{default:l(({row:t})=>[i(f(fe(t.expires_at)),1)]),_:1}),a(r,{label:"操作",width:"120",fixed:"right"},{default:l(({row:t})=>[a(s,{size:"small",type:"danger",plain:"",onClick:j=>ye(t.ip)},{default:l(()=>[...e[24]||(e[24]=[i("解除",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[Z,$.value]])])]),_:1}),a(x,{label:"用户黑名单",name:"users"},{default:l(()=>[p("div",yt,[te((c(),b(Y,{data:pe.value,style:{width:"100%"}},{default:l(()=>[a(r,{label:"用户ID",width:"180"},{default:l(({row:t})=>[a(W,{type:"primary",underline:!1,onClick:j=>ke(t.user_id)},{default:l(()=>[i(f(t.user_id??"-"),1)]),_:2},1032,["onClick"])]),_:1}),a(r,{prop:"reason",label:"原因","min-width":"260"}),a(r,{label:"过期时间",width:"190"},{default:l(({row:t})=>[i(f(fe(t.expires_at)),1)]),_:1}),a(r,{label:"操作",width:"120",fixed:"right"},{default:l(({row:t})=>[a(s,{size:"small",type:"danger",plain:"",onClick:j=>be(t.user_id)},{default:l(()=>[...e[25]||(e[25]=[i("解除",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[Z,$.value]])])]),_:1})]),_:1},8,["modelValue"])]),_:1}),a(x,{label:"风险查询",name:"risk"},{default:l(()=>[a(se,{modelValue:z.value,"onUpdate:modelValue":e[8]||(e[8]=t=>z.value=t),class:"inner-tabs"},{default:l(()=>[a(x,{label:"IP查询",name:"ip"},{default:l(()=>[p("div",bt,[a(M,{modelValue:A.value,"onUpdate:modelValue":e[6]||(e[6]=t=>A.value=t),placeholder:"输入IP如 1.2.3.4",style:{width:"260px"},clearable:""},null,8,["modelValue"]),a(s,{type:"primary",loading:k.value,onClick:J},{default:l(()=>[...e[26]||(e[26]=[i("查询",-1)])]),_:1},8,["loading"])])]),_:1}),a(x,{label:"用户查询",name:"user"},{default:l(()=>[p("div",gt,[a(M,{modelValue:G.value,"onUpdate:modelValue":e[7]||(e[7]=t=>G.value=t),placeholder:"输入用户ID如 123",style:{width:"260px"},clearable:""},null,8,["modelValue"]),a(s,{type:"primary",loading:k.value,onClick:ne},{default:l(()=>[...e[27]||(e[27]=[i("查询",-1)])]),_:1},8,["loading"])])]),_:1})]),_:1},8,["modelValue"]),_.value?(c(),b(he,{key:0,shadow:"never","body-style":{padding:"16px"},class:"sub-card"},{default:l(()=>[p("div",kt,[p("div",ht,[h.value==="ip"?(c(),P("strong",wt,"IP: "+f(_.value.ip),1)):(c(),P("strong",It,"用户ID: "+f(_.value.user_id),1)),e[30]||(e[30]=p("span",{class:"app-muted"},"风险分",-1)),a(I,{type:D(_.value.risk_score).type,effect:"light"},{default:l(()=>[i(f(_.value.risk_score??0),1)]),_:1},8,["type"]),_.value.is_banned?(c(),b(I,{key:2,type:"danger",effect:"light"},{default:l(()=>[...e[28]||(e[28]=[i("已封禁",-1)])]),_:1})):(c(),b(I,{key:3,type:"success",effect:"light"},{default:l(()=>[...e[29]||(e[29]=[i("未封禁",-1)])]),_:1}))]),p("div",Vt,[_.value.is_banned?(c(),b(s,{key:1,type:"danger",plain:"",onClick:Be},{default:l(()=>[...e[32]||(e[32]=[i("解除封禁",-1)])]),_:1})):(c(),b(s,{key:0,type:"primary",plain:"",onClick:Ue},{default:l(()=>[...e[31]||(e[31]=[i("封禁",-1)])]),_:1})),h.value==="ip"?(c(),b(s,{key:2,type:"warning",plain:"",loading:k.value,onClick:$e},{default:l(()=>[...e[33]||(e[33]=[i(" 清除风险分 ",-1)])]),_:1},8,["loading"])):ue("",!0)])]),p("div",xt,[te((c(),b(Y,{data:_.value.threat_history||[],style:{width:"100%"}},{default:l(()=>[a(r,{prop:"created_at",label:"时间",width:"180"}),a(r,{label:"类型",width:"170"},{default:l(({row:t})=>[a(I,{effect:"light",type:"info"},{default:l(()=>[i(f(t.threat_type||"unknown"),1)]),_:2},1024)]),_:1}),a(r,{label:"严重程度",width:"120"},{default:l(({row:t})=>[a(I,{type:D(t.score).type,effect:"light"},{default:l(()=>[i(f(D(t.score).label)+" ("+f(t.score??0)+") ",1)]),_:2},1032,["type"])]),_:1}),a(r,{label:"操作路径","min-width":"220"},{default:l(({row:t})=>[a(X,{content:K(t),placement:"top","show-after":300},{default:l(()=>[p("span",Ct,f(K(t)),1)]),_:2},1032,["content"])]),_:1}),a(r,{label:"Payload预览","min-width":"240"},{default:l(({row:t})=>[a(X,{content:me(t),placement:"top","show-after":300},{default:l(()=>[p("span",St,f(t.value_preview||"-"),1)]),_:2},1032,["content"])]),_:1})]),_:1},8,["data"])),[[Z,k.value]])])]),_:1})):ue("",!0)]),_:1})]),_:1},8,["modelValue"])]),_:1}),a(Le,{modelValue:S.value,"onUpdate:modelValue":e[17]||(e[17]=t=>S.value=t),title:"手动封禁",width:"min(520px, 92vw)",onClosed:_e},{footer:l(()=>[p("div",Tt,[e[38]||(e[38]=p("div",{class:"spacer"},null,-1)),a(s,{onClick:e[16]||(e[16]=t=>S.value=!1)},{default:l(()=>[...e[36]||(e[36]=[i("取消",-1)])]),_:1}),a(s,{type:"primary",loading:R.value,onClick:Pe},{default:l(()=>[...e[37]||(e[37]=[i("确认封禁",-1)])]),_:1},8,["loading"])])]),default:l(()=>[a(je,{"label-width":"120px"},{default:l(()=>[a(T,{label:"类型"},{default:l(()=>[a(Ne,{modelValue:o.value.kind,"onUpdate:modelValue":e[10]||(e[10]=t=>o.value.kind=t)},{default:l(()=>[a(we,{label:"ip"},{default:l(()=>[...e[34]||(e[34]=[i("IP",-1)])]),_:1}),a(we,{label:"user"},{default:l(()=>[...e[35]||(e[35]=[i("用户",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1}),o.value.kind==="ip"?(c(),b(T,{key:0,label:"IP"},{default:l(()=>[a(M,{modelValue:o.value.ip,"onUpdate:modelValue":e[11]||(e[11]=t=>o.value.ip=t),placeholder:"例如 1.2.3.4"},null,8,["modelValue"])]),_:1})):(c(),b(T,{key:1,label:"用户ID"},{default:l(()=>[a(M,{modelValue:o.value.user_id,"onUpdate:modelValue":e[12]||(e[12]=t=>o.value.user_id=t),placeholder:"例如 123"},null,8,["modelValue"])]),_:1})),a(T,{label:"原因"},{default:l(()=>[a(M,{modelValue:o.value.reason,"onUpdate:modelValue":e[13]||(e[13]=t=>o.value.reason=t),type:"textarea",rows:3,placeholder:"请输入封禁原因"},null,8,["modelValue"])]),_:1}),a(T,{label:"永久封禁"},{default:l(()=>[a(Fe,{modelValue:o.value.permanent,"onUpdate:modelValue":e[14]||(e[14]=t=>o.value.permanent=t)},null,8,["modelValue"])]),_:1}),o.value.permanent?ue("",!0):(c(),b(T,{key:2,label:"持续(小时)"},{default:l(()=>[a(Me,{modelValue:o.value.duration_hours,"onUpdate:modelValue":e[15]||(e[15]=t=>o.value.duration_hours=t),min:1,max:8760},null,8,["modelValue"])]),_:1}))]),_:1})]),_:1},8,["modelValue"])])}}},Ft=qe(Pt,[["__scopeId","data-v-94e0bde6"]]);export{Ft as default};