mirror of https://github.com/shunfei/cronsun
任务列表页,修复服务端一些 bug
parent
ff1d79bb4a
commit
5b4900d6c4
|
@ -64,14 +64,14 @@ func (c *Client) Put(key, val string, opts ...client.OpOption) (*client.PutRespo
|
||||||
return c.Client.Put(ctx, key, val, opts...)
|
return c.Client.Put(ctx, key, val, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) PutWithRev(key, val string, rev int64) (*client.PutResponse, error) {
|
func (c *Client) PutWithModRev(key, val string, rev int64) (*client.PutResponse, error) {
|
||||||
if rev == 0 {
|
if rev == 0 {
|
||||||
return c.Put(key, val)
|
return c.Put(key, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), c.reqTimeout)
|
ctx, cancel := context.WithTimeout(context.Background(), c.reqTimeout)
|
||||||
tresp, err := DefalutClient.Txn(ctx).
|
tresp, err := DefalutClient.Txn(ctx).
|
||||||
If(client.Compare(client.Version(key), "=", rev)).
|
If(client.Compare(client.ModRevision(key), "=", rev)).
|
||||||
Then(client.OpPut(key, val)).
|
Then(client.OpPut(key, val)).
|
||||||
Commit()
|
Commit()
|
||||||
cancel()
|
cancel()
|
||||||
|
|
|
@ -85,13 +85,13 @@ func (g *Group) Key() string {
|
||||||
return GroupKey(g.ID)
|
return GroupKey(g.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Group) Put(rev int64) (*client.PutResponse, error) {
|
func (g *Group) Put(modRev int64) (*client.PutResponse, error) {
|
||||||
b, err := json.Marshal(g)
|
b, err := json.Marshal(g)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return DefalutClient.PutWithRev(g.Key(), string(b), rev)
|
return DefalutClient.PutWithModRev(g.Key(), string(b), modRev)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Group) Check() error {
|
func (g *Group) Check() error {
|
||||||
|
|
|
@ -58,6 +58,11 @@ func (j *JobRule) included(nid string, gs map[string]*Group) (string, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetJob(group, id string) (job *Job, err error) {
|
func GetJob(group, id string) (job *Job, err error) {
|
||||||
|
job, _, err = GetJobAndRev(group, id)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetJobAndRev(group, id string) (job *Job, rev int64, err error) {
|
||||||
resp, err := DefalutClient.Get(JobKey(group, id))
|
resp, err := DefalutClient.Get(JobKey(group, id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -68,6 +73,7 @@ func GetJob(group, id string) (job *Job, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rev = resp.Kvs[0].ModRevision
|
||||||
err = json.Unmarshal(resp.Kvs[0].Value, &job)
|
err = json.Unmarshal(resp.Kvs[0].Value, &job)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
42
web/job.go
42
web/job.go
|
@ -3,7 +3,6 @@ package web
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -44,6 +43,39 @@ func (j *Job) DeleteJob(w http.ResponseWriter, r *http.Request) {
|
||||||
outJSONWithCode(w, http.StatusNoContent, nil)
|
outJSONWithCode(w, http.StatusNoContent, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (j *Job) ChangeJobStatus(w http.ResponseWriter, r *http.Request) {
|
||||||
|
job := &models.Job{}
|
||||||
|
decoder := json.NewDecoder(r.Body)
|
||||||
|
err := decoder.Decode(&job)
|
||||||
|
if err != nil {
|
||||||
|
outJSONError(w, http.StatusBadRequest, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.Body.Close()
|
||||||
|
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
originJob, rev, err := models.GetJobAndRev(vars["group"], vars["id"])
|
||||||
|
if err != nil {
|
||||||
|
outJSONError(w, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
originJob.Pause = job.Pause
|
||||||
|
b, err := json.Marshal(originJob)
|
||||||
|
if err != nil {
|
||||||
|
outJSONError(w, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = models.DefalutClient.PutWithModRev(originJob.Key(), string(b), rev)
|
||||||
|
if err != nil {
|
||||||
|
outJSONError(w, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
outJSON(w, originJob)
|
||||||
|
}
|
||||||
|
|
||||||
func (j *Job) UpdateJob(w http.ResponseWriter, r *http.Request) {
|
func (j *Job) UpdateJob(w http.ResponseWriter, r *http.Request) {
|
||||||
job := &models.Job{}
|
job := &models.Job{}
|
||||||
decoder := json.NewDecoder(r.Body)
|
decoder := json.NewDecoder(r.Body)
|
||||||
|
@ -71,7 +103,7 @@ func (j *Job) UpdateJob(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = models.DefalutClient.Put(path.Join(conf.Config.Cmd, job.Group, job.ID), string(b))
|
_, err = models.DefalutClient.Put(job.Key(), string(b))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
outJSONError(w, http.StatusInternalServerError, err.Error())
|
outJSONError(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
|
@ -107,7 +139,7 @@ func (j *Job) GetGroups(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
func (j *Job) GetListByGroupName(w http.ResponseWriter, r *http.Request) {
|
func (j *Job) GetListByGroupName(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
resp, err := models.DefalutClient.Get(path.Join(conf.Config.Cmd, vars["name"]), clientv3.WithPrefix(), clientv3.WithSort(clientv3.SortByKey, clientv3.SortAscend))
|
resp, err := models.DefalutClient.Get(conf.Config.Cmd+vars["name"], clientv3.WithPrefix(), clientv3.WithSort(clientv3.SortByKey, clientv3.SortAscend))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
outJSONError(w, http.StatusInternalServerError, err.Error())
|
outJSONError(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
|
@ -115,13 +147,13 @@ func (j *Job) GetListByGroupName(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
var jobList = make([]*models.Job, 0, resp.Count)
|
var jobList = make([]*models.Job, 0, resp.Count)
|
||||||
for i := range resp.Kvs {
|
for i := range resp.Kvs {
|
||||||
job := &models.Job{}
|
job := models.Job{}
|
||||||
err = json.Unmarshal(resp.Kvs[i].Value, &job)
|
err = json.Unmarshal(resp.Kvs[i].Value, &job)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
outJSONError(w, http.StatusInternalServerError, err.Error())
|
outJSONError(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jobList = append(jobList)
|
jobList = append(jobList, &job)
|
||||||
}
|
}
|
||||||
|
|
||||||
outJSON(w, jobList)
|
outJSON(w, jobList)
|
||||||
|
|
|
@ -39,9 +39,9 @@ func (n *Node) UpdateGroup(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// @TODO rev
|
// @TODO modRev
|
||||||
var rev int64 = 0
|
var modRev int64 = 0
|
||||||
if _, err = g.Put(rev); err != nil {
|
if _, err = g.Put(modRev); err != nil {
|
||||||
outJSONError(w, http.StatusBadRequest, err.Error())
|
outJSONError(w, http.StatusBadRequest, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,9 @@ func InitRouters() (s *http.Server, err error) {
|
||||||
// create/update a job
|
// create/update a job
|
||||||
h = BaseHandler{Handle: jobHandler.UpdateJob}
|
h = BaseHandler{Handle: jobHandler.UpdateJob}
|
||||||
subrouter.Handle("/job", h).Methods("PUT")
|
subrouter.Handle("/job", h).Methods("PUT")
|
||||||
|
// pause/start
|
||||||
|
h = BaseHandler{Handle: jobHandler.ChangeJobStatus}
|
||||||
|
subrouter.Handle("/job/{group}-{id}", h).Methods("POST")
|
||||||
// get a job
|
// get a job
|
||||||
h = BaseHandler{Handle: jobHandler.GetJob}
|
h = BaseHandler{Handle: jobHandler.GetJob}
|
||||||
subrouter.Handle("/job/{group}-{id}", h).Methods("GET")
|
subrouter.Handle("/job/{group}-{id}", h).Methods("GET")
|
||||||
|
|
|
@ -1,12 +1,44 @@
|
||||||
|
<style scope>
|
||||||
|
.clearfix:after {content:""; clear:both; display:table;}
|
||||||
|
</style>
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<JobToolbar/>
|
<JobToolbar class="clearfix"/>
|
||||||
<form class="ui form">
|
<form class="ui form">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>任务分组</label>
|
<label>选择一个分组显示其下的任务</label>
|
||||||
<Dropdown title="选择分组" v-bind:items="groups" v-on:change="changeGroup"/>
|
<Dropdown title="选择分组" v-bind:items="groups" v-on:change="changeGroup"/>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
<table class="ui hover celled striped blue table" v-if="jobs.length > 0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="collapsing center aligned">操作</th>
|
||||||
|
<th class="collapsing center aligned">状态</th>
|
||||||
|
<th width="200px" class="center aligned">分组</th>
|
||||||
|
<th class="center aligned">名称</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="(job, index) in jobs">
|
||||||
|
<td class="center aligned">
|
||||||
|
<div class="ui icon dropdown">
|
||||||
|
<i class="content icon"></i>
|
||||||
|
<div class="menu">
|
||||||
|
<div class="item" v-on:click="$router.push('/job/edit/'+job.group+'/'+job.id)">编辑</div>
|
||||||
|
<div class="item" v-if="job.pause" v-on:click="changeStatus(job.group, job.id, index, !job.pause)">开启</div>
|
||||||
|
<div class="item" v-if="!job.pause" v-on:click="changeStatus(job.group, job.id, index, !job.pause)">暂停</div>
|
||||||
|
<div class="divider"></div>
|
||||||
|
<div class="item" style="color:red;" v-on:click="removeJob(job.group, job.id, index)">删除</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="center aligned"><i class="icon" v-bind:class="{pause: job.pause, play: !job.pause, green: !job.pause}"></i></td>
|
||||||
|
<td>{{job.group}}</td>
|
||||||
|
<td>{{job.name}}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -18,7 +50,9 @@ export default {
|
||||||
name: 'job',
|
name: 'job',
|
||||||
data: function(){
|
data: function(){
|
||||||
return {
|
return {
|
||||||
groups: []
|
groups: [],
|
||||||
|
group: '',
|
||||||
|
jobs: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -31,7 +65,35 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
changeGroup: function(){}
|
changeGroup: function(val, text){
|
||||||
|
var vm = this;
|
||||||
|
this.group = val;
|
||||||
|
this.refreshList();
|
||||||
|
},
|
||||||
|
|
||||||
|
refreshList: function(){
|
||||||
|
var vm = this;
|
||||||
|
this.$rest.GET('job/group/'+this.group).onsucceed(200, (resp)=>{
|
||||||
|
vm.jobs = resp;
|
||||||
|
vm.$nextTick(()=>{
|
||||||
|
$(vm.$el).find('table .ui.dropdown').dropdown();
|
||||||
|
});
|
||||||
|
}).do();
|
||||||
|
},
|
||||||
|
|
||||||
|
removeJob: function(group, id, index){
|
||||||
|
var vm = this;
|
||||||
|
this.$rest.DELETE('job/'+group+'-'+id).onsucceed(204, (resp)=>{
|
||||||
|
vm.jobs.splice(index, 1);
|
||||||
|
}).do();
|
||||||
|
},
|
||||||
|
|
||||||
|
changeStatus: function(group, id, index, isPause){
|
||||||
|
var vm = this;
|
||||||
|
this.$rest.POST('job/'+group+'-'+id, {"pause": isPause}).onsucceed(200, (resp)=>{
|
||||||
|
vm.refreshList();
|
||||||
|
}).do();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<input type="text" v-model="job.cmd" placeholder="任务脚本">
|
<input type="text" v-model="job.cmd" placeholder="任务脚本">
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<span v-if="job.rules.length == 0"><i class="warning circle icon"></i>当前任务没有定时器,点击下面按钮来添加定时器</span>
|
<span v-if="!job.rules || job.rules.length == 0"><i class="warning circle icon"></i>当前任务没有定时器,点击下面按钮来添加定时器</span>
|
||||||
</div>
|
</div>
|
||||||
<JobEditRule v-for="(rule, index) in job.rules" :rule="rule" :index="index" v-on:remove="removeRule" v-on:change="changeRule"/>
|
<JobEditRule v-for="(rule, index) in job.rules" :rule="rule" :index="index" v-on:remove="removeRule" v-on:change="changeRule"/>
|
||||||
<div class="two fields">
|
<div class="two fields">
|
||||||
|
@ -84,7 +84,7 @@ export default {
|
||||||
var exceptCode = this.action == 'CREATE' ? 201 : 200;
|
var exceptCode = this.action == 'CREATE' ? 201 : 200;
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
var vm = this;
|
var vm = this;
|
||||||
this.$rest.PUT('job', JSON.stringify(this.job))
|
this.$rest.PUT('job', this.job)
|
||||||
.onsucceed(exceptCode, ()=>{vm.$router.push('/job')})
|
.onsucceed(exceptCode, ()=>{vm.$router.push('/job')})
|
||||||
.onfailed((resp)=>{console.log(resp)})
|
.onfailed((resp)=>{console.log(resp)})
|
||||||
.onend(()=>{vm.loading=false})
|
.onend(()=>{vm.loading=false})
|
||||||
|
@ -93,9 +93,15 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted: function(){
|
mounted: function(){
|
||||||
this.action = this.$route.path.indexOf('/job/create') === 0 ? 'CREATE' : 'UPDATE';
|
|
||||||
|
|
||||||
var vm = this;
|
var vm = this;
|
||||||
|
|
||||||
|
if (this.$route.path.indexOf('/job/create') === 0) {
|
||||||
|
this.action = 'CREATE';
|
||||||
|
} else {
|
||||||
|
this.action = 'UPDATE';
|
||||||
|
this.$rest.GET('job/'+this.$route.params.group+'-'+this.$route.params.id).onsucceed(200, (resp)=>{vm.job = resp}).do();
|
||||||
|
}
|
||||||
|
|
||||||
this.$rest.GET('job/groups').onsucceed(200, (resp)=>{
|
this.$rest.GET('job/groups').onsucceed(200, (resp)=>{
|
||||||
!resp.includes('default') && resp.unshift('default');
|
!resp.includes('default') && resp.unshift('default');
|
||||||
vm.groups = resp;
|
vm.groups = resp;
|
||||||
|
|
|
@ -37,6 +37,9 @@ var sendXHR = function(opt) {
|
||||||
typeof opt.onend == 'function' && opt.onend(xhr);
|
typeof opt.onend == 'function' && opt.onend(xhr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof opt.data == 'object') {
|
||||||
|
opt.data = JSON.stringify(opt.data);
|
||||||
|
}
|
||||||
xhr.send(opt.data);
|
xhr.send(opt.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ var routes = [
|
||||||
{path: '/log', component: Log},
|
{path: '/log', component: Log},
|
||||||
{path: '/job', component: Job},
|
{path: '/job', component: Job},
|
||||||
{path: '/job/create', component: JobEdit},
|
{path: '/job/create', component: JobEdit},
|
||||||
|
{path: '/job/edit/:group/:id', component: JobEdit},
|
||||||
{path: '/node', component: Node}
|
{path: '/node', component: Node}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue