Files
zsglpt/static/app/assets/SchedulesPage-CvQTwIDx.js
yuyx 1b20478a08 feat: 风险分定时衰减 + 密码提示修复 + 浏览器池API + next回跳
1. 风险分衰减定时任务:
   - services/scheduler.py: 每天 CST 04:00 自动执行 decay_scores()
   - 支持 RISK_SCORE_DECAY_TIME_CST 环境变量覆盖

2. 密码长度提示统一为8位:
   - app-frontend/src/pages/RegisterPage.vue
   - app-frontend/src/layouts/AppLayout.vue
   - admin-frontend/src/pages/SettingsPage.vue
   - templates/register.html

3. 浏览器池统计API:
   - GET /yuyx/api/browser_pool/stats
   - 返回 worker 状态、队列等待数等信息
   - browser_pool_worker.py: 增强 get_stats() 方法

4. 登录后支持 next 参数回跳:
   - app-frontend/src/pages/LoginPage.vue: 检查 ?next= 参数
   - 仅允许站内路径(防止开放重定向)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 18:28:21 +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{f as fe}from"./accounts-sBYX3ZUA.js";import{p as h,_ as _e,n as ye,a as y,r as be,c as we,o as ge,b,h as g,i as D,d as n,w as s,e as p,f as i,g as u,k as f,F as V,x as B,t as _,E as v,y as Q}from"./index-Dzjm38x5.js";async function he(){const{data:c}=await h.get("/schedules");return c}async function ke(c){const{data:d}=await h.post("/schedules",c);return d}async function Ve(c,d){const{data:w}=await h.put(`/schedules/${c}`,d);return w}async function xe(c){const{data:d}=await h.delete(`/schedules/${c}`);return d}async function Se(c,d){const{data:w}=await h.post(`/schedules/${c}/toggle`,d);return w}async function $e(c){const{data:d}=await h.post(`/schedules/${c}/run`,{});return d}async function Ce(c,d={}){const{data:w}=await h.get(`/schedules/${c}/logs`,{params:d});return w}async function Ne(c){const{data:d}=await h.delete(`/schedules/${c}/logs`);return d}const Be={class:"page"},Te={class:"vip-actions"},Ue={class:"panel-head"},Me={class:"panel-actions"},ze={key:1,class:"grid"},He={class:"schedule-top"},Ie={class:"schedule-main"},Ae={class:"schedule-title"},Le={class:"schedule-name"},Pe={class:"schedule-meta app-muted"},Ee={class:"schedule-meta app-muted"},Oe={key:0},je={class:"schedule-switch"},De={class:"schedule-actions"},Fe={class:"switch-row"},Re={key:1,class:"logs"},qe={class:"log-head"},Ge={class:"app-muted"},Je={class:"log-body"},Ke={key:0,class:"log-error"},Qe={__name:"SchedulesPage",setup(c){const d=ye(),w=y(!1),T=y([]),H=y(!1),I=y([]),x=y(!1),A=y(!1),C=y(null),U=y(!1),L=y(!1),S=y([]),M=y(null),k=y(!1),a=be({name:"",schedule_time:"08:00",weekdays:["1","2","3","4","5"],browse_type:"应读",enable_screenshot:!0,random_delay:!1,account_ids:[]}),W=[{label:"应读",value:"应读"},{label:"注册前未读",value:"注册前未读"}];function F(t){return String(t)==="注册前未读"?"注册前未读":"应读"}const R=[{label:"周一",value:"1"},{label:"周二",value:"2"},{label:"周三",value:"3"},{label:"周四",value:"4"},{label:"周五",value:"5"},{label:"周六",value:"6"},{label:"周日",value:"7"}],r=we(()=>d.isVip);function P(t){const e=String(t||"").match(/^(\d{1,2}):(\d{2})$/);if(!e)return null;const o=Number(e[1]),m=Number(e[2]);return Number.isNaN(o)||Number.isNaN(m)||o<0||o>23||m<0||m>59?null:`${String(o).padStart(2,"0")}:${String(m).padStart(2,"0")}`}function X(t){const e=Array.isArray(t)?t:String(t||"").split(",").filter(Boolean),o=Object.fromEntries(R.map(m=>[m.value,m.label]));return e.map(m=>o[String(m)]||String(m)).join(" ")}async function Y(){H.value=!0;try{const t=await fe({refresh:!1});I.value=(t||[]).map(e=>({label:e.username,value:e.id}))}catch{I.value=[]}finally{H.value=!1}}async function z(){w.value=!0;try{const t=await he();T.value=(Array.isArray(t)?t:[]).map(e=>({...e,browse_type:F(e?.browse_type)}))}catch(t){t?.response?.status===401&&(window.location.href="/login"),T.value=[]}finally{w.value=!1}}function Z(){C.value=null,a.name="",a.schedule_time="08:00",a.weekdays=["1","2","3","4","5"],a.browse_type="应读",a.enable_screenshot=!0,a.random_delay=!1,a.account_ids=[],x.value=!0}function ee(t){C.value=t.id,a.name=t.name||"",a.schedule_time=P(t.schedule_time)||"08:00",a.weekdays=String(t.weekdays||"").split(",").filter(Boolean).map(e=>String(e)),a.weekdays.length===0&&(a.weekdays=["1","2","3","4","5"]),a.browse_type=F(t.browse_type),a.enable_screenshot=Number(t.enable_screenshot??1)!==0,a.random_delay=Number(t.random_delay??0)!==0,a.account_ids=Array.isArray(t.account_ids)?t.account_ids.slice():[],x.value=!0}async function le(){if(!r.value){k.value=!0;return}const t=P(a.schedule_time);if(!t){v.error("时间格式错误,请使用 HH:MM");return}if(!a.weekdays||a.weekdays.length===0){v.warning("请选择至少一个执行日期");return}A.value=!0;try{const e={name:a.name.trim()||"我的定时任务",schedule_time:t,weekdays:a.weekdays.join(","),browse_type:a.browse_type,enable_screenshot:a.enable_screenshot?1:0,random_delay:a.random_delay?1:0,account_ids:a.account_ids};C.value?(await Ve(C.value,e),v.success("保存成功")):(await ke(e),v.success("创建成功")),x.value=!1,await z()}catch(e){const o=e?.response?.data;v.error(o?.error||"保存失败")}finally{A.value=!1}}async function te(t){try{await Q.confirm(`确定要删除定时任务「${t.name||"未命名任务"}」吗?`,"删除任务",{confirmButtonText:"删除",cancelButtonText:"取消",type:"warning"})}catch{return}try{const e=await xe(t.id);e?.success?(v.success("已删除"),await z()):v.error(e?.error||"删除失败")}catch(e){const o=e?.response?.data;v.error(o?.error||"删除失败")}}async function ae(t,e){if(!r.value){k.value=!0;return}try{(await Se(t.id,{enabled:e}))?.success&&(t.enabled=e?1:0,v.success(e?"已启用":"已禁用"))}catch{v.error("操作失败")}}async function ne(t){if(!r.value){k.value=!0;return}try{const e=await $e(t.id);e?.success?v.success(e?.message||"已开始执行"):v.error(e?.error||"执行失败")}catch(e){const o=e?.response?.data;v.error(o?.error||"执行失败")}}async function se(t){M.value=t,U.value=!0,L.value=!0;try{S.value=await Ce(t.id,{limit:20})}catch{S.value=[]}finally{L.value=!1}}async function oe(){const t=M.value;if(t){try{await Q.confirm("确定要清空该任务的所有执行日志吗?","清空日志",{confirmButtonText:"清空",cancelButtonText:"取消",type:"warning"})}catch{return}try{const e=await Ne(t.id);e?.success?(v.success(`已清空 ${e?.deleted||0} 条日志`),S.value=[]):v.error(e?.error||"操作失败")}catch{v.error("操作失败")}}}function ue(t){const e=String(t||"");return e==="success"||e==="completed"?"success":e==="failed"?"danger":"info"}function ie(t){const e=Number(t||0),o=Math.floor(e/60),m=e%60;return o<=0?`${m}`:`${o}${m}`}return ge(async()=>{d.vipInfo||d.refreshVipInfo().catch(()=>{window.location.href="/login"}),await Promise.all([Y(),z()])}),(t,e)=>{const o=p("el-button"),m=p("el-alert"),q=p("el-skeleton"),G=p("el-empty"),E=p("el-switch"),O=p("el-card"),de=p("el-input"),$=p("el-form-item"),re=p("el-time-picker"),ce=p("el-checkbox"),me=p("el-checkbox-group"),J=p("el-option"),K=p("el-select"),pe=p("el-form"),j=p("el-dialog"),ve=p("el-tag");return i(),b("div",Be,[r.value?D("",!0):(i(),g(m,{key:0,type:"warning","show-icon":"",closable:!1,title:"定时任务为 VIP 专属功能,升级后可使用。",class:"vip-alert"},{default:s(()=>[u("div",Te,[n(o,{type:"primary",plain:"",onClick:e[0]||(e[0]=l=>k.value=!0)},{default:s(()=>[...e[14]||(e[14]=[f("了解VIP特权",-1)])]),_:1})])]),_:1})),n(O,{shadow:"never",class:"panel","body-style":{padding:"14px"}},{default:s(()=>[u("div",Ue,[e[17]||(e[17]=u("div",{class:"panel-title"},"定时任务",-1)),u("div",Me,[n(o,{loading:w.value,onClick:z},{default:s(()=>[...e[15]||(e[15]=[f("刷新",-1)])]),_:1},8,["loading"]),n(o,{type:"primary",disabled:!r.value,onClick:Z},{default:s(()=>[...e[16]||(e[16]=[f("新建任务",-1)])]),_:1},8,["disabled"])])]),w.value?(i(),g(q,{key:0,rows:6,animated:""})):(i(),b(V,{key:1},[T.value.length===0?(i(),g(G,{key:0,description:"暂无定时任务"})):(i(),b("div",ze,[(i(!0),b(V,null,B(T.value,l=>(i(),g(O,{key:l.id,shadow:"never",class:"schedule-card","body-style":{padding:"14px"}},{default:s(()=>[u("div",He,[u("div",Ie,[u("div",Ae,[u("span",Le,_(l.name||"未命名任务"),1)]),u("div",Pe,[u("span",null,"⏰ "+_(P(l.schedule_time)||l.schedule_time),1),u("span",null,"📅 "+_(X(l.weekdays)),1)]),u("div",Ee,[u("span",null,"📋 "+_(l.browse_type||"应读"),1),u("span",null,"👥 "+_((l.account_ids||[]).length)+" 个账号",1),u("span",null,_(Number(l.enable_screenshot??1)!==0?"📸 截图":"📷 不截图"),1),Number(l.random_delay??0)!==0?(i(),b("span",Oe,"🎲 随机±15分钟")):D("",!0)])]),u("div",je,[n(E,{"model-value":!!Number(l.enabled),disabled:!r.value,"inline-prompt":"","active-text":"启用","inactive-text":"停用",onChange:N=>ae(l,N)},null,8,["model-value","disabled","onChange"])])]),u("div",De,[n(o,{size:"small",type:"primary",disabled:!r.value,onClick:N=>ne(l)},{default:s(()=>[...e[18]||(e[18]=[f("立即执行",-1)])]),_:1},8,["disabled","onClick"]),n(o,{size:"small",onClick:N=>se(l)},{default:s(()=>[...e[19]||(e[19]=[f("日志",-1)])]),_:1},8,["onClick"]),n(o,{size:"small",disabled:!r.value,onClick:N=>ee(l)},{default:s(()=>[...e[20]||(e[20]=[f("编辑",-1)])]),_:1},8,["disabled","onClick"]),n(o,{size:"small",type:"danger",text:"",disabled:!r.value,onClick:N=>te(l)},{default:s(()=>[...e[21]||(e[21]=[f("删除",-1)])]),_:1},8,["disabled","onClick"])])]),_:2},1024))),128))]))],64))]),_:1}),n(j,{modelValue:x.value,"onUpdate:modelValue":e[9]||(e[9]=l=>x.value=l),title:C.value?"编辑定时任务":"新建定时任务",width:"min(720px, 92vw)"},{footer:s(()=>[n(o,{onClick:e[8]||(e[8]=l=>x.value=!1)},{default:s(()=>[...e[22]||(e[22]=[f("取消",-1)])]),_:1}),n(o,{type:"primary",loading:A.value,disabled:!r.value,onClick:le},{default:s(()=>[...e[23]||(e[23]=[f("保存",-1)])]),_:1},8,["loading","disabled"])]),default:s(()=>[n(pe,{"label-position":"top"},{default:s(()=>[n($,{label:"任务名称"},{default:s(()=>[n(de,{modelValue:a.name,"onUpdate:modelValue":e[1]||(e[1]=l=>a.name=l),placeholder:"我的定时任务",disabled:!r.value},null,8,["modelValue","disabled"])]),_:1}),n($,{label:"执行时间HH:MM"},{default:s(()=>[n(re,{modelValue:a.schedule_time,"onUpdate:modelValue":e[2]||(e[2]=l=>a.schedule_time=l),placeholder:"选择时间",format:"HH:mm","value-format":"HH:mm",style:{width:"180px"},disabled:!r.value},null,8,["modelValue","disabled"])]),_:1}),n($,{label:"执行日期"},{default:s(()=>[n(me,{modelValue:a.weekdays,"onUpdate:modelValue":e[3]||(e[3]=l=>a.weekdays=l),disabled:!r.value},{default:s(()=>[(i(),b(V,null,B(R,l=>n(ce,{key:l.value,label:l.value},{default:s(()=>[f(_(l.label),1)]),_:2},1032,["label"])),64))]),_:1},8,["modelValue","disabled"])]),_:1}),n($,{label:"浏览类型"},{default:s(()=>[n(K,{modelValue:a.browse_type,"onUpdate:modelValue":e[4]||(e[4]=l=>a.browse_type=l),style:{width:"160px"},disabled:!r.value},{default:s(()=>[(i(),b(V,null,B(W,l=>n(J,{key:l.value,label:l.label,value:l.value},null,8,["label","value"])),64))]),_:1},8,["modelValue","disabled"])]),_:1}),n($,{label:"截图"},{default:s(()=>[u("div",Fe,[n(E,{modelValue:a.enable_screenshot,"onUpdate:modelValue":e[5]||(e[5]=l=>a.enable_screenshot=l),disabled:!r.value,"inline-prompt":"","active-text":"截图","inactive-text":"不截图"},null,8,["modelValue","disabled"]),n(E,{modelValue:a.random_delay,"onUpdate:modelValue":e[6]||(e[6]=l=>a.random_delay=l),disabled:!r.value,"inline-prompt":"","active-text":"随机±15分钟","inactive-text":"固定时间"},null,8,["modelValue","disabled"])])]),_:1}),n($,{label:"参与账号"},{default:s(()=>[n(K,{modelValue:a.account_ids,"onUpdate:modelValue":e[7]||(e[7]=l=>a.account_ids=l),multiple:"",filterable:"","collapse-tags":"","collapse-tags-tooltip":"",placeholder:"选择账号(可多选)",style:{width:"100%"},loading:H.value,disabled:!r.value},{default:s(()=>[(i(!0),b(V,null,B(I.value,l=>(i(),g(J,{key:l.value,label:l.label,value:l.value},null,8,["label","value"]))),128))]),_:1},8,["modelValue","loading","disabled"])]),_:1})]),_:1})]),_:1},8,["modelValue","title"]),n(j,{modelValue:U.value,"onUpdate:modelValue":e[11]||(e[11]=l=>U.value=l),title:M.value?`${M.value.name||"未命名任务"}】执行日志`:"执行日志",width:"min(760px, 92vw)"},{footer:s(()=>[n(o,{onClick:e[10]||(e[10]=l=>U.value=!1)},{default:s(()=>[...e[24]||(e[24]=[f("关闭",-1)])]),_:1}),n(o,{type:"danger",plain:"",disabled:S.value.length===0,onClick:oe},{default:s(()=>[...e[25]||(e[25]=[f("清空日志",-1)])]),_:1},8,["disabled"])]),default:s(()=>[L.value?(i(),g(q,{key:0,rows:6,animated:""})):(i(),b(V,{key:1},[S.value.length===0?(i(),g(G,{key:0,description:"暂无执行日志"})):(i(),b("div",Re,[(i(!0),b(V,null,B(S.value,l=>(i(),g(O,{key:l.id,shadow:"never",class:"log-card","body-style":{padding:"12px"}},{default:s(()=>[u("div",qe,[n(ve,{size:"small",effect:"light",type:ue(l.status)},{default:s(()=>[f(_(l.status==="failed"?"失败":l.status==="running"?"进行中":"成功"),1)]),_:2},1032,["type"]),u("span",Ge,_(l.created_at||""),1)]),u("div",Je,[u("div",null,"账号数:"+_(l.total_accounts||0)+" 个",1),u("div",null,"成功:"+_(l.success_count||0)+" 个 · 失败:"+_(l.failed_count||0)+" 个",1),u("div",null,"耗时:"+_(ie(l.duration||0)),1),l.error_message?(i(),b("div",Ke,"错误:"+_(l.error_message),1)):D("",!0)])]),_:2},1024))),128))]))],64))]),_:1},8,["modelValue","title"]),n(j,{modelValue:k.value,"onUpdate:modelValue":e[13]||(e[13]=l=>k.value=l),title:"VIP 特权",width:"min(560px, 92vw)"},{footer:s(()=>[n(o,{type:"primary",onClick:e[12]||(e[12]=l=>k.value=!1)},{default:s(()=>[...e[26]||(e[26]=[f("我知道了",-1)])]),_:1})]),default:s(()=>[n(m,{type:"info",closable:!1,title:"升级 VIP 后可解锁:无限账号、优先排队、定时任务、批量操作。","show-icon":""}),e[27]||(e[27]=u("div",{class:"vip-body"},[u("div",{class:"vip-tip app-muted"},"升级方式:请通过“反馈”联系管理员开通。")],-1))]),_:1},8,["modelValue"])])}}},Ye=_e(Qe,[["__scopeId","data-v-e7d93ff5"]]);export{Ye as default};