mirror of
https://github.com/lkddi/nexusphp.git
synced 2026-04-23 11:27:24 +08:00
add backup and admin dist
This commit is contained in:
+2
-2
@@ -1,5 +1,5 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
*.local
|
||||
.env.development
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
.el-card[data-v-0a6d742e]{margin-bottom:20px}.table-base-info[data-v-0a6d742e]{width:100%;text-align:left}.table-base-info tr th[data-v-0a6d742e]{padding-bottom:10px}.table-base-info tr td[data-v-0a6d742e]{padding:10px 0}
|
||||
Vendored
+1
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
+1
@@ -0,0 +1 @@
|
||||
import{o as n,c as o}from"./index.ad419675.js";const r={};r.render=function(r,e){return n(),o("div",null,"Agent Allow Form")};export default r;
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
var e=Object.defineProperty,a=Object.prototype.hasOwnProperty,r=Object.getOwnPropertySymbols,l=Object.prototype.propertyIsEnumerable,o=(a,r,l)=>r in a?e(a,r,{enumerable:!0,configurable:!0,writable:!0,value:l}):a[r]=l,t=(e,t)=>{for(var s in t||(t={}))a.call(t,s)&&o(e,s,t[s]);if(r)for(var s of r(t))l.call(t,s)&&o(e,s,t[s]);return e};import{r as s,a as d,j as m,n as u,t as n,q as p,s as i,u as f,b as c,p as w,d as b,e as y,o as _,c as D,f as V,g as v,i as h}from"./index.ad419675.js";const x={name:"UserForm",setup(){const{proxy:e}=p();console.log("proxy",e);const a=s(null),r=i(),l=f(),{id:o}=r.query,w=d({id:o,formData:{username:"",email:"",password:"",password_confirmation:""},rules:{username:[{required:"true"}],email:[{required:"true",type:"email"}],password:[{required:"true",min:6,max:40}],password_confirmation:[{required:"true",min:6,max:40}]}});m((()=>{})),u((()=>{}));return t(t({},n(w)),{formRef:a,submitAdd:()=>{a.value.validate((async e=>{if(e){let e=w.formData;await c.storeUser(e),await l.push({name:"user"})}}))}})}},U=v();w("data-v-21744c02");const j=h("Submit");b();const q=U(((e,a,r,l,o,t)=>{const s=y("el-input"),d=y("el-form-item"),m=y("el-button"),u=y("el-form"),n=y("el-col"),p=y("el-row");return _(),D("div",null,[V(p,null,{default:U((()=>[V(n,{span:12},{default:U((()=>[V(u,{model:e.formData,rules:e.rules,ref:"formRef","label-width":"200px",class:"formData"},{default:U((()=>[V(d,{label:"Username",prop:"username"},{default:U((()=>[V(s,{modelValue:e.formData.username,"onUpdate:modelValue":a[1]||(a[1]=a=>e.formData.username=a),placeholder:""},null,8,["modelValue"])])),_:1}),V(d,{label:"Email",prop:"email"},{default:U((()=>[V(s,{modelValue:e.formData.email,"onUpdate:modelValue":a[2]||(a[2]=a=>e.formData.email=a),placeholder:""},null,8,["modelValue"])])),_:1}),V(d,{label:"Password",prop:"password"},{default:U((()=>[V(s,{type:"password",modelValue:e.formData.password,"onUpdate:modelValue":a[3]||(a[3]=a=>e.formData.password=a),placeholder:""},null,8,["modelValue"])])),_:1}),V(d,{label:"Password Confirmation",prop:"password_confirmation"},{default:U((()=>[V(s,{type:"password",modelValue:e.formData.password_confirmation,"onUpdate:modelValue":a[4]||(a[4]=a=>e.formData.password_confirmation=a),placeholder:""},null,8,["modelValue"])])),_:1}),V(d,null,{default:U((()=>[V(m,{type:"primary",onClick:a[5]||(a[5]=e=>l.submitAdd())},{default:U((()=>[j])),_:1})])),_:1})])),_:1},8,["model","rules"])])),_:1})])),_:1})])}));x.render=q,x.__scopeId="data-v-21744c02";export default x;
|
||||
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
@@ -0,0 +1 @@
|
||||
.swiper-container[data-v-79c0c4a2]{min-height:100%}.el-card.is-always-shadow[data-v-79c0c4a2]{min-height:100%!important}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
import{o as n,c as e}from"./index.ad419675.js";const o={};o.render=function(o,r){return n(),e("div",null,"Agent Allow Index")};export default o;
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
var e=Object.defineProperty,a=Object.prototype.hasOwnProperty,l=Object.getOwnPropertySymbols,t=Object.prototype.propertyIsEnumerable,o=(a,l,t)=>l in a?e(a,l,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[l]=t,r=(e,r)=>{for(var n in r||(r={}))a.call(r,n)&&o(e,n,r[n]);if(l)for(var n of l(r))t.call(r,n)&&o(e,n,r[n]);return e};import{r as n,j as s,b as d,t as u,u as p,v as i,p as c,d as m,e as b,k as g,o as f,c as h,f as C,m as y,g as w,i as S}from"./index.ad419675.js";import{u as v,r as D,a as _}from"./table.43f553f4.js";const x={name:"UserTable",setup(){const e=n(null),a=p(),l=v();s((()=>{console.log("UserTable onMounted"),t()}));const t=async()=>{l.loading=!0;let e=await d.listUser(l.query);D(e,l),l.loading=!1};return r(r({},u(l)),{multipleTable:e,handleSelectionChange:e=>{l.multipleSelection=e},handleAdd:()=>{a.push({name:"user-form"})},handleEdit:e=>{a.push({name:"user-form",query:{id:e}})},handleDelete:async e=>{let a=await d.deleteExam(e);i.success(a.msg),l.query.page=1,await t()},handleDetail:e=>{a.push({name:"user-detail",query:{id:e}})},fetchTableData:t,changePage:e=>{l.query.page=e,t()},handleSortChange:e=>{_(e,l),t()},formatColumnClass:(e,a)=>e.class_text,formatColumnUploaded:(e,a)=>e.uploaded_text,formatColumnDownloaded:(e,a)=>e.downloaded_text})}},j=w();c("data-v-ae65dbc0");const k={class:"header"},P=S("Add");m();const U=j(((e,a,l,t,o,r)=>{const n=b("el-button"),s=b("el-table-column"),d=b("el-table"),u=b("el-pagination"),p=b("el-card"),i=g("loading");return f(),h(p,null,{header:j((()=>[C("div",k,[C(n,{type:"primary",size:"small",icon:"el-icon-plus",onClick:t.handleAdd},{default:j((()=>[P])),_:1},8,["onClick"])])])),default:j((()=>[y(C(d,{ref:"multipleTable",data:e.tableData,"tooltip-effect":"dark",onSortChange:t.handleSortChange,onSelectionChange:t.handleSelectionChange},{default:j((()=>[C(s,{type:"selection",width:"55"}),C(s,{prop:"id",label:"Id",width:"60",sortable:"custom"}),C(s,{prop:"username",label:"Username",sortable:"custom"}),C(s,{prop:"email",label:"Email"}),C(s,{prop:"class",label:"Class",sortable:"custom",formatter:t.formatColumnClass},null,8,["formatter"]),C(s,{prop:"uploaded",label:"Uploaded",sortable:"custom",formatter:t.formatColumnUploaded},null,8,["formatter"]),C(s,{prop:"downloaded",label:"Downloaded",sortable:"custom",formatter:t.formatColumnDownloaded},null,8,["formatter"]),C(s,{prop:"bonus",label:"Bonus"}),C(s,{prop:"status",label:"Status"}),C(s,{prop:"added",label:"Added"}),C(s,{label:"Action",width:"100"},{default:j((e=>[C("a",{style:{cursor:"pointer","margin-right":"10px"},onClick:a=>t.handleDetail(e.row.id)},"Detail",8,["onClick"])])),_:1})])),_:1},8,["data","onSortChange","onSelectionChange"]),[[i,e.loading]]),C(u,{background:"",layout:"prev, pager, next",total:e.total,"page-size":e.perPage,"current-page":e.currentPage,onCurrentChange:t.changePage},null,8,["total","page-size","current-page","onCurrentChange"])])),_:1})}));x.render=U,x.__scopeId="data-v-ae65dbc0";export default x;
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
var e=Object.defineProperty,a=Object.prototype.hasOwnProperty,t=Object.getOwnPropertySymbols,l=Object.prototype.propertyIsEnumerable,n=(a,t,l)=>t in a?e(a,t,{enumerable:!0,configurable:!0,writable:!0,value:l}):a[t]=l,r=(e,r)=>{for(var o in r||(r={}))a.call(r,o)&&n(e,o,r[o]);if(t)for(var o of t(r))l.call(r,o)&&n(e,o,r[o]);return e};import{r as o,j as i,b as s,t as d,u as p,v as c,p as u,d as g,e as m,k as f,o as b,c as h,f as y,m as w,g as x,i as C}from"./index.ad419675.js";import{u as _,r as v}from"./table.43f553f4.js";const T={name:"ExamTable",setup(){const e=o(null),a=p(),t=_();i((()=>{console.log("ExamTable onMounted"),l()}));const l=async()=>{t.loading=!0;let e=await s.listExam(t.query);v(e,t),t.loading=!1};return r(r({},d(t)),{multipleTable:e,handleSelectionChange:e=>{t.multipleSelection=e},handleAdd:()=>{a.push({name:"exam-form"})},handleEdit:e=>{a.push({path:"/exam-form",query:{id:e}})},handleDelete:async e=>{let a=await s.deleteExam(e);c.success(a.msg),t.query.page=1,await l()},fetchTableData:l,changePage:e=>{t.query.page=e,l()}})}},E=x();u("data-v-79c0c4a2");const j={class:"nexus-table-header"},k=y("div",{class:"left"},null,-1),D={class:"right"},P=C("Add"),S=y("a",{style:{cursor:"pointer"}},"Delete",-1);g();const O=E(((e,a,t,l,n,r)=>{const o=m("el-button"),i=m("el-table-column"),s=m("el-popconfirm"),d=m("el-table"),p=m("el-pagination"),c=m("el-card"),u=f("loading");return b(),h(c,{class:""},{header:E((()=>[y("div",j,[k,y("div",D,[y(o,{type:"primary",size:"small",icon:"el-icon-plus",onClick:l.handleAdd},{default:E((()=>[P])),_:1},8,["onClick"])])])])),default:E((()=>[w(y(d,{ref:"multipleTable",data:e.tableData,"tooltip-effect":"dark",onSelectionChange:l.handleSelectionChange},{default:E((()=>[y(i,{type:"selection",width:"55"}),y(i,{prop:"id",label:"Id",width:"50"}),y(i,{prop:"name",label:"Name"}),y(i,{label:"Indexes",width:"250px"},{default:E((e=>[y("p",{style:{"white-space":"pre-line"},innerHTML:e.row.indexes_formatted},null,8,["innerHTML"])])),_:1}),y(i,{prop:"begin",label:"Begin"}),y(i,{prop:"end",label:"End"}),y(i,{label:"Target users",width:"350px"},{default:E((e=>[y("p",{style:{"white-space":"pre-line"},innerHTML:e.row.filters_formatted},null,8,["innerHTML"])])),_:1}),y(i,{prop:"is_discovered_text",label:"Discovered"}),y(i,{prop:"status_text",label:"Status"}),y(i,{label:"Action",width:"100"},{default:E((e=>[y("a",{style:{cursor:"pointer","margin-right":"10px"},onClick:a=>l.handleEdit(e.row.id)},"Edit",8,["onClick"]),y(s,{title:"Confirm Delete ?",onConfirm:a=>l.handleDelete(e.row.id)},{reference:E((()=>[S])),_:2},1032,["onConfirm"])])),_:1})])),_:1},8,["data","onSelectionChange"]),[[u,e.loading]]),y(p,{background:"",layout:"prev, pager, next",total:e.total,"page-size":e.perPage,"current-page":e.currentPage,onCurrentChange:l.changePage},null,8,["total","page-size","current-page","onCurrentChange"])])),_:1})}));T.render=O,T.__scopeId="data-v-79c0c4a2";export default T;
|
||||
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+35
File diff suppressed because one or more lines are too long
Vendored
+1
@@ -0,0 +1 @@
|
||||
import{o as r,c as n}from"./index.ad419675.js";const o={};o.render=function(o,a){return r(),n("div",null,"Dashboard")};export default o;
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
var e=Object.defineProperty,o=Object.prototype.hasOwnProperty,a=Object.getOwnPropertySymbols,r=Object.prototype.propertyIsEnumerable,s=(o,a,r)=>a in o?e(o,a,{enumerable:!0,configurable:!0,writable:!0,value:r}):o[a]=r,l=(e,l)=>{for(var t in l||(l={}))o.call(l,t)&&s(e,t,l[t]);if(a)for(var t of a(l))r.call(l,t)&&s(e,t,l[t]);return e};import{r as t,a as n,t as u,u as d,b as i,l as m,p,d as c,e as f,o as v,c as b,f as y,w as g,g as F,h as w,i as h}from"./index.ad419675.js";const _={name:"Login",setup(){const e=t(null),o=d(),a=n({ruleForm:{username:"",password:""},checked:!0,rules:{username:[{required:"true"}],password:[{required:"true"}]}});return l(l({},u(a)),{loginForm:e,submitForm:async()=>{e.value.validate((e=>{if(!e)return console.log("error submit!!"),!1;i.login(a.ruleForm).then((e=>{console.log(e),m("token",e.data.token),m("userInfo",e.data),o.push({name:"dashboard"})}))}))},resetForm:()=>{e.value.resetFields()}})}},x=F();p("data-v-35112e00");const O={class:"login-body"},P={class:"login-container"},V=w('<div class="head" data-v-35112e00><img class="logo" src="http://demo.nexusphp.org/favicon.ico" data-v-35112e00><div class="name" data-v-35112e00><div class="title" data-v-35112e00>NexusPHP</div><div class="tips" data-v-35112e00>Management system</div></div></div>',1),j=h("Submit");c();const k=x(((e,o,a,r,s,l)=>{const t=f("el-input"),n=f("el-form-item"),u=f("el-button"),d=f("el-form");return v(),b("div",O,[y("div",P,[V,y(d,{"label-position":"top",rules:e.rules,model:e.ruleForm,ref:"loginForm",class:"login-form"},{default:x((()=>[y(n,{label:"Username",prop:"username"},{default:x((()=>[y(t,{type:"text",modelValue:e.ruleForm.username,"onUpdate:modelValue":o[1]||(o[1]=o=>e.ruleForm.username=o),modelModifiers:{trim:!0},autocomplete:"off",onKeyup:g(r.submitForm,["enter"])},null,8,["modelValue","onKeyup"])])),_:1}),y(n,{label:"Password",prop:"password"},{default:x((()=>[y(t,{type:"password",modelValue:e.ruleForm.password,"onUpdate:modelValue":o[2]||(o[2]=o=>e.ruleForm.password=o),modelModifiers:{trim:!0},autocomplete:"off",onKeyup:g(r.submitForm,["enter"])},null,8,["modelValue","onKeyup"])])),_:1}),y(n,{style:{"margin-top":"50px"}},{default:x((()=>[y(u,{style:{width:"100%"},type:"primary",onClick:r.submitForm},{default:x((()=>[j])),_:1},8,["onClick"])])),_:1})])),_:1},8,["rules","model"])])])}));_.render=k,_.__scopeId="data-v-35112e00";export default _;
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
.login-body[data-v-35112e00]{display:flex;justify-content:center;align-items:center;width:100%;background-color:#fff}.login-container[data-v-35112e00]{width:420px;height:500px;background-color:#fff;border-radius:4px;box-shadow:0 21px 41px 0 rgba(0,0,0,.2)}.head[data-v-35112e00]{display:flex;justify-content:center;align-items:center;padding:40px 0 20px 0}.head img[data-v-35112e00]{width:100px;height:100px;margin-right:20px}.head .title[data-v-35112e00]{font-size:28px;color:#1baeae;font-weight:700}.head .tips[data-v-35112e00]{font-size:12px;color:#999}.login-form[data-v-35112e00]{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
@@ -0,0 +1 @@
|
||||
import{a}from"./index.ad419675.js";const e=()=>a({loading:!1,query:{page:1,sort_field:"id",sort_type:"desc"},tableData:[],multipleSelection:[],total:0,currentPage:1,perPage:10}),t=(a,e)=>{e.tableData=a.data.data,e.page=a.data.meta.current_page,e.total=a.data.meta.total,e.currentPage=a.data.meta.current_page,e.perPage=a.data.meta.per_page},r=(a,e)=>{console.log("resetTableSort",a),e.query.page=1,e.query.sort_field=a.prop,e.query.sort_type=a.order};export{r as a,t as r,e as u};
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
var e=Object.defineProperty,a=Object.prototype.hasOwnProperty,t=Object.getOwnPropertySymbols,l=Object.prototype.propertyIsEnumerable,r=(a,t,l)=>t in a?e(a,t,{enumerable:!0,configurable:!0,writable:!0,value:l}):a[t]=l,n=(e,n)=>{for(var o in n||(n={}))a.call(n,o)&&r(e,o,n[o]);if(t)for(var o of t(n))l.call(n,o)&&r(e,o,n[o]);return e};import{r as o,j as s,b as d,t as u,u as i,v as m,p,d as c,e as g,k as f,o as h,c as b,m as C,f as y,g as x}from"./index.ad419675.js";import{u as w,r as v,a as S}from"./table.43f553f4.js";const _={name:"ExamUserTable",setup(){const e=o(null),a=i(),t=w();s((()=>{l()}));const l=async()=>{t.loading=!0;let e=await d.listExamUser(t.query);v(e,t),t.loading=!1};return n(n({},u(t)),{multipleTable:e,handleSelectionChange:e=>{t.multipleSelection=e},handleAdd:()=>{a.push({name:"user-form"})},handleEdit:e=>{a.push({name:"user-form",query:{id:e}})},handleDelete:async e=>{let a=await d.deleteExam(e);m.success(a.msg),t.query.page=1,await l()},handleDetail:e=>{a.push({name:"user-detail",query:{id:e}})},fetchTableData:l,changePage:e=>{t.query.page=e,l()},handleSortChange:e=>{S(e,t),l()},formatColumnUser:(e,a)=>e.user.username,formatColumnExam:(e,a)=>e.exam.name,formatColumnDownloaded:(e,a)=>e.downloaded_text})}},E=x();p("data-v-50017f64");const j=y("div",{class:"nexus-table-header"},[y("div",{class:"left"}),y("div",{class:"right"})],-1);c();const D=E(((e,a,t,l,r,n)=>{const o=g("el-table-column"),s=g("el-table"),d=g("el-pagination"),u=g("el-card"),i=f("loading");return h(),b(u,null,{header:E((()=>[j])),default:E((()=>[C(y(s,{ref:"multipleTable",data:e.tableData,"tooltip-effect":"dark",onSortChange:l.handleSortChange,onSelectionChange:l.handleSelectionChange},{default:E((()=>[y(o,{type:"selection",width:"55"}),y(o,{prop:"id",label:"Id",width:"60",sortable:"custom"}),y(o,{prop:"exam_id",label:"Exam",formatter:l.formatColumnExam},null,8,["formatter"]),y(o,{prop:"uid",label:"User",formatter:l.formatColumnUser},null,8,["formatter"]),y(o,{prop:"status_text",label:"Status"}),y(o,{prop:"created_at",label:"Created At"}),y(o,{label:"Action",width:"100"},{default:E((e=>[y("a",{style:{cursor:"pointer","margin-right":"10px"},onClick:a=>l.handleDetail(e.row.uid)},"Detail",8,["onClick"])])),_:1})])),_:1},8,["data","onSortChange","onSelectionChange"]),[[i,e.loading]]),y(d,{background:"",layout:"prev, pager, next",total:e.total,"page-size":e.perPage,"current-page":e.currentPage,onCurrentChange:l.changePage},null,8,["total","page-size","current-page","onCurrentChange"])])),_:1})}));_.render=D,_.__scopeId="data-v-50017f64";export default _;
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
.nexus-table-header[data-v-50017f64]{display:flex;justify-content:space-between}
|
||||
Vendored
BIN
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
<!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>Vite App</title>
|
||||
<script type="module" crossorigin src="/admin/assets/index.ad419675.js"></script>
|
||||
<link rel="stylesheet" href="/admin/assets/index.94df6daa.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
+3
-3
@@ -2,9 +2,9 @@
|
||||
"name": "admin",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"serve": "vite preview"
|
||||
"dev": "vite --mode development",
|
||||
"build": "vite build --mode production",
|
||||
"serve": "vite preview --mode preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.21.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="footer">
|
||||
<div class="left">Designed By Xiaomlove</div>
|
||||
<div class="left">NexusPHP v1.6.0-beta5</div>
|
||||
<div class="right">
|
||||
<a target="_blank" href="https://nexusphp.org/">nexusphp.org</a>
|
||||
</div>
|
||||
|
||||
Vendored
+1
@@ -2,6 +2,7 @@ import { createRouter, createWebHashHistory } from 'vue-router'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(), // hash模式:createWebHashHistory,history模式:createWebHistory
|
||||
base: '/admin/',
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
|
||||
Vendored
+13
-13
@@ -8,54 +8,54 @@ const api = {
|
||||
return axios.post('logout');
|
||||
},
|
||||
listAllowAgent: (params = {}) => {
|
||||
return axios.get('agent-allow', {params: params});
|
||||
return axios.get('agent-allows', {params: params});
|
||||
},
|
||||
storeAllowAgent: (params = {}) => {
|
||||
return axios.post('agent-allow', params);
|
||||
return axios.post('agent-allows', params);
|
||||
},
|
||||
updateAllowAgent: (id, params = {}) => {
|
||||
return axios.put('agent-allow/' + id, params);
|
||||
return axios.put('agent-allows/' + id, params);
|
||||
},
|
||||
getAllowAgent: (id) => {
|
||||
return axios.get('agent-allow/' + id);
|
||||
return axios.get('agent-allows/' + id);
|
||||
},
|
||||
deleteAllowAgent: (id) => {
|
||||
return axios.delete('agent-allow/' + id);
|
||||
return axios.delete('agent-allows/' + id);
|
||||
},
|
||||
|
||||
listUser: (params = {}) => {
|
||||
return axios.get('user', {params: params});
|
||||
return axios.get('users', {params: params});
|
||||
},
|
||||
getUser: (id, params = {}) => {
|
||||
return axios.get('user/' + id, {params: params});
|
||||
return axios.get('users/' + id, {params: params});
|
||||
},
|
||||
getUserBase: (params = {}) => {
|
||||
return axios.get('user-base', {params: params});
|
||||
},
|
||||
storeUser: (params = {}) => {
|
||||
return axios.post('user', params);
|
||||
return axios.post('users', params);
|
||||
},
|
||||
listUserMatchExams: (params = {}) => {
|
||||
return axios.get('user-match-exams', {params: params});
|
||||
},
|
||||
|
||||
listExam: (params = {}) => {
|
||||
return axios.get('exam', {params: params});
|
||||
return axios.get('exams', {params: params});
|
||||
},
|
||||
listExamIndex: (params = {}) => {
|
||||
return axios.get('exam-indexes', {params: params});
|
||||
},
|
||||
storeExam: (params = {}) => {
|
||||
return axios.post('exam', params);
|
||||
return axios.post('exams', params);
|
||||
},
|
||||
updateExam: (id, params = {}) => {
|
||||
return axios.put('exam/' + id, params);
|
||||
return axios.put('exams/' + id, params);
|
||||
},
|
||||
getExam: (id) => {
|
||||
return axios.get('exam/' + id);
|
||||
return axios.get('exams/' + id);
|
||||
},
|
||||
deleteExam: (id) => {
|
||||
return axios.delete('exam/' + id);
|
||||
return axios.delete('exams/' + id);
|
||||
},
|
||||
listClass: (params = {}) => {
|
||||
return axios.get('user-classes', {params: params});
|
||||
|
||||
Vendored
+3
-1
@@ -3,7 +3,9 @@ import { ElMessage } from 'element-plus'
|
||||
import {localGet} from "./index"
|
||||
import router from '../router/index'
|
||||
|
||||
axios.defaults.baseURL = 'http://nexus-php8.tinyhd.net/api'
|
||||
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'
|
||||
|
||||
@@ -31,6 +31,13 @@
|
||||
</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"
|
||||
@@ -108,6 +115,7 @@ export default {
|
||||
register_time_range: []
|
||||
},
|
||||
status: '',
|
||||
is_discovered: ''
|
||||
},
|
||||
rules: {
|
||||
name: [
|
||||
@@ -119,6 +127,9 @@ export default {
|
||||
status: [
|
||||
{ required: 'true',}
|
||||
],
|
||||
is_discovered: [
|
||||
{ required: 'true',}
|
||||
],
|
||||
},
|
||||
})
|
||||
onMounted( () => {
|
||||
@@ -133,6 +144,7 @@ export default {
|
||||
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()
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="Index"
|
||||
label="Indexes"
|
||||
width="250px"
|
||||
>
|
||||
<template #default="scope" >
|
||||
@@ -51,13 +51,20 @@
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="Target User"
|
||||
width="400px"
|
||||
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"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="status_text"
|
||||
label="Status"
|
||||
@@ -105,19 +112,6 @@ export default {
|
||||
setup() {
|
||||
const multipleTable = ref(null)
|
||||
const router = useRouter()
|
||||
// const state = reactive({
|
||||
// loading: false,
|
||||
// query: {
|
||||
// page: 1,
|
||||
// sort_field: 'id',
|
||||
// sort_type: 'desc'
|
||||
// },
|
||||
// tableData: [], // 数据列表
|
||||
// multipleSelection: [], // 选中项
|
||||
// total: 0, // 总条数
|
||||
// currentPage: 1, // 当前页
|
||||
// pageSize: 10 // 分页大小
|
||||
// })
|
||||
|
||||
const state = useTable()
|
||||
|
||||
@@ -125,21 +119,12 @@ export default {
|
||||
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 renderTableData = (res) => {
|
||||
// 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.pageSize = res.data.meta.per_page
|
||||
// state.loading = false
|
||||
// }
|
||||
const handleAdd = () => {
|
||||
router.push({ name: 'exam-form' })
|
||||
}
|
||||
@@ -152,7 +137,6 @@ export default {
|
||||
state.query.page = 1;
|
||||
await fetchTableData()
|
||||
}
|
||||
// 选择项
|
||||
const handleSelectionChange = (val) => {
|
||||
state.multipleSelection = val
|
||||
}
|
||||
@@ -160,14 +144,6 @@ export default {
|
||||
state.query.page = val
|
||||
fetchTableData()
|
||||
}
|
||||
const handleStatus = (id, status) => {
|
||||
axios.put(`/goods/status/${status}`, {
|
||||
ids: id ? [id] : []
|
||||
}).then(() => {
|
||||
ElMessage.success('修改成功')
|
||||
fetchTableData()
|
||||
})
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
multipleTable,
|
||||
@@ -177,7 +153,6 @@ export default {
|
||||
handleDelete,
|
||||
fetchTableData,
|
||||
changePage,
|
||||
handleStatus
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>Base Info</span>
|
||||
<span>Base info</span>
|
||||
</div>
|
||||
</template>
|
||||
<table class="table-base-info">
|
||||
@@ -59,7 +59,7 @@
|
||||
<el-card v-if="examInfo">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>Exam</span>
|
||||
<span>Exam on the way</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-row>
|
||||
@@ -70,11 +70,11 @@
|
||||
<td>{{examInfo.exam && examInfo.exam.name}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Created At</td>
|
||||
<td>Created at</td>
|
||||
<td>{{examInfo.created_at}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Exam Time</td>
|
||||
<td>Exam time</td>
|
||||
<td>{{examInfo.begin}} ~ {{examInfo.end}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
Vendored
+2
-1
@@ -3,5 +3,6 @@ import vue from '@vitejs/plugin-vue'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [vue()]
|
||||
plugins: [vue()],
|
||||
base: '/admin/'
|
||||
})
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Repositories\ToolRepository;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class BackuAll extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'backup:all';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Backup all data, include web root and database';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$rep = new ToolRepository();
|
||||
$result = $rep->backupAll();
|
||||
$log = sprintf('[%s], %s, result: %s', REQUEST_ID, __METHOD__, var_export($result, true));
|
||||
$this->info($log);
|
||||
do_log($log);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Repositories\ToolRepository;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class BackupDatabase extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'backup:database';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Backup database data';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$rep = new ToolRepository();
|
||||
$result = $rep->backupDatabase();
|
||||
$log = sprintf('[%s], %s, result: %s', REQUEST_ID, __METHOD__, var_export($result, true));
|
||||
$this->info($log);
|
||||
do_log($log);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Repositories\ToolRepository;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class BackupWeb extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'backup:web';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'BackupWeb webRoot data';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$rep = new ToolRepository();
|
||||
$result = $rep->backupWebRoot();
|
||||
$log = sprintf('[%s], %s, result: %s', REQUEST_ID, __METHOD__, var_export($result, true));
|
||||
$this->info($log);
|
||||
do_log($log);
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,9 @@ class ExamAssign extends Command
|
||||
$end = $this->option('end');
|
||||
$this->info(sprintf('uid: %s, examId: %s, begin: %s, end: %s', $uid, $examId, $begin, $end));
|
||||
$result = $examRep->assignToUser($uid, $examId, $begin, $end);
|
||||
$this->info(sprintf('%s, [assignToUser], result: %s, request_id: %s', __METHOD__, var_export($result, true), REQUEST_ID));
|
||||
$log = sprintf('[%s], %s, result: %s', REQUEST_ID, __METHOD__, var_export($result, true));
|
||||
$this->info($log);
|
||||
do_log($log);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,9 @@ class ExamAssignCronjob extends Command
|
||||
{
|
||||
$examRep = new ExamRepository();
|
||||
$result = $examRep->cronjonAssign();
|
||||
$this->info(sprintf('%s, [cronjonAssign], result: %s, request_id: %s', __METHOD__, var_export($result, true), REQUEST_ID));
|
||||
$log = sprintf('[%s], %s, result: %s', REQUEST_ID, __METHOD__, var_export($result, true));
|
||||
$this->info($log);
|
||||
do_log($log);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,9 @@ class ExamCheckoutCronjob extends Command
|
||||
$ignoreTimeRange = $this->option('ignore-time-range');
|
||||
$this->info('ignore-time-range: ' . var_export($ignoreTimeRange, true));
|
||||
$result = $examRep->cronjobCheckout($ignoreTimeRange);
|
||||
$this->info(sprintf('%s, [cronjobCheckout], result: %s, request_id: %s', __METHOD__, var_export($result, true), REQUEST_ID));
|
||||
$log = sprintf('[%s], %s, result: %s', REQUEST_ID, __METHOD__, var_export($result, true));
|
||||
$this->info($log);
|
||||
do_log($log);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,15 +46,17 @@ class Test extends Command
|
||||
{
|
||||
$rep = new ExamRepository();
|
||||
// $r = $rep->assignToUser(1, 1);
|
||||
$r = $rep->addProgress(1, 1, [
|
||||
1 => 25*1024*1024*1024,
|
||||
2 => 55*3600,
|
||||
3 => 10*1024*1024*1024,
|
||||
4 => 1252
|
||||
]);
|
||||
dd($r);
|
||||
// $r = $rep->addProgress(1, 1, [
|
||||
// 1 => 25*1024*1024*1024,
|
||||
// 2 => 55*3600,
|
||||
// 3 => 10*1024*1024*1024,
|
||||
// 4 => 1252
|
||||
// ]);
|
||||
// dd($r);
|
||||
// $rep->assignCronjob();
|
||||
// $rep->cronjobCheckout();
|
||||
$r = DB::select(DB::raw('select version() as info'))[0]->info;
|
||||
dd($r);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Repositories\ToolRepository;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ToolController extends Controller
|
||||
{
|
||||
private $repository;
|
||||
|
||||
public function __construct(ToolRepository $repository)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
public function systemInfo()
|
||||
{
|
||||
$result = $this->repository->getSystemInfo();
|
||||
return $this->success($result);
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,8 @@ class ExamResource extends JsonResource
|
||||
'indexes_formatted' => $this->formatIndexes($this->resource),
|
||||
'status' => $this->status,
|
||||
'status_text' => $this->statusText,
|
||||
'is_discovered' => $this->is_discovered,
|
||||
'is_discovered_text' => $this->is_discovered_text,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
+17
-4
@@ -4,7 +4,7 @@ namespace App\Models;
|
||||
|
||||
class Exam extends NexusModel
|
||||
{
|
||||
protected $fillable = ['name', 'description', 'begin', 'end', 'status', 'filters', 'indexes'];
|
||||
protected $fillable = ['name', 'description', 'begin', 'end', 'status', 'is_discovered', 'filters', 'indexes'];
|
||||
|
||||
public $timestamps = true;
|
||||
|
||||
@@ -21,6 +21,14 @@ class Exam extends NexusModel
|
||||
self::STATUS_DISABLED => ['text' => 'Disabled'],
|
||||
];
|
||||
|
||||
const DISCOVERED_YES = 1;
|
||||
const DISCOVERED_NO = 0;
|
||||
|
||||
public static $discovers = [
|
||||
self::DISCOVERED_NO => ['text' => 'No'],
|
||||
self::DISCOVERED_YES => ['text' => 'Yes'],
|
||||
];
|
||||
|
||||
const INDEX_UPLOADED = 1;
|
||||
const INDEX_SEED_TIME_AVERAGE = 2;
|
||||
const INDEX_DOWNLOADED = 3;
|
||||
@@ -28,7 +36,7 @@ class Exam extends NexusModel
|
||||
|
||||
public static $indexes = [
|
||||
self::INDEX_UPLOADED => ['name' => 'Uploaded', 'unit' => 'GB'],
|
||||
self::INDEX_SEED_TIME_AVERAGE => ['name' => 'Seed Time Average', 'unit' => 'Hour'],
|
||||
self::INDEX_SEED_TIME_AVERAGE => ['name' => 'Seed time average', 'unit' => 'Hour'],
|
||||
self::INDEX_DOWNLOADED => ['name' => 'Downloaded', 'unit' => 'GB'],
|
||||
self::INDEX_BONUS => ['name' => 'Bonus', 'unit' => ''],
|
||||
];
|
||||
@@ -37,8 +45,8 @@ class Exam extends NexusModel
|
||||
const FILTER_USER_REGISTER_TIME_RANGE = 'register_time_range';
|
||||
|
||||
public static $filters = [
|
||||
self::FILTER_USER_CLASS => ['name' => 'User Class'],
|
||||
self::FILTER_USER_REGISTER_TIME_RANGE => ['name' => 'User Register Time Range'],
|
||||
self::FILTER_USER_CLASS => ['name' => 'User class'],
|
||||
self::FILTER_USER_REGISTER_TIME_RANGE => ['name' => 'User register time range'],
|
||||
];
|
||||
|
||||
public function getStatusTextAttribute(): string
|
||||
@@ -46,4 +54,9 @@ class Exam extends NexusModel
|
||||
return self::$status[$this->status]['text'] ?? '';
|
||||
}
|
||||
|
||||
public function getIsDiscoveredTextAttribute(): string
|
||||
{
|
||||
return self::$discovers[$this->is_discovered]['text'] ?? '';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@ class ExamRepository extends BaseRepository
|
||||
public function store(array $params)
|
||||
{
|
||||
$this->checkIndexes($params);
|
||||
$valid = $this->listValid();
|
||||
$valid = $this->listValid(null, Exam::DISCOVERED_YES);
|
||||
if ($valid->isNotEmpty() && $params['status'] == Exam::STATUS_ENABLED) {
|
||||
throw new NexusException("Valid exam already exists.");
|
||||
throw new NexusException("Enabled and discovered exam already exists.");
|
||||
}
|
||||
$exam = Exam::query()->create($params);
|
||||
return $exam;
|
||||
@@ -38,9 +38,9 @@ class ExamRepository extends BaseRepository
|
||||
public function update(array $params, $id)
|
||||
{
|
||||
$this->checkIndexes($params);
|
||||
$valid = $this->listValid($id);
|
||||
$valid = $this->listValid($id, Exam::DISCOVERED_YES);
|
||||
if ($valid->isNotEmpty() && $params['status'] == Exam::STATUS_ENABLED) {
|
||||
throw new NexusException("Valid exam already exists.");
|
||||
throw new NexusException("Enabled and discovered exam already exists.");
|
||||
}
|
||||
$exam = Exam::query()->findOrFail($id);
|
||||
$exam->update($params);
|
||||
@@ -52,10 +52,18 @@ class ExamRepository extends BaseRepository
|
||||
if (empty($params['indexes'])) {
|
||||
throw new \InvalidArgumentException("Require index.");
|
||||
}
|
||||
$validIndex = array_filter($params['indexes'], function ($value) {
|
||||
return isset($value['checked']) && $value['checked']
|
||||
&& isset($value['require_value']) && $value['require_value'] > 0;
|
||||
});
|
||||
$validIndex = [];
|
||||
foreach ($params['indexes'] as $index) {
|
||||
if (!isset($index['checked']) || !$index['checked']) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($index['require_value']) || !ctype_digit((string)$index['require_value'])) {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
'Invalid require value for index: %s.', $index['name']
|
||||
));
|
||||
}
|
||||
$validIndex[] = $index;
|
||||
}
|
||||
if (empty($validIndex)) {
|
||||
throw new \InvalidArgumentException("Require valid index.");
|
||||
}
|
||||
@@ -91,7 +99,7 @@ class ExamRepository extends BaseRepository
|
||||
* @param null $excludeId
|
||||
* @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function listValid($excludeId = null)
|
||||
public function listValid($excludeId = null, $isDiscovered = null)
|
||||
{
|
||||
$now = Carbon::now();
|
||||
$query = Exam::query()
|
||||
@@ -99,9 +107,12 @@ class ExamRepository extends BaseRepository
|
||||
->where('end', '>=', $now)
|
||||
->where('status', Exam::STATUS_ENABLED)
|
||||
->orderBy('id', 'desc');
|
||||
if ($excludeId) {
|
||||
if (!is_null($excludeId)) {
|
||||
$query->whereNotIn('id', Arr::wrap($excludeId));
|
||||
}
|
||||
if (!is_null($isDiscovered)) {
|
||||
$query->where('is_discovered', $isDiscovered);
|
||||
}
|
||||
return $query->get();
|
||||
}
|
||||
|
||||
@@ -175,27 +186,15 @@ class ExamRepository extends BaseRepository
|
||||
* assign exam to user
|
||||
*
|
||||
* @param int $uid
|
||||
* @param null $examId
|
||||
* @param int $examId
|
||||
* @param null $begin
|
||||
* @param null $end
|
||||
* @return mixed
|
||||
*/
|
||||
public function assignToUser(int $uid, $examId = null, $begin = null, $end = null)
|
||||
public function assignToUser(int $uid, int $examId, $begin = null, $end = null)
|
||||
{
|
||||
$logPrefix = "uid: $uid, examId: $examId, begin: $begin, end: $end";
|
||||
if ($examId > 0) {
|
||||
$exam = Exam::query()->find($examId);
|
||||
} else {
|
||||
$exams = $this->listValid();
|
||||
if ($exams->isEmpty()) {
|
||||
throw new NexusException("No valid exam.");
|
||||
}
|
||||
if ($exams->count() > 1) {
|
||||
do_log(last_query());
|
||||
throw new NexusException("valid exam more than 1.");
|
||||
}
|
||||
$exam = $exams->first();
|
||||
}
|
||||
$exam = Exam::query()->find($examId);
|
||||
$user = User::query()->findOrFail($uid);
|
||||
if (!$this->isExamMatchUser($exam, $user)) {
|
||||
throw new NexusException("Exam: {$exam->id} no match this user.");
|
||||
@@ -414,6 +413,7 @@ class ExamRepository extends BaseRepository
|
||||
$currentValueFormatted = $currentValue;
|
||||
$requireValueAtomic = $requireValue;
|
||||
}
|
||||
$index['name'] = Exam::$indexes[$index['index']]['name'] ?? '';
|
||||
$index['index_formatted'] = nexus_trans('exam.index_text_' . $index['index']);
|
||||
$index['require_value_formatted'] = "$requireValue " . ($index['unit'] ?? '');
|
||||
$index['current_value'] = $currentValue;
|
||||
@@ -437,13 +437,13 @@ class ExamRepository extends BaseRepository
|
||||
|
||||
public function cronjonAssign()
|
||||
{
|
||||
$exams = $this->listValid();
|
||||
$exams = $this->listValid(null, Exam::DISCOVERED_YES);
|
||||
if ($exams->isEmpty()) {
|
||||
do_log("No valid exam.");
|
||||
do_log("No valid and discovered exam.");
|
||||
return false;
|
||||
}
|
||||
if ($exams->count() > 1) {
|
||||
do_log("Valid exam more than 1.", "warning");
|
||||
do_log("Valid and discovered exam more than 1.", "warning");
|
||||
}
|
||||
/** @var Exam $exam */
|
||||
$exam = $exams->first();
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
namespace App\Repositories;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ToolRepository extends BaseRepository
|
||||
{
|
||||
public function getSystemInfo()
|
||||
{
|
||||
$systemInfo = [
|
||||
'nexus_version' => config('app.nexus_version'),
|
||||
'laravel_version' => \Illuminate\Foundation\Application::VERSION,
|
||||
'php_version' => PHP_VERSION,
|
||||
'mysql_version' => DB::select(DB::raw('select version() as info'))[0]->info,
|
||||
'os' => PHP_OS,
|
||||
'server_software' => $_SERVER['SERVER_SOFTWARE'],
|
||||
|
||||
];
|
||||
|
||||
return $systemInfo;
|
||||
}
|
||||
|
||||
public function backupWebRoot()
|
||||
{
|
||||
$webRoot = base_path();
|
||||
$dirName = basename($webRoot);
|
||||
$filename = sprintf('%s/%s.%s.tar.gz', sys_get_temp_dir(), $dirName, date('Ymd.His'));
|
||||
$command = sprintf(
|
||||
'tar --exclude=vendor --exclude=.git -czf %s -C %s %s',
|
||||
$filename, dirname($webRoot), $dirName
|
||||
);
|
||||
$result = exec($command, $output, $resultCode);
|
||||
do_log(sprintf(
|
||||
"command: %s, output: %s, resultCode: %s, result: %s, filename: %s",
|
||||
$command, json_encode($output), $resultCode, $result, $filename
|
||||
));
|
||||
return compact('result', 'filename');
|
||||
}
|
||||
|
||||
public function backupDatabase()
|
||||
{
|
||||
$connectionName = config('database.default');
|
||||
$config = config("database.connections.$connectionName");
|
||||
$filename = sprintf('%s/%s.database.%s.sql', sys_get_temp_dir(), basename(base_path()), date('Ymd.His'));
|
||||
$command = sprintf(
|
||||
'mysqldump --user=%s --password=%s --port=%s --single-transaction --databases %s >> %s',
|
||||
$config['username'], $config['password'], $config['port'], $config['database'], $filename,
|
||||
);
|
||||
$result = exec($command, $output, $resultCode);
|
||||
do_log(sprintf(
|
||||
"command: %s, output: %s, resultCode: %s, result: %s, filename: %s",
|
||||
$command, json_encode($output), $resultCode, $result, $filename
|
||||
));
|
||||
return compact('result', 'filename');
|
||||
}
|
||||
|
||||
public function backupAll()
|
||||
{
|
||||
$backupWeb = $this->backupWebRoot();
|
||||
if ($backupWeb['result'] != 0) {
|
||||
throw new \RuntimeException("backup web fail: " . json_encode($backupWeb));
|
||||
}
|
||||
$backupDatabase = $this->backupDatabase();
|
||||
if ($backupDatabase['result'] != 0) {
|
||||
throw new \RuntimeException("backup database fail: " . json_encode($backupDatabase));
|
||||
}
|
||||
$filename = sprintf('%s/%s.%s.tar.gz', sys_get_temp_dir(), basename(base_path()), date('Ymd.His'));
|
||||
$command = sprintf(
|
||||
'tar -czf %s -C %s %s -C %s %s',
|
||||
$filename,
|
||||
dirname($backupWeb['filename']), basename($backupWeb['filename']),
|
||||
dirname($backupDatabase['filename']), basename($backupDatabase['filename'])
|
||||
);
|
||||
$result = exec($command, $output, $resultCode);
|
||||
do_log(sprintf(
|
||||
"command: %s, output: %s, resultCode: %s, result: %s, filename: %s",
|
||||
$command, json_encode($output), $resultCode, $result, $filename
|
||||
));
|
||||
return compact('result', 'filename');
|
||||
|
||||
}
|
||||
}
|
||||
@@ -230,4 +230,6 @@ return [
|
||||
|
||||
],
|
||||
|
||||
'nexus_version' => '1.6.0-beta5',
|
||||
|
||||
];
|
||||
|
||||
@@ -22,6 +22,7 @@ class CreateExamsTable extends Migration
|
||||
$table->text('filters')->nullable();
|
||||
$table->text('indexes');
|
||||
$table->tinyInteger('status')->default(0);
|
||||
$table->tinyInteger('is_discovered')->default(0);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -290,7 +290,7 @@ function readEnvFile($envFile)
|
||||
{
|
||||
if (!file_exists($envFile)) {
|
||||
if (php_sapi_name() == 'cli') {
|
||||
return [];
|
||||
return [];
|
||||
}
|
||||
throw new \RuntimeException("env file : $envFile is not exists in the root path.");
|
||||
}
|
||||
|
||||
@@ -317,18 +317,6 @@ $lang_functions = array
|
||||
'text_invalid' => '非法',
|
||||
'text_technical_info' => '技术信息',
|
||||
'text_technical_info_help_text' => '文件技术信息来自软件 <b><a href="https://mediaarea.net/en/MediaInfo" target=\'_blank\'>MediaInfo</a></b>,用该软件打开文件,点击菜单视图(View)->文件(Text),在框中右键->全选,再右键->复制,粘贴到这里来。',
|
||||
'exam_name' => '考核名称',
|
||||
'exam_time_range' => '考核时间',
|
||||
'exam_index' => '考核指标',
|
||||
'exam_require' => '要求',
|
||||
'exam_progress_current' => '当前',
|
||||
'exam_progress_result' => '结果',
|
||||
'exam_progress_result_pass_yes' => '通过!',
|
||||
'exam_progress_result_pass_no' => '<bold style="color: red">未通过!</bold>',
|
||||
'exam_index_' . \App\Models\Exam::INDEX_UPLOADED => '上传量',
|
||||
'exam_index_' . \App\Models\Exam::INDEX_SEED_TIME_AVERAGE => '平均做种时间',
|
||||
'exam_index_' . \App\Models\Exam::INDEX_DOWNLOADED => '下载量',
|
||||
'exam_index_' . \App\Models\Exam::INDEX_BONUS => '魔力值',
|
||||
);
|
||||
|
||||
?>
|
||||
|
||||
@@ -318,18 +318,6 @@ $lang_functions = array
|
||||
'text_invalid' => '非法',
|
||||
'text_technical_info' => '技術信息',
|
||||
'text_technical_info_help_text' => '文件技術信息來自軟件 <b><a href="https://mediaarea.net/en/MediaInfo" target=\'_blank\'>MediaInfo</a></b>,用該軟件打開文件,點擊菜單視圖(View)->文件(Text),在框中右鍵->全選,再右鍵->復制,粘貼到這裏來。',
|
||||
'exam_name' => '考核名稱',
|
||||
'exam_time_range' => '考核時間',
|
||||
'exam_index' => '考核指標',
|
||||
'exam_require' => '要求',
|
||||
'exam_progress_current' => '當前',
|
||||
'exam_progress_result' => '結果',
|
||||
'exam_progress_result_pass_yes' => '通過!',
|
||||
'exam_progress_result_pass_no' => '<bold style="color: red">未通過!</bold>',
|
||||
'exam_index_' . \App\Models\Exam::INDEX_UPLOADED => '上傳量',
|
||||
'exam_index_' . \App\Models\Exam::INDEX_SEED_TIME_AVERAGE => '平均做種時間',
|
||||
'exam_index_' . \App\Models\Exam::INDEX_DOWNLOADED => '下載量',
|
||||
'exam_index_' . \App\Models\Exam::INDEX_BONUS => '魔力值',
|
||||
);
|
||||
|
||||
?>
|
||||
|
||||
@@ -319,18 +319,6 @@ $lang_functions = array
|
||||
'text_invalid' => 'Invalid',
|
||||
'text_technical_info' => 'Technical Info',
|
||||
'text_technical_info_help_text' => 'Technical Information comes from software <b><a href="https://mediaarea.net/en/MediaInfo" target=\'_blank\'>MediaInfo</a></b>,open file, click the view menu > text > right click in the box > select all > copy > past into this box.',
|
||||
'exam_name' => 'Exam Name',
|
||||
'exam_time_range' => 'Exam Time',
|
||||
'exam_index' => 'Exam Index',
|
||||
'exam_require' => 'Require',
|
||||
'exam_progress_current' => 'Current',
|
||||
'exam_progress_result' => 'Result',
|
||||
'exam_progress_result_pass_yes' => 'Pass!',
|
||||
'exam_progress_result_pass_no' => '<bold style="color: red">Not Pass!</bold>',
|
||||
'exam_index_' . \App\Models\Exam::INDEX_UPLOADED => 'Uploaded',
|
||||
'exam_index_' . \App\Models\Exam::INDEX_SEED_TIME_AVERAGE => 'Seed Time Average',
|
||||
'exam_index_' . \App\Models\Exam::INDEX_DOWNLOADED => 'Downloaded',
|
||||
'exam_index_' . \App\Models\Exam::INDEX_BONUS => 'Bonus',
|
||||
);
|
||||
|
||||
?>
|
||||
|
||||
@@ -12,7 +12,7 @@ return [
|
||||
'current_value' => 'Current',
|
||||
'result' => 'Result',
|
||||
'result_pass' => 'Pass!',
|
||||
'result_not_pass' => '<bold color="red">Not pass!</bold>',
|
||||
'result_not_pass' => '<span style="color: red">Not pass!</span>',
|
||||
'checkout_pass_message_subject' => 'Exam pass!',
|
||||
'checkout_pass_message_content' => 'Congratulation! You have complete the exam: :exam_name in time(:begin ~ :end)',
|
||||
'checkout_not_pass_message_subject' => 'Exam not pass, and account is banned!',
|
||||
|
||||
@@ -12,7 +12,7 @@ return [
|
||||
'current_value' => '当前',
|
||||
'result' => '结果',
|
||||
'result_pass' => '通过!',
|
||||
'result_not_pass' => '<bold color="red">未通过!</bold>',
|
||||
'result_not_pass' => '<span style="color: red">未通过!</span>',
|
||||
'checkout_pass_message_subject' => '考核通过!',
|
||||
'checkout_pass_message_content' => '恭喜!你在规定时间内(:begin ~ :end)顺利完成了考核::exam_name。',
|
||||
'checkout_not_pass_message_subject' => '考核未通过,账号被禁用!',
|
||||
|
||||
@@ -12,7 +12,7 @@ return [
|
||||
'current_value' => '當前',
|
||||
'result' => '結果',
|
||||
'result_pass' => '通過!',
|
||||
'result_not_pass' => '<bold color="red">未通過!</bold>',
|
||||
'result_not_pass' => '<span style="color: red">未通過!</span>',
|
||||
'checkout_pass_message_subject' => '考核通過!',
|
||||
'checkout_pass_message_content' => '恭喜!你在規定時間內(:begin ~ :end)順利完成了考核::exam_name。',
|
||||
'checkout_not_pass_message_subject' => '考核未通過,賬號被禁用!',
|
||||
|
||||
+5
-3
@@ -17,18 +17,20 @@ use Illuminate\Support\Facades\Route;
|
||||
Route::group(['middleware' => ['auth:sanctum', 'permission', 'locale']], function () {
|
||||
Route::post('logout', [\App\Http\Controllers\AuthenticateController::class, 'logout']);
|
||||
|
||||
Route::resource('agent-allow', \App\Http\Controllers\AgentAllowController::class);
|
||||
Route::resource('agent-allows', \App\Http\Controllers\AgentAllowController::class);
|
||||
|
||||
Route::resource('user', \App\Http\Controllers\UserController::class);
|
||||
Route::resource('users', \App\Http\Controllers\UserController::class);
|
||||
Route::get('user-base', [\App\Http\Controllers\UserController::class, 'base']);
|
||||
Route::get('user-classes', [\App\Http\Controllers\UserController::class, 'classes']);
|
||||
Route::get('user-match-exams', [\App\Http\Controllers\UserController::class, 'matchExams']);
|
||||
|
||||
Route::resource('exam', \App\Http\Controllers\ExamController::class);
|
||||
Route::resource('exams', \App\Http\Controllers\ExamController::class);
|
||||
Route::get('exam-indexes', [\App\Http\Controllers\ExamController::class, 'indexes']);
|
||||
|
||||
Route::resource('exam-users', \App\Http\Controllers\ExamUserController::class);
|
||||
|
||||
Route::get('system-info', [\App\Http\Controllers\ToolController::class, 'systemInfo']);
|
||||
|
||||
});
|
||||
|
||||
Route::post('login', [\App\Http\Controllers\AuthenticateController::class, 'login']);
|
||||
|
||||
Reference in New Issue
Block a user