mirror of
https://github.com/lkddi/nexusphp.git
synced 2026-04-23 11:27:24 +08:00
remove vue admin + include/smtp+browser
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist-ssr
|
||||
*.local
|
||||
.env.development
|
||||
-1
@@ -1 +0,0 @@
|
||||
.table-base-info[data-v-08693874]{width:100%;text-align:left}.table-base-info tr td[data-v-08693874]{padding:4px}
|
||||
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-1
@@ -1 +0,0 @@
|
||||
var A=Object.defineProperty,B=Object.defineProperties;var P=Object.getOwnPropertyDescriptors;var y=Object.getOwnPropertySymbols;var T=Object.prototype.hasOwnProperty,U=Object.prototype.propertyIsEnumerable;var w=(e,a,o)=>a in e?A(e,a,{enumerable:!0,configurable:!0,writable:!0,value:o}):e[a]=o,b=(e,a)=>{for(var o in a||(a={}))T.call(a,o)&&w(e,o,a[o]);if(y)for(var o of y(a))U.call(a,o)&&w(e,o,a[o]);return e},C=(e,a)=>B(e,P(a));import{_ as k,s as M,l as N,v as V,u as $,r as E,o as L,x as j,a as p,t as z,b as c,c as F,d as v,e as G,f as m,w as d,E as I,g as J,j as q,m as t,i as l,y as K,z as O,A as Q,h as S}from"./index.dabb5305.js";const W={name:"HrDetail",setup(){const{proxy:e}=M();console.log("proxy",e);const a=N(null),o=V(),_=$(),{id:i}=o.query,u=E({loading:!1,id:i,agentAllows:[],formData:{},rules:{family_id:[{required:"true"}],name:[{required:"true"}],peer_id:[{required:"true"}],agent:[{required:"true"}]}});L(async()=>{i&&await f()}),j(()=>{});const h=()=>{a.value.validate(async r=>{if(r){let s=u.formData;console.log(s),i?await p.updateAgentDeny(i,s):await p.storeAgentDeny(s),await _.push({name:"agent-deny"})}})},f=async()=>{u.loading=!0;let r=await p.getHr(i);u.loading=!1,u.formData=r.data},D=async r=>{let s=await p.deleteHr(r);I.success(s.msg),await _.push({name:"hr"})},g=async r=>{let s=await p.pardonHr(r);I.success(s.msg),await f()};return C(b({},z(u)),{formRef:a,submitAdd:h,handleDelete:D,handlePardon:g})}},n=e=>(O("data-v-08693874"),e=e(),Q(),e),X={class:"table-base-info"},Y=n(()=>t("td",null,"ID",-1)),Z=n(()=>t("td",null,"Status",-1)),x=n(()=>t("td",null,"UID",-1)),tt=n(()=>t("td",null,"Username",-1)),et=n(()=>t("td",null,"Torrent ID",-1)),at=n(()=>t("td",null,"Torrent name",-1)),nt=n(()=>t("td",null,"Uploaded",-1)),ot=n(()=>t("td",null,"Downloaded",-1)),lt=n(()=>t("td",null,"Share ratio",-1)),rt=n(()=>t("td",null,"Seed time required",-1)),st=n(()=>t("td",null,"Inspect time left",-1)),dt=n(()=>t("td",null,"Comment",-1)),it=["innerHTML"],ut=n(()=>t("td",null,"Created at",-1)),ct=n(()=>t("td",null,"Updated at",-1)),mt={style:{"text-align":"center"}},_t=S("Remove"),ft=S("Pardon");function pt(e,a,o,_,i,u){const h=c("el-divider"),f=c("el-button"),D=c("el-popconfirm"),g=c("el-card"),r=c("el-col"),s=c("el-row"),H=F("loading");return v(),G("div",null,[m(s,null,{default:d(()=>[J((v(),q(r,{span:12},{default:d(()=>[m(g,{class:"box-card"},{default:d(()=>[t("table",X,[t("tr",null,[Y,t("td",null,l(e.formData.id),1)]),t("tr",null,[Z,t("td",null,l(e.formData.status_text),1)]),t("tr",null,[x,t("td",null,l(e.formData.uid),1)]),t("tr",null,[tt,t("td",null,l(e.formData.user&&e.formData.user.username),1)]),t("tr",null,[et,t("td",null,l(e.formData.torrent&&e.formData.torrent.id),1)]),t("tr",null,[at,t("td",null,l(e.formData.torrent&&e.formData.torrent.name),1)]),t("tr",null,[nt,t("td",null,l(e.formData.snatch&&e.formData.snatch.upload_text),1)]),t("tr",null,[ot,t("td",null,l(e.formData.snatch&&e.formData.snatch.download_text),1)]),t("tr",null,[lt,t("td",null,l(e.formData.snatch&&e.formData.snatch.share_ratio),1)]),t("tr",null,[rt,t("td",null,l(e.formData.seed_time_required),1)]),t("tr",null,[st,t("td",null,l(e.formData.inspect_time_left),1)]),t("tr",null,[dt,t("td",{innerHTML:e.formData.comment},null,8,it)]),t("tr",null,[ut,t("td",null,l(e.formData.created_at),1)]),t("tr",null,[ct,t("td",null,l(e.formData.updated_at),1)])]),m(h),t("div",mt,[m(D,{title:"Confirm Remove ?",onConfirm:a[0]||(a[0]=R=>_.handleDelete(e.formData.id))},{reference:d(()=>[m(f,{type:"danger"},{default:d(()=>[_t]),_:1})]),_:1}),[1,3].includes(e.formData.status)?(v(),q(D,{key:0,title:"Confirm Pardon ?",onConfirm:a[1]||(a[1]=R=>_.handlePardon(e.formData.id))},{reference:d(()=>[m(f,{type:"primary"},{default:d(()=>[ft]),_:1})]),_:1})):K("",!0)])]),_:1})]),_:1})),[[H,e.loading]])]),_:1})])}var gt=k(W,[["render",pt],["__scopeId","data-v-08693874"]]);export{gt as default};
|
||||
-1
@@ -1 +0,0 @@
|
||||
.el-card[data-v-806fd958]{margin-bottom:20px}.table-base-info[data-v-806fd958]{width:100%;text-align:left}.table-base-info tr th[data-v-806fd958]{padding-bottom:4px}
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
var R=Object.defineProperty,B=Object.defineProperties;var $=Object.getOwnPropertyDescriptors;var w=Object.getOwnPropertySymbols;var g=Object.prototype.hasOwnProperty,A=Object.prototype.propertyIsEnumerable;var V=(a,e,s)=>e in a?R(a,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):a[e]=s,b=(a,e)=>{for(var s in e||(e={}))g.call(e,s)&&V(a,s,e[s]);if(w)for(var s of w(e))A.call(e,s)&&V(a,s,e[s]);return a},D=(a,e)=>B(a,$(e));import{_ as F,s as E,l as I,v as N,u as P,r as j,o as L,x as M,a as y,t as S,b as n,d as f,e as C,f as o,w as r,F as T,k as z,h as G,j as H}from"./index.dabb5305.js";const J={name:"UserForm",setup(){const{proxy:a}=E();console.log("proxy",a);const e=I(null),s=N(),p=P(),{id:c}=s.query,d=j({id:c,userClasses:[],formData:{username:"",email:"",password:"",password_confirmation:"",id:"",class:""},rules:{username:[{required:"true"}],email:[{required:"true",type:"email"}],password:[{required:"true",min:6,max:40}],password_confirmation:[{required:"true",min:6,max:40}]}});L(async()=>{await t()}),M(()=>{});const m=()=>{e.value.validate(async u=>{if(u){let i=d.formData;await y.storeUser(i),await p.push({name:"user"})}})},t=async()=>{let u=await y.listClass();d.userClasses=u.data};return D(b({},S(d)),{formRef:e,submitAdd:m})}},K=G("Submit");function O(a,e,s,p,c,d){const m=n("el-input"),t=n("el-form-item"),u=n("el-option"),i=n("el-select"),U=n("el-button"),v=n("el-form"),k=n("el-col"),q=n("el-row");return f(),C("div",null,[o(q,null,{default:r(()=>[o(k,{span:12},{default:r(()=>[o(v,{model:a.formData,rules:a.rules,ref:"formRef","label-width":"200px",class:"formData"},{default:r(()=>[o(t,{label:"Username",prop:"username"},{default:r(()=>[o(m,{modelValue:a.formData.username,"onUpdate:modelValue":e[0]||(e[0]=l=>a.formData.username=l),placeholder:""},null,8,["modelValue"])]),_:1}),o(t,{label:"Email",prop:"email"},{default:r(()=>[o(m,{modelValue:a.formData.email,"onUpdate:modelValue":e[1]||(e[1]=l=>a.formData.email=l),placeholder:""},null,8,["modelValue"])]),_:1}),o(t,{label:"Password",prop:"password"},{default:r(()=>[o(m,{type:"password",modelValue:a.formData.password,"onUpdate:modelValue":e[2]||(e[2]=l=>a.formData.password=l),placeholder:""},null,8,["modelValue"])]),_:1}),o(t,{label:"Password Confirmation",prop:"password_confirmation"},{default:r(()=>[o(m,{type:"password",modelValue:a.formData.password_confirmation,"onUpdate:modelValue":e[3]||(e[3]=l=>a.formData.password_confirmation=l),placeholder:""},null,8,["modelValue"])]),_:1}),o(t,{label:"UID",prop:"id"},{default:r(()=>[o(m,{modelValue:a.formData.id,"onUpdate:modelValue":e[4]||(e[4]=l=>a.formData.id=l),type:"number",placeholder:""},null,8,["modelValue"])]),_:1}),o(t,{label:"Class",prop:"class"},{default:r(()=>[o(i,{modelValue:a.formData.class,"onUpdate:modelValue":e[5]||(e[5]=l=>a.formData.class=l),filterable:"",clearable:""},{default:r(()=>[(f(!0),C(T,null,z(a.userClasses,(l,_)=>(f(),H(u,{key:_,label:l,value:_},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),o(t,null,{default:r(()=>[o(U,{type:"primary",onClick:e[6]||(e[6]=l=>p.submitAdd())},{default:r(()=>[K]),_:1})]),_:1})]),_:1},8,["model","rules"])]),_:1})]),_:1})])}var X=F(J,[["render",O]]);export{X as default};
|
||||
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-1
@@ -1 +0,0 @@
|
||||
var C=Object.defineProperty,q=Object.defineProperties;var M=Object.getOwnPropertyDescriptors;var V=Object.getOwnPropertySymbols;var k=Object.prototype.hasOwnProperty,B=Object.prototype.propertyIsEnumerable;var y=(a,e,n)=>e in a?C(a,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):a[e]=n,b=(a,e)=>{for(var n in e||(e={}))k.call(e,n)&&y(a,n,e[n]);if(V)for(var n of V(e))B.call(e,n)&&y(a,n,e[n]);return a},v=(a,e)=>q(a,M(e));import{_ as I,s as R,l as h,v as j,u as E,r as $,B as G,o as N,a as c,x as S,t as A,b as s,d as F,e as P,f as o,w as t,E as T,h as D}from"./index.dabb5305.js";const z={name:"MedalForm",setup(){const{proxy:a}=R();console.log("proxy",a);const e=h(null),n=j(),g=E(),{id:p}=n.query,d=$({token:G("token")||"",id:p,allClasses:[],formData:{name:"",description:"",image_large:"",image_small:"",duration:"",price:"",get_type:""},rules:{name:[{required:"true"}],price:[{required:"true"}],image_large:[{required:"true"}],image_small:[{required:"true"}],description:[{required:"true"}],get_type:[{required:"true"}]}});N(async()=>{p&&c.getMedal(p).then(l=>{d.formData.name=l.data.name,d.formData.image_large=l.data.image_large,d.formData.image_small=l.data.image_small,d.formData.description=l.data.description,d.formData.price=l.data.price,d.formData.duration=l.data.duration,d.formData.get_type=l.data.get_type})}),S(()=>{});const u=()=>{e.value.validate(async l=>{if(l){let i=d.formData;console.log(i),p?await c.updateMedal(p,i):await c.storeMedal(i),await g.push({name:"medal"})}})},m=l=>{const i=l.name.split(".")[1]||"";if(!["jpg","jpeg","png"].includes(i))return T.error("\u8BF7\u4E0A\u4F20 jpg\u3001jpeg\u3001png \u683C\u5F0F\u7684\u56FE\u7247"),!1},f=l=>{d.formData.goodsCoverImg=l.data||""},_=l=>{d.categoryId=l[2]||0};return v(b({},A(d)),{formRef:e,submitAdd:u,handleBeforeUpload:m,handleUrlSuccess:f,handleChangeCate:_})}},H=D("Exchange"),J=D("Grant"),K=D("Submit");function L(a,e,n,g,p,d){const u=s("el-input"),m=s("el-form-item"),f=s("el-radio"),_=s("el-radio-group"),l=s("el-button"),i=s("el-form"),U=s("el-col"),w=s("el-row");return F(),P("div",null,[o(w,null,{default:t(()=>[o(U,{span:12},{default:t(()=>[o(i,{model:a.formData,rules:a.rules,ref:"formRef","label-width":"200px",class:"formData"},{default:t(()=>[o(m,{label:"Name",prop:"name"},{default:t(()=>[o(u,{modelValue:a.formData.name,"onUpdate:modelValue":e[0]||(e[0]=r=>a.formData.name=r),placeholder:""},null,8,["modelValue"])]),_:1}),o(m,{label:"Price",prop:"price"},{default:t(()=>[o(u,{modelValue:a.formData.price,"onUpdate:modelValue":e[1]||(e[1]=r=>a.formData.price=r),placeholder:"Seed bonus"},null,8,["modelValue"])]),_:1}),o(m,{label:"Get type",prop:"get_type"},{default:t(()=>[o(_,{modelValue:a.formData.get_type,"onUpdate:modelValue":e[2]||(e[2]=r=>a.formData.get_type=r)},{default:t(()=>[o(f,{label:1},{default:t(()=>[H]),_:1}),o(f,{label:2},{default:t(()=>[J]),_:1})]),_:1},8,["modelValue"])]),_:1}),o(m,{label:"Image large",prop:"image_large"},{default:t(()=>[o(u,{modelValue:a.formData.image_large,"onUpdate:modelValue":e[3]||(e[3]=r=>a.formData.image_large=r),placeholder:""},null,8,["modelValue"])]),_:1}),o(m,{label:"Image small",prop:"image_small"},{default:t(()=>[o(u,{modelValue:a.formData.image_small,"onUpdate:modelValue":e[4]||(e[4]=r=>a.formData.image_small=r),placeholder:""},null,8,["modelValue"])]),_:1}),o(m,{label:"Duration",prop:"duration"},{default:t(()=>[o(u,{modelValue:a.formData.duration,"onUpdate:modelValue":e[5]||(e[5]=r=>a.formData.duration=r),placeholder:"Unit: day, if empty, it's valid forever"},null,8,["modelValue"])]),_:1}),o(m,{label:"Description",prop:"description"},{default:t(()=>[o(u,{type:"textarea",modelValue:a.formData.description,"onUpdate:modelValue":e[6]||(e[6]=r=>a.formData.description=r),placeholder:""},null,8,["modelValue"])]),_:1}),o(m,null,{default:t(()=>[o(l,{type:"primary",onClick:e[7]||(e[7]=r=>g.submitAdd())},{default:t(()=>[K]),_:1})]),_:1})]),_:1},8,["model","rules"])]),_:1})]),_:1})])}var W=I(z,[["render",L]]);export{W as default};
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
var v=Object.defineProperty,U=Object.defineProperties;var w=Object.getOwnPropertyDescriptors;var D=Object.getOwnPropertySymbols;var k=Object.prototype.hasOwnProperty,z=Object.prototype.propertyIsEnumerable;var g=(a,o,t)=>o in a?v(a,o,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[o]=t,V=(a,o)=>{for(var t in o||(o={}))k.call(o,t)&&g(a,t,o[t]);if(D)for(var t of D(o))z.call(o,t)&&g(a,t,o[t]);return a},_=(a,o)=>U(a,w(o));import{_ as B,s as T,l as h,v as R,u as C,r as $,B as q,o as F,a as s,x as N,t as A,b as f,d as M,e as P,f as e,w as n,h as E}from"./index.dabb5305.js";const G={name:"TagForm",setup(){const{proxy:a}=T();console.log("proxy",a);const o=h(null),t=R(),p=C(),{id:u}=t.query,d=$({token:q("token")||"",id:u,list:[],formData:{color:"",name:"",priority:"",font_color:"#ffffff",font_size:"12px",margin:0,padding:0,border_radius:0},rules:{color:[{required:"true"}],name:[{required:"true"}]}});F(async()=>{u&&s.getTag(u).then(l=>{d.formData.name=l.data.name,d.formData.color=l.data.color,d.formData.priority=l.data.priority,d.formData.font_color=l.data.font_color,d.formData.font_size=l.data.font_size,d.formData.margin=l.data.margin,d.formData.padding=l.data.padding,d.formData.border_radius=l.data.border_radius})}),N(()=>{});const m=()=>{o.value.validate(async l=>{if(l){let i=d.formData;console.log(i),u?await s.updateTag(u,i):await s.storeTag(i),await p.push({name:"tag"})}})};return _(V({},A(d)),{formRef:o,submitAdd:m})}},I=E("Submit");function S(a,o,t,p,u,d){const m=f("el-input"),l=f("el-form-item"),i=f("el-button"),b=f("el-form"),c=f("el-col"),y=f("el-row");return M(),P("div",null,[e(y,null,{default:n(()=>[e(c,{span:12},{default:n(()=>[e(b,{model:a.formData,rules:a.rules,ref:"formRef","label-width":"200px",class:"formData"},{default:n(()=>[e(l,{label:"Name",prop:"name"},{default:n(()=>[e(m,{modelValue:a.formData.name,"onUpdate:modelValue":o[0]||(o[0]=r=>a.formData.name=r),placeholder:""},null,8,["modelValue"])]),_:1}),e(l,{label:"Background color",prop:"color"},{default:n(()=>[e(m,{modelValue:a.formData.color,"onUpdate:modelValue":o[1]||(o[1]=r=>a.formData.color=r),placeholder:""},null,8,["modelValue"])]),_:1}),e(l,{label:"Font color",prop:"font_color"},{default:n(()=>[e(m,{modelValue:a.formData.font_color,"onUpdate:modelValue":o[2]||(o[2]=r=>a.formData.font_color=r),placeholder:""},null,8,["modelValue"])]),_:1}),e(l,{label:"Font size",prop:"font_size"},{default:n(()=>[e(m,{modelValue:a.formData.font_size,"onUpdate:modelValue":o[3]||(o[3]=r=>a.formData.font_size=r),placeholder:""},null,8,["modelValue"])]),_:1}),e(l,{label:"Padding",prop:"padding"},{default:n(()=>[e(m,{modelValue:a.formData.padding,"onUpdate:modelValue":o[4]||(o[4]=r=>a.formData.padding=r),placeholder:""},null,8,["modelValue"])]),_:1}),e(l,{label:"Margin",prop:"margin"},{default:n(()=>[e(m,{modelValue:a.formData.margin,"onUpdate:modelValue":o[5]||(o[5]=r=>a.formData.margin=r),placeholder:""},null,8,["modelValue"])]),_:1}),e(l,{label:"Border radius",prop:"border_radius"},{default:n(()=>[e(m,{modelValue:a.formData.border_radius,"onUpdate:modelValue":o[6]||(o[6]=r=>a.formData.border_radius=r),placeholder:""},null,8,["modelValue"])]),_:1}),e(l,{label:"Priority",prop:"priority"},{default:n(()=>[e(m,{modelValue:a.formData.priority,"onUpdate:modelValue":o[7]||(o[7]=r=>a.formData.priority=r),placeholder:"The higher the value, the higher the ranking"},null,8,["modelValue"])]),_:1}),e(l,null,{default:n(()=>[e(i,{type:"primary",onClick:o[8]||(o[8]=r=>p.submitAdd())},{default:n(()=>[I]),_:1})]),_:1})]),_:1},8,["model","rules"])]),_:1})]),_:1})])}var J=B(G,[["render",S]]);export{J as default};
|
||||
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-1
@@ -1 +0,0 @@
|
||||
var U=Object.defineProperty,q=Object.defineProperties;var B=Object.getOwnPropertyDescriptors;var g=Object.getOwnPropertySymbols;var C=Object.prototype.hasOwnProperty,R=Object.prototype.propertyIsEnumerable;var y=(a,e,n)=>e in a?U(a,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):a[e]=n,D=(a,e)=>{for(var n in e||(e={}))C.call(e,n)&&y(a,n,e[n]);if(g)for(var n of g(e))R.call(e,n)&&y(a,n,e[n]);return a},V=(a,e)=>q(a,B(e));import{_ as F,s as $,l as N,v as j,u as E,r as G,B as I,o as L,a as i,x as M,t as P,b as u,d as c,e as w,f as t,w as r,F as S,k as T,h as z,j as H}from"./index.dabb5305.js";const J={name:"AgentAllowForm",setup(){const{proxy:a}=$();console.log("proxy",a);const e=N(null),n=j(),f=E(),{id:s}=n.query,m=G({token:I("token")||"",id:s,agentAllows:[],formData:{family_id:"",name:"",peer_id:"",agent:"",comment:""},rules:{family_id:[{required:"true"}],name:[{required:"true"}],peer_id:[{required:"true"}],agent:[{required:"true"}]}});L(async()=>{await _(),s&&i.getAgentDeny(s).then(l=>{m.formData.family_id=l.data.family_id,m.formData.name=l.data.name,m.formData.peer_id=l.data.peer_id,m.formData.agent=l.data.agent,m.formData.comment=l.data.comment})}),M(()=>{});const p=()=>{e.value.validate(async l=>{if(l){let d=m.formData;console.log(d),s?await i.updateAgentDeny(s,d):await i.storeAgentDeny(d),await f.push({name:"agent-deny"})}})},_=async()=>{let l=await i.listAllAgentAllow();m.agentAllows=l.data};return V(D({},P(m)),{formRef:e,submitAdd:p})}},K=z("Submit");function O(a,e,n,f,s,m){const p=u("el-option"),_=u("el-select"),l=u("el-form-item"),d=u("el-input"),A=u("el-button"),b=u("el-form"),v=u("el-col"),k=u("el-row");return c(),w("div",null,[t(k,null,{default:r(()=>[t(v,{span:12},{default:r(()=>[t(b,{model:a.formData,rules:a.rules,ref:"formRef","label-width":"200px",class:"formData"},{default:r(()=>[t(l,{label:"Family",prop:"family_id"},{default:r(()=>[t(_,{modelValue:a.formData.family_id,"onUpdate:modelValue":e[0]||(e[0]=o=>a.formData.family_id=o),filterable:""},{default:r(()=>[(c(!0),w(S,null,T(a.agentAllows,o=>(c(),H(p,{key:o.id,label:o.family,value:o.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),t(l,{label:"Name",prop:"name"},{default:r(()=>[t(d,{modelValue:a.formData.name,"onUpdate:modelValue":e[1]||(e[1]=o=>a.formData.name=o),placeholder:""},null,8,["modelValue"])]),_:1}),t(l,{label:"Peer id",prop:"peer_id"},{default:r(()=>[t(d,{modelValue:a.formData.peer_id,"onUpdate:modelValue":e[2]||(e[2]=o=>a.formData.peer_id=o),placeholder:""},null,8,["modelValue"])]),_:1}),t(l,{label:"Agent",prop:"agent"},{default:r(()=>[t(d,{modelValue:a.formData.agent,"onUpdate:modelValue":e[3]||(e[3]=o=>a.formData.agent=o),placeholder:""},null,8,["modelValue"])]),_:1}),t(l,{label:"Comment",prop:"comment"},{default:r(()=>[t(d,{type:"textarea",modelValue:a.formData.comment,"onUpdate:modelValue":e[4]||(e[4]=o=>a.formData.comment=o),placeholder:""},null,8,["modelValue"])]),_:1}),t(l,null,{default:r(()=>[t(A,{type:"primary",onClick:e[5]||(e[5]=o=>f.submitAdd())},{default:r(()=>[K]),_:1})]),_:1})]),_:1},8,["model","rules"])]),_:1})]),_:1})])}var X=F(J,[["render",O]]);export{X as default};
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
.swiper-container[data-v-9699ec70]{min-height:100%}.el-card.is-always-shadow[data-v-9699ec70]{min-height:100%!important}
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
.swiper-container[data-v-79667e75]{min-height:100%}.el-card.is-always-shadow[data-v-79667e75]{min-height:100%!important}
|
||||
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-1
@@ -1 +0,0 @@
|
||||
var M=Object.defineProperty,P=Object.defineProperties;var A=Object.getOwnPropertyDescriptors;var h=Object.getOwnPropertySymbols;var E=Object.prototype.hasOwnProperty,I=Object.prototype.propertyIsEnumerable;var f=(e,t,a)=>t in e?M(e,t,{enumerable:!0,configurable:!0,writable:!0,value:a}):e[t]=a,b=(e,t)=>{for(var a in t||(t={}))E.call(t,a)&&f(e,a,t[a]);if(h)for(var a of h(t))I.call(t,a)&&f(e,a,t[a]);return e},y=(e,t)=>P(e,A(t));import{_ as q,l as N,u as z,o as B,a as v,t as V,b as i,c as R,d as w,j as C,w as r,E as j,m as d,f as o,g as G,z as L,A as $,h as F}from"./index.dabb5305.js";import{u as H,r as J}from"./table.6af03a03.js";const K={name:"MedalTable",setup(){const e=N(null),t=z(),a=H();B(()=>{console.log("MedalTable onMounted"),s()});const s=async()=>{a.loading=!0;let l=await v.listMedal(a.query);J(l,a),a.loading=!1},g=()=>{t.push({name:"medal-form"})},m=l=>{t.push({path:"/medal-form",query:{id:l}})},_=async l=>{let u=await v.deleteMedal(l);j.success(u.msg),a.query.page=1,await s()},n=l=>{a.multipleSelection=l},p=l=>{a.query.page=l,s()};return y(b({},V(a)),{multipleTable:e,handleSelectionChange:n,handleAdd:g,handleEdit:m,handleDelete:_,fetchTableData:s,changePage:p})}},x=e=>(L("data-v-63382e05"),e=e(),$(),e),O={class:"nexus-table-header"},Q=x(()=>d("div",{class:"left"},null,-1)),U={class:"right"},W=F("Add"),X=["onClick"],Y=x(()=>d("a",{style:{cursor:"pointer"}},"Delete",-1));function Z(e,t,a,s,g,m){const _=i("el-button"),n=i("el-table-column"),p=i("el-image"),l=i("el-popconfirm"),u=i("el-table"),D=i("el-pagination"),S=i("el-card"),k=R("loading");return w(),C(S,{class:""},{header:r(()=>[d("div",O,[Q,d("div",U,[o(_,{type:"primary",icon:"Plus",onClick:s.handleAdd},{default:r(()=>[W]),_:1},8,["onClick"])])])]),default:r(()=>[G((w(),C(u,{ref:"multipleTable",data:e.tableData,"tooltip-effect":"dark",onSelectionChange:s.handleSelectionChange},{default:r(()=>[o(n,{type:"selection",width:"55"}),o(n,{prop:"id",label:"Id",width:"50"}),o(n,{prop:"name",label:"Name"}),o(n,{prop:"image_large",label:"Large image"},{default:r(c=>[o(p,{src:c.row.image_large,style:{"max-height":"200px"}},null,8,["src"])]),_:1}),o(n,{prop:"image_small",label:"Small image"},{default:r(c=>[o(p,{src:c.row.image_small,style:{"max-height":"200px"}},null,8,["src"])]),_:1}),o(n,{prop:"get_type_text",label:"Get type"}),o(n,{prop:"price",label:"Price(bonus)"}),o(n,{prop:"duration",label:"Duration(day)"}),o(n,{label:"Action",width:""},{default:r(c=>[d("a",{style:{cursor:"pointer","margin-right":"10px"},onClick:T=>s.handleEdit(c.row.id)},"Edit",8,X),o(l,{title:"Confirm Delete ?",onConfirm:T=>s.handleDelete(c.row.id)},{reference:r(()=>[Y]),_:2},1032,["onConfirm"])]),_:1})]),_:1},8,["data","onSelectionChange"])),[[k,e.loading]]),o(D,{background:"",layout:"prev, pager, next",total:e.total,"page-size":e.perPage,"current-page":e.currentPage,onCurrentChange:s.changePage},null,8,["total","page-size","current-page","onCurrentChange"])]),_:1})}var oe=q(K,[["render",Z],["__scopeId","data-v-63382e05"]]);export{oe as default};
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
var A=Object.defineProperty,B=Object.defineProperties;var P=Object.getOwnPropertyDescriptors;var S=Object.getOwnPropertySymbols;var R=Object.prototype.hasOwnProperty,N=Object.prototype.propertyIsEnumerable;var U=(a,t,e)=>t in a?A(a,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):a[t]=e,T=(a,t)=>{for(var e in t||(t={}))R.call(t,e)&&U(a,e,t[e]);if(S)for(var e of S(t))N.call(t,e)&&U(a,e,t[e]);return a},E=(a,t)=>B(a,P(t));import{_ as z,l as F,u as I,r as L,o as M,a as D,t as j,b as u,c as Q,d as _,j as k,w as d,E as x,m as f,f as l,e as G,k as H,F as J,g as K,h as V}from"./index.dabb5305.js";import{u as O,r as W,a as X}from"./table.6af03a03.js";const Y={name:"UserTable",setup(){const a=F(null),t=I(),e=O();let s=L({classes:[]});M(()=>{D.listClass().then(function(o){s.classes=o.data}),c()});const c=async()=>{e.loading=!0;let o=await D.listUser(e.query);W(o,e),e.loading=!1},v=()=>{t.push({name:"user-form"})},m=o=>{t.push({name:"user-form",query:{id:o}})},i=async o=>{let n=await D.deleteExam(o);x.success(n.msg),e.query.page=1,await c()},h=o=>{e.multipleSelection=o},b=o=>{e.query.page=o,c()},p=o=>{X(o,e),c()},g=()=>{e.query.id="",e.query.username="",e.query.email="",e.query.class="",e.query.sort_field="",e.query.sort_type=""},r=o=>{t.push({name:"user-detail",query:{id:o}})},y=(o,n)=>o.class_text,C=(o,n)=>o.uploaded_text,w=(o,n)=>o.downloaded_text;return E(T({},j(e)),{multipleTable:a,extraData:s,handleSelectionChange:h,handleAdd:v,handleEdit:m,handleDelete:i,handleDetail:r,fetchTableData:c,changePage:b,handleSortChange:p,formatColumnClass:y,formatColumnUploaded:C,formatColumnDownloaded:w,handleReset:g})}},Z={class:"nexus-table-header"},$={class:"left"},ee=V("Query"),le=V("Reset"),ae={class:"right"},te=V("Add"),oe=["onClick"];function ne(a,t,e,s,c,v){const m=u("el-input"),i=u("el-form-item"),h=u("el-option"),b=u("el-select"),p=u("el-button"),g=u("el-form"),r=u("el-table-column"),y=u("el-table"),C=u("el-pagination"),w=u("el-card"),o=Q("loading");return _(),k(w,null,{header:d(()=>[f("div",Z,[f("div",$,[l(g,{inline:!0,model:a.query},{default:d(()=>[l(i,{label:""},{default:d(()=>[l(m,{placeholder:"ID",modelValue:a.query.id,"onUpdate:modelValue":t[0]||(t[0]=n=>a.query.id=n)},null,8,["modelValue"])]),_:1}),l(i,{label:""},{default:d(()=>[l(m,{placeholder:"Username",modelValue:a.query.username,"onUpdate:modelValue":t[1]||(t[1]=n=>a.query.username=n)},null,8,["modelValue"])]),_:1}),l(i,{label:""},{default:d(()=>[l(m,{placeholder:"Email",modelValue:a.query.email,"onUpdate:modelValue":t[2]||(t[2]=n=>a.query.email=n)},null,8,["modelValue"])]),_:1}),l(i,{label:""},{default:d(()=>[l(b,{modelValue:a.query.class,"onUpdate:modelValue":t[3]||(t[3]=n=>a.query.class=n),filterable:"",placeholder:"Class"},{default:d(()=>[(_(!0),G(J,null,H(s.extraData.classes,(n,q)=>(_(),k(h,{key:q,label:n,value:q},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),l(i,null,{default:d(()=>[l(p,{type:"primary",onClick:s.fetchTableData},{default:d(()=>[ee]),_:1},8,["onClick"]),l(p,{type:"primary",onClick:s.handleReset},{default:d(()=>[le]),_:1},8,["onClick"])]),_:1})]),_:1},8,["model"])]),f("div",ae,[l(p,{type:"primary",icon:"Plus",onClick:s.handleAdd},{default:d(()=>[te]),_:1},8,["onClick"])])])]),default:d(()=>[K((_(),k(y,{ref:"multipleTable",data:a.tableData,"tooltip-effect":"dark",onSortChange:s.handleSortChange,onSelectionChange:s.handleSelectionChange},{default:d(()=>[l(r,{type:"selection",width:"55"}),l(r,{prop:"id",label:"Id",width:"80",sortable:"custom"}),l(r,{prop:"username",label:"Username",sortable:"custom"}),l(r,{prop:"email",label:"Email",width:"200"}),l(r,{prop:"class",label:"Class",sortable:"custom",width:"120",formatter:s.formatColumnClass},null,8,["formatter"]),l(r,{prop:"uploaded",label:"Uploaded",sortable:"custom",formatter:s.formatColumnUploaded},null,8,["formatter"]),l(r,{prop:"downloaded",label:"Downloaded",sortable:"custom",formatter:s.formatColumnDownloaded},null,8,["formatter"]),l(r,{prop:"bonus",label:"Bonus"}),l(r,{prop:"status",label:"Status",width:"100"}),l(r,{prop:"enabled",label:"Enabled",width:"100"}),l(r,{prop:"last_access",label:"Last access",width:"150"}),l(r,{prop:"added",label:"Added",width:"150"}),l(r,{label:"Action",width:"100"},{default:d(n=>[f("a",{style:{cursor:"pointer","margin-right":"10px"},onClick:q=>s.handleDetail(n.row.id)},"Detail",8,oe)]),_:1})]),_:1},8,["data","onSortChange","onSelectionChange"])),[[o,a.loading]]),l(C,{background:"",layout:"prev, pager, next",total:a.total,"page-size":a.perPage,"current-page":a.currentPage,onCurrentChange:s.changePage},null,8,["total","page-size","current-page","onCurrentChange"])]),_:1})}var ue=z(Y,[["render",ne]]);export{ue as default};
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
var x=Object.defineProperty,P=Object.defineProperties;var A=Object.getOwnPropertyDescriptors;var f=Object.getOwnPropertySymbols;var q=Object.prototype.hasOwnProperty,z=Object.prototype.propertyIsEnumerable;var v=(e,t,a)=>t in e?x(e,t,{enumerable:!0,configurable:!0,writable:!0,value:a}):e[t]=a,y=(e,t)=>{for(var a in t||(t={}))q.call(t,a)&&v(e,a,t[a]);if(f)for(var a of f(t))z.call(t,a)&&v(e,a,t[a]);return e},C=(e,t)=>P(e,A(t));import{_ as B,l as E,u as I,r as N,o as M,a as w,t as R,b as s,c as V,d as D,j as T,w as i,E as F,m as c,f as o,g as j,z as U,A as $,h as G}from"./index.dabb5305.js";import{u as H,r as J}from"./table.6af03a03.js";const K={name:"TagTable",setup(){const e=E(null),t=I(),a=H();let r=N({agentAllows:[]});M(()=>{d()});const d=async()=>{a.loading=!0;let l=await w.listTag(a.query);J(l,a),a.loading=!1},b=()=>{t.push({name:"tag-form"})},p=l=>{t.push({path:"/tag-form",query:{id:l}})},n=async l=>{let h=await w.deleteTag(l);F.success(h.msg),a.query.page=1,await d()},_=l=>{a.multipleSelection=l},u=l=>{a.query.page=l,d()},g=()=>{a.query.family_id=""};return C(y({},R(a)),{extraData:r,multipleTable:e,handleSelectionChange:_,handleAdd:b,handleEdit:p,handleDelete:n,fetchTableData:d,changePage:u,handleReset:g})}},k=e=>(U("data-v-2dbb3b07"),e=e(),$(),e),L={class:"nexus-table-header"},O=k(()=>c("div",{class:"left"},null,-1)),Q={class:"right"},W=G("Add"),X=["onClick"],Y=k(()=>c("a",{style:{cursor:"pointer"}},"Delete",-1));function Z(e,t,a,r,d,b){const p=s("el-button"),n=s("el-table-column"),_=s("el-popconfirm"),u=s("el-table"),g=s("el-pagination"),l=s("el-card"),h=V("loading");return D(),T(l,{class:""},{header:i(()=>[c("div",L,[O,c("div",Q,[o(p,{type:"primary",icon:"Plus",onClick:r.handleAdd},{default:i(()=>[W]),_:1},8,["onClick"])])])]),default:i(()=>[j((D(),T(u,{ref:"multipleTable",data:e.tableData,"tooltip-effect":"dark",onSelectionChange:r.handleSelectionChange},{default:i(()=>[o(n,{type:"selection",width:"55"}),o(n,{prop:"id",label:"Id",width:"50"}),o(n,{prop:"name",label:"Name"}),o(n,{prop:"color",label:"Background color"}),o(n,{prop:"font_color",label:"Font color"}),o(n,{prop:"font_size",label:"Font size"}),o(n,{prop:"margin",label:"Margin"}),o(n,{prop:"padding",label:"Padding"}),o(n,{prop:"border_radius",label:"Border radius"}),o(n,{prop:"priority",label:"Priority"}),o(n,{prop:"updated_at",label:"Updated at"}),o(n,{label:"Action",width:"120"},{default:i(m=>[c("a",{style:{cursor:"pointer","margin-right":"10px"},onClick:S=>r.handleEdit(m.row.id)},"Edit",8,X),o(_,{title:"Confirm Delete ?",onConfirm:S=>r.handleDelete(m.row.id)},{reference:i(()=>[Y]),_:2},1032,["onConfirm"])]),_:1})]),_:1},8,["data","onSelectionChange"])),[[h,e.loading]]),o(g,{background:"",layout:"prev, pager, next",total:e.total,"page-size":e.perPage,"current-page":e.currentPage,onCurrentChange:r.changePage},null,8,["total","page-size","current-page","onCurrentChange"])]),_:1})}var oe=B(K,[["render",Z],["__scopeId","data-v-2dbb3b07"]]);export{oe as default};
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
.swiper-container[data-v-63382e05]{min-height:100%}.el-card.is-always-shadow[data-v-63382e05]{min-height:100%!important}
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
var S=Object.defineProperty,k=Object.defineProperties;var M=Object.getOwnPropertyDescriptors;var g=Object.getOwnPropertySymbols;var I=Object.prototype.hasOwnProperty,P=Object.prototype.propertyIsEnumerable;var f=(e,a,t)=>a in e?S(e,a,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[a]=t,b=(e,a)=>{for(var t in a||(a={}))I.call(a,t)&&f(e,t,a[t]);if(g)for(var t of g(a))P.call(a,t)&&f(e,t,a[t]);return e},w=(e,a)=>k(e,M(a));import{_ as A,l as q,u as B,o as H,a as v,t as L,b as c,c as N,d as x,j as y,w as r,E as z,m as i,f as n,g as V,z as R,A as j,h as $}from"./index.dabb5305.js";import{u as F,r as G}from"./table.6af03a03.js";const J={name:"ExamTable",setup(){const e=q(null),a=B(),t=F();H(()=>{console.log("ExamTable onMounted"),s()});const s=async()=>{t.loading=!0;let l=await v.listExam(t.query);G(l,t),t.loading=!1},h=()=>{a.push({name:"exam-form"})},m=l=>{a.push({path:"/exam-form",query:{id:l}})},p=async l=>{let u=await v.deleteExam(l);z.success(u.msg),t.query.page=1,await s()},o=l=>{t.multipleSelection=l},_=l=>{t.query.page=l,s()};return w(b({},L(t)),{multipleTable:e,handleSelectionChange:o,handleAdd:h,handleEdit:m,handleDelete:p,fetchTableData:s,changePage:_})}},C=e=>(R("data-v-79667e75"),e=e(),j(),e),K={class:"nexus-table-header"},O=C(()=>i("div",{class:"left"},null,-1)),Q={class:"right"},U=$("Add"),W=["innerHTML"],X=["innerHTML"],Y=["onClick"],Z=C(()=>i("a",{style:{cursor:"pointer"}},"Delete",-1));function ee(e,a,t,s,h,m){const p=c("el-button"),o=c("el-table-column"),_=c("el-popconfirm"),l=c("el-table"),u=c("el-pagination"),T=c("el-card"),D=N("loading");return x(),y(T,{class:""},{header:r(()=>[i("div",K,[O,i("div",Q,[n(p,{type:"primary",icon:"Plus",onClick:s.handleAdd},{default:r(()=>[U]),_:1},8,["onClick"])])])]),default:r(()=>[V((x(),y(l,{ref:"multipleTable",data:e.tableData,"tooltip-effect":"dark",onSelectionChange:s.handleSelectionChange},{default:r(()=>[n(o,{type:"selection",width:"55"}),n(o,{prop:"id",label:"Id",width:"50"}),n(o,{prop:"name",label:"Name"}),n(o,{label:"Indexes",width:"250px"},{default:r(d=>[i("p",{style:{"white-space":"pre-line"},innerHTML:d.row.indexes_formatted},null,8,W)]),_:1}),n(o,{prop:"begin",label:"Begin",width:"160"}),n(o,{prop:"end",label:"End",width:"160"}),n(o,{prop:"duration_text",label:"Duration"}),n(o,{label:"Target users",width:"350px"},{default:r(d=>[i("p",{style:{"white-space":"pre-line"},innerHTML:d.row.filters_formatted},null,8,X)]),_:1}),n(o,{prop:"is_discovered_text",label:"Discovered",width:"110"}),n(o,{prop:"priority",label:"Priority"}),n(o,{prop:"status_text",label:"Status"}),n(o,{label:"Action",width:"120"},{default:r(d=>[i("a",{style:{cursor:"pointer","margin-right":"10px"},onClick:E=>s.handleEdit(d.row.id)},"Edit",8,Y),n(_,{title:"Confirm Delete ?",onConfirm:E=>s.handleDelete(d.row.id)},{reference:r(()=>[Z]),_:2},1032,["onConfirm"])]),_:1})]),_:1},8,["data","onSelectionChange"])),[[D,e.loading]]),n(u,{background:"",layout:"prev, pager, next",total:e.total,"page-size":e.perPage,"current-page":e.currentPage,onCurrentChange:s.changePage},null,8,["total","page-size","current-page","onCurrentChange"])]),_:1})}var oe=A(J,[["render",ee],["__scopeId","data-v-79667e75"]]);export{oe as default};
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
var S=Object.defineProperty;var T=Object.getOwnPropertySymbols;var V=Object.prototype.hasOwnProperty,$=Object.prototype.propertyIsEnumerable;var y=(t,l,s)=>l in t?S(t,l,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[l]=s,k=(t,l)=>{for(var s in l||(l={}))V.call(l,s)&&y(t,s,l[s]);if(T)for(var s of T(l))$.call(l,s)&&y(t,s,l[s]);return t};import{_ as B,u as L,r as N,o as A,a as w,t as C,b as i,c as E,d as n,e as _,f as a,w as e,g as x,F as f,h as p,i as c,j as m,k as D}from"./index.dabb5305.js";const F={name:"Dashboard",emits:["updateVersion"],setup(t,l){L();const s=N({statData:{loading:!0,user:{},torrent:{},user_class:{},system_info:{}},latestUser:{loading:!0,data:[]},latestTorrent:{loading:!0,data:[]}});return A(()=>{w.listStatData().then(d=>{s.statData=d.data,s.statData.loading=!1,l.emit("updateVersion",d.data.system_info.data)}),w.listLatestUser().then(d=>{s.latestUser.data=d.data,s.latestUser.loading=!1}),w.listLatestTorrent().then(d=>{s.latestTorrent.data=d.data,s.latestTorrent.loading=!1})}),k({},C(s))}};function R(t,l,s,d,j,I){const o=i("el-table-column"),U=i("el-table"),z=i("el-card"),u=i("el-col"),v=i("el-row"),b=i("el-descriptions-item"),g=i("el-descriptions"),h=E("loading");return n(),_(f,null,[a(v,null,{default:e(()=>[a(u,{span:12,class:"stat-box"},{default:e(()=>[a(z,null,{header:e(()=>[p(c(t.latestUser.data.page_title),1)]),default:e(()=>[x((n(),m(U,{data:t.latestUser.data.data,size:"mini"},{default:e(()=>[a(o,{prop:"username",label:"Username"}),a(o,{prop:"email",label:"Email"}),a(o,{prop:"status",label:"Status"}),a(o,{prop:"added",label:"Added",width:"180"})]),_:1},8,["data"])),[[h,t.latestUser.loading]])]),_:1})]),_:1}),a(u,{span:12,class:"stat-box"},{default:e(()=>[a(z,null,{header:e(()=>[p(c(t.latestTorrent.data.page_title),1)]),default:e(()=>[x((n(),m(U,{data:t.latestTorrent.data.data,size:"mini"},{default:e(()=>[a(o,{prop:"name",label:"Name"}),a(o,{prop:"user.username",label:"User",width:"150"}),a(o,{prop:"size_human",label:"Size",width:"100"}),a(o,{prop:"added",label:"Added",width:"180"})]),_:1},8,["data"])),[[h,t.latestTorrent.loading]])]),_:1})]),_:1})]),_:1}),x((n(),_("div",null,[a(v,{class:"row"},{default:e(()=>[a(u,{span:12,class:"stat-box"},{default:e(()=>[a(g,{title:t.statData.user.text,column:2,size:"mini",border:""},{default:e(()=>[(n(!0),_(f,null,D(t.statData.user.data,r=>(n(),m(b,{label:r.text},{default:e(()=>[p(c(r.value),1)]),_:2},1032,["label"]))),256))]),_:1},8,["title"])]),_:1}),a(u,{span:12,class:"stat-box"},{default:e(()=>[a(g,{title:t.statData.user_class.text,column:2,size:"mini",border:""},{default:e(()=>[(n(!0),_(f,null,D(t.statData.user_class.data,r=>(n(),m(b,{label:r.class_text},{default:e(()=>[p(c(r.counts),1)]),_:2},1032,["label"]))),256))]),_:1},8,["title"])]),_:1})]),_:1}),a(v,{class:"row"},{default:e(()=>[a(u,{span:12,class:"stat-box"},{default:e(()=>[a(g,{title:t.statData.torrent.text,column:2,size:"mini",border:""},{default:e(()=>[(n(!0),_(f,null,D(t.statData.torrent.data,r=>(n(),m(b,{label:r.text},{default:e(()=>[p(c(r.value),1)]),_:2},1032,["label"]))),256))]),_:1},8,["title"])]),_:1}),a(u,{span:12,class:"stat-box"},{default:e(()=>[a(g,{title:t.statData.system_info.text,column:2,size:"mini",border:""},{default:e(()=>[(n(!0),_(f,null,D(t.statData.system_info.data,r=>(n(),m(b,{label:r.text},{default:e(()=>[p(c(r.value),1)]),_:2},1032,["label"]))),256))]),_:1},8,["title"])]),_:1})]),_:1})])),[[h,t.statData.loading]])],64)}var G=B(F,[["render",R],["__scopeId","data-v-64158476"]]);export{G as default};
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
var F=Object.defineProperty,P=Object.defineProperties;var V=Object.getOwnPropertyDescriptors;var k=Object.getOwnPropertySymbols;var x=Object.prototype.hasOwnProperty,R=Object.prototype.propertyIsEnumerable;var D=(e,t,a)=>t in e?F(e,t,{enumerable:!0,configurable:!0,writable:!0,value:a}):e[t]=a,T=(e,t)=>{for(var a in t||(t={}))x.call(t,a)&&D(e,a,t[a]);if(k)for(var a of k(t))R.call(t,a)&&D(e,a,t[a]);return e},q=(e,t)=>P(e,V(t));import{_ as B,l as M,u as N,r as z,o as j,a as C,t as L,b as i,c as Q,d as f,j as v,w as r,E as U,m,f as l,e as G,k as H,F as J,g as K,h as w,z as O,A as W}from"./index.dabb5305.js";import{u as X,r as Y}from"./table.6af03a03.js";const Z={name:"ClientTable",setup(){const e=M(null),t=N(),a=X();let o=z({agentAllows:[]});j(()=>{console.log("MedalTable onMounted"),c()});const c=async()=>{a.loading=!0,await y();let n=await C.listAgentDeny(a.query);Y(n,a),a.loading=!1},A=()=>{t.push({name:"agent-deny-form"})},g=n=>{t.push({path:"/agent-deny-form",query:{id:n}})},h=async n=>{let u=await C.deleteAgentDeny(n);U.success(u.msg),a.query.page=1,await c()},p=n=>{a.multipleSelection=n},_=n=>{a.query.page=n,c()},y=async()=>{let n=await C.listAllAgentAllow();o.agentAllows=n.data},s=()=>{a.query.family_id=""},b=(n,u)=>n.family.family;return q(T({},L(a)),{extraData:o,multipleTable:e,handleSelectionChange:p,handleAdd:A,handleEdit:g,handleDelete:h,fetchTableData:c,changePage:_,handleReset:s,formatColumnFamilyId:b})}},$=e=>(O("data-v-1119bb88"),e=e(),W(),e),ee={class:"nexus-table-header"},ae={class:"left"},te=w("Query"),le=w("Reset"),ne={class:"right"},oe=w("Add"),re=["onClick"],ie=$(()=>m("a",{style:{cursor:"pointer"}},"Delete",-1));function se(e,t,a,o,c,A){const g=i("el-option"),h=i("el-select"),p=i("el-form-item"),_=i("el-button"),y=i("el-form"),s=i("el-table-column"),b=i("el-popconfirm"),n=i("el-table"),u=i("el-pagination"),S=i("el-card"),I=Q("loading");return f(),v(S,{class:""},{header:r(()=>[m("div",ee,[m("div",ae,[l(y,{inline:!0,model:e.query},{default:r(()=>[l(p,{label:""},{default:r(()=>[l(h,{modelValue:e.query.family_id,"onUpdate:modelValue":t[0]||(t[0]=d=>e.query.family_id=d),filterable:"",placeholder:"Family"},{default:r(()=>[(f(!0),G(J,null,H(o.extraData.agentAllows,d=>(f(),v(g,{key:d.id,label:d.family,value:d.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),l(p,null,{default:r(()=>[l(_,{type:"primary",onClick:o.fetchTableData},{default:r(()=>[te]),_:1},8,["onClick"]),l(_,{type:"primary",onClick:o.handleReset},{default:r(()=>[le]),_:1},8,["onClick"])]),_:1})]),_:1},8,["model"])]),m("div",ne,[l(_,{type:"primary",icon:"Plus",onClick:o.handleAdd},{default:r(()=>[oe]),_:1},8,["onClick"])])])]),default:r(()=>[K((f(),v(n,{ref:"multipleTable",data:e.tableData,"tooltip-effect":"dark",onSelectionChange:o.handleSelectionChange},{default:r(()=>[l(s,{type:"selection",width:"55"}),l(s,{prop:"id",label:"Id",width:"50"}),l(s,{prop:"family_id",label:"Family",formatter:o.formatColumnFamilyId},null,8,["formatter"]),l(s,{prop:"name",label:"Name"}),l(s,{prop:"peer_id",label:"Peer id"}),l(s,{prop:"agent",label:"Agent"}),l(s,{label:"Action",width:"120"},{default:r(d=>[m("a",{style:{cursor:"pointer","margin-right":"10px"},onClick:E=>o.handleEdit(d.row.id)},"Edit",8,re),l(b,{title:"Confirm Delete ?",onConfirm:E=>o.handleDelete(d.row.id)},{reference:r(()=>[ie]),_:2},1032,["onConfirm"])]),_:1})]),_:1},8,["data","onSelectionChange"])),[[I,e.loading]]),l(u,{background:"",layout:"prev, pager, next",total:e.total,"page-size":e.perPage,"current-page":e.currentPage,onCurrentChange:o.changePage},null,8,["total","page-size","current-page","onCurrentChange"])]),_:1})}var me=B(Z,[["render",se],["__scopeId","data-v-1119bb88"]]);export{me as default};
|
||||
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-1
@@ -1 +0,0 @@
|
||||
.swiper-container[data-v-1119bb88]{min-height:100%}.el-card.is-always-shadow[data-v-1119bb88]{min-height:100%!important}
|
||||
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-1
@@ -1 +0,0 @@
|
||||
.swiper-container[data-v-2dbb3b07]{min-height:100%}.el-card.is-always-shadow[data-v-2dbb3b07]{min-height:100%!important}
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
.stat-box[data-v-64158476]{padding:15px}
|
||||
Vendored
-47
File diff suppressed because one or more lines are too long
Vendored
-1
@@ -1 +0,0 @@
|
||||
.swiper-container[data-v-68116b30]{min-height:100%}.el-card.is-always-shadow[data-v-68116b30]{min-height:100%!important}
|
||||
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-1
@@ -1 +0,0 @@
|
||||
.login-body[data-v-68d0c3e2]{display:flex;justify-content:center;align-items:center;width:100%;background-color:#fff}.login-container[data-v-68d0c3e2]{width:420px;height:500px;background-color:#fff;border-radius:4px;box-shadow:0 21px 41px #0003}.head[data-v-68d0c3e2]{display:flex;justify-content:center;align-items:center;padding:40px 0 20px}.head img[data-v-68d0c3e2]{width:100px;height:100px;margin-right:20px}.head .title[data-v-68d0c3e2]{font-size:28px;color:#1baeae;font-weight:700}.head .tips[data-v-68d0c3e2]{font-size:12px;color:#999}.login-form[data-v-68d0c3e2]{width:70%;margin:0 auto}.el-form--label-top .el-form-item__label{padding:0}.login-form .el-form-item{margin-bottom:12px}
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
var y=Object.defineProperty,x=Object.defineProperties;var U=Object.getOwnPropertyDescriptors;var m=Object.getOwnPropertySymbols;var _=Object.prototype.hasOwnProperty,w=Object.prototype.propertyIsEnumerable;var p=(e,o,t)=>o in e?y(e,o,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[o]=t,A=(e,o)=>{for(var t in o||(o={}))_.call(o,t)&&p(e,t,o[t]);if(m)for(var t of m(o))w.call(o,t)&&p(e,t,o[t]);return e},f=(e,o)=>x(e,U(o));import{_ as C,l as F,u as R,r as k,t as z,b as l,d as J,e as V,m as j,f as a,w as n,a as Y,n as g,p as E,q as h,h as S}from"./index.dabb5305.js";var I="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAVMSURBVFhHxVYJb1VFFO4vUZBoSEiIJEZBhURFrFERxRCVILTspVRUqAqV1FCBAMFEllba2pYKbWW1tJQWrMUaWiBQu0EXu72W17f17Wu3zzP33rn3zr2vJUrUL/ny3pw5M/PNmTPnTgL+Z/wrAsKjk+h2jqG+N4Z+97hijY9HFjA2AVh9E2joj+HUnQj2/hLAtp99WHfOiw3nfUj+yYvSprDibcbfFuAOT6DFOoYLLREcvh5EeoUfa896sZ4W23TRh5RyP1LJllYpk/1PIhE9rviRmFYAC+WfznHUdEaR0xDCrio/NrJdnfUJC26hRdhCU3Ed+Za3RZRZRQgCWChv9MVwzzaGATq7LjrH+44xdBA76X8nianoiGJzuS8uiyjUXbRTI9nYIe80EZgk5twIYWWJBx9RuGq6o7BMMYBhT10QG+icjSy8G8agzzxOiiQJYesYkWAPTOBSexQflniRTKFae0HjgfqQ4iaigyKh9zMyszYoLcrAftOvBLC6zCtF2IgElr37acDKUg9WUzIZycGOQo/c2+G4/pzcn/2y9vunPbhlGZVseiR0kkNeYxgrTnmwklQayZH1axDOkLaDEO2MJWK8MYz3FAHn2qJSm81/kkQbkRCMTaK2K4ZlhW7JyUiOzGsBiXpUUkLGG8PYbpcFnKHrytrLiz34im6REVISWijjl+aPYPlJt4kcu6v9UtsYRm43sp1uEkNZc0Rqv1vkRhIdQ0TJDQ5JQHRsEsnU+fYPI1hWIJIjg9Sz9oYzHoQoahx9I+OmMYxtw7IAVgW57fXvXVSQZDuHWgd2VfjwZq6LIiGSY+dln2rLawwqVhmsrR/D2DosR6qEria3MQFV98SCpAoovhlCYrYTb5wQyfHFJa9g79XthOXRikKX0N9qlQWcuhNSbYk5ThypE/NIFdBIFXDxEQcSj4vkSL/oEeysrcfVjojQ3/JAFvDjbdqYYnvtmAMpdN31UAXYqIIlHnXg1SN2gRzbz3tMfTX3xXDqfZqHZAEnbwZV22LiWxTlEd11VgUwrCly4aXDNrz8rUaOT864BTvj0uN2BKNaQrJN8L4/BmOSraghKIxZdMiGFkUcgyBgT6UPCw8Ok5NGjrSyEcHOua9KK1YMBTcCkr1JEcDbnC/S/KV0LByCgDLqWLDPihf2a+RIPe0S7Ho2WeTFGAIUkfey7aot//eA4Ps8zZ+hyx9BQCuF5tk9VszPeqCSI6XYJdj1XJWrJSvD9c4I7g7IAvJ+8wu+zxE/oBsxoZycIMBLr50ldEbPZA6p5NhY6BTsRpY0itcrEJUT7USd3+S7IMsKq/K5FwQwJOU5MS9jUCXH+nyHYDdyEe3M6jG/BXJqfSbfpzOGUKvcIJOAA1Tx5u4cxNwvLRI5knPtqm0qbivWChdH9jWaz+hL8xfUyxEzCbjcHMacdAvm7BjA/N1aBNbk2CXbw3i7J6qMkHGsxmv2+9yC6lb502wS0GUblQTM/rQfey9qX8Oj1V7J9jC+kqXlDYM67jPGAczebsGO0hFMxktChhh9Gc/dCuJmt/kVe38oJtmfTOublt9VadeMCVj49RCSchw4WOlFHZ396LhWvEwCGLqUL9lUeGJLr8bUXsxK7cOsrcS0fsyj8L5zeBhepdzaqTqGdNXSiLgCWOLM3NKHGZt6RG7uwczNvZiZQqT+pz7ux5JvHiCVrmhurR+N9Jp2+Kd+TcdDXAFsksU08eO02GO0MPudQbudn2HBqmM2HKrw4EpzCAP03teH858grgAGGxWK41fpiX3WjdKGANqptgci5mf1o2JKAf8NgL8AnzfNbLNwcf4AAAAASUVORK5CYII=";const q={name:"Login",setup(){const e=F(null),o=R(),t=k({ruleForm:{username:"",password:""},checked:!0,rules:{username:[{required:"true"}],password:[{required:"true"}]}}),s=async()=>{e.value.validate(u=>{if(u)Y.login(t.ruleForm).then(r=>{console.log(r),g("token",r.data.token),g("userInfo",r.data),o.push({name:"dashboard"})});else return console.log("error submit!!"),!1})},c=()=>{e.value.resetFields()};return f(A({},z(t)),{loginForm:e,submitForm:s,resetForm:c})}},B={class:"login-body"},L={class:"login-container"},N=E('<div class="head" data-v-68d0c3e2><img class="logo" src="'+I+'" data-v-68d0c3e2><div class="name" data-v-68d0c3e2><div class="title" data-v-68d0c3e2>NexusPHP</div><div class="tips" data-v-68d0c3e2>Management system</div></div></div>',1),G=S("Submit");function M(e,o,t,s,c,u){const r=l("el-input"),d=l("el-form-item"),v=l("el-button"),b=l("el-form");return J(),V("div",B,[j("div",L,[N,a(b,{"label-position":"top",rules:e.rules,model:e.ruleForm,ref:"loginForm",class:"login-form"},{default:n(()=>[a(d,{label:"Username",prop:"username"},{default:n(()=>[a(r,{type:"text",modelValue:e.ruleForm.username,"onUpdate:modelValue":o[0]||(o[0]=i=>e.ruleForm.username=i),modelModifiers:{trim:!0},autocomplete:"off",onKeyup:h(s.submitForm,["enter"])},null,8,["modelValue","onKeyup"])]),_:1}),a(d,{label:"Password",prop:"password"},{default:n(()=>[a(r,{type:"password",modelValue:e.ruleForm.password,"onUpdate:modelValue":o[1]||(o[1]=i=>e.ruleForm.password=i),modelModifiers:{trim:!0},autocomplete:"off",onKeyup:h(s.submitForm,["enter"])},null,8,["modelValue","onKeyup"])]),_:1}),a(d,{style:{"margin-top":"50px"}},{default:n(()=>[a(v,{style:{width:"100%"},type:"primary",onClick:s.submitForm},{default:n(()=>[G]),_:1},8,["onClick"])]),_:1})]),_:1},8,["rules","model"])])])}var W=C(q,[["render",M],["__scopeId","data-v-68d0c3e2"]]);export{W as default};
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
import{r as t}from"./index.dabb5305.js";const o=()=>t({loading:!1,query:{page:1,sort_field:"id",sort_type:"desc"},tableData:[],multipleSelection:[],total:0,currentPage:1,perPage:10}),l=(e,a)=>{a.tableData=e.data.data,a.page=e.data.meta.current_page,a.total=e.data.meta.total,a.currentPage=e.data.meta.current_page,a.perPage=e.data.meta.per_page},p=(e,a)=>{console.log("resetTableSort",e),a.query.page=1,a.query.sort_field=e.prop,a.query.sort_type=e.order};export{p as a,l as r,o as u};
|
||||
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-1
@@ -1 +0,0 @@
|
||||
.nexus-table-header[data-v-d2c322e8]{display:flex;justify-content:space-between}
|
||||
Vendored
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB |
Vendored
-15
@@ -1,15 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/admin/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>NexusPHP</title>
|
||||
<script type="module" crossorigin src="/admin/assets/index.dabb5305.js"></script>
|
||||
<link rel="stylesheet" href="/admin/assets/index.e4c1c305.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,13 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>NexusPHP</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Generated
-1937
File diff suppressed because it is too large
Load Diff
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "admin",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"dev": "vite --mode development",
|
||||
"build": "vite build --mode production",
|
||||
"serve": "vite preview --mode preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.0.5",
|
||||
"axios": "^0.27.2",
|
||||
"dayjs": "^1.11.0",
|
||||
"element-plus": "^2.2.5",
|
||||
"vue": "^3.2.37",
|
||||
"vue-router": "^4.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^2.3.3",
|
||||
"@vue/compiler-sfc": "^3.0.5",
|
||||
"sass": "^1.32.11",
|
||||
"vite": "^2.1.5"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,223 +0,0 @@
|
||||
<template>
|
||||
<div class="layout">
|
||||
<el-container v-if="state.showMenu" class="container">
|
||||
<el-aside class="aside">
|
||||
<div class="head">
|
||||
<div>
|
||||
<!-- <img src="http://demo.nexusphp.org/favicon.ico" alt="logo">-->
|
||||
<span>NexusPHP</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="line" />
|
||||
<el-menu
|
||||
:default-openeds="state.defaultOpen"
|
||||
background-color="#222832"
|
||||
text-color="#fff"
|
||||
:router="true"
|
||||
:default-active='state.currentPath'
|
||||
:collapse="false"
|
||||
>
|
||||
<el-menu-item index="/"><i class="el-icon-odometer" />Dashboard</el-menu-item>
|
||||
<el-sub-menu index="2">
|
||||
<template #title>
|
||||
<span>User</span>
|
||||
</template>
|
||||
<el-menu-item-group>
|
||||
<el-menu-item index="/user"><i class="el-icon-user" />User list</el-menu-item>
|
||||
<el-menu-item index="/hr"><i class="el-icon-user" />H&R</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
</el-sub-menu>
|
||||
<el-sub-menu index="3">
|
||||
<template #title>
|
||||
<span>Agent</span>
|
||||
</template>
|
||||
<el-menu-item-group>
|
||||
<el-menu-item index="/agent-allow"><i class="el-icon-user" />Allow</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
<el-menu-item-group>
|
||||
<el-menu-item index="/agent-deny"><i class="el-icon-user" />Deny</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
</el-sub-menu>
|
||||
<el-sub-menu index="4">
|
||||
<template #title>
|
||||
<span>System</span>
|
||||
</template>
|
||||
<el-menu-item-group>
|
||||
<el-menu-item index="/exam"><i class="el-icon-menu" />Exam</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
<el-menu-item-group>
|
||||
<el-menu-item index="/exam-user"><i class="el-icon-menu" />Exam user</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
<el-menu-item-group>
|
||||
<el-menu-item index="/medal"><i class="el-icon-menu" />Medal</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
<el-menu-item-group>
|
||||
<el-menu-item index="/tag"><i class="el-icon-menu" />Tag</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
<el-menu-item-group>
|
||||
<el-menu-item index="/setting"><i class="el-icon-menu" />Setting</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
</el-sub-menu>
|
||||
</el-menu>
|
||||
</el-aside>
|
||||
<el-container class="content">
|
||||
<Header :router-name="state.routerName"/>
|
||||
<div class="main">
|
||||
<router-view @update-version="updateVersion" />
|
||||
</div>
|
||||
<Footer :version="state.version"/>
|
||||
</el-container>
|
||||
</el-container>
|
||||
<el-container v-else class="container">
|
||||
<router-view />
|
||||
</el-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { reactive, onMounted, onUnmounted } from 'vue'
|
||||
import Header from './components/Header.vue'
|
||||
import Footer from './components/Footer.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { pathMap, localGet } from './utils'
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
Header,
|
||||
Footer
|
||||
},
|
||||
setup() {
|
||||
const noMenu = ['/login']
|
||||
const router = useRouter()
|
||||
const state = reactive({
|
||||
defaultOpen: ['1', '2', '3', '4'],
|
||||
showMenu: true,
|
||||
currentPath: '/dashboard',
|
||||
count: {
|
||||
number: 1
|
||||
},
|
||||
routerName: router.name,
|
||||
version: '',
|
||||
})
|
||||
onMounted(() => {
|
||||
|
||||
})
|
||||
onUnmounted(() => {
|
||||
unwatch()
|
||||
})
|
||||
const unwatch = router.beforeEach((to, from, next) => {
|
||||
if (to.path == '/login') {
|
||||
// 如果路径是 /login 则正常执行
|
||||
next()
|
||||
} else {
|
||||
// 如果不是 /login,判断是否有 token
|
||||
if (!localGet('token')) {
|
||||
// 如果没有,则跳至登录页面
|
||||
next({ path: '/login' })
|
||||
} else {
|
||||
// 否则继续执行
|
||||
next()
|
||||
}
|
||||
}
|
||||
state.showMenu = !noMenu.includes(to.path)
|
||||
state.currentPath = to.path
|
||||
document.title = pathMap[to.name]
|
||||
})
|
||||
const updateVersion = (val) => {
|
||||
// console.log('updateVersion', val)
|
||||
state.version = val.nexus_version.value
|
||||
}
|
||||
return {
|
||||
state,
|
||||
updateVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.layout {
|
||||
min-height: 100vh;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.container {
|
||||
height: 100vh;
|
||||
}
|
||||
.aside {
|
||||
width: 200px!important;
|
||||
background-color: #222832;
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
-ms-overflow-style: none;
|
||||
overflow: -moz-scrollbars-none;
|
||||
}
|
||||
.aside::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
.head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 50px;
|
||||
}
|
||||
.head > div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.head img {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.head span {
|
||||
font-size: 20px;
|
||||
color: #ffffff;
|
||||
}
|
||||
.line {
|
||||
border-top: 1px solid hsla(0,0%,100%,.05);
|
||||
border-bottom: 1px solid rgba(0,0,0,.2);
|
||||
}
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
.main {
|
||||
height: calc(100vh - 100px);
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.el-menu {
|
||||
border-right: none!important;
|
||||
}
|
||||
.el-sub-menu {
|
||||
border-top: 1px solid hsla(0, 0%, 100%, .05);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, .2);
|
||||
}
|
||||
.el-sub-menu:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
.el-sub-menu [class^="el-icon-"] {
|
||||
vertical-align: -1px!important;
|
||||
}
|
||||
a {
|
||||
color: #409eff;
|
||||
text-decoration: none;
|
||||
}
|
||||
.el-pagination {
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.el-popper__arrow {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1,28 +0,0 @@
|
||||
<template>
|
||||
<div class="footer">
|
||||
<div class="left">Powered by <a target="_blank" href="https://nexusphp.org/">NexusPHP</a></div>
|
||||
<div class="right" v-if="version">
|
||||
Version: {{version}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Footer',
|
||||
props: {
|
||||
version: String
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.footer {
|
||||
height: 50px;
|
||||
border-top: 1px solid #e9e9e9;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 20px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,123 +0,0 @@
|
||||
<template>
|
||||
<div class="header">
|
||||
<div class="left">
|
||||
<i v-if="hasBack" class="el-icon-back" @click="back"></i>
|
||||
<span style="font-size: 20px">{{ name }}</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<el-popover
|
||||
placement="bottom"
|
||||
:width="320"
|
||||
trigger="click"
|
||||
popper-class="popper-user-box"
|
||||
>
|
||||
<template #reference>
|
||||
<div class="author">
|
||||
<i class="icon el-icon-s-custom" />
|
||||
{{ userInfo && userInfo.username || '' }}
|
||||
<i class="el-icon-caret-bottom" />
|
||||
</div>
|
||||
</template>
|
||||
<div class="nickname">
|
||||
<p>Email:{{ userInfo && userInfo.email || '' }}</p>
|
||||
<p>Class:{{ userInfo && userInfo.class_text || '' }}</p>
|
||||
<el-tag size="small" effect="dark" class="logout" @click="logout">Logout</el-tag>
|
||||
</div>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {computed, onMounted, reactive, toRefs, watch} from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import {localGet, localSet, localRemove, pathMap} from '../utils'
|
||||
import api from "../utils/api";
|
||||
|
||||
|
||||
export default {
|
||||
name: 'Header',
|
||||
props: {
|
||||
},
|
||||
setup(props, context) {
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const userInfoKey = 'userInfo'
|
||||
const state = reactive({
|
||||
name: 'dashboard',
|
||||
userInfo: null,
|
||||
hasBack: false
|
||||
})
|
||||
onMounted(async () => {
|
||||
console.log("Head onMounted!")
|
||||
console.log(props)
|
||||
let userInfo = localGet(userInfoKey);
|
||||
if (userInfo) {
|
||||
state.userInfo = userInfo;
|
||||
}
|
||||
})
|
||||
const logout = () => {
|
||||
api.logout().then(() => {
|
||||
localRemove('token')
|
||||
localRemove(userInfoKey)
|
||||
router.push({ name: 'login' })
|
||||
})
|
||||
}
|
||||
const back = () => {
|
||||
router.back()
|
||||
}
|
||||
router.afterEach((to) => {
|
||||
console.log("Head afterEach to", to)
|
||||
const { id } = to.query
|
||||
state.name = pathMap[to.name]
|
||||
})
|
||||
return {
|
||||
...toRefs(state),
|
||||
logout,
|
||||
back
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.header {
|
||||
height: 50px;
|
||||
border-bottom: 1px solid #e9e9e9;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 20px;
|
||||
}
|
||||
.el-icon-back {
|
||||
border: 1px solid #e9e9e9;
|
||||
padding: 4px;
|
||||
border-radius: 50px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.right > div > .icon{
|
||||
font-size: 18px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
.author {
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.popper-user-box {
|
||||
background: url('../assets/account-banner-bg.png') 50% 50% no-repeat!important;
|
||||
background-size: cover!important;
|
||||
border-radius: 0!important;
|
||||
}
|
||||
.popper-user-box .nickname {
|
||||
position: relative;
|
||||
color: #ffffff;
|
||||
}
|
||||
.popper-user-box .nickname .logout {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
@@ -1,33 +0,0 @@
|
||||
<template>
|
||||
<h1>{{ msg }}</h1>
|
||||
|
||||
<p>
|
||||
<a href="https://vitejs.dev/guide/features.html" target="_blank">
|
||||
Vite Documentation
|
||||
</a>
|
||||
|
|
||||
<a href="https://v3.vuejs.org/" target="_blank">Vue 3 Documentation</a>
|
||||
</p>
|
||||
|
||||
<button @click="state.count++">count is: {{ state.count }}</button>
|
||||
<p>
|
||||
Edit
|
||||
<code>components/HelloWorld.vue</code> to test hot module replacement.
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps, reactive } from 'vue'
|
||||
|
||||
defineProps({
|
||||
msg: String
|
||||
})
|
||||
|
||||
const state = reactive({ count: 0 })
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
||||
Vendored
-13
@@ -1,13 +0,0 @@
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import ElementPlus from 'element-plus'
|
||||
import router from './router/index'
|
||||
import 'element-plus/theme-chalk/index.css'
|
||||
import './styles/common.scss'
|
||||
import * as ElIcons from '@element-plus/icons-vue'
|
||||
|
||||
const app = createApp(App)
|
||||
for (const name in ElIcons) {
|
||||
app.component(name, ElIcons[name])
|
||||
}
|
||||
app.use(ElementPlus).use(router).mount('#app')
|
||||
Vendored
-115
@@ -1,115 +0,0 @@
|
||||
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(), // hash模式:createWebHashHistory,history模式:createWebHistory
|
||||
base: '/admin/',
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
name: 'dashboard',
|
||||
component: () => import('../views/dashboard/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
component: () => import('../views/login.vue')
|
||||
},
|
||||
{
|
||||
path: '/user',
|
||||
name: 'user',
|
||||
component: () => import('../views/user/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/user-form',
|
||||
name: 'user-form',
|
||||
component: () => import('../views/user/form.vue')
|
||||
},
|
||||
{
|
||||
path: '/user-detail',
|
||||
name: 'user-detail',
|
||||
component: () => import('../views/user/detail.vue')
|
||||
},
|
||||
{
|
||||
path: '/exam',
|
||||
name: 'exam',
|
||||
component: () => import('../views/exam/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/exam-form',
|
||||
name: 'exam-form',
|
||||
component: () => import('../views/exam/form.vue')
|
||||
},
|
||||
{
|
||||
path: '/exam-user',
|
||||
name: 'exam-user',
|
||||
component: () => import('../views/exam/user.vue')
|
||||
},
|
||||
{
|
||||
path: '/agent-allow',
|
||||
name: 'agent-allow',
|
||||
component: () => import('../views/agent-allow/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/agent-allow-form',
|
||||
name: 'agent-allow-form',
|
||||
component: () => import('../views/agent-allow/form.vue')
|
||||
},
|
||||
{
|
||||
path: '/medal',
|
||||
name: 'medal',
|
||||
component: () => import('../views/medal/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/medal-form',
|
||||
name: 'medal-form',
|
||||
component: () => import('../views/medal/form.vue')
|
||||
},
|
||||
{
|
||||
path: '/agent-allow',
|
||||
name: 'agent-allow',
|
||||
component: () => import('../views/agent-allow/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/agent-allow-form',
|
||||
name: 'agent-allow-form',
|
||||
component: () => import('../views/agent-allow/form.vue')
|
||||
},
|
||||
{
|
||||
path: '/agent-deny',
|
||||
name: 'agent-deny',
|
||||
component: () => import('../views/agent-deny/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/agent-deny-form',
|
||||
name: 'agent-deny-form',
|
||||
component: () => import('../views/agent-deny/form.vue')
|
||||
},
|
||||
{
|
||||
path: '/setting',
|
||||
name: 'setting',
|
||||
component: () => import('../views/setting/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/tag',
|
||||
name: 'tag',
|
||||
component: () => import('../views/tag/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/tag-form',
|
||||
name: 'tag-form',
|
||||
component: () => import('../views/tag/form.vue')
|
||||
},
|
||||
{
|
||||
path: '/hr',
|
||||
name: 'hr',
|
||||
component: () => import('../views/hr/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/hr-detail',
|
||||
name: 'hr-detail',
|
||||
component: () => import('../views/hr/detail.vue')
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
export default router
|
||||
Vendored
-26
@@ -1,26 +0,0 @@
|
||||
.nexus-table-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.nexus-help-text {
|
||||
color: #aaa;
|
||||
}
|
||||
.pre-line {
|
||||
white-space: pre-line;
|
||||
}
|
||||
.text-one-line{
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow:ellipsis;
|
||||
}
|
||||
.text-two-line {
|
||||
width:200px;
|
||||
word-break:break-all;
|
||||
display:-webkit-box;
|
||||
-webkit-line-clamp:2;
|
||||
-webkit-box-orient:vertical;
|
||||
overflow:hidden;
|
||||
}
|
||||
Vendored
-216
@@ -1,216 +0,0 @@
|
||||
import axios from "./axios";
|
||||
|
||||
const api = {
|
||||
login: (params = {}) => {
|
||||
return axios.post('login', params);
|
||||
},
|
||||
logout: (params = {}) => {
|
||||
return axios.post('logout');
|
||||
},
|
||||
listAgentAllow: (params = {}) => {
|
||||
return axios.get('agent-allows', {params: params});
|
||||
},
|
||||
listAllAgentAllow: (params = {}) => {
|
||||
return axios.get('all-agent-allows', {params: params});
|
||||
},
|
||||
storeAgentAllow: (params = {}) => {
|
||||
return axios.post('agent-allows', params);
|
||||
},
|
||||
updateAgentAllow: (id, params = {}) => {
|
||||
return axios.put('agent-allows/' + id, params);
|
||||
},
|
||||
getAgentAllow: (id) => {
|
||||
return axios.get('agent-allows/' + id);
|
||||
},
|
||||
deleteAgentAllow: (id) => {
|
||||
return axios.delete('agent-allows/' + id);
|
||||
},
|
||||
|
||||
listAgentDeny: (params = {}) => {
|
||||
return axios.get('agent-denies', {params: params});
|
||||
},
|
||||
storeAgentDeny: (params = {}) => {
|
||||
return axios.post('agent-denies', params);
|
||||
},
|
||||
updateAgentDeny: (id, params = {}) => {
|
||||
return axios.put('agent-denies/' + id, params);
|
||||
},
|
||||
getAgentDeny: (id) => {
|
||||
return axios.get('agent-denies/' + id);
|
||||
},
|
||||
deleteAgentDeny: (id) => {
|
||||
return axios.delete('agent-denies/' + id);
|
||||
},
|
||||
checkAgent: (params = {}) => {
|
||||
return axios.post('agent-check', params);
|
||||
},
|
||||
|
||||
listUser: (params = {}) => {
|
||||
return axios.get('users', {params: params});
|
||||
},
|
||||
getUser: (id, params = {}) => {
|
||||
return axios.get('users/' + id, {params: params});
|
||||
},
|
||||
getUserBase: (params = {}) => {
|
||||
return axios.get('user-base', {params: params});
|
||||
},
|
||||
getInviteInfo: (params = {}) => {
|
||||
return axios.get('user-invite-info', {params: params});
|
||||
},
|
||||
getUserModComment: (params = {}) => {
|
||||
return axios.get('user-mod-comment', {params: params});
|
||||
},
|
||||
storeUser: (params = {}) => {
|
||||
return axios.post('users', params);
|
||||
},
|
||||
disableUser: (params = {}) => {
|
||||
return axios.post('user-disable', params);
|
||||
},
|
||||
enableUser: (params = {}) => {
|
||||
return axios.post('user-enable', params);
|
||||
},
|
||||
incrementDecrementUserField: (params = {}) => {
|
||||
return axios.put('user-increment-decrement', params);
|
||||
},
|
||||
resetPassword: (params = {}) => {
|
||||
return axios.post('user-reset-password', params);
|
||||
},
|
||||
listUserMatchExams: (params = {}) => {
|
||||
return axios.get('user-match-exams', {params: params});
|
||||
},
|
||||
|
||||
listExam: (params = {}) => {
|
||||
return axios.get('exams', {params: params});
|
||||
},
|
||||
listExamAll: (params = {}) => {
|
||||
return axios.get('exams-all', {params: params});
|
||||
},
|
||||
listExamIndex: (params = {}) => {
|
||||
return axios.get('exam-indexes', {params: params});
|
||||
},
|
||||
storeExam: (params = {}) => {
|
||||
return axios.post('exams', params);
|
||||
},
|
||||
updateExam: (id, params = {}) => {
|
||||
return axios.put('exams/' + id, params);
|
||||
},
|
||||
getExam: (id) => {
|
||||
return axios.get('exams/' + id);
|
||||
},
|
||||
deleteExam: (id) => {
|
||||
return axios.delete('exams/' + id);
|
||||
},
|
||||
|
||||
listMedal: (params = {}) => {
|
||||
return axios.get('medals', {params: params});
|
||||
},
|
||||
storeMedal: (params = {}) => {
|
||||
return axios.post('medals', params);
|
||||
},
|
||||
updateMedal: (id, params = {}) => {
|
||||
return axios.put('medals/' + id, params);
|
||||
},
|
||||
getMedal: (id) => {
|
||||
return axios.get('medals/' + id);
|
||||
},
|
||||
deleteMedal: (id) => {
|
||||
return axios.delete('medals/' + id);
|
||||
},
|
||||
|
||||
|
||||
listClass: (params = {}) => {
|
||||
return axios.get('user-classes', {params: params});
|
||||
},
|
||||
listExamUser: (params = {}) => {
|
||||
return axios.get('exam-users', {params: params});
|
||||
},
|
||||
deleteExamUser: (id) => {
|
||||
return axios.delete('exam-users/' + id);
|
||||
},
|
||||
avoidExamUser: (id) => {
|
||||
return axios.put('exam-users-avoid', {id});
|
||||
},
|
||||
avoidExamUserBulk: (params = {}) => {
|
||||
return axios.put('exam-users-avoid-bulk', params);
|
||||
},
|
||||
deleteExamUserBulk: (params = {}) => {
|
||||
return axios.put('exam-users-delete-bulk', params);
|
||||
},
|
||||
recoverExamUser: (id) => {
|
||||
return axios.put('exam-users-recover', {id});
|
||||
},
|
||||
storeExamUser: (params) => {
|
||||
return axios.post('exam-users', params);
|
||||
},
|
||||
storeSetting: (params) => {
|
||||
return axios.post('settings', params);
|
||||
},
|
||||
listSetting: (params) => {
|
||||
return axios.get('settings', {params});
|
||||
},
|
||||
listStatData: () => {
|
||||
return axios.get('dashboard/stat-data')
|
||||
},
|
||||
listLatestUser: () => {
|
||||
return axios.get('dashboard/latest-user')
|
||||
},
|
||||
listLatestTorrent: () => {
|
||||
return axios.get('dashboard/latest-torrent')
|
||||
},
|
||||
listSystemInfo: () => {
|
||||
return axios.get('dashboard/system-info')
|
||||
},
|
||||
removeUserMedal: (id) => {
|
||||
return axios.delete('user-medals/' + id);
|
||||
},
|
||||
storeUserMedal: (params) => {
|
||||
return axios.post('user-medals', params);
|
||||
},
|
||||
listTag: (params = {}) => {
|
||||
return axios.get('tags', {params: params});
|
||||
},
|
||||
storeTag: (params = {}) => {
|
||||
return axios.post('tags', params);
|
||||
},
|
||||
updateTag: (id, params = {}) => {
|
||||
return axios.put('tags/' + id, params);
|
||||
},
|
||||
getTag: (id) => {
|
||||
return axios.get('tags/' + id);
|
||||
},
|
||||
deleteTag: (id) => {
|
||||
return axios.delete('tags/' + id);
|
||||
},
|
||||
listHr: (params = {}) => {
|
||||
return axios.get('hr', {params: params});
|
||||
},
|
||||
listHrStatus: (params = {}) => {
|
||||
return axios.get('hr-status');
|
||||
},
|
||||
storeHr: (params = {}) => {
|
||||
return axios.post('hr', params);
|
||||
},
|
||||
updateHr: (id, params = {}) => {
|
||||
return axios.put('hr/' + id, params);
|
||||
},
|
||||
getHr: (id) => {
|
||||
return axios.get('hr/' + id);
|
||||
},
|
||||
deleteHr: (id) => {
|
||||
return axios.delete('hr/' + id);
|
||||
},
|
||||
pardonHr: (id) => {
|
||||
return axios.put('hr-pardon/' + id);
|
||||
},
|
||||
deleteHrBulk: (params = {}) => {
|
||||
return axios.put('hr-delete', params);
|
||||
},
|
||||
pardonHrBulk: (params = {}) => {
|
||||
return axios.put('hr-pardon', params);
|
||||
},
|
||||
removeTwoStepAuthentication: (params = {}) => {
|
||||
return axios.put('user-remove-two-step', params);
|
||||
},
|
||||
}
|
||||
|
||||
export default api
|
||||
Vendored
-46
@@ -1,46 +0,0 @@
|
||||
import axios from 'axios'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {localGet} from "./index"
|
||||
import router from '../router/index'
|
||||
|
||||
console.log(import.meta.env)
|
||||
|
||||
axios.defaults.baseURL = import.meta.env.VITE_BASE_URL || '/api'
|
||||
axios.defaults.withCredentials = true
|
||||
axios.defaults.headers['X-Requested-With'] = 'XMLHttpRequest'
|
||||
axios.defaults.headers['Content-Type'] = 'application/json'
|
||||
axios.defaults.headers['Accept'] = 'application/json'
|
||||
axios.defaults.headers['Platform'] = 'admin'
|
||||
// axios.defaults.headers['Authorization'] = 'Bearer ' + localGet('token')
|
||||
|
||||
axios.interceptors.request.use(config => {
|
||||
config.headers['Authorization'] = 'Bearer ' + localGet('token')
|
||||
return config
|
||||
}, error => {
|
||||
return Promise.reject(error)
|
||||
})
|
||||
|
||||
axios.interceptors.response.use(res => {
|
||||
console.log(res)
|
||||
if (typeof res.data !== 'object') {
|
||||
ElMessage.error('Server Error 1')
|
||||
return Promise.reject(res)
|
||||
}
|
||||
if (res.data.ret && res.data.ret != 0) {
|
||||
ElMessage.error(res.data.msg)
|
||||
return Promise.reject(res.data)
|
||||
}
|
||||
return res.data
|
||||
}, error => {
|
||||
let res = error.response;
|
||||
console.log(res)
|
||||
if (res.status == 401) {
|
||||
router.push({
|
||||
name: 'login'
|
||||
})
|
||||
}
|
||||
ElMessage.error(res.data.msg || 'Server Error 2')
|
||||
return Promise.reject(error)
|
||||
})
|
||||
|
||||
export default axios
|
||||
Vendored
-58
@@ -1,58 +0,0 @@
|
||||
export function localGet (key) {
|
||||
const value = window.localStorage.getItem(key)
|
||||
try {
|
||||
return JSON.parse(window.localStorage.getItem(key))
|
||||
} catch (error) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
export function localSet (key, value) {
|
||||
window.localStorage.setItem(key, JSON.stringify(value))
|
||||
}
|
||||
|
||||
export function localRemove (key) {
|
||||
window.localStorage.removeItem(key)
|
||||
}
|
||||
|
||||
// 判断内容是否含有表情字符,现有数据库不支持。
|
||||
export function hasEmoji (str = '') {
|
||||
const reg = /[^\u0020-\u007E\u00A0-\u00BE\u2E80-\uA4CF\uF900-\uFAFF\uFE30-\uFE4F\uFF00-\uFFEF\u0080-\u009F\u2000-\u201f\u2026\u2022\u20ac\r\n]/g;
|
||||
return str.match(reg) && str.match(reg).length
|
||||
}
|
||||
|
||||
export const pathMap = {
|
||||
login: 'Login',
|
||||
introduce: '系统介绍',
|
||||
dashboard: 'Dashboard',
|
||||
add: '添加商品',
|
||||
swiper: '轮播图配置',
|
||||
hot: '热销商品配置',
|
||||
new: '新品上线配置',
|
||||
recommend: '为你推荐配置',
|
||||
category: '分类管理',
|
||||
level2: '分类二级管理',
|
||||
level3: '分类三级管理',
|
||||
good: '商品管理',
|
||||
guest: '会员管理',
|
||||
order: '订单管理',
|
||||
order_detail: '订单详情',
|
||||
account: '修改账户',
|
||||
'agent-allow': 'Agent allow',
|
||||
'agent-allow-form': 'Agent allow form',
|
||||
'agent-deny': 'Agent deny',
|
||||
'agent-deny-form': 'Agent deny form',
|
||||
'user': 'User',
|
||||
'user-form': 'User form',
|
||||
'user-detail': 'User detail',
|
||||
'exam': 'Exam',
|
||||
'exam-form': 'Exam form',
|
||||
'exam-user': 'Exam user',
|
||||
'setting': "Setting",
|
||||
'medal': 'Medal',
|
||||
'medal-form': 'Medal form',
|
||||
'tag': 'Tag',
|
||||
'tag-form': 'Tag form',
|
||||
'hr': 'H&R',
|
||||
'hr-detail': 'H&R Detail'
|
||||
}
|
||||
Vendored
-39
@@ -1,39 +0,0 @@
|
||||
import {ref, reactive} from 'vue'
|
||||
|
||||
const useTable = () => {
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
query: {
|
||||
page: 1,
|
||||
sort_field: 'id',
|
||||
sort_type: 'desc',
|
||||
},
|
||||
tableData: [],
|
||||
multipleSelection: [],
|
||||
total: 0,
|
||||
currentPage: 1,
|
||||
perPage: 10
|
||||
})
|
||||
return state
|
||||
}
|
||||
|
||||
const renderTableData = (res, state) => {
|
||||
state.tableData = res.data.data
|
||||
state.page = res.data.meta.current_page
|
||||
state.total = res.data.meta.total
|
||||
state.currentPage = res.data.meta.current_page
|
||||
state.perPage = res.data.meta.per_page
|
||||
}
|
||||
|
||||
const resetTableSort = (val, state) => {
|
||||
console.log('resetTableSort', val)
|
||||
state.query.page = 1
|
||||
state.query.sort_field = val.prop
|
||||
state.query.sort_type = val.order
|
||||
}
|
||||
|
||||
export {
|
||||
useTable,
|
||||
renderTableData,
|
||||
resetTableSort
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="Check client is allowed or not"
|
||||
v-model="visible"
|
||||
center
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form
|
||||
:model="formData"
|
||||
label-width="100px"
|
||||
v-loading="loading"
|
||||
ref="formRef"
|
||||
:rules="rules">
|
||||
<el-form-item label="Peer id" prop="peer_id">
|
||||
<el-input type="text" v-model="formData.peer_id"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Agent" prop="agent">
|
||||
<el-input type="text" v-model="formData.agent"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="visible = false">Cancel</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">Check</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {useRoute, useRouter} from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
|
||||
export default {
|
||||
name: "DialogCheck",
|
||||
props: {
|
||||
reload: Function
|
||||
},
|
||||
setup(props, context) {
|
||||
const formRef = ref(null)
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
visible: false,
|
||||
result: '',
|
||||
formData: {
|
||||
peer_id: '',
|
||||
agent: '',
|
||||
},
|
||||
rules: {
|
||||
peer_id: [{ required: 'true'}],
|
||||
agent: [{ required: 'true'}]
|
||||
}
|
||||
})
|
||||
const open = (uid) => {
|
||||
state.formData.uid = uid
|
||||
state.visible = true
|
||||
|
||||
}
|
||||
const handleSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res = await api.checkAgent(state.formData)
|
||||
ElMessage.success(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
handleSubmit,
|
||||
formRef,
|
||||
open,
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,199 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form :model="formData" :rules="rules" ref="formRef" label-width="200px" class="formData">
|
||||
<el-form-item label="Family" prop="family">
|
||||
<el-input v-model="formData.family" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Start name" prop="start_name">
|
||||
<el-input v-model="formData.start_name" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Peer id start" prop="peer_id_start">
|
||||
<el-input v-model="formData.peer_id_start" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Peer id pattern" prop="peer_id_pattern">
|
||||
<el-input v-model="formData.peer_id_pattern" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Peer id match num" prop="peer_id_match_num">
|
||||
<el-input v-model="formData.peer_id_match_num" placeholder="" type="number"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Peer id match type" prop="peer_id_matchtype">
|
||||
<el-radio-group v-model="formData.peer_id_matchtype">
|
||||
<el-radio label="dec">dec</el-radio>
|
||||
<el-radio label="hex">hex</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Agent start" prop="agent_start">
|
||||
<el-input v-model="formData.agent_start" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Agent pattern" prop="agent_pattern">
|
||||
<el-input v-model="formData.agent_pattern" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Agent match num" prop="agent_match_num">
|
||||
<el-input v-model="formData.agent_match_num" placeholder="" type="number"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Agent match type" prop="agent_matchtype">
|
||||
<el-radio-group v-model="formData.agent_matchtype">
|
||||
<el-radio label="dec">dec</el-radio>
|
||||
<el-radio label="hex">hex</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Exception" prop="exception">
|
||||
<el-radio-group v-model="formData.exception">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="Allow https" prop="allowhttps">
|
||||
<el-radio-group v-model="formData.allowhttps">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="Comment" prop="comment">
|
||||
<el-input type="textarea" v-model="formData.comment" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submitAdd()">Submit</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { reactive, ref, toRefs, onMounted, onBeforeUnmount, getCurrentInstance } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { localGet } from '../../utils'
|
||||
import api from "../../utils/api";
|
||||
|
||||
export default {
|
||||
name: 'AgentAllowForm',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance()
|
||||
console.log('proxy', proxy)
|
||||
const formRef = ref(null)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { id } = route.query
|
||||
const state = reactive({
|
||||
token: localGet('token') || '',
|
||||
id: id,
|
||||
allClasses: [],
|
||||
formData: {
|
||||
family: '',
|
||||
start_name: '',
|
||||
peer_id_pattern: '',
|
||||
peer_id_match_num: '',
|
||||
peer_id_matchtype: '',
|
||||
peer_id_start: '',
|
||||
agent_pattern: '',
|
||||
agent_match_num: '',
|
||||
agent_matchtype: '',
|
||||
agent_start: '',
|
||||
exception: '',
|
||||
allowhttps: '',
|
||||
comment: '',
|
||||
},
|
||||
rules: {
|
||||
family: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
start_name: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
peer_id_pattern: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
peer_id_match_num: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
peer_id_matchtype: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
peer_id_start: [
|
||||
{required: 'true'}
|
||||
],
|
||||
agent_pattern: [
|
||||
{required: 'true'}
|
||||
],
|
||||
agent_match_num: [
|
||||
{required: 'true'}
|
||||
],
|
||||
agent_matchtype: [
|
||||
{required: 'true'}
|
||||
],
|
||||
agent_start: [
|
||||
{required: 'true'}
|
||||
],
|
||||
exception: [
|
||||
{required: 'true'}
|
||||
],
|
||||
allowhttps: [
|
||||
{required: 'true'}
|
||||
],
|
||||
},
|
||||
})
|
||||
onMounted( async () => {
|
||||
if (id) {
|
||||
api.getAgentAllow(id).then(res => {
|
||||
state.formData.family = res.data.family
|
||||
state.formData.start_name = res.data.start_name
|
||||
|
||||
state.formData.peer_id_pattern = res.data.peer_id_pattern
|
||||
state.formData.peer_id_match_num = res.data.peer_id_match_num
|
||||
state.formData.peer_id_matchtype = res.data.peer_id_matchtype
|
||||
state.formData.peer_id_start = res.data.peer_id_start
|
||||
|
||||
state.formData.agent_pattern = res.data.agent_pattern
|
||||
state.formData.agent_match_num = res.data.agent_match_num
|
||||
state.formData.agent_matchtype = res.data.agent_matchtype
|
||||
state.formData.agent_start = res.data.agent_start
|
||||
|
||||
state.formData.exception = res.data.exception
|
||||
state.formData.allowhttps = res.data.allowhttps
|
||||
state.formData.comment = res.data.comment
|
||||
})
|
||||
}
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
|
||||
})
|
||||
const submitAdd = () => {
|
||||
formRef.value.validate(async (vaild) => {
|
||||
if (vaild) {
|
||||
let params = state.formData;
|
||||
console.log(params)
|
||||
if (id) {
|
||||
await api.updateAgentAllow(id, params)
|
||||
} else {
|
||||
await api.storeAgentAllow(params)
|
||||
}
|
||||
await router.push({name: 'agent-allow'})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getAgentAllow = async (id) => {
|
||||
let res = await api.getAgentAllow(id)
|
||||
console.log(res)
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
formRef,
|
||||
submitAdd,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,198 +0,0 @@
|
||||
<template>
|
||||
<el-card class="">
|
||||
<template #header>
|
||||
<div class="nexus-table-header">
|
||||
<div class="left">
|
||||
<el-form :inline="true" :model="query">
|
||||
<el-form-item label="">
|
||||
<el-input placeholder="Family" v-model="query.family"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="fetchTableData">Query</el-button>
|
||||
<el-button type="primary" @click="handleReset">Reset</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="right">
|
||||
<el-button type="primary" icon="Check" @click="handleCheck">Check</el-button>
|
||||
<el-button type="primary" icon="Plus" @click="handleAdd">Add</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
ref="multipleTable"
|
||||
:data="tableData"
|
||||
tooltip-effect="dark"
|
||||
@selection-change="handleSelectionChange">
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="55">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="Id"
|
||||
width="50"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="family"
|
||||
label="Family"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="start_name"
|
||||
label="Start name"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="peer_id_start"
|
||||
label="Peer id start"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="peer_id_pattern"
|
||||
label="Peer id pattern"
|
||||
></el-table-column>
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="peer_id_match_num"-->
|
||||
<!-- label="Peer id match num"-->
|
||||
<!-- ></el-table-column>-->
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="peer_id_matchtype"-->
|
||||
<!-- label="Peer id match type"-->
|
||||
<!-- ></el-table-column>-->
|
||||
|
||||
<el-table-column
|
||||
prop="agent_start"
|
||||
label="Agent start"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="agent_pattern"
|
||||
label="Agent pattern"
|
||||
></el-table-column>
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="agent_match_num"-->
|
||||
<!-- label="Agent match num"-->
|
||||
<!-- ></el-table-column>-->
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="agent_matchtype"-->
|
||||
<!-- label="Agent match type"-->
|
||||
<!-- ></el-table-column>-->
|
||||
|
||||
|
||||
|
||||
<el-table-column
|
||||
label="Action"
|
||||
width="120"
|
||||
>
|
||||
<template #default="scope">
|
||||
<a style="cursor: pointer; margin-right: 10px" @click="handleEdit(scope.row.id)">Edit</a>
|
||||
<el-popconfirm
|
||||
title="Confirm Delete ?"
|
||||
@confirm="handleDelete(scope.row.id)"
|
||||
>
|
||||
<template #reference>
|
||||
<a style="cursor: pointer">Delete</a>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--总数超过一页,再展示分页器-->
|
||||
<el-pagination
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
:total="total"
|
||||
:page-size="perPage"
|
||||
:current-page="currentPage"
|
||||
@current-change="changePage"
|
||||
/>
|
||||
</el-card>
|
||||
<DialogCheck ref="refDialogCheck" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRouter } from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
import { useTable, renderTableData } from '../../utils/table'
|
||||
import DialogCheck from "../agent-allow/dialog-check.vue"
|
||||
|
||||
|
||||
export default {
|
||||
name: 'ClientTable',
|
||||
components: {
|
||||
DialogCheck,
|
||||
},
|
||||
setup() {
|
||||
const multipleTable = ref(null)
|
||||
const router = useRouter()
|
||||
|
||||
const state = useTable()
|
||||
const refDialogCheck = ref(null)
|
||||
|
||||
onMounted(() => {
|
||||
console.log('MedalTable onMounted')
|
||||
fetchTableData()
|
||||
})
|
||||
const fetchTableData = async () => {
|
||||
state.loading = true
|
||||
let res = await api.listAgentAllow(state.query)
|
||||
renderTableData(res, state)
|
||||
state.loading = false
|
||||
}
|
||||
const handleAdd = () => {
|
||||
router.push({ name: 'agent-allow-form' })
|
||||
}
|
||||
const handleEdit = (id) => {
|
||||
router.push({ path: '/agent-allow-form', query: { id } })
|
||||
}
|
||||
const handleDelete = async (id) => {
|
||||
let res = await api.deleteAgentAllow(id)
|
||||
ElMessage.success(res.msg)
|
||||
state.query.page = 1;
|
||||
await fetchTableData()
|
||||
}
|
||||
const handleSelectionChange = (val) => {
|
||||
state.multipleSelection = val
|
||||
}
|
||||
const changePage = (val) => {
|
||||
state.query.page = val
|
||||
fetchTableData()
|
||||
}
|
||||
const handleReset = () => {
|
||||
state.query.family = '';
|
||||
}
|
||||
|
||||
const handleCheck = () => {
|
||||
refDialogCheck.value.open()
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
multipleTable,
|
||||
handleSelectionChange,
|
||||
handleAdd,
|
||||
handleEdit,
|
||||
handleDelete,
|
||||
fetchTableData,
|
||||
changePage,
|
||||
handleReset,
|
||||
handleCheck,
|
||||
refDialogCheck
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.swiper-container {
|
||||
min-height: 100%;
|
||||
}
|
||||
.el-card.is-always-shadow {
|
||||
min-height: 100%!important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,133 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form :model="formData" :rules="rules" ref="formRef" label-width="200px" class="formData">
|
||||
<el-form-item label="Family" prop="family_id">
|
||||
<el-select v-model="formData.family_id" filterable>
|
||||
<el-option
|
||||
v-for="item in agentAllows"
|
||||
:key="item.id"
|
||||
:label="item.family"
|
||||
:value="item.id"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="Name" prop="name">
|
||||
<el-input v-model="formData.name" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Peer id" prop="peer_id">
|
||||
<el-input v-model="formData.peer_id" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Agent" prop="agent">
|
||||
<el-input v-model="formData.agent" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Comment" prop="comment">
|
||||
<el-input type="textarea" v-model="formData.comment" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submitAdd()">Submit</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { reactive, ref, toRefs, onMounted, onBeforeUnmount, getCurrentInstance } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { localGet } from '../../utils'
|
||||
import api from "../../utils/api";
|
||||
|
||||
export default {
|
||||
name: 'AgentAllowForm',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance()
|
||||
console.log('proxy', proxy)
|
||||
const formRef = ref(null)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { id } = route.query
|
||||
const state = reactive({
|
||||
token: localGet('token') || '',
|
||||
id: id,
|
||||
agentAllows: [],
|
||||
formData: {
|
||||
family_id: '',
|
||||
name: '',
|
||||
peer_id: '',
|
||||
agent: '',
|
||||
comment: '',
|
||||
},
|
||||
rules: {
|
||||
family_id: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
name: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
peer_id: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
agent: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
},
|
||||
})
|
||||
onMounted( async () => {
|
||||
await listAgentAllows()
|
||||
if (id) {
|
||||
api.getAgentDeny(id).then(res => {
|
||||
state.formData.family_id = res.data.family_id
|
||||
state.formData.name = res.data.name
|
||||
|
||||
state.formData.peer_id = res.data.peer_id
|
||||
state.formData.agent = res.data.agent
|
||||
state.formData.comment = res.data.comment
|
||||
})
|
||||
}
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
|
||||
})
|
||||
const submitAdd = () => {
|
||||
formRef.value.validate(async (vaild) => {
|
||||
if (vaild) {
|
||||
let params = state.formData;
|
||||
console.log(params)
|
||||
if (id) {
|
||||
await api.updateAgentDeny(id, params)
|
||||
} else {
|
||||
await api.storeAgentDeny(params)
|
||||
}
|
||||
await router.push({name: 'agent-deny'})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const listAgentAllows = async () => {
|
||||
let res = await api.listAllAgentAllow()
|
||||
state.agentAllows = res.data
|
||||
}
|
||||
|
||||
const getAgentAllow = async (id) => {
|
||||
let res = await api.getAgentAllow(id)
|
||||
console.log(res)
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
formRef,
|
||||
submitAdd,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,181 +0,0 @@
|
||||
<template>
|
||||
<el-card class="">
|
||||
<template #header>
|
||||
<div class="nexus-table-header">
|
||||
<div class="left">
|
||||
<el-form :inline="true" :model="query">
|
||||
<el-form-item label="">
|
||||
<el-select v-model="query.family_id" filterable placeholder="Family">
|
||||
<el-option
|
||||
v-for="item in extraData.agentAllows"
|
||||
:key="item.id"
|
||||
:label="item.family"
|
||||
:value="item.id"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="fetchTableData">Query</el-button>
|
||||
<el-button type="primary" @click="handleReset">Reset</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="right">
|
||||
<el-button type="primary" icon="Plus" @click="handleAdd">Add</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
ref="multipleTable"
|
||||
:data="tableData"
|
||||
tooltip-effect="dark"
|
||||
@selection-change="handleSelectionChange">
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="55">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="Id"
|
||||
width="50"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="family_id"
|
||||
label="Family"
|
||||
:formatter="formatColumnFamilyId"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="Name"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="peer_id"
|
||||
label="Peer id"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="agent"
|
||||
label="Agent"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="Action"
|
||||
width="120"
|
||||
>
|
||||
<template #default="scope">
|
||||
<a style="cursor: pointer; margin-right: 10px" @click="handleEdit(scope.row.id)">Edit</a>
|
||||
<el-popconfirm
|
||||
title="Confirm Delete ?"
|
||||
@confirm="handleDelete(scope.row.id)"
|
||||
>
|
||||
<template #reference>
|
||||
<a style="cursor: pointer">Delete</a>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--总数超过一页,再展示分页器-->
|
||||
<el-pagination
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
:total="total"
|
||||
:page-size="perPage"
|
||||
:current-page="currentPage"
|
||||
@current-change="changePage"
|
||||
/>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRouter } from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
import { useTable, renderTableData } from '../../utils/table'
|
||||
|
||||
export default {
|
||||
name: 'ClientTable',
|
||||
setup() {
|
||||
const multipleTable = ref(null)
|
||||
const router = useRouter()
|
||||
|
||||
const state = useTable()
|
||||
let extraData = reactive({
|
||||
agentAllows: []
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
console.log('MedalTable onMounted')
|
||||
fetchTableData()
|
||||
})
|
||||
const fetchTableData = async () => {
|
||||
state.loading = true
|
||||
await listAgentAllows()
|
||||
let res = await api.listAgentDeny(state.query)
|
||||
renderTableData(res, state)
|
||||
state.loading = false
|
||||
}
|
||||
const handleAdd = () => {
|
||||
router.push({ name: 'agent-deny-form' })
|
||||
}
|
||||
const handleEdit = (id) => {
|
||||
router.push({ path: '/agent-deny-form', query: { id } })
|
||||
}
|
||||
const handleDelete = async (id) => {
|
||||
let res = await api.deleteAgentDeny(id)
|
||||
ElMessage.success(res.msg)
|
||||
state.query.page = 1;
|
||||
await fetchTableData()
|
||||
}
|
||||
const handleSelectionChange = (val) => {
|
||||
state.multipleSelection = val
|
||||
}
|
||||
const changePage = (val) => {
|
||||
state.query.page = val
|
||||
fetchTableData()
|
||||
}
|
||||
|
||||
const listAgentAllows = async () => {
|
||||
let res = await api.listAllAgentAllow()
|
||||
extraData.agentAllows = res.data
|
||||
}
|
||||
|
||||
const handleReset = () => {
|
||||
state.query.family_id = '';
|
||||
}
|
||||
|
||||
const formatColumnFamilyId = (row, column) => {
|
||||
return row.family.family
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
extraData,
|
||||
multipleTable,
|
||||
handleSelectionChange,
|
||||
handleAdd,
|
||||
handleEdit,
|
||||
handleDelete,
|
||||
fetchTableData,
|
||||
changePage,
|
||||
handleReset,
|
||||
formatColumnFamilyId
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.swiper-container {
|
||||
min-height: 100%;
|
||||
}
|
||||
.el-card.is-always-shadow {
|
||||
min-height: 100%!important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,146 +0,0 @@
|
||||
<template>
|
||||
<el-row>
|
||||
<el-col :span="12" class="stat-box">
|
||||
<el-card>
|
||||
<template #header>{{latestUser.data.page_title}}</template>
|
||||
<el-table
|
||||
:data="latestUser.data.data"
|
||||
v-loading="latestUser.loading"
|
||||
size="mini"
|
||||
>
|
||||
<el-table-column
|
||||
prop="username"
|
||||
label="Username"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="email"
|
||||
label="Email"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="status"
|
||||
label="Status"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="added"
|
||||
label="Added"
|
||||
width="180"
|
||||
></el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="12" class="stat-box">
|
||||
<el-card>
|
||||
<template #header>{{latestTorrent.data.page_title}}</template>
|
||||
<el-table
|
||||
:data="latestTorrent.data.data"
|
||||
v-loading="latestTorrent.loading"
|
||||
size="mini"
|
||||
>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="Name"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="user.username"
|
||||
label="User"
|
||||
width="150"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="size_human"
|
||||
label="Size"
|
||||
width="100"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="added"
|
||||
label="Added"
|
||||
width="180"
|
||||
></el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div v-loading="statData.loading">
|
||||
<el-row class="row">
|
||||
<el-col :span="12" class="stat-box">
|
||||
<el-descriptions :title="statData.user.text" :column="2" size="mini" border>
|
||||
<el-descriptions-item :label="item.text" v-for="item in statData.user.data">{{item.value}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-col>
|
||||
<el-col :span="12" class="stat-box">
|
||||
<el-descriptions :title="statData.user_class.text" :column="2" size="mini" border>
|
||||
<el-descriptions-item :label="item.class_text" v-for="item in statData.user_class.data">{{item.counts}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="row">
|
||||
<el-col :span="12" class="stat-box">
|
||||
<el-descriptions :title="statData.torrent.text" :column="2" size="mini" border>
|
||||
<el-descriptions-item :label="item.text" v-for="item in statData.torrent.data">{{item.value}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-col>
|
||||
<el-col :span="12" class="stat-box">
|
||||
<el-descriptions :title="statData.system_info.text" :column="2" size="mini" border>
|
||||
<el-descriptions-item :label="item.text" v-for="item in statData.system_info.data">{{item.value}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRouter } from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
|
||||
export default {
|
||||
name: "Dashboard",
|
||||
emits: ['updateVersion'],
|
||||
setup(props, context) {
|
||||
const router = useRouter()
|
||||
const state = reactive({
|
||||
statData: {
|
||||
loading: true,
|
||||
user: {},
|
||||
torrent: {},
|
||||
user_class: {},
|
||||
system_info: {}
|
||||
},
|
||||
latestUser: {
|
||||
loading: true,
|
||||
data: []
|
||||
},
|
||||
latestTorrent: {
|
||||
loading: true,
|
||||
data: []
|
||||
}
|
||||
})
|
||||
onMounted(() => {
|
||||
api.listStatData().then(res => {
|
||||
state.statData = res.data
|
||||
state.statData.loading = false
|
||||
context.emit('updateVersion', res.data.system_info.data)
|
||||
})
|
||||
api.listLatestUser().then(res => {
|
||||
state.latestUser.data = res.data
|
||||
state.latestUser.loading = false
|
||||
})
|
||||
api.listLatestTorrent().then(res => {
|
||||
state.latestTorrent.data = res.data
|
||||
state.latestTorrent.loading = false
|
||||
})
|
||||
})
|
||||
|
||||
return {
|
||||
...toRefs(state)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.stat-box {
|
||||
padding: 15px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,245 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form :model="formData" :rules="rules" ref="formRef" label-width="200px" class="formData">
|
||||
<el-form-item label="Name" prop="name">
|
||||
<el-input v-model="formData.name" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Index" prop="indexes">
|
||||
<template v-for="(item, index) in formData.indexes" :key="index">
|
||||
<el-row style="width: 100%">
|
||||
<el-col :span="6">
|
||||
<el-checkbox v-model="item.checked" :label="item.checked">{{item.name}}</el-checkbox>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-input type="number" v-model="item.require_value"></el-input>
|
||||
</el-col>
|
||||
<el-col :span="6" style="padding: 0 20px; color: #aaa">
|
||||
<template v-if="item.unit">
|
||||
Unit: {{item.unit}}
|
||||
</template>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Status" prop="status">
|
||||
<el-radio-group v-model="formData.status">
|
||||
<el-radio :label="0">Enabled</el-radio>
|
||||
<el-radio :label="1">Disabled</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Discovered" prop="is_discovered">
|
||||
<el-radio-group v-model="formData.is_discovered">
|
||||
<el-radio :label="0">No</el-radio>
|
||||
<el-radio :label="1">Yes</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Priority" prop="priority">
|
||||
<el-input v-model="formData.priority" type="number" placeholder=""></el-input>
|
||||
<div style="color: #aaa">The higher the value, the higher the priority, and when multiple exam match the same user, the one with the highest priority is assigned.</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Begin" prop="begin">
|
||||
<el-date-picker
|
||||
v-model="formData.begin"
|
||||
type="datetime"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
placeholder="Select Begin Time">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="End" prop="end">
|
||||
<el-date-picker
|
||||
v-model="formData.end"
|
||||
type="datetime"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
placeholder="Select End Time">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Duration" prop="duration">
|
||||
<el-input v-model="formData.duration" type="number" placeholder=""></el-input>
|
||||
<div style="color: #aaa">Unit: days. When assign to user, begin and end are used if they are specified. Otherwise begin time is the time at assignment, and the end time is the time at assignment plus the duration.</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Target user class" prop="filters.classes">
|
||||
<el-checkbox-group v-model="formData.filters.classes">
|
||||
<el-checkbox v-for="(item, index) in allClasses" :label="index" :key="index">{{item}}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Target user donated" prop="filters.donate_status">
|
||||
<el-checkbox-group v-model="formData.filters.donate_status">
|
||||
<el-checkbox label="no">No</el-checkbox>
|
||||
<el-checkbox label="yes">Yes</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Target user register time">
|
||||
<el-date-picker
|
||||
v-model="formData.filters.register_time_range"
|
||||
type="datetimerange"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
range-separator="to"
|
||||
start-placeholder="Begin"
|
||||
end-placeholder="End">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Description" prop="description">
|
||||
<el-input type="textarea" v-model="formData.description" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submitAdd()">Submit</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { reactive, ref, toRefs, onMounted, onBeforeUnmount, getCurrentInstance } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { localGet } from '../../utils'
|
||||
import api from "../../utils/api";
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
export default {
|
||||
name: 'ExamForm',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance()
|
||||
console.log('proxy', proxy)
|
||||
const formRef = ref(null)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { id } = route.query
|
||||
const state = reactive({
|
||||
token: localGet('token') || '',
|
||||
id: id,
|
||||
allClasses: [],
|
||||
formData: {
|
||||
name: '',
|
||||
description: '',
|
||||
begin: '',
|
||||
end: '',
|
||||
duration: '',
|
||||
indexes: [],
|
||||
filters: {
|
||||
classes: [],
|
||||
register_time_range: [],
|
||||
donate_status: []
|
||||
},
|
||||
status: '',
|
||||
is_discovered: '',
|
||||
priority: ''
|
||||
},
|
||||
rules: {
|
||||
name: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
indexes: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
status: [
|
||||
{ required: 'true',}
|
||||
],
|
||||
is_discovered: [
|
||||
{ required: 'true',}
|
||||
],
|
||||
},
|
||||
})
|
||||
onMounted( async () => {
|
||||
await listAllClass()
|
||||
await listAllIndex()
|
||||
if (id) {
|
||||
api.getExam(id).then(res => {
|
||||
state.formData.name = res.data.name
|
||||
state.formData.description = res.data.description
|
||||
state.formData.begin = res.data.begin
|
||||
state.formData.end = res.data.end
|
||||
state.formData.duration = res.data.duration
|
||||
state.formData.indexes = res.data.indexes
|
||||
state.formData.filters = res.data.filters
|
||||
state.formData.status = res.data.status
|
||||
state.formData.is_discovered = res.data.is_discovered
|
||||
state.formData.priority = res.data.priority
|
||||
})
|
||||
}
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
|
||||
})
|
||||
const submitAdd = () => {
|
||||
formRef.value.validate(async (vaild) => {
|
||||
if (vaild) {
|
||||
let params = state.formData;
|
||||
console.log(params)
|
||||
if (params.begin) {
|
||||
params.begin = dayjs(params.begin).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
if (params.end) {
|
||||
params.end = dayjs(params.end).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
if (params.filters.register_time_range && params.filters.register_time_range[0]) {
|
||||
params.filters.register_time_range[0] = dayjs(params.filters.register_time_range[0]).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
if (params.filters.register_time_range && params.filters.register_time_range[1]) {
|
||||
params.filters.register_time_range[1] = dayjs(params.filters.register_time_range[1]).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
console.log(params)
|
||||
if (id) {
|
||||
await api.updateExam(id, params)
|
||||
} else {
|
||||
await api.storeExam(params)
|
||||
}
|
||||
await router.push({name: 'exam'})
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleBeforeUpload = (file) => {
|
||||
const sufix = file.name.split('.')[1] || ''
|
||||
if (!['jpg', 'jpeg', 'png'].includes(sufix)) {
|
||||
ElMessage.error('请上传 jpg、jpeg、png 格式的图片')
|
||||
return false
|
||||
}
|
||||
}
|
||||
const handleUrlSuccess = (val) => {
|
||||
state.formData.goodsCoverImg = val.data || ''
|
||||
}
|
||||
const handleChangeCate = (val) => {
|
||||
state.categoryId = val[2] || 0
|
||||
}
|
||||
|
||||
const listAllClass = async () => {
|
||||
let res = await api.listClass()
|
||||
state.allClasses = res.data
|
||||
}
|
||||
const listAllIndex = async () => {
|
||||
let res = await api.listExamIndex()
|
||||
state.formData.indexes = res.data
|
||||
}
|
||||
const getExam = async (id) => {
|
||||
let res = await api.getExam(id)
|
||||
console.log(res)
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
formRef,
|
||||
submitAdd,
|
||||
handleBeforeUpload,
|
||||
handleUrlSuccess,
|
||||
handleChangeCate,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,182 +0,0 @@
|
||||
<template>
|
||||
<el-card class="">
|
||||
<template #header>
|
||||
<div class="nexus-table-header">
|
||||
<div class="left">
|
||||
|
||||
</div>
|
||||
<div class="right">
|
||||
<el-button type="primary" icon="Plus" @click="handleAdd">Add</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
ref="multipleTable"
|
||||
:data="tableData"
|
||||
tooltip-effect="dark"
|
||||
@selection-change="handleSelectionChange">
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="55">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="Id"
|
||||
width="50"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="Name"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="Indexes"
|
||||
width="250px"
|
||||
>
|
||||
<template #default="scope" >
|
||||
<p style="white-space: pre-line" v-html="scope.row.indexes_formatted"></p>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="begin"
|
||||
label="Begin"
|
||||
width="160"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="end"
|
||||
label="End"
|
||||
width="160"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="duration_text"
|
||||
label="Duration"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="Target users"
|
||||
width="350px"
|
||||
>
|
||||
<template #default="scope" >
|
||||
<p style="white-space: pre-line" v-html="scope.row.filters_formatted"></p>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="is_discovered_text"
|
||||
label="Discovered"
|
||||
width="110"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="priority"
|
||||
label="Priority"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="status_text"
|
||||
label="Status"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="Action"
|
||||
width="120"
|
||||
>
|
||||
<template #default="scope">
|
||||
<a style="cursor: pointer; margin-right: 10px" @click="handleEdit(scope.row.id)">Edit</a>
|
||||
<el-popconfirm
|
||||
title="Confirm Delete ?"
|
||||
@confirm="handleDelete(scope.row.id)"
|
||||
>
|
||||
<template #reference>
|
||||
<a style="cursor: pointer">Delete</a>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--总数超过一页,再展示分页器-->
|
||||
<el-pagination
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
:total="total"
|
||||
:page-size="perPage"
|
||||
:current-page="currentPage"
|
||||
@current-change="changePage"
|
||||
/>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRouter } from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
import { useTable, renderTableData } from '../../utils/table'
|
||||
|
||||
export default {
|
||||
name: 'ExamTable',
|
||||
setup() {
|
||||
const multipleTable = ref(null)
|
||||
const router = useRouter()
|
||||
|
||||
const state = useTable()
|
||||
|
||||
onMounted(() => {
|
||||
console.log('ExamTable onMounted')
|
||||
fetchTableData()
|
||||
})
|
||||
const fetchTableData = async () => {
|
||||
state.loading = true
|
||||
let res = await api.listExam(state.query)
|
||||
renderTableData(res, state)
|
||||
state.loading = false
|
||||
}
|
||||
const handleAdd = () => {
|
||||
router.push({ name: 'exam-form' })
|
||||
}
|
||||
const handleEdit = (id) => {
|
||||
router.push({ path: '/exam-form', query: { id } })
|
||||
}
|
||||
const handleDelete = async (id) => {
|
||||
let res = await api.deleteExam(id)
|
||||
ElMessage.success(res.msg)
|
||||
state.query.page = 1;
|
||||
await fetchTableData()
|
||||
}
|
||||
const handleSelectionChange = (val) => {
|
||||
state.multipleSelection = val
|
||||
}
|
||||
const changePage = (val) => {
|
||||
state.query.page = val
|
||||
fetchTableData()
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
multipleTable,
|
||||
handleSelectionChange,
|
||||
handleAdd,
|
||||
handleEdit,
|
||||
handleDelete,
|
||||
fetchTableData,
|
||||
changePage,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.swiper-container {
|
||||
min-height: 100%;
|
||||
}
|
||||
.el-card.is-always-shadow {
|
||||
min-height: 100%!important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,268 +0,0 @@
|
||||
<template>
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div class="nexus-table-header">
|
||||
<div class="left">
|
||||
<el-form :inline="true" :model="query">
|
||||
<el-form-item>
|
||||
<el-popconfirm
|
||||
title="Confirm Remove ?"
|
||||
@confirm="handleDeleteBulk"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button type="default">Remove</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
<el-popconfirm
|
||||
title="Confirm Avoid ?"
|
||||
@confirm="handleAvoidBulk"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button type="default">Avoid</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</el-form-item>
|
||||
<el-form-item label="">
|
||||
<el-select v-model="query.exam_id" filterable placeholder="Exam" clearable>
|
||||
<el-option
|
||||
v-for="item in extraData.exams"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="">
|
||||
<el-select v-model="query.is_done" filterable placeholder="IsDone" clearable>
|
||||
<el-option label="Yes" value="1"></el-option>
|
||||
<el-option label="No" value="0"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="">
|
||||
<el-select v-model="query.status" filterable placeholder="Status" clearable>
|
||||
<el-option label="Avoided" value="-1"></el-option>
|
||||
<el-option label="Normal" value="0"></el-option>
|
||||
<el-option label="Finished" value="1"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="fetchTableData">Query</el-button>
|
||||
<el-button type="primary" @click="handleReset">Reset</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="right">
|
||||
<!-- <el-button type="primary" size="small" icon="el-icon-plus" @click="handleAdd">Add</el-button>-->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
ref="multipleTable"
|
||||
:data="tableData"
|
||||
tooltip-effect="dark"
|
||||
@sort-change="handleSortChange"
|
||||
@selection-change="handleSelectionChange">
|
||||
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="55">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="Id"
|
||||
width="100"
|
||||
sortable="custom"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="exam_id"
|
||||
label="Exam"
|
||||
:formatter="formatColumnExam"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="uid"
|
||||
label="User"
|
||||
:formatter="formatColumnUser"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="is_done_text"
|
||||
label="Is done"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="status_text"
|
||||
label="Status"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="created_at"
|
||||
label="Created At"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="Action"
|
||||
width="100"
|
||||
>
|
||||
<template #default="scope">
|
||||
<a style="cursor: pointer; margin-right: 10px" @click="handleDetail(scope.row.uid)">Detail</a>
|
||||
<!-- <el-popconfirm-->
|
||||
<!-- title="Confirm Delete ?"-->
|
||||
<!-- @confirm="handleDelete(scope.row.id)"-->
|
||||
<!-- >-->
|
||||
<!-- <template #reference>-->
|
||||
<!-- <a style="cursor: pointer">Delete</a>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-popconfirm>-->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--总数超过一页,再展示分页器-->
|
||||
<el-pagination
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
:total="total"
|
||||
:page-size="perPage"
|
||||
:current-page="currentPage"
|
||||
@current-change="changePage"
|
||||
/>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRouter } from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
import { useTable, renderTableData, resetTableSort } from '../../utils/table'
|
||||
|
||||
export default {
|
||||
name: 'ExamUserTable',
|
||||
setup() {
|
||||
const multipleTable = ref(null)
|
||||
const router = useRouter()
|
||||
|
||||
const state = useTable()
|
||||
|
||||
let extraData = reactive({
|
||||
exams: []
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
api.listExamAll().then(res => {
|
||||
extraData.exams = res.data
|
||||
})
|
||||
fetchTableData()
|
||||
})
|
||||
const fetchTableData = async () => {
|
||||
state.loading = true
|
||||
let res = await api.listExamUser(state.query)
|
||||
renderTableData(res, state)
|
||||
state.loading = false
|
||||
}
|
||||
const handleAdd = () => {
|
||||
router.push({ name: 'user-form' })
|
||||
}
|
||||
const handleEdit = (id) => {
|
||||
router.push({ name: 'user-form', query: { id } })
|
||||
}
|
||||
const handleDelete = async (id) => {
|
||||
let res = await api.deleteExam(id)
|
||||
ElMessage.success(res.msg)
|
||||
state.query.page = 1;
|
||||
await fetchTableData()
|
||||
}
|
||||
const handleAvoidBulk = async () => {
|
||||
let ids = state.multipleSelection.map(item => item.id)
|
||||
if (ids.length == 0) {
|
||||
ElMessage.error("No data selected !")
|
||||
return
|
||||
}
|
||||
console.log(ids)
|
||||
let res = await api.avoidExamUserBulk({id: ids})
|
||||
ElMessage.success(res.msg)
|
||||
state.query.page = 1;
|
||||
await fetchTableData()
|
||||
}
|
||||
const handleDeleteBulk = async () => {
|
||||
let ids = state.multipleSelection.map(item => item.id)
|
||||
if (ids.length == 0) {
|
||||
ElMessage.error("No data selected !")
|
||||
return
|
||||
}
|
||||
console.log(ids)
|
||||
let res = await api.deleteExamUserBulk({id: ids})
|
||||
ElMessage.success(res.msg)
|
||||
state.query.page = 1;
|
||||
await fetchTableData()
|
||||
}
|
||||
// 选择项
|
||||
const handleSelectionChange = (val) => {
|
||||
state.multipleSelection = val
|
||||
}
|
||||
const changePage = (val) => {
|
||||
state.query.page = val
|
||||
fetchTableData()
|
||||
}
|
||||
const handleSortChange = (val) => {
|
||||
resetTableSort(val, state)
|
||||
fetchTableData()
|
||||
}
|
||||
const handleDetail = (id) => {
|
||||
router.push({
|
||||
name: 'user-detail',
|
||||
query: {id: id}
|
||||
})
|
||||
}
|
||||
|
||||
const formatColumnUser = (row, column) => {
|
||||
return row.user.username
|
||||
}
|
||||
|
||||
const formatColumnExam = (row, column) => {
|
||||
return row.exam.name
|
||||
}
|
||||
const formatColumnDownloaded = (row, column) => {
|
||||
return row.downloaded_text
|
||||
}
|
||||
|
||||
const handleReset = () => {
|
||||
state.query.is_done = '';
|
||||
state.query.status = '';
|
||||
state.query.exam_id = '';
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
multipleTable,
|
||||
extraData,
|
||||
handleSelectionChange,
|
||||
handleAdd,
|
||||
handleEdit,
|
||||
handleDelete,
|
||||
handleDetail,
|
||||
handleAvoidBulk,
|
||||
handleDeleteBulk,
|
||||
fetchTableData,
|
||||
changePage,
|
||||
handleSortChange,
|
||||
formatColumnUser,
|
||||
formatColumnExam,
|
||||
formatColumnDownloaded,
|
||||
handleReset
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.nexus-table-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
||||
@@ -1,198 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<el-col :span="12" v-loading="loading">
|
||||
<el-card class="box-card">
|
||||
<table class="table-base-info">
|
||||
<tr>
|
||||
<td>ID</td>
|
||||
<td>{{formData.id}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Status</td>
|
||||
<td>{{formData.status_text}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>UID</td>
|
||||
<td>{{formData.uid}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Username</td>
|
||||
<td>{{formData.user && formData.user.username}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Torrent ID</td>
|
||||
<td>{{formData.torrent && formData.torrent.id}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Torrent name</td>
|
||||
<td>{{formData.torrent && formData.torrent.name}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Uploaded</td>
|
||||
<td>{{formData.snatch && formData.snatch.upload_text}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Downloaded</td>
|
||||
<td>{{formData.snatch && formData.snatch.download_text}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Share ratio</td>
|
||||
<td>{{formData.snatch && formData.snatch.share_ratio}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Seed time required</td>
|
||||
<td>{{formData.seed_time_required}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Inspect time left</td>
|
||||
<td>{{formData.inspect_time_left}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Comment</td>
|
||||
<td v-html="formData.comment"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Created at</td>
|
||||
<td>{{formData.created_at}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Updated at</td>
|
||||
<td>{{formData.updated_at}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<el-divider></el-divider>
|
||||
<div style="text-align: center">
|
||||
<el-popconfirm
|
||||
title="Confirm Remove ?"
|
||||
@confirm="handleDelete(formData.id)"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button type="danger">Remove</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
<el-popconfirm
|
||||
title="Confirm Pardon ?"
|
||||
@confirm="handlePardon(formData.id)"
|
||||
v-if="[1,3].includes(formData.status)"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button type="primary">Pardon</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import { reactive, ref, toRefs, onMounted, onBeforeUnmount, getCurrentInstance } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { localGet } from '../../utils'
|
||||
import api from "../../utils/api";
|
||||
|
||||
export default {
|
||||
name: 'HrDetail',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance()
|
||||
console.log('proxy', proxy)
|
||||
const formRef = ref(null)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { id } = route.query
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
id: id,
|
||||
agentAllows: [],
|
||||
formData: {
|
||||
|
||||
},
|
||||
rules: {
|
||||
family_id: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
name: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
peer_id: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
agent: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
},
|
||||
})
|
||||
onMounted( async () => {
|
||||
if (id) {
|
||||
await fetchPageData()
|
||||
}
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
|
||||
})
|
||||
const submitAdd = () => {
|
||||
formRef.value.validate(async (vaild) => {
|
||||
if (vaild) {
|
||||
let params = state.formData;
|
||||
console.log(params)
|
||||
if (id) {
|
||||
await api.updateAgentDeny(id, params)
|
||||
} else {
|
||||
await api.storeAgentDeny(params)
|
||||
}
|
||||
await router.push({name: 'agent-deny'})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const fetchPageData = async () => {
|
||||
state.loading = true;
|
||||
let res = await api.getHr(id)
|
||||
state.loading = false
|
||||
state.formData = res.data
|
||||
}
|
||||
|
||||
const getAgentAllow = async (id) => {
|
||||
let res = await api.getAgentAllow(id)
|
||||
console.log(res)
|
||||
}
|
||||
|
||||
const handleDelete = async (id) => {
|
||||
let res = await api.deleteHr(id)
|
||||
ElMessage.success(res.msg)
|
||||
await router.push({name: 'hr'})
|
||||
}
|
||||
|
||||
const handlePardon = async (id) => {
|
||||
let res = await api.pardonHr(id)
|
||||
ElMessage.success(res.msg)
|
||||
await fetchPageData()
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
formRef,
|
||||
submitAdd,
|
||||
handleDelete,
|
||||
handlePardon
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.table-base-info {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
tr {
|
||||
td {
|
||||
padding: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,289 +0,0 @@
|
||||
<template>
|
||||
<el-card class="">
|
||||
<template #header>
|
||||
<div class="nexus-table-header">
|
||||
<div class="left">
|
||||
<el-form :inline="true" :model="query">
|
||||
<el-form-item>
|
||||
<el-popconfirm
|
||||
title="Confirm Remove ?"
|
||||
@confirm="handleDeleteBulk"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button type="default">Remove</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
<el-popconfirm
|
||||
title="Confirm Pardon ?"
|
||||
@confirm="handlePardonBulk"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button type="default">Pardon</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="">
|
||||
<el-select v-model="query.status" filterable placeholder="Status">
|
||||
<el-option
|
||||
v-for="(item) in extraData.status"
|
||||
:key="item.status"
|
||||
:label="item.text"
|
||||
:value="item.status"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="">
|
||||
<el-input placeholder="UID" v-model="query.uid"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="">
|
||||
<el-input placeholder="Username" v-model="query.username"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="">
|
||||
<el-input placeholder="Torrent ID" v-model="query.torrent_id"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="fetchTableData">Query</el-button>
|
||||
<el-button type="primary" @click="handleReset">Reset</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<!-- <div class="right">-->
|
||||
<!-- <el-button type="primary" icon="Plus" @click="handleAdd">Add</el-button>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
</template>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
ref="multipleTable"
|
||||
:data="tableData"
|
||||
tooltip-effect="dark"
|
||||
@selection-change="handleSelectionChange">
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="55">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="Id"
|
||||
width="100"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop=""
|
||||
label="Username"
|
||||
width="120"
|
||||
:formatter="formatColumnUsername"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop=""
|
||||
label="Torrent"
|
||||
>
|
||||
<template #default="scope">
|
||||
<a class="text-one-line" :title="scope.row.torrent.name" :href="scope.row.torrent.details_url" target="_blank">{{scope.row.torrent.name}}</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop=""
|
||||
label="Uploaded"
|
||||
width="200"
|
||||
:formatter="formatColumnUploaded"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop=""
|
||||
label="Downloaded"
|
||||
width="200"
|
||||
:formatter="formatColumnDownloaded"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop=""
|
||||
label="Share ratio"
|
||||
width="120"
|
||||
:formatter="formatColumnShareRatio"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="seed_time_required"
|
||||
label="Seed time required"
|
||||
width="160"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="inspect_time_left"
|
||||
label="Inspect time left"
|
||||
width="160"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="status_text"
|
||||
label="Status"
|
||||
width="70"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="Action"
|
||||
width="120"
|
||||
>
|
||||
<template #default="scope">
|
||||
<a style="cursor: pointer; margin-right: 10px" @click="handleDetail(scope.row.id)">Detail</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--总数超过一页,再展示分页器-->
|
||||
<el-pagination
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
:total="total"
|
||||
:page-size="perPage"
|
||||
:current-page="currentPage"
|
||||
@current-change="changePage"
|
||||
/>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRouter } from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
import { useTable, renderTableData } from '../../utils/table'
|
||||
|
||||
export default {
|
||||
name: 'HrTable',
|
||||
setup() {
|
||||
const multipleTable = ref(null)
|
||||
const router = useRouter()
|
||||
|
||||
const state = useTable()
|
||||
let extraData = reactive({
|
||||
status: []
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
console.log('MedalTable onMounted')
|
||||
listHrStatus()
|
||||
fetchTableData()
|
||||
})
|
||||
const fetchTableData = async () => {
|
||||
state.loading = true
|
||||
let res = await api.listHr(state.query)
|
||||
renderTableData(res, state)
|
||||
state.loading = false
|
||||
}
|
||||
const handlePardon = () => {
|
||||
router.push({ name: 'agent-deny-form' })
|
||||
}
|
||||
const handlePardonBulk = async () => {
|
||||
let ids = state.multipleSelection.map(item => item.id)
|
||||
if (ids.length == 0) {
|
||||
ElMessage.error("No data selected !")
|
||||
return
|
||||
}
|
||||
console.log(ids)
|
||||
let res = await api.pardonHrBulk({id: ids})
|
||||
ElMessage.success(res.msg)
|
||||
state.query.page = 1;
|
||||
await fetchTableData()
|
||||
}
|
||||
const handleDetail = (id) => {
|
||||
router.push({ path: '/hr-detail', query: { id } })
|
||||
}
|
||||
const handleDelete = async (id) => {
|
||||
let res = await api.deleteHr(id)
|
||||
ElMessage.success(res.msg)
|
||||
state.query.page = 1;
|
||||
await fetchTableData()
|
||||
}
|
||||
const handleDeleteBulk = async () => {
|
||||
let ids = state.multipleSelection.map(item => item.id)
|
||||
if (ids.length == 0) {
|
||||
ElMessage.error("No data selected !")
|
||||
return
|
||||
}
|
||||
console.log(ids)
|
||||
let res = await api.deleteHrBulk({id: ids})
|
||||
ElMessage.success(res.msg)
|
||||
state.query.page = 1;
|
||||
await fetchTableData()
|
||||
}
|
||||
const handleSelectionChange = (val) => {
|
||||
state.multipleSelection = val
|
||||
}
|
||||
const changePage = (val) => {
|
||||
state.query.page = val
|
||||
fetchTableData()
|
||||
}
|
||||
|
||||
const listHrStatus = async () => {
|
||||
let res = await api.listHrStatus()
|
||||
extraData.status = res.data
|
||||
}
|
||||
|
||||
const handleReset = () => {
|
||||
state.query.status = '';
|
||||
state.query.uid = '';
|
||||
state.query.username = '';
|
||||
state.query.torrent_id = '';
|
||||
}
|
||||
|
||||
const formatColumnUsername = (row, column) => {
|
||||
return row.user.username
|
||||
}
|
||||
|
||||
const formatColumnTorrent = (row, column) => {
|
||||
return '<a href="" target="_blank">' + row.torrent.name + '</a>'
|
||||
}
|
||||
|
||||
const formatColumnUploaded = (row, column) => {
|
||||
return row.snatch.upload_text
|
||||
}
|
||||
|
||||
const formatColumnDownloaded = (row, column) => {
|
||||
return row.snatch.download_text
|
||||
}
|
||||
|
||||
const formatColumnShareRatio = (row, column) => {
|
||||
return row.snatch.share_ratio
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
extraData,
|
||||
multipleTable,
|
||||
handleSelectionChange,
|
||||
handlePardon,
|
||||
handleDetail,
|
||||
handleDelete,
|
||||
handlePardonBulk,
|
||||
handleDeleteBulk,
|
||||
fetchTableData,
|
||||
changePage,
|
||||
handleReset,
|
||||
formatColumnUsername,
|
||||
formatColumnTorrent,
|
||||
formatColumnUploaded,
|
||||
formatColumnDownloaded,
|
||||
formatColumnShareRatio,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.swiper-container {
|
||||
min-height: 100%;
|
||||
}
|
||||
.el-card.is-always-shadow {
|
||||
min-height: 100%!important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,131 +0,0 @@
|
||||
<template>
|
||||
<div class="login-body">
|
||||
<div class="login-container">
|
||||
<div class="head">
|
||||
<img class="logo" src="../assets/logo.png" />
|
||||
<div class="name">
|
||||
<div class="title">NexusPHP</div>
|
||||
<div class="tips">Management system</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-form label-position="top" :rules="rules" :model="ruleForm" ref="loginForm" class="login-form">
|
||||
<el-form-item label="Username" prop="username">
|
||||
<el-input type="text" v-model.trim="ruleForm.username" autocomplete="off" @keyup.enter="submitForm"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Password" prop="password">
|
||||
<el-input type="password" v-model.trim="ruleForm.password" autocomplete="off" @keyup.enter="submitForm"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-top: 50px">
|
||||
<!-- <div style="color: #333">登录表示您已同意<a>《服务条款》</a></div>-->
|
||||
<el-button style="width: 100%" type="primary" @click="submitForm">Submit</el-button>
|
||||
<!-- <el-checkbox v-model="checked" @change="!checked">下次自动登录</el-checkbox>-->
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from '../utils/axios'
|
||||
import { reactive, ref, toRefs } from 'vue'
|
||||
import { localSet } from '../utils'
|
||||
import api from '../utils/api'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
|
||||
export default {
|
||||
name: 'Login',
|
||||
setup() {
|
||||
const loginForm = ref(null)
|
||||
const router = useRouter()
|
||||
const state = reactive({
|
||||
ruleForm: {
|
||||
username: '',
|
||||
password: ''
|
||||
},
|
||||
checked: true,
|
||||
rules: {
|
||||
username: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
password: [
|
||||
{ required: 'true', }
|
||||
]
|
||||
}
|
||||
})
|
||||
const submitForm = async () => {
|
||||
loginForm.value.validate((valid) => {
|
||||
if (valid) {
|
||||
api.login(state.ruleForm).then(res => {
|
||||
console.log(res)
|
||||
localSet('token', res.data.token)
|
||||
localSet('userInfo', res.data)
|
||||
router.push({name: 'dashboard'})
|
||||
})
|
||||
} else {
|
||||
console.log('error submit!!')
|
||||
return false;
|
||||
}
|
||||
})
|
||||
}
|
||||
const resetForm = () => {
|
||||
loginForm.value.resetFields();
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
loginForm,
|
||||
submitForm,
|
||||
resetForm
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.login-body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
/* background-image: linear-gradient(25deg, #077f7c, #3aa693, #5ecfaa, #7ffac2); */
|
||||
}
|
||||
.login-container {
|
||||
width: 420px;
|
||||
height: 500px;
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0px 21px 41px 0px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.head {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 40px 0 20px 0;
|
||||
}
|
||||
.head img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.head .title {
|
||||
font-size: 28px;
|
||||
color: #1BAEAE;
|
||||
font-weight: bold;
|
||||
}
|
||||
.head .tips {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
.login-form {
|
||||
width: 70%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.el-form--label-top .el-form-item__label {
|
||||
padding: 0;
|
||||
}
|
||||
.login-form .el-form-item {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,162 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form :model="formData" :rules="rules" ref="formRef" label-width="200px" class="formData">
|
||||
<el-form-item label="Name" prop="name">
|
||||
<el-input v-model="formData.name" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Price" prop="price">
|
||||
<el-input v-model="formData.price" placeholder="Seed bonus"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Get type" prop="get_type">
|
||||
<el-radio-group v-model="formData.get_type">
|
||||
<el-radio :label="1">Exchange</el-radio>
|
||||
<el-radio :label="2">Grant</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="Image large" prop="image_large">
|
||||
<el-input v-model="formData.image_large" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Image small" prop="image_small">
|
||||
<el-input v-model="formData.image_small" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Duration" prop="duration">
|
||||
<el-input v-model="formData.duration" placeholder="Unit: day, if empty, it's valid forever"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Description" prop="description">
|
||||
<el-input type="textarea" v-model="formData.description" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submitAdd()">Submit</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { reactive, ref, toRefs, onMounted, onBeforeUnmount, getCurrentInstance } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { localGet } from '../../utils'
|
||||
import api from "../../utils/api";
|
||||
|
||||
export default {
|
||||
name: 'MedalForm',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance()
|
||||
console.log('proxy', proxy)
|
||||
const formRef = ref(null)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { id } = route.query
|
||||
const state = reactive({
|
||||
token: localGet('token') || '',
|
||||
id: id,
|
||||
allClasses: [],
|
||||
formData: {
|
||||
name: '',
|
||||
description: '',
|
||||
image_large: '',
|
||||
image_small: '',
|
||||
duration: '',
|
||||
price: '',
|
||||
get_type: ''
|
||||
},
|
||||
rules: {
|
||||
name: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
price: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
image_large: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
image_small: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
description: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
get_type: [
|
||||
{required: 'true'}
|
||||
]
|
||||
},
|
||||
})
|
||||
onMounted( async () => {
|
||||
if (id) {
|
||||
api.getMedal(id).then(res => {
|
||||
state.formData.name = res.data.name
|
||||
state.formData.image_large = res.data.image_large
|
||||
state.formData.image_small = res.data.image_small
|
||||
state.formData.description = res.data.description
|
||||
state.formData.price = res.data.price
|
||||
state.formData.duration = res.data.duration
|
||||
state.formData.get_type = res.data.get_type
|
||||
})
|
||||
}
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
|
||||
})
|
||||
const submitAdd = () => {
|
||||
formRef.value.validate(async (vaild) => {
|
||||
if (vaild) {
|
||||
let params = state.formData;
|
||||
console.log(params)
|
||||
if (id) {
|
||||
await api.updateMedal(id, params)
|
||||
} else {
|
||||
await api.storeMedal(params)
|
||||
}
|
||||
await router.push({name: 'medal'})
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleBeforeUpload = (file) => {
|
||||
const sufix = file.name.split('.')[1] || ''
|
||||
if (!['jpg', 'jpeg', 'png'].includes(sufix)) {
|
||||
ElMessage.error('请上传 jpg、jpeg、png 格式的图片')
|
||||
return false
|
||||
}
|
||||
}
|
||||
const handleUrlSuccess = (val) => {
|
||||
state.formData.goodsCoverImg = val.data || ''
|
||||
}
|
||||
const handleChangeCate = (val) => {
|
||||
state.categoryId = val[2] || 0
|
||||
}
|
||||
|
||||
const listAllClass = async () => {
|
||||
let res = await api.listClass()
|
||||
state.allClasses = res.data
|
||||
}
|
||||
const listAllIndex = async () => {
|
||||
let res = await api.listMedalIndex()
|
||||
state.formData.indexes = res.data
|
||||
}
|
||||
const getMedal = async (id) => {
|
||||
let res = await api.getMedal(id)
|
||||
console.log(res)
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
formRef,
|
||||
submitAdd,
|
||||
handleBeforeUpload,
|
||||
handleUrlSuccess,
|
||||
handleChangeCate,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,159 +0,0 @@
|
||||
<template>
|
||||
<el-card class="">
|
||||
<template #header>
|
||||
<div class="nexus-table-header">
|
||||
<div class="left">
|
||||
|
||||
</div>
|
||||
<div class="right">
|
||||
<el-button type="primary" icon="Plus" @click="handleAdd">Add</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
ref="multipleTable"
|
||||
:data="tableData"
|
||||
tooltip-effect="dark"
|
||||
@selection-change="handleSelectionChange">
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="55">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="Id"
|
||||
width="50"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="Name"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="image_large"
|
||||
label="Large image"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-image :src="scope.row.image_large" style="max-height: 200px" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="image_small"
|
||||
label="Small image"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-image :src="scope.row.image_small" style="max-height: 200px" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="get_type_text"
|
||||
label="Get type"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="price"
|
||||
label="Price(bonus)"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="duration"
|
||||
label="Duration(day)"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="Action"
|
||||
width=""
|
||||
>
|
||||
<template #default="scope">
|
||||
<a style="cursor: pointer; margin-right: 10px" @click="handleEdit(scope.row.id)">Edit</a>
|
||||
<el-popconfirm
|
||||
title="Confirm Delete ?"
|
||||
@confirm="handleDelete(scope.row.id)"
|
||||
>
|
||||
<template #reference>
|
||||
<a style="cursor: pointer">Delete</a>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--总数超过一页,再展示分页器-->
|
||||
<el-pagination
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
:total="total"
|
||||
:page-size="perPage"
|
||||
:current-page="currentPage"
|
||||
@current-change="changePage"
|
||||
/>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRouter } from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
import { useTable, renderTableData } from '../../utils/table'
|
||||
|
||||
export default {
|
||||
name: 'MedalTable',
|
||||
setup() {
|
||||
const multipleTable = ref(null)
|
||||
const router = useRouter()
|
||||
|
||||
const state = useTable()
|
||||
|
||||
onMounted(() => {
|
||||
console.log('MedalTable onMounted')
|
||||
fetchTableData()
|
||||
})
|
||||
const fetchTableData = async () => {
|
||||
state.loading = true
|
||||
let res = await api.listMedal(state.query)
|
||||
renderTableData(res, state)
|
||||
state.loading = false
|
||||
}
|
||||
const handleAdd = () => {
|
||||
router.push({ name: 'medal-form' })
|
||||
}
|
||||
const handleEdit = (id) => {
|
||||
router.push({ path: '/medal-form', query: { id } })
|
||||
}
|
||||
const handleDelete = async (id) => {
|
||||
let res = await api.deleteMedal(id)
|
||||
ElMessage.success(res.msg)
|
||||
state.query.page = 1;
|
||||
await fetchTableData()
|
||||
}
|
||||
const handleSelectionChange = (val) => {
|
||||
state.multipleSelection = val
|
||||
}
|
||||
const changePage = (val) => {
|
||||
state.query.page = val
|
||||
fetchTableData()
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
multipleTable,
|
||||
handleSelectionChange,
|
||||
handleAdd,
|
||||
handleEdit,
|
||||
handleDelete,
|
||||
fetchTableData,
|
||||
changePage,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.swiper-container {
|
||||
min-height: 100%;
|
||||
}
|
||||
.el-card.is-always-shadow {
|
||||
min-height: 100%!important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,179 +0,0 @@
|
||||
<template>
|
||||
<el-form :model="formData" :rules="rules" ref="formRef" label-width="250px" class="formData" size="mini" :v-loading="loading">
|
||||
<el-form-item label="Enabled" prop="backup.enabled">
|
||||
<el-radio v-model="formData.backup.enabled" label="yes">Yes</el-radio>
|
||||
<el-radio v-model="formData.backup.enabled" label="no">No</el-radio>
|
||||
<div class="nexus-help-text">
|
||||
Enable backup or not.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Frequency" prop="backup.frequency">
|
||||
<el-radio v-model="formData.backup.frequency" label="daily">Daily</el-radio>
|
||||
<el-radio v-model="formData.backup.frequency" label="hourly">Hourly</el-radio>
|
||||
<div class="nexus-help-text">
|
||||
Backup Frequency.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Hour" prop="backup.hour">
|
||||
<el-select v-model="formData.backup.hour" filterable >
|
||||
<el-option
|
||||
v-for="item in 24"
|
||||
:key="item"
|
||||
:label="item-1"
|
||||
:value="item-1">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<div class="nexus-help-text">
|
||||
Do backup at this hour.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Minute" prop="backup.minute">
|
||||
<el-select v-model="formData.backup.minute" filterable >
|
||||
<el-option
|
||||
v-for="item in 60"
|
||||
:key="item"
|
||||
:label="item-1"
|
||||
:value="item-1">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<div class="nexus-help-text">
|
||||
Do backup at this minute, If frequency = 'hourly', this value will be ignore.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Google drive client ID" prop="backup.google_drive_client_id">
|
||||
<el-input v-model="formData.backup.google_drive_client_id" label="Google drive client ID"></el-input>
|
||||
<div class="nexus-help-text">
|
||||
Google drive client ID.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Google drive client secret" prop="backup.google_drive_client_secret">
|
||||
<el-input v-model="formData.backup.google_drive_client_secret" label="Google drive client secret"></el-input>
|
||||
<div class="nexus-help-text">
|
||||
Google drive client secret.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Google drive refresh token" prop="backup.google_drive_refresh_token">
|
||||
<el-input v-model="formData.backup.google_drive_refresh_token" label="Google drive refresh token"></el-input>
|
||||
<div class="nexus-help-text">
|
||||
Google drive refresh token.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Google drive folder ID" prop="backup.google_drive_folder_id">
|
||||
<el-input v-model="formData.backup.google_drive_folder_id" label="Google drive folder ID"></el-input>
|
||||
<div class="nexus-help-text">
|
||||
Google drive folder ID. If not set, will store in root.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Via ftp" prop="backup.via_ftp">
|
||||
<el-radio v-model="formData.backup.via_ftp" label="yes">Yes</el-radio>
|
||||
<el-radio v-model="formData.backup.via_ftp" label="no">No</el-radio>
|
||||
<div class="nexus-help-text">
|
||||
Via ftp or not. If yes, add configuration to .env, refer to <a href="https://laravel.com/docs/master/filesystem#ftp-driver-configuration">Laravel doc.</a>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Via sftp" prop="backup.via_sftp">
|
||||
<el-radio v-model="formData.backup.via_sftp" label="yes">Yes</el-radio>
|
||||
<el-radio v-model="formData.backup.via_sftp" label="no">No</el-radio>
|
||||
<div class="nexus-help-text">
|
||||
Via sftp or not. If yes, add configuration to .env, refer to <a href="https://laravel.com/docs/master/filesystem#sftp-driver-configuration">Laravel doc.</a>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submitAdd()">Submit</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { reactive, ref, toRefs, onMounted, onBeforeUnmount, getCurrentInstance } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { localGet } from '../../utils'
|
||||
import api from "../../utils/api";
|
||||
|
||||
export default {
|
||||
name: 'SettingFormBasic',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance()
|
||||
const formRef = ref(null)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { id } = route.query
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
token: localGet('token') || '',
|
||||
id: id,
|
||||
allClasses: [],
|
||||
formData: {
|
||||
backup: {
|
||||
enabled: '',
|
||||
frequency: '',
|
||||
hour: '',
|
||||
minute: '',
|
||||
google_drive_client_id: '',
|
||||
google_drive_client_secret: '',
|
||||
google_drive_refresh_token: '',
|
||||
google_drive_folder_id: '',
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
'backup.enabled': [{ required: 'true', }],
|
||||
},
|
||||
})
|
||||
|
||||
onMounted( () => {
|
||||
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
|
||||
})
|
||||
const submitAdd = () => {
|
||||
formRef.value.validate(async (vaild) => {
|
||||
if (vaild) {
|
||||
let params = state.formData;
|
||||
console.log(params)
|
||||
let res = await api.storeSetting(params)
|
||||
ElMessage.success(res.msg)
|
||||
await listSetting();
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleBeforeUpload = (file) => {
|
||||
const sufix = file.name.split('.')[1] || ''
|
||||
if (!['jpg', 'jpeg', 'png'].includes(sufix)) {
|
||||
ElMessage.error('请上传 jpg、jpeg、png 格式的图片')
|
||||
return false
|
||||
}
|
||||
}
|
||||
const listSetting = async () => {
|
||||
//not work....
|
||||
state.loading = true
|
||||
let res = await api.listSetting({prefix: "backup"})
|
||||
console.log("listSetting", res)
|
||||
state.formData = res.data
|
||||
state.loading = false
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
formRef,
|
||||
submitAdd,
|
||||
handleBeforeUpload,
|
||||
listSetting,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,127 +0,0 @@
|
||||
<template>
|
||||
<el-form :model="formData" :rules="rules" ref="formRef" label-width="200px" class="formData">
|
||||
<el-form-item label="Site Name" prop="basic.SITENAME">
|
||||
<el-input v-model="formData.basic.SITENAME" placeholder=""></el-input>
|
||||
<div class="nexus-help-text">
|
||||
Website name
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submitAdd()">Submit</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { reactive, ref, toRefs, onMounted, onBeforeUnmount, getCurrentInstance } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { localGet } from '../../utils'
|
||||
import api from "../../utils/api";
|
||||
|
||||
export default {
|
||||
name: 'SettingFormBasic',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance()
|
||||
const formRef = ref(null)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { id } = route.query
|
||||
const state = reactive({
|
||||
token: localGet('token') || '',
|
||||
id: id,
|
||||
allClasses: [],
|
||||
formData: {
|
||||
basic: {
|
||||
SITENAME: ''
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
'basic.name': [
|
||||
{ required: 'true', }
|
||||
],
|
||||
},
|
||||
})
|
||||
onMounted( () => {
|
||||
if (id) {
|
||||
api.getExam(id).then(res => {
|
||||
state.formData.name = res.data.name
|
||||
state.formData.description = res.data.description
|
||||
state.formData.begin = res.data.begin
|
||||
state.formData.end = res.data.end
|
||||
state.formData.duration = res.data.duration
|
||||
state.formData.indexes = res.data.indexes
|
||||
state.formData.filters = res.data.filters
|
||||
state.formData.status = res.data.status
|
||||
state.formData.is_discovered = res.data.is_discovered
|
||||
})
|
||||
} else {
|
||||
let res = api.listExamIndex()
|
||||
state.formData.indexes = res.data
|
||||
}
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
|
||||
})
|
||||
const submitAdd = () => {
|
||||
formRef.value.validate(async (vaild) => {
|
||||
if (vaild) {
|
||||
let params = state.formData;
|
||||
if (params.begin) {
|
||||
params.begin = dayjs(params.begin).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
if (params.end) {
|
||||
params.end = dayjs(params.end).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
console.log(params)
|
||||
if (id) {
|
||||
await api.updateExam(id, params)
|
||||
} else {
|
||||
await api.storeExam(params)
|
||||
}
|
||||
await router.push({name: 'exam'})
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleBeforeUpload = (file) => {
|
||||
const sufix = file.name.split('.')[1] || ''
|
||||
if (!['jpg', 'jpeg', 'png'].includes(sufix)) {
|
||||
ElMessage.error('请上传 jpg、jpeg、png 格式的图片')
|
||||
return false
|
||||
}
|
||||
}
|
||||
const handleUrlSuccess = (val) => {
|
||||
state.formData.goodsCoverImg = val.data || ''
|
||||
}
|
||||
const handleChangeCate = (val) => {
|
||||
state.categoryId = val[2] || 0
|
||||
}
|
||||
|
||||
const listAllClass = async () => {
|
||||
let res = await api.listClass()
|
||||
state.allClasses = res.data
|
||||
}
|
||||
const listAllIndex = async () => {
|
||||
let res = await api.listExamIndex()
|
||||
state.formData.indexes = res.data
|
||||
}
|
||||
const getExam = async (id) => {
|
||||
let res = await api.getExam(id)
|
||||
console.log(res)
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
formRef,
|
||||
submitAdd,
|
||||
handleBeforeUpload,
|
||||
handleUrlSuccess,
|
||||
handleChangeCate,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,112 +0,0 @@
|
||||
<template>
|
||||
<el-form :model="formData" :rules="rules" ref="formRef" label-width="250px" class="formData" size="mini">
|
||||
<el-form-item label="Mode" prop="hr.mode">
|
||||
<el-radio v-model="formData.hr.mode" label="disabled">Disabled</el-radio>
|
||||
<el-radio v-model="formData.hr.mode" label="manual">Manual</el-radio>
|
||||
<el-radio v-model="formData.hr.mode" label="global">Global</el-radio>
|
||||
<div class="nexus-help-text">
|
||||
Set H&R mode.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Inspect time" prop="hr.inspect_time">
|
||||
<el-input v-model="formData.hr.inspect_time" type="number"></el-input>
|
||||
<div class="nexus-help-text">
|
||||
Inspect time duration after download complete(Unit: Hour).
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Seed time minimum" prop="hr.seed_time_minimum">
|
||||
<el-input v-model="formData.hr.seed_time_minimum" type="number"></el-input>
|
||||
<div class="nexus-help-text">
|
||||
Seed time minimum (Unit: Hour, must be less than Inspect time).
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Ignore" prop="hr.ignore_when_ratio_reach">
|
||||
<el-input v-model="formData.hr.ignore_when_ratio_reach" type="number"></el-input>
|
||||
<div class="nexus-help-text">
|
||||
When ratio reach this value, this H&R will be ignored.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Disable user" prop="hr.disable_user_when_counts_reach">
|
||||
<el-input v-model="formData.hr.ban_user_when_counts_reach"></el-input>
|
||||
<div class="nexus-help-text">
|
||||
When total H&R counts reach this value, user account will be disabled.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submitAdd()">Submit</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { reactive, ref, toRefs, onMounted, onBeforeUnmount, getCurrentInstance } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { localGet } from '../../utils'
|
||||
import api from "../../utils/api";
|
||||
|
||||
export default {
|
||||
name: 'SettingFormHR',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance()
|
||||
const formRef = ref(null)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { id } = route.query
|
||||
const state = reactive({
|
||||
token: localGet('token') || '',
|
||||
id: id,
|
||||
allClasses: [],
|
||||
formData: {
|
||||
hr: {
|
||||
mode: '',
|
||||
inspect_time: '',
|
||||
seed_time_minimum: '',
|
||||
ignore_when_ratio_reach: '',
|
||||
ban_user_when_counts_reach: '',
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
'hr.enabled': [{ required: 'true', }],
|
||||
},
|
||||
})
|
||||
onMounted( () => {
|
||||
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
|
||||
})
|
||||
const submitAdd = () => {
|
||||
formRef.value.validate(async (vaild) => {
|
||||
if (vaild) {
|
||||
let params = state.formData;
|
||||
console.log(params)
|
||||
let res = await api.storeSetting(params)
|
||||
ElMessage.success(res.msg)
|
||||
await listSetting();
|
||||
}
|
||||
})
|
||||
}
|
||||
const listSetting = async () => {
|
||||
let res = await api.listSetting({prefix: "hr"})
|
||||
console.log("listSetting", res)
|
||||
state.formData = res.data
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
formRef,
|
||||
submitAdd,
|
||||
listSetting,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,418 +0,0 @@
|
||||
<template>
|
||||
<el-form :model="formData" :rules="rules" ref="formRef" label-width="250px" class="formData">
|
||||
<el-form-item label="Site online" prop="main.site_online">
|
||||
<el-radio-group v-model="formData.main.site_online">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'yes'. Want to turn off your site while performing updates or other types of maintenance? Please Note: Administrators will still be able to see the site.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Enable invite system" prop="main.invitesystem">
|
||||
<el-radio-group v-model="formData.main.invitesystem">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'yes'. Allow Registrations via Invite System.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Initial uploading amount" prop="main.iniupload">
|
||||
<el-input v-model="formData.main.iniupload" placeholder="" type="number"></el-input>
|
||||
<div class="nexus-help-text">
|
||||
How many uploading credit (in Byte, i.e. 1073741824 = 1GB) should each user be given upon registration? Default '0'.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Initial number of invites" prop="main.invite_count">
|
||||
<el-input v-model="formData.main.invite_count" placeholder="" type="number"></el-input>
|
||||
<div class="nexus-help-text">
|
||||
How many invites should each user be given upon registration? Default '0'.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Invite timeout" prop="main.invite_timeout">
|
||||
<el-input v-model="formData.main.invite_timeout" placeholder="" type="number"></el-input>
|
||||
<div class="nexus-help-text">
|
||||
In days. Delete invite code after X days who didn't respond the invite request. Default '7'.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Enable registration system" prop="main.registration">
|
||||
<el-radio-group v-model="formData.main.registration">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Allow open registrations. Default 'yes'.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Verification type" prop="main.verification">
|
||||
<el-radio-group v-model="formData.main.verification">
|
||||
<el-radio label="email">Email</el-radio>
|
||||
<el-radio label="admin">Admin</el-radio>
|
||||
<el-radio label="automatic">Automatically</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
EMAIL: Sent confirmation email. ADMIN: Manual activate. AUTOMATIC: Activate user after registration.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Enable wait system" prop="main.waitsystem">
|
||||
<el-radio-group v-model="formData.main.waitsystem">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Enable or disable wait system (see FAQ).
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Enable max slots system" prop="main.maxdlsystemyes">
|
||||
<el-radio-group v-model="formData.main.maxdlsystemyes">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'no'. Enable or disable maximum concurrent downloads (AKA Max Slots) (see FAQ).
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Show polls" prop="main.showpolls">
|
||||
<el-radio-group v-model="formData.main.showpolls">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'yes'. Show POLL system on main page.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Show stats" prop="main.showstats">
|
||||
<el-radio-group v-model="formData.main.showstats">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'yes'. Show STATS system on main page.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Show last x forum posts" prop="main.showlastxforumposts">
|
||||
<el-radio-group v-model="formData.main.showlastxforumposts">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'no'. Show Last x Forum Posts on main page.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Show Last x Torrents" prop="main.showlastxtorrents">
|
||||
<el-radio-group v-model="formData.main.showlastxtorrents">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'no'. Show Last x Torrents on main page.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Show server load" prop="main.showtrackerload">
|
||||
<el-radio-group v-model="formData.main.showtrackerload">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'yes'. Show Server Load on main page.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Show forum stats" prop="main.showforumstats">
|
||||
<el-radio-group v-model="formData.main.showforumstats">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'yes'. Show forum stats on forums page.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Show hot" prop="main.showhotmovies">
|
||||
<el-radio-group v-model="formData.main.showhotmovies">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'yes'. Show hot resources on main page. Hot resources are automatically picked by system or manually by staff members.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Show classic" prop="main.showclassicmovies">
|
||||
<el-radio-group v-model="formData.main.showclassicmovies">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'no'. Show classic resources on main page. Only designated moderators or above can pick classic resources.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Enable IMDb system" prop="main.showimdbinfo">
|
||||
<el-radio-group v-model="formData.main.showimdbinfo">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'yes'. System-wide IMDb info setting.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Enable PT-Gen system" prop="main.enable_pt_gen_system">
|
||||
<el-radio-group v-model="formData.main.enable_pt_gen_system">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'no'. System-wide PT-Gen info setting.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="PT-Gen api point" prop="main.pt_gen_api_point">
|
||||
<el-input v-model="formData.main.pt_gen_api_point" placeholder=""></el-input>
|
||||
<div class="nexus-help-text">
|
||||
Default '', when required, reference to Documatation to build yourself
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Enable NFO" prop="main.enablenfo">
|
||||
<el-radio-group v-model="formData.main.enablenfo">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'yes'. System-wide NFO setting.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Enable technical information" prop="main.enable_technical_info">
|
||||
<el-radio-group v-model="formData.main.enable_technical_info">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'No'. Technical Information comes from software MediaInfo Text view
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Enable school system" prop="main.enableschoolyes">
|
||||
<el-radio-group v-model="formData.main.enableschoolyes">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'no'. <span style="color: red; font-weight: bold">DO NOT</span> enable this unless you know what you are doing!
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Restrict email domain" prop="main.restrictemail">
|
||||
<el-radio-group v-model="formData.main.restrictemail">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'no'. Set it to 'yes' to only allow certain email domains to register. See here.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Show Shoutbox" prop="main.showshoutbox">
|
||||
<el-radio-group v-model="formData.main.showshoutbox">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'yes'. Show shoutbox on main page.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Show funbox" prop="main.showfunbox">
|
||||
<el-radio-group v-model="formData.main.showfunbox">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'no'. Show funbox on main page.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Enable offer section" prop="main.showoffer">
|
||||
<el-radio-group v-model="formData.main.showoffer">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Default 'yes'. Enable or disable offer section.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Enable Donation" prop="main.donation">
|
||||
<el-radio-group v-model="formData.main.donation">
|
||||
<el-radio label="yes">Yes</el-radio>
|
||||
<el-radio label="no">No</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="nexus-help-text">
|
||||
Show donation and donation top ten.
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submitAdd()">Submit</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { reactive, ref, toRefs, onMounted, onBeforeUnmount, getCurrentInstance } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { localGet } from '../../utils'
|
||||
import api from "../../utils/api";
|
||||
|
||||
export default {
|
||||
name: 'SettingFormBasic',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance()
|
||||
console.log('proxy', proxy)
|
||||
const formRef = ref(null)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { id } = route.query
|
||||
const state = reactive({
|
||||
token: localGet('token') || '',
|
||||
id: id,
|
||||
allClasses: [],
|
||||
formData: {
|
||||
main: {
|
||||
site_online: '',
|
||||
invitesystem: '',
|
||||
iniupload: '',
|
||||
invite_count: '',
|
||||
invite_timeout: '',
|
||||
verification: '',
|
||||
waitsystem: '',
|
||||
maxdlsystemyes: '',
|
||||
showpolls: '',
|
||||
showstats: '',
|
||||
showtrackerload: '',
|
||||
showforumstats: '',
|
||||
showlastxforumposts: '',
|
||||
showlastxtorrents: '',
|
||||
showhotmovies: '',
|
||||
showclassicmovies: '',
|
||||
showimdbinfo: '',
|
||||
enable_pt_gen_system: '',
|
||||
pt_gen_api_point: '',
|
||||
enablenfo: '',
|
||||
enable_technical_info: '',
|
||||
enableschoolyes: '',
|
||||
restrictemail: '',
|
||||
showshoutbox: '',
|
||||
showfunbox: '',
|
||||
showoffer: '',
|
||||
donation: '',
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
'main.site_online': [
|
||||
{ required: 'true', }
|
||||
],
|
||||
},
|
||||
})
|
||||
onMounted( () => {
|
||||
listAllClass()
|
||||
listAllIndex()
|
||||
if (id) {
|
||||
api.getExam(id).then(res => {
|
||||
state.formData.name = res.data.name
|
||||
state.formData.description = res.data.description
|
||||
state.formData.begin = res.data.begin
|
||||
state.formData.end = res.data.end
|
||||
state.formData.duration = res.data.duration
|
||||
state.formData.indexes = res.data.indexes
|
||||
state.formData.filters = res.data.filters
|
||||
state.formData.status = res.data.status
|
||||
state.formData.is_discovered = res.data.is_discovered
|
||||
})
|
||||
} else {
|
||||
let res = api.listExamIndex()
|
||||
state.formData.indexes = res.data
|
||||
}
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
|
||||
})
|
||||
const submitAdd = () => {
|
||||
formRef.value.validate(async (vaild) => {
|
||||
if (vaild) {
|
||||
let params = state.formData;
|
||||
if (params.begin) {
|
||||
params.begin = dayjs(params.begin).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
if (params.end) {
|
||||
params.end = dayjs(params.end).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
console.log(params)
|
||||
if (id) {
|
||||
await api.updateExam(id, params)
|
||||
} else {
|
||||
await api.storeExam(params)
|
||||
}
|
||||
await router.push({name: 'exam'})
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleBeforeUpload = (file) => {
|
||||
const sufix = file.name.split('.')[1] || ''
|
||||
if (!['jpg', 'jpeg', 'png'].includes(sufix)) {
|
||||
ElMessage.error('请上传 jpg、jpeg、png 格式的图片')
|
||||
return false
|
||||
}
|
||||
}
|
||||
const handleUrlSuccess = (val) => {
|
||||
state.formData.goodsCoverImg = val.data || ''
|
||||
}
|
||||
const handleChangeCate = (val) => {
|
||||
state.categoryId = val[2] || 0
|
||||
}
|
||||
|
||||
const listAllClass = async () => {
|
||||
let res = await api.listClass()
|
||||
state.allClasses = res.data
|
||||
}
|
||||
const listAllIndex = async () => {
|
||||
let res = await api.listExamIndex()
|
||||
state.formData.indexes = res.data
|
||||
}
|
||||
const getExam = async (id) => {
|
||||
let res = await api.getExam(id)
|
||||
console.log(res)
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
formRef,
|
||||
submitAdd,
|
||||
handleBeforeUpload,
|
||||
handleUrlSuccess,
|
||||
handleChangeCate,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,225 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form :model="formData" :rules="rules" ref="formRef" label-width="200px" class="formData">
|
||||
<el-form-item label="Name" prop="name">
|
||||
<el-input v-model="formData.name" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Index" prop="indexes">
|
||||
<template v-for="(item, index) in formData.indexes" :key="index">
|
||||
<el-row>
|
||||
<el-col :span="6">
|
||||
<el-checkbox v-model="item.checked" :label="item.checked">{{item.name}}</el-checkbox>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-input type="number" v-model="item.require_value"></el-input>
|
||||
</el-col>
|
||||
<el-col :span="6" style="padding: 0 20px; color: #aaa">
|
||||
<template v-if="item.unit">
|
||||
Unit: {{item.unit}}
|
||||
</template>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Status" prop="status">
|
||||
<el-radio-group v-model="formData.status">
|
||||
<el-radio :label="0">Enabled</el-radio>
|
||||
<el-radio :label="1">Disabled</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Discovered" prop="is_discovered">
|
||||
<el-radio-group v-model="formData.is_discovered">
|
||||
<el-radio :label="0">No</el-radio>
|
||||
<el-radio :label="1">Yes</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Begin" prop="begin">
|
||||
<el-date-picker
|
||||
v-model="formData.begin"
|
||||
type="datetime"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
placeholder="Select Begin Time">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="End" prop="end">
|
||||
<el-date-picker
|
||||
v-model="formData.end"
|
||||
type="datetime"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
placeholder="Select End Time">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Duration" prop="duration">
|
||||
<el-input v-model="formData.duration" type="number" placeholder=""></el-input>
|
||||
<div style="color: #aaa">Unit: days. When assign to user, begin and end are used if they are specified. Otherwise begin time is the time at assignment, and the end time is the time at assignment plus the duration.</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Target User Class" prop="filters.classes">
|
||||
<el-checkbox-group v-model="formData.filters.classes">
|
||||
<el-checkbox v-for="(item, index) in allClasses" :label="index" :key="index">{{item}}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Target User Register Time">
|
||||
<el-date-picker
|
||||
v-model="formData.filters.register_time_range"
|
||||
type="datetimerange"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
range-separator="to"
|
||||
start-placeholder="Begin"
|
||||
end-placeholder="End">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Description" prop="description">
|
||||
<el-input type="textarea" v-model="formData.description" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submitAdd()">Submit</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { reactive, ref, toRefs, onMounted, onBeforeUnmount, getCurrentInstance } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { localGet } from '../../utils'
|
||||
import api from "../../utils/api";
|
||||
|
||||
export default {
|
||||
name: 'ExamForm',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance()
|
||||
console.log('proxy', proxy)
|
||||
const formRef = ref(null)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { id } = route.query
|
||||
const state = reactive({
|
||||
token: localGet('token') || '',
|
||||
id: id,
|
||||
allClasses: [],
|
||||
formData: {
|
||||
name: '',
|
||||
description: '',
|
||||
begin: '',
|
||||
end: '',
|
||||
duration: '',
|
||||
indexes: [],
|
||||
filters: {
|
||||
classes: [],
|
||||
register_time_range: []
|
||||
},
|
||||
status: '',
|
||||
is_discovered: ''
|
||||
},
|
||||
rules: {
|
||||
name: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
indexes: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
status: [
|
||||
{ required: 'true',}
|
||||
],
|
||||
is_discovered: [
|
||||
{ required: 'true',}
|
||||
],
|
||||
},
|
||||
})
|
||||
onMounted( () => {
|
||||
listAllClass()
|
||||
listAllIndex()
|
||||
if (id) {
|
||||
api.getExam(id).then(res => {
|
||||
state.formData.name = res.data.name
|
||||
state.formData.description = res.data.description
|
||||
state.formData.begin = res.data.begin
|
||||
state.formData.end = res.data.end
|
||||
state.formData.duration = res.data.duration
|
||||
state.formData.indexes = res.data.indexes
|
||||
state.formData.filters = res.data.filters
|
||||
state.formData.status = res.data.status
|
||||
state.formData.is_discovered = res.data.is_discovered
|
||||
})
|
||||
} else {
|
||||
let res = api.listExamIndex()
|
||||
state.formData.indexes = res.data
|
||||
}
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
|
||||
})
|
||||
const submitAdd = () => {
|
||||
formRef.value.validate(async (vaild) => {
|
||||
if (vaild) {
|
||||
let params = state.formData;
|
||||
if (params.begin) {
|
||||
params.begin = dayjs(params.begin).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
if (params.end) {
|
||||
params.end = dayjs(params.end).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
console.log(params)
|
||||
if (id) {
|
||||
await api.updateExam(id, params)
|
||||
} else {
|
||||
await api.storeExam(params)
|
||||
}
|
||||
await router.push({name: 'exam'})
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleBeforeUpload = (file) => {
|
||||
const sufix = file.name.split('.')[1] || ''
|
||||
if (!['jpg', 'jpeg', 'png'].includes(sufix)) {
|
||||
ElMessage.error('请上传 jpg、jpeg、png 格式的图片')
|
||||
return false
|
||||
}
|
||||
}
|
||||
const handleUrlSuccess = (val) => {
|
||||
state.formData.goodsCoverImg = val.data || ''
|
||||
}
|
||||
const handleChangeCate = (val) => {
|
||||
state.categoryId = val[2] || 0
|
||||
}
|
||||
|
||||
const listAllClass = async () => {
|
||||
let res = await api.listClass()
|
||||
state.allClasses = res.data
|
||||
}
|
||||
const listAllIndex = async () => {
|
||||
let res = await api.listExamIndex()
|
||||
state.formData.indexes = res.data
|
||||
}
|
||||
const getExam = async (id) => {
|
||||
let res = await api.getExam(id)
|
||||
console.log(res)
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
formRef,
|
||||
submitAdd,
|
||||
handleBeforeUpload,
|
||||
handleUrlSuccess,
|
||||
handleChangeCate,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,85 +0,0 @@
|
||||
<template>
|
||||
<el-tabs type="border-card" @tab-click="handleTabClick">
|
||||
<el-tab-pane label="Backup"><FormBackup ref="backup" /></el-tab-pane>
|
||||
<el-tab-pane label="H&R"><FormHR ref="hr" /></el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRouter } from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
import { useTable, renderTableData } from '../../utils/table'
|
||||
import FormBasic from './form-basic.vue'
|
||||
import FormMain from './form-main.vue'
|
||||
import FormBackup from './form-backup.vue'
|
||||
import FormHR from './form-hr.vue'
|
||||
|
||||
export default {
|
||||
name: 'Setting',
|
||||
components: {
|
||||
FormBasic, FormMain, FormBackup, FormHR
|
||||
},
|
||||
setup() {
|
||||
const multipleTable = ref(null)
|
||||
const router = useRouter()
|
||||
const backup = ref(null)
|
||||
const hr = ref(null)
|
||||
const state = useTable()
|
||||
let activeTabIndex = 0
|
||||
const tabs = [backup, hr]
|
||||
|
||||
onMounted(() => {
|
||||
console.log('Setting onMounted')
|
||||
tabs[activeTabIndex].value.listSetting()
|
||||
})
|
||||
const fetchTableData = async () => {
|
||||
state.loading = true
|
||||
let res = await api.listExam(state.query)
|
||||
renderTableData(res, state)
|
||||
state.loading = false
|
||||
}
|
||||
const handleAdd = () => {
|
||||
router.push({ name: 'exam-form' })
|
||||
}
|
||||
const handleEdit = (id) => {
|
||||
router.push({ path: '/exam-form', query: { id } })
|
||||
}
|
||||
const handleDelete = async (id) => {
|
||||
let res = await api.deleteExam(id)
|
||||
ElMessage.success(res.msg)
|
||||
state.query.page = 1;
|
||||
await fetchTableData()
|
||||
}
|
||||
const handleSelectionChange = (val) => {
|
||||
state.multipleSelection = val
|
||||
}
|
||||
const changePage = (val) => {
|
||||
state.query.page = val
|
||||
fetchTableData()
|
||||
}
|
||||
const handleTabClick = (tab) => {
|
||||
activeTabIndex = tab.index
|
||||
tabs[activeTabIndex].value.listSetting()
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
multipleTable,
|
||||
handleSelectionChange,
|
||||
handleAdd,
|
||||
handleEdit,
|
||||
handleDelete,
|
||||
handleTabClick,
|
||||
fetchTableData,
|
||||
changePage,
|
||||
backup,
|
||||
hr
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,139 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form :model="formData" :rules="rules" ref="formRef" label-width="200px" class="formData">
|
||||
<el-form-item label="Name" prop="name">
|
||||
<el-input v-model="formData.name" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Background color" prop="color">
|
||||
<el-input v-model="formData.color" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Font color" prop="font_color">
|
||||
<el-input v-model="formData.font_color" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Font size" prop="font_size">
|
||||
<el-input v-model="formData.font_size" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Padding" prop="padding">
|
||||
<el-input v-model="formData.padding" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Margin" prop="margin">
|
||||
<el-input v-model="formData.margin" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Border radius" prop="border_radius">
|
||||
<el-input v-model="formData.border_radius" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Priority" prop="priority">
|
||||
<el-input v-model="formData.priority" placeholder="The higher the value, the higher the ranking"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submitAdd()">Submit</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { reactive, ref, toRefs, onMounted, onBeforeUnmount, getCurrentInstance } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { localGet } from '../../utils'
|
||||
import api from "../../utils/api";
|
||||
|
||||
export default {
|
||||
name: 'TagForm',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance()
|
||||
console.log('proxy', proxy)
|
||||
const formRef = ref(null)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { id } = route.query
|
||||
const state = reactive({
|
||||
token: localGet('token') || '',
|
||||
id: id,
|
||||
list: [],
|
||||
formData: {
|
||||
color: '',
|
||||
name: '',
|
||||
priority: '',
|
||||
font_color: '#ffffff',
|
||||
font_size: '12px',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
border_radius: 0,
|
||||
},
|
||||
rules: {
|
||||
color: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
name: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
},
|
||||
})
|
||||
onMounted( async () => {
|
||||
if (id) {
|
||||
api.getTag(id).then(res => {
|
||||
state.formData.name = res.data.name
|
||||
state.formData.color = res.data.color
|
||||
state.formData.priority = res.data.priority
|
||||
state.formData.font_color = res.data.font_color
|
||||
state.formData.font_size = res.data.font_size
|
||||
state.formData.margin = res.data.margin
|
||||
state.formData.padding = res.data.padding
|
||||
state.formData.border_radius = res.data.border_radius
|
||||
|
||||
})
|
||||
}
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
|
||||
})
|
||||
const submitAdd = () => {
|
||||
formRef.value.validate(async (vaild) => {
|
||||
if (vaild) {
|
||||
let params = state.formData;
|
||||
console.log(params)
|
||||
if (id) {
|
||||
await api.updateTag(id, params)
|
||||
} else {
|
||||
await api.storeTag(params)
|
||||
}
|
||||
await router.push({name: 'tag'})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const listTag = async () => {
|
||||
let res = await api.listTag()
|
||||
state.list = res.data
|
||||
}
|
||||
|
||||
const getTag = async (id) => {
|
||||
let res = await api.getTag(id)
|
||||
console.log(res)
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
formRef,
|
||||
submitAdd,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,184 +0,0 @@
|
||||
<template>
|
||||
<el-card class="">
|
||||
<template #header>
|
||||
<div class="nexus-table-header">
|
||||
<div class="left">
|
||||
|
||||
</div>
|
||||
<div class="right">
|
||||
<el-button type="primary" icon="Plus" @click="handleAdd">Add</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
ref="multipleTable"
|
||||
:data="tableData"
|
||||
tooltip-effect="dark"
|
||||
@selection-change="handleSelectionChange">
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="55">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="Id"
|
||||
width="50"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="Name"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="color"
|
||||
label="Background color"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="font_color"
|
||||
label="Font color"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="font_size"
|
||||
label="Font size"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="margin"
|
||||
label="Margin"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="padding"
|
||||
label="Padding"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="border_radius"
|
||||
label="Border radius"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="priority"
|
||||
label="Priority"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="updated_at"
|
||||
label="Updated at"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="Action"
|
||||
width="120"
|
||||
>
|
||||
<template #default="scope">
|
||||
<a style="cursor: pointer; margin-right: 10px" @click="handleEdit(scope.row.id)">Edit</a>
|
||||
<el-popconfirm
|
||||
title="Confirm Delete ?"
|
||||
@confirm="handleDelete(scope.row.id)"
|
||||
>
|
||||
<template #reference>
|
||||
<a style="cursor: pointer">Delete</a>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--总数超过一页,再展示分页器-->
|
||||
<el-pagination
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
:total="total"
|
||||
:page-size="perPage"
|
||||
:current-page="currentPage"
|
||||
@current-change="changePage"
|
||||
/>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRouter } from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
import { useTable, renderTableData } from '../../utils/table'
|
||||
|
||||
export default {
|
||||
name: 'TagTable',
|
||||
setup() {
|
||||
const multipleTable = ref(null)
|
||||
const router = useRouter()
|
||||
|
||||
const state = useTable()
|
||||
let extraData = reactive({
|
||||
agentAllows: []
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
fetchTableData()
|
||||
})
|
||||
const fetchTableData = async () => {
|
||||
state.loading = true
|
||||
let res = await api.listTag(state.query)
|
||||
renderTableData(res, state)
|
||||
state.loading = false
|
||||
}
|
||||
const handleAdd = () => {
|
||||
router.push({ name: 'tag-form' })
|
||||
}
|
||||
const handleEdit = (id) => {
|
||||
router.push({ path: '/tag-form', query: { id } })
|
||||
}
|
||||
const handleDelete = async (id) => {
|
||||
let res = await api.deleteTag(id)
|
||||
ElMessage.success(res.msg)
|
||||
state.query.page = 1;
|
||||
await fetchTableData()
|
||||
}
|
||||
const handleSelectionChange = (val) => {
|
||||
state.multipleSelection = val
|
||||
}
|
||||
const changePage = (val) => {
|
||||
state.query.page = val
|
||||
fetchTableData()
|
||||
}
|
||||
|
||||
const handleReset = () => {
|
||||
state.query.family_id = '';
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
extraData,
|
||||
multipleTable,
|
||||
handleSelectionChange,
|
||||
handleAdd,
|
||||
handleEdit,
|
||||
handleDelete,
|
||||
fetchTableData,
|
||||
changePage,
|
||||
handleReset,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.swiper-container {
|
||||
min-height: 100%;
|
||||
}
|
||||
.el-card.is-always-shadow {
|
||||
min-height: 100%!important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,406 +0,0 @@
|
||||
<template>
|
||||
<div class="page-user-detail" v-loading="loading">
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>Base info</span>
|
||||
</div>
|
||||
</template>
|
||||
<table class="table-base-info" >
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Actions</th>
|
||||
<th>Other</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Username</td>
|
||||
<td>{{baseInfo.username}}</td>
|
||||
<td></td>
|
||||
<td colspan="11">
|
||||
<div class="other-actions">
|
||||
<el-button type="primary" size="default" @click="handleGetModComment">Mod comment</el-button>
|
||||
<el-button type="primary" size="default" @click="handleResetPassword">Reset password</el-button>
|
||||
<el-button type="primary" size="default" @click="handleAssignExam">Assign exam</el-button>
|
||||
<el-button type="primary" size="default" @click="handleGrantMedal">Grant medal</el-button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Email</td>
|
||||
<td>{{baseInfo.email}}</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Enabled</td>
|
||||
<td>{{baseInfo.enabled}}</td>
|
||||
<td>
|
||||
<template v-if="baseInfo.enabled && baseInfo.enabled == 'yes'">
|
||||
<el-button size="small" @click="handleDisableUser">Disable</el-button>
|
||||
</template>
|
||||
<template v-if="baseInfo.enabled && baseInfo.enabled == 'no'">
|
||||
<el-popconfirm
|
||||
title="Confirm Enable ?"
|
||||
@confirm="handleEnableUser"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button size="small">Enable</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Added</td>
|
||||
<td>{{baseInfo.added}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Last access</td>
|
||||
<td>{{baseInfo.last_access}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Class</td>
|
||||
<td>{{baseInfo.class_text}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Invite by</td>
|
||||
<td>{{baseInfo.inviter && baseInfo.inviter.username}}</td>
|
||||
<td><el-button size="small" @click="handleViewInviteInfo">View</el-button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Two-step authentication</td>
|
||||
<td>{{baseInfo.two_step_secret ? 'Enabled' : 'Disabled'}}</td>
|
||||
<td>
|
||||
<el-popconfirm
|
||||
v-if="baseInfo.two_step_secret"
|
||||
title="Confirm Disable Two-step authentication ?"
|
||||
@confirm="handleRemoveTwoStepAuthentication"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button type="default" size="small">Disable</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Seed points</td>
|
||||
<td>{{baseInfo.seed_points}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Attendance card</td>
|
||||
<td>{{baseInfo.attendance_card}}</td>
|
||||
<td><el-button size="small" @click="handleIncrementDecrement('attendance_card')">Change</el-button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Invites</td>
|
||||
<td>{{baseInfo.invites}}</td>
|
||||
<td><el-button size="small" @click="handleIncrementDecrement('invites')">Change</el-button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Uploaded</td>
|
||||
<td>{{baseInfo.uploaded_text}}</td>
|
||||
<td><el-button size="small" @click="handleIncrementDecrement('uploaded')">Change</el-button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Downloaded</td>
|
||||
<td>{{baseInfo.downloaded_text}}</td>
|
||||
<td><el-button size="small" @click="handleIncrementDecrement('downloaded')">Change</el-button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Bonus</td>
|
||||
<td>{{baseInfo.bonus}}</td>
|
||||
<td><el-button size="small" @click="handleIncrementDecrement('bonus')">Change</el-button></td>
|
||||
</tr>
|
||||
</table>
|
||||
</el-card>
|
||||
|
||||
<el-card v-if="examInfo">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>Exam on the way</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<table class="table-base-info">
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td>{{examInfo.exam && examInfo.exam.name}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Created at</td>
|
||||
<td>{{examInfo.created_at}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Exam time</td>
|
||||
<td>{{examInfo.begin}} ~ {{examInfo.end}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Status</td>
|
||||
<td>{{examInfo.status_text}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Action</td>
|
||||
<td>
|
||||
<el-popconfirm
|
||||
title="Confirm Remove ?"
|
||||
@confirm="handleRemoveExam(examInfo.id)"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button type="danger" size="small">Remove</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
<el-popconfirm
|
||||
v-if="examInfo.status === 0"
|
||||
title="Confirm Avoid ?"
|
||||
@confirm="handleAvoidExam(examInfo.id)"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button type="info" size="small">Avoid</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
<el-popconfirm
|
||||
v-if="examInfo.status === -1"
|
||||
title="Confirm Recover ?"
|
||||
@confirm="handleRecoverExam(examInfo.id)"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button type="primary" size="small">Recover</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-table :data="examInfo.progress_formatted">
|
||||
<el-table-column prop="name" label="Index"></el-table-column>
|
||||
<el-table-column prop="require_value_formatted" label="Require"></el-table-column>
|
||||
<el-table-column prop="current_value_formatted" label="Current"></el-table-column>
|
||||
<el-table-column prop="result" label="Result">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.passed" type="success">Pass !</el-tag>
|
||||
<el-tag v-if="!scope.row.passed" type="danger">Not Pass !</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-row v-if="baseInfo.valid_medals && baseInfo.valid_medals.length">
|
||||
<el-col :span="12">
|
||||
<el-card >
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>Medal</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
ref="multipleTable"
|
||||
:data="baseInfo.valid_medals"
|
||||
tooltip-effect="dark"
|
||||
>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="Name"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="image_large"
|
||||
label="Image"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-image :src="scope.row.image_large" style="max-height: 200px" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="expire_at"
|
||||
label="Expire at"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="Action"
|
||||
width="100"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-popconfirm
|
||||
title="Confirm Remove ?"
|
||||
@confirm="handleRemoveUserMedal(scope.row.user_medal_id)"
|
||||
>
|
||||
<template #reference>
|
||||
<a style="cursor: pointer">Remove</a>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<DialogAssignExam ref="assignExam" :reload="fetchPageData"/>
|
||||
<DialogGrantMedal ref="grantMedal" :reload="fetchPageData"/>
|
||||
<DialogViewInviteInfo ref="viewInviteInfo" />
|
||||
<DialogDisableUser ref="disableUser" :reload="fetchPageData" />
|
||||
<DialogModComment ref="modComment" />
|
||||
<DialogResetPassword ref="resetPassword" />
|
||||
<DialogIncrementDecrement ref="incrementDecrement" :reload="fetchPageData" :title="dialogTitle" :valuePlaceholder="valuePlaceholder" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {useRoute, useRouter} from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
import DialogAssignExam from './dialog-assign-exam.vue'
|
||||
import DialogViewInviteInfo from './dialog-invite-info.vue'
|
||||
import DialogDisableUser from './dialog-disable-user.vue'
|
||||
import DialogModComment from './dialog-mod-comment.vue'
|
||||
import DialogResetPassword from './dialog-reset-password.vue'
|
||||
import DialogGrantMedal from './dialog-grant-medal.vue'
|
||||
import DialogIncrementDecrement from './dialog-increment-decrement.vue'
|
||||
|
||||
export default {
|
||||
name: "UserDetail",
|
||||
components: {
|
||||
DialogAssignExam, DialogViewInviteInfo, DialogDisableUser, DialogModComment, DialogResetPassword, DialogGrantMedal,
|
||||
DialogIncrementDecrement
|
||||
},
|
||||
setup() {
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { id } = route.query
|
||||
const assignExam = ref(null)
|
||||
const grantMedal = ref(null)
|
||||
const viewInviteInfo = ref(null)
|
||||
const disableUser = ref(null)
|
||||
const modComment = ref(null)
|
||||
const resetPassword = ref(null)
|
||||
const incrementDecrement = ref(null)
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
baseInfo: {},
|
||||
examInfo: null,
|
||||
dialogTitle: '',
|
||||
valuePlaceholder: '',
|
||||
})
|
||||
onMounted(() => {
|
||||
fetchPageData()
|
||||
})
|
||||
const fetchPageData = async () => {
|
||||
state.loading = true;
|
||||
let res = await api.getUser(id)
|
||||
state.loading = false
|
||||
state.baseInfo = res.data.base_info
|
||||
state.examInfo = res.data.exam_info
|
||||
}
|
||||
const handleRemoveExam = async (id) => {
|
||||
let res = await api.deleteExamUser(id)
|
||||
ElMessage.success(res.msg)
|
||||
await fetchPageData()
|
||||
}
|
||||
|
||||
const handleAvoidExam = async (id) => {
|
||||
let res = await api.avoidExamUser(id)
|
||||
ElMessage.success(res.msg)
|
||||
await fetchPageData()
|
||||
}
|
||||
|
||||
const handleRecoverExam = async (id) => {
|
||||
let res = await api.recoverExamUser(id)
|
||||
ElMessage.success(res.msg)
|
||||
await fetchPageData()
|
||||
}
|
||||
|
||||
const handleAssignExam = async () => {
|
||||
assignExam.value.open(id)
|
||||
}
|
||||
const handleGrantMedal = async () => {
|
||||
grantMedal.value.open(id)
|
||||
}
|
||||
const handleViewInviteInfo = async () => {
|
||||
viewInviteInfo.value.open(id)
|
||||
}
|
||||
const handleDisableUser = async () => {
|
||||
disableUser.value.open(id)
|
||||
}
|
||||
const handleIncrementDecrement = async (field) => {
|
||||
state.dialogTitle = 'Change ' + field
|
||||
if (['uploaded', 'downloaded'].includes(field)) {
|
||||
state.valuePlaceholder = 'Unit: GB'
|
||||
} else {
|
||||
state.valuePlaceholder = ''
|
||||
}
|
||||
incrementDecrement.value.open(id, field)
|
||||
}
|
||||
const handleEnableUser = async () => {
|
||||
let res = await api.enableUser({uid: id})
|
||||
ElMessage.success(res.msg)
|
||||
await fetchPageData()
|
||||
}
|
||||
const handleGetModComment = async () => {
|
||||
modComment.value.open(id)
|
||||
}
|
||||
const handleResetPassword = async () => {
|
||||
resetPassword.value.open(id)
|
||||
}
|
||||
|
||||
const handleRemoveUserMedal = async (id) => {
|
||||
let res = await api.removeUserMedal(id)
|
||||
ElMessage.success(res.msg)
|
||||
await fetchPageData()
|
||||
}
|
||||
const handleRemoveTwoStepAuthentication = async () => {
|
||||
let res = await api.removeTwoStepAuthentication({uid: id})
|
||||
ElMessage.success(res.msg)
|
||||
await fetchPageData()
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
handleRemoveExam,
|
||||
handleAvoidExam,
|
||||
handleAssignExam,
|
||||
handleGrantMedal,
|
||||
handleRecoverExam,
|
||||
handleEnableUser,
|
||||
handleViewInviteInfo,
|
||||
handleDisableUser,
|
||||
handleGetModComment,
|
||||
handleResetPassword,
|
||||
fetchPageData,
|
||||
handleRemoveUserMedal,
|
||||
handleIncrementDecrement,
|
||||
handleRemoveTwoStepAuthentication,
|
||||
assignExam,
|
||||
grantMedal,
|
||||
viewInviteInfo,
|
||||
disableUser,
|
||||
modComment,
|
||||
resetPassword,
|
||||
incrementDecrement,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.el-card {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.table-base-info {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
tr {
|
||||
th {
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
td {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,106 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="Assign exam to user"
|
||||
v-model="visible"
|
||||
center
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form
|
||||
:model="formData"
|
||||
label-width="100px"
|
||||
v-loading="loading"
|
||||
ref="formRef"
|
||||
:rules="rules">
|
||||
<el-form-item label="Exam" prop="exam_id">
|
||||
<el-select v-model="formData.exam_id" placeholder="Select an exam...">
|
||||
<el-option
|
||||
v-for="item in matchExams"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="Time range" prop="time_range">
|
||||
<el-date-picker
|
||||
v-model="formData.time_range"
|
||||
type="datetimerange"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
range-separator="to"
|
||||
start-placeholder="Begin"
|
||||
end-placeholder="End">
|
||||
</el-date-picker>
|
||||
<div class="time-range-help-text">If the time range is not specified, the exam's own configured time range will be used.</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="visible = false">Cancel</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">Save</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {useRoute, useRouter} from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
|
||||
export default {
|
||||
name: "DialogAssignExam",
|
||||
props: {
|
||||
reload: Function
|
||||
},
|
||||
setup(props, context) {
|
||||
const formRef = ref(null)
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
matchExams: [],
|
||||
visible: false,
|
||||
formData: {
|
||||
uid: 0,
|
||||
exam_id: '',
|
||||
time_range: []
|
||||
},
|
||||
rules: {
|
||||
exam_id: [{ required: 'true'}]
|
||||
}
|
||||
})
|
||||
const listMatchExams = async () => {
|
||||
let res = await api.listUserMatchExams({uid: state.formData.uid})
|
||||
state.matchExams = res.data
|
||||
}
|
||||
const open = (uid) => {
|
||||
state.formData.uid = uid
|
||||
if (state.matchExams.length == 0) {
|
||||
state.loading = true
|
||||
listMatchExams()
|
||||
state.loading = false
|
||||
}
|
||||
state.visible = true
|
||||
|
||||
}
|
||||
const handleSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res = await api.storeExamUser(state.formData)
|
||||
state.visible = false
|
||||
ElMessage.success(res.msg)
|
||||
if (props.reload) {
|
||||
props.reload()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
handleSubmit,
|
||||
formRef,
|
||||
open,
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,77 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="Disable user"
|
||||
v-model="visible"
|
||||
center
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form
|
||||
:model="formData"
|
||||
label-width="100px"
|
||||
v-loading="loading"
|
||||
ref="formRef"
|
||||
:rules="rules">
|
||||
<el-form-item label="Reason" prop="reason">
|
||||
<el-input type="textarea" v-model="formData.reason"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="visible = false">Cancel</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">Save</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {useRoute, useRouter} from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
|
||||
export default {
|
||||
name: "DialogDisableUser",
|
||||
props: {
|
||||
reload: Function
|
||||
},
|
||||
setup(props, context) {
|
||||
const formRef = ref(null)
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
visible: false,
|
||||
formData: {
|
||||
uid: 0,
|
||||
reason: '',
|
||||
},
|
||||
rules: {
|
||||
reason: [{ required: 'true'}]
|
||||
}
|
||||
})
|
||||
const open = (uid) => {
|
||||
state.formData.uid = uid
|
||||
state.visible = true
|
||||
|
||||
}
|
||||
const handleSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res = await api.disableUser(state.formData)
|
||||
state.visible = false
|
||||
ElMessage.success(res.msg)
|
||||
if (props.reload) {
|
||||
props.reload()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
handleSubmit,
|
||||
formRef,
|
||||
open,
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,98 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="Grant medal to user"
|
||||
v-model="visible"
|
||||
center
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form
|
||||
:model="formData"
|
||||
label-width="100px"
|
||||
v-loading="loading"
|
||||
ref="formRef"
|
||||
:rules="rules">
|
||||
<el-form-item label="Medal" prop="medal_id">
|
||||
<el-select v-model="formData.medal_id" placeholder="Select an medal...">
|
||||
<el-option
|
||||
v-for="item in medals"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="Duration" prop="duration">
|
||||
<el-input v-model="formData.duration" placeholder="Unit: day, if empty, it's valid forever"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="visible = false">Cancel</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">Save</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {useRoute, useRouter} from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
|
||||
export default {
|
||||
name: "DialogGrantMedal",
|
||||
props: {
|
||||
reload: Function
|
||||
},
|
||||
setup(props, context) {
|
||||
const formRef = ref(null)
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
medals: [],
|
||||
visible: false,
|
||||
formData: {
|
||||
uid: 0,
|
||||
medal_id: '',
|
||||
duration: '',
|
||||
},
|
||||
rules: {
|
||||
medal_id: [{ required: 'true'}]
|
||||
}
|
||||
})
|
||||
const listMedals = async () => {
|
||||
let res = await api.listMedal()
|
||||
state.medals = res.data.data
|
||||
}
|
||||
const open = (uid) => {
|
||||
state.formData.uid = uid
|
||||
if (state.medals.length == 0) {
|
||||
state.loading = true
|
||||
listMedals()
|
||||
state.loading = false
|
||||
}
|
||||
state.visible = true
|
||||
|
||||
}
|
||||
const handleSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res = await api.storeUserMedal(state.formData)
|
||||
state.visible = false
|
||||
ElMessage.success(res.msg)
|
||||
if (props.reload) {
|
||||
props.reload()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
handleSubmit,
|
||||
formRef,
|
||||
open,
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,93 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="title"
|
||||
v-model="visible"
|
||||
center
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form
|
||||
:model="formData"
|
||||
label-width="100px"
|
||||
v-loading="loading"
|
||||
ref="formRef"
|
||||
:rules="rules">
|
||||
<el-form-item label="Action" prop="action">
|
||||
<el-radio-group v-model="formData.action">
|
||||
<el-radio label="Increment" />
|
||||
<el-radio label="Decrement" />
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="Value" prop="value">
|
||||
<el-input v-model="formData.value" type="number" :placeholder="valuePlaceholder" />
|
||||
</el-form-item>
|
||||
<el-form-item label="Reason" prop="reason">
|
||||
<el-input type="textarea" v-model="formData.reason"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="visible = false">Cancel</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">Save</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {useRoute, useRouter} from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
|
||||
export default {
|
||||
name: "DialogIncrementDecrement",
|
||||
props: {
|
||||
reload: Function,
|
||||
title: String,
|
||||
valuePlaceholder: String
|
||||
},
|
||||
setup(props, context) {
|
||||
const formRef = ref(null)
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
visible: false,
|
||||
formData: {
|
||||
uid: 0,
|
||||
field: '',
|
||||
reason: '',
|
||||
value: '',
|
||||
action: '',
|
||||
},
|
||||
rules: {
|
||||
value: [{ required: 'true'}],
|
||||
action: [{ required: 'true'}],
|
||||
}
|
||||
})
|
||||
const open = (uid, field) => {
|
||||
state.formData.uid = uid
|
||||
state.formData.field = field
|
||||
state.visible = true
|
||||
|
||||
}
|
||||
const handleSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res = await api.incrementDecrementUserField(state.formData)
|
||||
state.visible = false
|
||||
ElMessage.success(res.msg)
|
||||
if (props.reload) {
|
||||
props.reload()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
handleSubmit,
|
||||
formRef,
|
||||
open,
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,63 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="Invite info"
|
||||
v-model="visible"
|
||||
center
|
||||
width="65%"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-table :data="inviteInfo" v-loading="loading">
|
||||
<el-table-column prop="id" label="ID" width="80"></el-table-column>
|
||||
<el-table-column prop="inviter_user.username" label="Inviter" width="150"></el-table-column>
|
||||
<el-table-column prop="invitee" label="Receive email"></el-table-column>
|
||||
<el-table-column prop="hash" label="Hash" width="300"></el-table-column>
|
||||
<el-table-column prop="valid_text" label="Hash valid" width="100"></el-table-column>
|
||||
<el-table-column prop="invitee_register_email" label="Register email"></el-table-column>
|
||||
<el-table-column prop="time_invited" label="Time invited" width="180"></el-table-column>
|
||||
</el-table>
|
||||
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {useRoute, useRouter} from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
|
||||
export default {
|
||||
name: "DialogInviteInfo",
|
||||
props: {
|
||||
reload: Function
|
||||
},
|
||||
setup(props, context) {
|
||||
const formRef = ref(null)
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
visible: false,
|
||||
uid: 0,
|
||||
inviteInfo: [],
|
||||
})
|
||||
const getInviteInfo = async () => {
|
||||
let res = await api.getInviteInfo({uid: state.uid})
|
||||
state.inviteInfo.push(res.data)
|
||||
}
|
||||
const open = (uid) => {
|
||||
state.uid = uid
|
||||
if (state.inviteInfo.length == 0) {
|
||||
state.loading = true
|
||||
getInviteInfo()
|
||||
state.loading = false
|
||||
}
|
||||
state.visible = true
|
||||
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
formRef,
|
||||
open,
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,54 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="Mod comment"
|
||||
v-model="visible"
|
||||
center
|
||||
width="40%"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-card v-loading="loading">
|
||||
<div v-html="modComment" class="pre-line"></div>
|
||||
</el-card>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {useRoute, useRouter} from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
|
||||
export default {
|
||||
name: "DialogModComment",
|
||||
props: {
|
||||
reload: Function
|
||||
},
|
||||
setup(props, context) {
|
||||
const formRef = ref(null)
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
visible: false,
|
||||
uid: 0,
|
||||
modComment: ''
|
||||
})
|
||||
const getUserModComment = async () => {
|
||||
let res = await api.getUserModComment({uid: state.uid})
|
||||
state.modComment = res.data
|
||||
}
|
||||
const open = (uid) => {
|
||||
state.uid = uid
|
||||
state.loading = true
|
||||
getUserModComment()
|
||||
state.loading = false
|
||||
state.visible = true
|
||||
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
formRef,
|
||||
open,
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,83 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="Reset password"
|
||||
v-model="visible"
|
||||
center
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form
|
||||
:model="formData"
|
||||
label-width="200px"
|
||||
v-loading="loading"
|
||||
ref="formRef"
|
||||
:rules="rules">
|
||||
<el-form-item label="Password" prop="password">
|
||||
<el-input v-model="formData.password"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Password confirmation" prop="password_confirmation">
|
||||
<el-input v-model="formData.password_confirmation"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="visible = false">Cancel</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">Save</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {useRoute, useRouter} from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
|
||||
export default {
|
||||
name: "DialogResetPassword",
|
||||
props: {
|
||||
reload: Function
|
||||
},
|
||||
setup(props, context) {
|
||||
const formRef = ref(null)
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
visible: false,
|
||||
formData: {
|
||||
uid: 0,
|
||||
password: '',
|
||||
password_confirmation: ''
|
||||
},
|
||||
rules: {
|
||||
password: [{ required: 'true'}],
|
||||
password_confirmation: [{ required: 'true'}],
|
||||
}
|
||||
})
|
||||
const open = (uid) => {
|
||||
state.formData.uid = uid
|
||||
state.visible = true
|
||||
|
||||
}
|
||||
const handleSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res = await api.resetPassword(state.formData)
|
||||
state.visible = false
|
||||
ElMessage.success(res.msg)
|
||||
if (props.reload) {
|
||||
props.reload()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
handleSubmit,
|
||||
formRef,
|
||||
open,
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,122 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form :model="formData" :rules="rules" ref="formRef" label-width="200px" class="formData">
|
||||
|
||||
<el-form-item label="Username" prop="username">
|
||||
<el-input v-model="formData.username" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Email" prop="email">
|
||||
<el-input v-model="formData.email" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Password" prop="password">
|
||||
<el-input type="password" v-model="formData.password" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Password Confirmation" prop="password_confirmation">
|
||||
<el-input type="password" v-model="formData.password_confirmation" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="UID" prop="id">
|
||||
<el-input v-model="formData.id" type="number" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Class" prop="class">
|
||||
<el-select v-model="formData.class" filterable clearable>
|
||||
<el-option
|
||||
v-for="(item, index) in userClasses"
|
||||
:key="index"
|
||||
:label="item"
|
||||
:value="index"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submitAdd()">Submit</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { reactive, ref, toRefs, onMounted, onBeforeUnmount, getCurrentInstance } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { localGet } from '../../utils'
|
||||
import api from "../../utils/api";
|
||||
|
||||
export default {
|
||||
name: 'UserForm',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance()
|
||||
console.log('proxy', proxy)
|
||||
const formRef = ref(null)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { id } = route.query
|
||||
const state = reactive({
|
||||
id: id,
|
||||
userClasses: [],
|
||||
formData: {
|
||||
username: '',
|
||||
email: '',
|
||||
password: '',
|
||||
password_confirmation: '',
|
||||
id: '',
|
||||
class: ''
|
||||
},
|
||||
rules: {
|
||||
username: [
|
||||
{ required: 'true'}
|
||||
],
|
||||
email: [
|
||||
{ required: 'true', type: 'email'}
|
||||
],
|
||||
password: [
|
||||
{ required: 'true', min: 6, max: 40}
|
||||
],
|
||||
password_confirmation: [
|
||||
{ required: 'true', min: 6, max: 40}
|
||||
],
|
||||
},
|
||||
})
|
||||
onMounted( async () => {
|
||||
await listAllClass()
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
|
||||
})
|
||||
const submitAdd = () => {
|
||||
formRef.value.validate(async (vaild) => {
|
||||
if (vaild) {
|
||||
let params = state.formData;
|
||||
await api.storeUser(params)
|
||||
await router.push({name: 'user'})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const listAllClass = async () => {
|
||||
let res = await api.listClass()
|
||||
state.userClasses = res.data
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
formRef,
|
||||
submitAdd,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,255 +0,0 @@
|
||||
<template>
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div class="nexus-table-header">
|
||||
<div class="left">
|
||||
<el-form :inline="true" :model="query">
|
||||
<el-form-item label="">
|
||||
<el-input placeholder="ID" v-model="query.id"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="">
|
||||
<el-input placeholder="Username" v-model="query.username"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="">
|
||||
<el-input placeholder="Email" v-model="query.email"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="">
|
||||
<el-select v-model="query.class" filterable placeholder="Class">
|
||||
<el-option
|
||||
v-for="(item, index) in extraData.classes"
|
||||
:key="index"
|
||||
:label="item"
|
||||
:value="index"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="fetchTableData">Query</el-button>
|
||||
<el-button type="primary" @click="handleReset">Reset</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="right">
|
||||
<el-button type="primary" icon="Plus" @click="handleAdd">Add</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
ref="multipleTable"
|
||||
:data="tableData"
|
||||
tooltip-effect="dark"
|
||||
@sort-change="handleSortChange"
|
||||
@selection-change="handleSelectionChange">
|
||||
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="55">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="Id"
|
||||
width="80"
|
||||
sortable="custom"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="username"
|
||||
label="Username"
|
||||
sortable="custom"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="email"
|
||||
label="Email"
|
||||
width="200"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="class"
|
||||
label="Class"
|
||||
sortable="custom"
|
||||
width="120"
|
||||
:formatter="formatColumnClass"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="uploaded"
|
||||
label="Uploaded"
|
||||
sortable="custom"
|
||||
:formatter="formatColumnUploaded"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="downloaded"
|
||||
label="Downloaded"
|
||||
sortable="custom"
|
||||
:formatter="formatColumnDownloaded"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="bonus"
|
||||
label="Bonus"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="status"
|
||||
label="Status"
|
||||
width="100"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="enabled"
|
||||
label="Enabled"
|
||||
width="100"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="last_access"
|
||||
label="Last access"
|
||||
width="150"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="added"
|
||||
label="Added"
|
||||
width="150"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="Action"
|
||||
width="100"
|
||||
>
|
||||
<template #default="scope">
|
||||
<a style="cursor: pointer; margin-right: 10px" @click="handleDetail(scope.row.id)">Detail</a>
|
||||
<!-- <el-popconfirm-->
|
||||
<!-- title="Confirm Delete ?"-->
|
||||
<!-- @confirm="handleDelete(scope.row.id)"-->
|
||||
<!-- >-->
|
||||
<!-- <template #reference>-->
|
||||
<!-- <a style="cursor: pointer">Delete</a>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-popconfirm>-->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--总数超过一页,再展示分页器-->
|
||||
<el-pagination
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
:total="total"
|
||||
:page-size="perPage"
|
||||
:current-page="currentPage"
|
||||
@current-change="changePage"
|
||||
/>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRouter } from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
import { useTable, renderTableData, resetTableSort } from '../../utils/table'
|
||||
|
||||
export default {
|
||||
name: 'UserTable',
|
||||
setup() {
|
||||
const multipleTable = ref(null)
|
||||
const router = useRouter()
|
||||
|
||||
const state = useTable()
|
||||
|
||||
let extraData = reactive({
|
||||
classes: []
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
api.listClass().then(function (res) {
|
||||
extraData.classes = res.data
|
||||
})
|
||||
fetchTableData()
|
||||
})
|
||||
const fetchTableData = async () => {
|
||||
state.loading = true
|
||||
let res = await api.listUser(state.query)
|
||||
renderTableData(res, state)
|
||||
state.loading = false
|
||||
}
|
||||
const handleAdd = () => {
|
||||
router.push({ name: 'user-form' })
|
||||
}
|
||||
const handleEdit = (id) => {
|
||||
router.push({ name: 'user-form', query: { id } })
|
||||
}
|
||||
const handleDelete = async (id) => {
|
||||
let res = await api.deleteExam(id)
|
||||
ElMessage.success(res.msg)
|
||||
state.query.page = 1;
|
||||
await fetchTableData()
|
||||
}
|
||||
// 选择项
|
||||
const handleSelectionChange = (val) => {
|
||||
state.multipleSelection = val
|
||||
}
|
||||
const changePage = (val) => {
|
||||
state.query.page = val
|
||||
fetchTableData()
|
||||
}
|
||||
const handleSortChange = (val) => {
|
||||
resetTableSort(val, state)
|
||||
fetchTableData()
|
||||
}
|
||||
|
||||
const handleReset = () => {
|
||||
state.query.id = '';
|
||||
state.query.username = '';
|
||||
state.query.email = '';
|
||||
state.query.class = '';
|
||||
state.query.sort_field = '';
|
||||
state.query.sort_type = '';
|
||||
}
|
||||
|
||||
const handleDetail = (id) => {
|
||||
router.push({
|
||||
name: 'user-detail',
|
||||
query: {id: id}
|
||||
})
|
||||
}
|
||||
|
||||
const formatColumnClass = (row, column) => {
|
||||
return row.class_text
|
||||
}
|
||||
|
||||
const formatColumnUploaded = (row, column) => {
|
||||
return row.uploaded_text
|
||||
}
|
||||
const formatColumnDownloaded = (row, column) => {
|
||||
return row.downloaded_text
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
multipleTable,
|
||||
extraData,
|
||||
handleSelectionChange,
|
||||
handleAdd,
|
||||
handleEdit,
|
||||
handleDelete,
|
||||
handleDetail,
|
||||
fetchTableData,
|
||||
changePage,
|
||||
handleSortChange,
|
||||
formatColumnClass,
|
||||
formatColumnUploaded,
|
||||
formatColumnDownloaded,
|
||||
handleReset
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
Vendored
-8
@@ -1,8 +0,0 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [vue()],
|
||||
base: '/admin/'
|
||||
})
|
||||
@@ -1,270 +0,0 @@
|
||||
<?php
|
||||
/***************************************************************************
|
||||
|
||||
Browser Emulating file functions v2.0
|
||||
(c) Kai Blankenhorn
|
||||
www.bitfolge.de/en
|
||||
kaib@bitfolge.de
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
****************************************************************************
|
||||
|
||||
|
||||
Changelog:
|
||||
|
||||
v2.0 03-09-03
|
||||
added a wrapper class; this has the advantage that you no longer need
|
||||
to specify a lot of parameters, just call the methods to set
|
||||
each option
|
||||
added option to use a special port number, may be given by setPort or
|
||||
as part of the URL (e.g. server.com:80)
|
||||
added getLastResponseHeaders()
|
||||
|
||||
v1.5
|
||||
added Basic HTTP user authorization
|
||||
minor optimizations
|
||||
|
||||
v1.0
|
||||
initial release
|
||||
|
||||
|
||||
|
||||
***************************************************************************/
|
||||
/**
|
||||
* BrowserEmulator class. Provides methods for opening urls and emulating
|
||||
* a web browser request.
|
||||
**/
|
||||
class BrowserEmulator {
|
||||
|
||||
var $headerLines = Array ();
|
||||
var $postData = Array ();
|
||||
var $authUser = "";
|
||||
var $authPass = "";
|
||||
var $port;
|
||||
var $lastResponse = Array ();
|
||||
|
||||
function __construct () {
|
||||
$this->resetHeaderLines ();
|
||||
$this->resetPort ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a single header field to the HTTP request header. The resulting header
|
||||
* line will have the format
|
||||
* $name: $value\n
|
||||
**/
|
||||
function addHeaderLine ($name, $value) {
|
||||
$this->headerLines[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all custom header lines. This will not remove the User-Agent header field,
|
||||
* which is necessary for correct operation.
|
||||
**/
|
||||
function resetHeaderLines () {
|
||||
$this->headerLines = Array ();
|
||||
|
||||
/*******************************************************************************/
|
||||
/************** YOU MAX SET THE USER AGENT STRING HERE *******************/
|
||||
/* */
|
||||
/* default is "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)", */
|
||||
/* which means Internet Explorer 6.0 on WinXP */
|
||||
|
||||
$this->headerLines["User-Agent"] =
|
||||
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
|
||||
|
||||
/*******************************************************************************/
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a post parameter. Post parameters are sent in the body of an HTTP POST request.
|
||||
**/
|
||||
function addPostData ($name, $value) {
|
||||
$this->postData[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all custom post parameters.
|
||||
**/
|
||||
function resetPostData () {
|
||||
$this->postData = Array ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an auth user and password to use for the request.
|
||||
* Set both as empty strings to disable authentication.
|
||||
**/
|
||||
function setAuth ($user, $pass) {
|
||||
$this->authUser = $user;
|
||||
$this->authPass = $pass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects a custom port to use for the request.
|
||||
**/
|
||||
function setPort ($portNumber) {
|
||||
$this->port = $portNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the port used for request to the HTTP default (80).
|
||||
**/
|
||||
function resetPort () {
|
||||
$this->port = 80;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an fopen call to $url with the parameters set by previous member
|
||||
* method calls. Send all set headers, post data and user authentication data.
|
||||
* Returns a file handle on success, or false on failure.
|
||||
**/
|
||||
function fopen ($url) {
|
||||
$debug = false;
|
||||
|
||||
$this->lastResponse = Array ();
|
||||
|
||||
preg_match ("~([a-z]*://)?([^:^/]*)(:([0-9]{1,5}))?(/.*)?~i", $url,
|
||||
$matches);
|
||||
if ($debug)
|
||||
var_dump ($matches);
|
||||
$protocol = $matches[1];
|
||||
$server = $matches[2];
|
||||
$port = $matches[4];
|
||||
$path = $matches[5];
|
||||
if ($port != "") {
|
||||
$this->setPort ($port);
|
||||
}
|
||||
if ($path == "")
|
||||
$path = "/";
|
||||
$socket = false;
|
||||
$socket = fsockopen ($server, $this->port);
|
||||
if ($socket) {
|
||||
$this->headerLines["Host"] = $server;
|
||||
|
||||
if ($this->authUser != "" AND $this->authPass != "") {
|
||||
$headers["Authorization"] =
|
||||
"Basic ".base64_encode ($this->authUser.":".$this->
|
||||
authPass);
|
||||
}
|
||||
|
||||
if (count ($this->postData) == 0) {
|
||||
$request = "GET $path HTTP/1.0\r\n";
|
||||
}
|
||||
else {
|
||||
$request = "POST $path HTTP/1.0\r\n";
|
||||
}
|
||||
|
||||
if ($debug)
|
||||
echo $request;
|
||||
fputs ($socket, $request);
|
||||
|
||||
if (count ($this->postData) > 0) {
|
||||
$PostStringArray = Array ();
|
||||
foreach ($this->postData AS $key => $value) {
|
||||
$PostStringArray[] = "$key=$value";
|
||||
}
|
||||
$PostString = join ("&", $PostStringArray);
|
||||
$this->headerLines["Content-Length"] =
|
||||
strlen ($PostString);
|
||||
}
|
||||
|
||||
foreach ($this->headerLines AS $key => $value) {
|
||||
if ($debug)
|
||||
echo "$key: $value\n";
|
||||
fputs ($socket, "$key: $value\r\n");
|
||||
}
|
||||
if ($debug)
|
||||
echo "\n";
|
||||
fputs ($socket, "\r\n");
|
||||
if (count ($this->postData) > 0) {
|
||||
if ($debug)
|
||||
echo "$PostString";
|
||||
fputs ($socket, $PostString."\r\n");
|
||||
}
|
||||
}
|
||||
if ($debug)
|
||||
echo "\n";
|
||||
if ($socket) {
|
||||
$line = fgets ($socket, 1000);
|
||||
if ($debug)
|
||||
echo $line;
|
||||
$this->lastResponse[] = $line;
|
||||
$status = substr ($line, 9, 3);
|
||||
while (trim ($line = fgets ($socket, 1000)) != "") {
|
||||
if ($debug)
|
||||
echo "$line";
|
||||
$this->lastResponse[] = $line;
|
||||
if ($status == "401" AND strpos ($line, "WWW-Authenticate: Basic realm=\"") === 0) {
|
||||
fclose ($socket);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an file call to $url with the parameters set by previous member
|
||||
* method calls. Send all set headers, post data and user authentication data.
|
||||
* Returns the requested file as an array on success, or false on failure.
|
||||
**/
|
||||
function file ($url) {
|
||||
$file = Array ();
|
||||
$socket = $this->fopen ($url);
|
||||
if ($socket) {
|
||||
$file = Array ();
|
||||
while (!feof ($socket)) {
|
||||
$file[] = fgets ($socket, 10000);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
return $file;
|
||||
}
|
||||
|
||||
function getLastResponseHeaders () {
|
||||
return $this->lastResponse;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// example code
|
||||
/*
|
||||
$be = new BrowserEmulator();
|
||||
//$be->addHeaderLine("Referer", "http://previous.server.com/");
|
||||
//$be->addHeaderLine("Accept-Encoding", "x-compress; x-zip");
|
||||
//$be->addPostData("Submit", "OK");
|
||||
//$be->addPostData("item", "42");
|
||||
//$be->setAuth("admin", "secretpass");
|
||||
// also possible:
|
||||
// $be->setPort(10080);
|
||||
|
||||
$file = $be->fopen("http://us.imdb.com/Title?0209144");
|
||||
$response = $be->getLastResponseHeaders();
|
||||
|
||||
while ($line = fgets($file, 1024)) {
|
||||
// do something with the file
|
||||
echo $line;
|
||||
}
|
||||
fclose($file);
|
||||
|
||||
*/
|
||||
|
||||
?>
|
||||
@@ -1,114 +0,0 @@
|
||||
<?php
|
||||
|
||||
class info_extractor{
|
||||
function __construct(){}
|
||||
|
||||
/** truncate a given string
|
||||
* @method truncate
|
||||
* @param string src(source string), string s_str(starting needle), string e_str(ending needle, "" for open end), integer e_offset(optional where to start finding the $e_str)
|
||||
* @return string trucated string
|
||||
*/
|
||||
function truncate($src, $s_str, $e_str = "", $e_offset = 0)
|
||||
{
|
||||
$ret = "";
|
||||
$e_offset = strlen($s_str);
|
||||
|
||||
$ret = strstr($src, $s_str);
|
||||
if($ret == false)
|
||||
return "";
|
||||
|
||||
if($e_str != "")
|
||||
{
|
||||
$endpos = strpos ($ret , $e_str, $e_offset);
|
||||
if($endpos == false)
|
||||
return "";
|
||||
}
|
||||
|
||||
return substr($ret, strlen($s_str), $endpos - strlen($s_str));
|
||||
}
|
||||
|
||||
/** find a certain pattern in a given string
|
||||
* @method find_pattern
|
||||
* @param string src(source string), string regex(regular expression), boolean multiple(if pattern has multiple occurance), array string res_where_array(where the res should be in regex, order of res_where_array and res_array should be the same, for example: res_array could be "array(array('Name' => '', 'Cloudsize' => '', 'Link' => ''))", then the first element in res_where_array could be, say, "3", which corrsponds to 'Name'), array string res_array(one or multi-dimensional array for the extraced info)
|
||||
* @return boolean found_pattern
|
||||
*/
|
||||
function find_pattern($src, $regex, $multiple, $res_where_array)
|
||||
{
|
||||
$res_array = array();
|
||||
if($multiple == true)
|
||||
{
|
||||
if(!preg_match_all($regex,$src,$info_block,PREG_SET_ORDER))
|
||||
return false;
|
||||
else
|
||||
{
|
||||
$counter_infoblock = 0;
|
||||
foreach($info_block as $info)
|
||||
{
|
||||
$counter_reswhere = 0;
|
||||
foreach ($res_where_array as $res_where_array_each)
|
||||
{
|
||||
$res_array[$counter_infoblock][$counter_reswhere] = $info[$res_where_array_each];
|
||||
$counter_reswhere++;
|
||||
}
|
||||
$counter_infoblock++;
|
||||
}
|
||||
return $res_array;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!preg_match($regex,$src,$info))
|
||||
return false;
|
||||
else
|
||||
{
|
||||
$counter = 0;
|
||||
foreach ($res_where_array as $res_where_array_each)
|
||||
{
|
||||
$res_array[$counter] = $info[$res_where_array_each];
|
||||
$counter++;
|
||||
}
|
||||
return $res_array;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** remove a given pattern from a given string
|
||||
* @method truncate
|
||||
* @param string src(source string), string $regex_s(starting needle), string $regex_e(ending needle), integer max(set it to 1 if you are sure the pattern only occurs once, otherwise, it indicates the maximum possible occurance in case of dead loop), boolean all(if remove all or just the pattern)
|
||||
* @return string processed string
|
||||
*/
|
||||
function remove($src, $regex_s, $regex_e, $max = 100, $all = false)
|
||||
{
|
||||
$ret = "";
|
||||
$ret = preg_replace("/" . $regex_s . "((\s|.)+?)" . $regex_e . "/i", ($all == false ? "\\1" : ""), $src, $max);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/** trim a given array of strings types from a given string
|
||||
* @method trim_str
|
||||
* @param string src(source string), string array regex_trim_array(specifies strings to be trimmed), integersafe_counter(maximum possible occurance of string to be trimmed)
|
||||
* @return string processed string
|
||||
*/
|
||||
function trim_str($src, $regex_trim_array, $safe_counter =10)
|
||||
{
|
||||
$ret = "";
|
||||
|
||||
while($safe_counter>0)
|
||||
{
|
||||
$safe_counter--;
|
||||
$break_flag = true;
|
||||
foreach($regex_trim_array as $regex_trim_array_each)
|
||||
{
|
||||
$ret = preg_replace("/^((" . $regex_trim_array_each . ")*)((\s|.)+?)((" . $regex_trim_array_each . ")*)$/i","\\3", trim($src), 1);
|
||||
if($ret != $src)
|
||||
$break_flag = false;
|
||||
$src = $ret;
|
||||
}
|
||||
if($break_flag)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
|
||||
$mechs = array('LOGIN', 'PLAIN', 'CRAM_MD5');
|
||||
|
||||
foreach ($mechs as $mech) {
|
||||
if (!defined($mech)) {
|
||||
define($mech, $mech);
|
||||
} elseif (constant($mech) != $mech) {
|
||||
trigger_error(sprintf("Constant %s already defined, can't proceed", $mech), E_USER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* SASL Mechanisms
|
||||
* @package SASL
|
||||
* @author Fredrik Haugbergsmyr <smtp.lib@lagnut.net>
|
||||
*/
|
||||
$rootpath = './';
|
||||
require_once ($rootpath . 'include/smtp/net.const.php');
|
||||
|
||||
/**
|
||||
* @version 0.0.1
|
||||
* @access public
|
||||
* @todo phpdoc
|
||||
*/
|
||||
class sasl
|
||||
{
|
||||
|
||||
|
||||
function _hmac_md5($key, $data)
|
||||
{
|
||||
if (strlen($key) > 64) {
|
||||
$key = pack('H32', md5($key));
|
||||
}
|
||||
|
||||
if (strlen($key) < 64) {
|
||||
$key = str_pad($key, 64, chr(0));
|
||||
}
|
||||
|
||||
$k_ipad = substr($key, 0, 64) ^ str_repeat(chr(0x36), 64);
|
||||
$k_opad = substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64);
|
||||
|
||||
$inner = pack('H32', md5($k_ipad . $data));
|
||||
$digest = md5($k_opad . $inner);
|
||||
|
||||
return $digest;
|
||||
}
|
||||
|
||||
function cram_md5($user, $pass, $challenge)
|
||||
{
|
||||
var_dump($challenge);
|
||||
$chall = base64_decode($challenge);
|
||||
var_dump($chall);
|
||||
return base64_encode(sprintf('%s %s', $user, $this->_hmac_md5($pass, $chall)));
|
||||
}
|
||||
|
||||
function plain($username, $password)
|
||||
{
|
||||
return base64_encode(sprintf('%c%s%c%s', 0, $username, 0, $password));
|
||||
}
|
||||
|
||||
function login($input)
|
||||
{
|
||||
return base64_encode(sprintf('%s', $input));
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -1,531 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Allows users to send email without e-mailserver on the localmachine
|
||||
* @package SMTP
|
||||
* @author Fredrik Haugbergsmyr <smtp.lib@lagnut.net>
|
||||
*/
|
||||
|
||||
require_once ('net.const.php');
|
||||
|
||||
/**
|
||||
* @version 0.0.2.2
|
||||
* @access public
|
||||
* @todo split messages, attachments
|
||||
*/
|
||||
class smtp
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* lagnut-smtp version, send in the headers
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $_version = '0.0.2.2';
|
||||
|
||||
|
||||
/**
|
||||
* Turn debugon / off
|
||||
*
|
||||
* @var bool
|
||||
* @access private
|
||||
*/
|
||||
var $_debug = false;
|
||||
|
||||
|
||||
/**
|
||||
* Serverconnection resource
|
||||
*
|
||||
* @var resource
|
||||
* @access private
|
||||
*/
|
||||
var $_connection = null;
|
||||
|
||||
|
||||
/**
|
||||
* E-mailheaders
|
||||
*
|
||||
* @var array headers
|
||||
* @access private
|
||||
*/
|
||||
var $_hdrs = array();
|
||||
|
||||
|
||||
/**
|
||||
* E-mailbody
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $_body = '';
|
||||
|
||||
|
||||
/**
|
||||
* Default Content type
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $_mime = 'text/html';
|
||||
|
||||
|
||||
/**
|
||||
* Default Charset
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $_charset = 'UTF-8';
|
||||
|
||||
/**
|
||||
* Default Transfer-Content-Encoding
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $_CTEncoding = 'base64';
|
||||
|
||||
// These are actually not necessary, but for the shitty eYou email system
|
||||
/**
|
||||
* Charset for Special Case
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $_charset_eYou = 'GBK';
|
||||
|
||||
/**
|
||||
* Charset for Special Case
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $_specialcase = 'eYou';
|
||||
|
||||
/**
|
||||
* Class contruction, sets client headers
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function smtp($charset = 'UTF-8', $specialcase = "")
|
||||
{
|
||||
$this->_specialcase = $specialcase;
|
||||
$this->_charset = $charset;
|
||||
$this->_add_hdr('X-Mailer', sprintf('LAGNUT-SMTP/%s', $this->_version));
|
||||
$this->_add_hdr('User-Agent', sprintf('LAGNUT-SMTP/%s', $this->_version));
|
||||
$this->_add_hdr('MIME-Version', '1.0');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Turn debugging on/off
|
||||
*
|
||||
* @access public
|
||||
* @param bool $debug command
|
||||
*/
|
||||
function debug($debug)
|
||||
{
|
||||
$this->_debug = (bool)$debug;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clean input to prevent injection
|
||||
*
|
||||
* @param string $input User data
|
||||
*/
|
||||
function _clean(&$input)
|
||||
{
|
||||
if (!is_string($input)) {
|
||||
return false;
|
||||
}
|
||||
$input = urldecode($input);
|
||||
$input = str_replace("\n", '', str_replace("\r", '', $input));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send command to server
|
||||
*
|
||||
* @access private
|
||||
* @param string $cmdcommand
|
||||
* @param optional $data data
|
||||
*/
|
||||
function _cmd($cmd, $data = false)
|
||||
{
|
||||
$this->_clean($cmd);
|
||||
$this->_clean($data);
|
||||
|
||||
if ($this->_is_closed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$data) {
|
||||
$command = sprintf("%s\r\n", $cmd);
|
||||
}else {
|
||||
$command = sprintf("%s: %s\r\n", $cmd,$data);
|
||||
}
|
||||
|
||||
fwrite($this->_connection, $command);
|
||||
$resp = $this->_read();
|
||||
if ($this->_debug){
|
||||
printf($command);
|
||||
printf($resp);
|
||||
}
|
||||
if ($this->_is_closed($resp)) {
|
||||
return false;
|
||||
}
|
||||
return $resp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Collects header
|
||||
*
|
||||
* @access private
|
||||
* @param string$key
|
||||
* @param string $data
|
||||
*/
|
||||
function _add_hdr($key, $data)
|
||||
{
|
||||
$this->_clean($key);
|
||||
$this->_clean($data);
|
||||
$this->_hdrs[$key] = sprintf("%s: %s\r\n", $key, $data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read server output
|
||||
*
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
function _read()
|
||||
{
|
||||
if ($this->_is_closed()) {
|
||||
return false;
|
||||
}
|
||||
$o = '';
|
||||
do {
|
||||
$str = @fgets($this->_connection, 515);
|
||||
if (!$str) {
|
||||
break;
|
||||
}
|
||||
$o .= $str;
|
||||
if (substr($str, 3, 1) == ' ') {
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if server denies more commands
|
||||
*
|
||||
* @access private
|
||||
* @param $int
|
||||
* @return bool true if connection is closed
|
||||
*/
|
||||
function _is_closed($response = false)
|
||||
{
|
||||
if (!$this->_connection) {
|
||||
return true;
|
||||
}
|
||||
if (isset($response{0}) && ($response{0} == 4|| $response{0}== 5)) {
|
||||
$this->close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Open connection to server
|
||||
*
|
||||
* @access public
|
||||
* @param string $server SMTP server
|
||||
* @param int $port Server port
|
||||
*/
|
||||
function open($server, $port = 25)
|
||||
{
|
||||
$this->_connection = fsockopen($server, $port, $e, $er, 8);
|
||||
|
||||
if ($this->_is_closed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$init= $this->_read();
|
||||
if ($this->_debug){
|
||||
printf($init);
|
||||
}
|
||||
|
||||
if ($this->_is_closed($init)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$lhost = (isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : '127.0.0.1');
|
||||
|
||||
if (strpos($init,'ESMTP') === false){
|
||||
$this->_cmd('HELO '. gethostbyaddr($lhost));
|
||||
} else {
|
||||
$this->_cmd('EHLO '. gethostbyaddr($lhost));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Start TLS communication
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function start_tls()
|
||||
{
|
||||
if (!function_exists('stream_socket_enable_crypto')) {
|
||||
trigger_error('TLS is not supported', E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$this->_cmd('STARTTLS');
|
||||
stream_socket_enable_crypto($this->_connection, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs SMTP authentication
|
||||
*
|
||||
* @access public
|
||||
* @param string $username username
|
||||
* @param string $password password
|
||||
* @param int authentication mecanism
|
||||
*/
|
||||
function auth($username, $password, $type = LOGIN)
|
||||
{
|
||||
|
||||
include_once ('sasl.lib.php');
|
||||
$sasl =& new sasl($sasl, $username, $password);
|
||||
switch ($type) {
|
||||
case PLAIN:
|
||||
$this->_cmd('AUTH PLAIN');
|
||||
$this->_cmd($sasl->plain($username, $password));
|
||||
break;
|
||||
case LOGIN:
|
||||
$this->_cmd('AUTH LOGIN');
|
||||
$this->_cmd($sasl->login($username));
|
||||
$this->_cmd($sasl->login($password));
|
||||
break;
|
||||
case CRAM_MD5:
|
||||
$resp = explode(' ', $this->_cmd('AUTH CRAM-MD5'));
|
||||
$this->_cmd($sasl->cram_md5($username, $password, trim($resp[1])));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closes connection to the server
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function close()
|
||||
{
|
||||
if ($this->_is_closed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->_cmd('RSET');
|
||||
$this->_cmd('QUIT');
|
||||
fclose($this->_connection);
|
||||
$this->_connection = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* E-mail sender
|
||||
*
|
||||
* @access public
|
||||
* @param string $from Sender
|
||||
*/
|
||||
function from($email, $name = '')
|
||||
{
|
||||
$from = !empty($name) ? sprintf('%s <%s>', $name, $email) : $email;
|
||||
$this->_cmd('MAIL FROM', sprintf('<%s>', $email));
|
||||
$this->_add_hdr('FROM', $from);
|
||||
$this->_add_hdr('Return-path', $email);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set BCC header
|
||||
*
|
||||
* @access public
|
||||
* @param string $tolist recipients whose email address should be concealed
|
||||
*/
|
||||
function bcc($tolist)
|
||||
{
|
||||
$this->_add_hdr('Bcc', $tolist);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send reply-to header
|
||||
*
|
||||
* @param string $to
|
||||
*/
|
||||
function reply_to($email, $name = '')
|
||||
{
|
||||
$to = !empty($name) ? sprintf('%s <%s>', $name, $email) : $email;
|
||||
$this->_add_hdr('REPLY-TO', $to);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* E-mail reciever
|
||||
*
|
||||
* @access public
|
||||
* @param string $to Reciever
|
||||
*/
|
||||
function to($email, $name = '')
|
||||
{
|
||||
$to = !empty($name) ? sprintf('%s <%s>', $name, $email) : $email;
|
||||
$this->_cmd('RCPT TO', sprintf('<%s>', $email));
|
||||
$this->_add_hdr('TO', $to);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiple E-mail reciever
|
||||
*
|
||||
* @access public
|
||||
* @param string $email Reciever, with out other recepients info disclosed
|
||||
*/
|
||||
function multi_to($email)
|
||||
{
|
||||
$this->_cmd('RCPT TO', sprintf('<%s>', $email));
|
||||
}
|
||||
|
||||
/**
|
||||
* E-mail reciever
|
||||
*
|
||||
* @access public
|
||||
* @param string $email TO head on mass mailing
|
||||
*/
|
||||
function multi_to_head($to)
|
||||
{
|
||||
$this->_add_hdr('TO', $to);
|
||||
}
|
||||
|
||||
/**
|
||||
* MIME type
|
||||
*
|
||||
* @access public
|
||||
* @param string $mime MIME type
|
||||
*/
|
||||
function mime_charset($mime = 'text/html',$charset = 'UTF-8')
|
||||
{
|
||||
$this->_charset = $charset;
|
||||
$this->_mime = $mime;
|
||||
$this->_add_hdr('Content-type', sprintf('%s; charset=%s', $this->_mime, $this->_charset));
|
||||
}
|
||||
|
||||
/**
|
||||
* MIME Content-Transfer-Encoding
|
||||
*
|
||||
* @access public
|
||||
* @param string $mime MIME type
|
||||
*/
|
||||
function mime_content_transfer_encoding($CTEncoding = 'base64')
|
||||
{
|
||||
$this->_CTEncoding = $CTEncoding;
|
||||
$this->_add_hdr('Content-Transfer-Encoding', sprintf('%s', $this->_CTEncoding));
|
||||
}
|
||||
|
||||
/**
|
||||
* E-mail subject
|
||||
*
|
||||
* @access public
|
||||
* @param string $subject subject
|
||||
*/
|
||||
function subject($subject)
|
||||
{
|
||||
$this->_clean($subject);
|
||||
|
||||
if($this->_specialcase = "")
|
||||
$this->_add_hdr('SUBJECT', $this->encode_hdrs($subject));
|
||||
elseif($this->_specialcase = "eYou")
|
||||
{
|
||||
$temp = $this->_charset;
|
||||
$this->_charset = $this->_charset_eYou;
|
||||
$this->_add_hdr('SUBJECT', $this->encode_hdrs($subject));
|
||||
$this->_charset = $temp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* E-mail body
|
||||
*
|
||||
* @access public
|
||||
* @param string $body body
|
||||
*/
|
||||
function body($body)
|
||||
{
|
||||
$body = preg_replace("/([\n|\r])\.([\n|\r])/", "$1..$2", $body);
|
||||
|
||||
if($this->_CTEncoding == 'base64')
|
||||
$this->_body = sprintf("\r\n%s", base64_encode($body));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send the mail
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function send()
|
||||
{
|
||||
$resp = $this->_cmd('DATA');
|
||||
if ($this->_is_closed($resp)) {
|
||||
$this->close();
|
||||
return false;
|
||||
}
|
||||
foreach ($this->_hdrs as $header) {
|
||||
fwrite($this->_connection, $header);
|
||||
if ($this->_debug) {
|
||||
printf($header);
|
||||
}
|
||||
}
|
||||
fwrite($this->_connection,$this->_body);
|
||||
fwrite($this->_connection, "\r\n.\r\n");
|
||||
$resp = trim($this->_read());
|
||||
if ($this->_debug){
|
||||
printf("%s\r\n", $this->_body);
|
||||
printf("\r\n.\r\n");
|
||||
printf('%s', $resp);
|
||||
}
|
||||
if ((int)$resp{0} != 2) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* encode headers
|
||||
*
|
||||
* @access private
|
||||
* @param string $input
|
||||
* @return string
|
||||
*/
|
||||
function encode_hdrs($input)
|
||||
{
|
||||
$replacement = preg_replace('/([\x80-\xFF])/e', '"=" . strtoupper(dechex(ord("\1")))', $input);
|
||||
|
||||
$input = str_replace($input, sprintf('=?%s?Q?%s?=', $this->_charset, $replacement), $input);
|
||||
return $input;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user