完善任务编辑

pull/21/merge
ouqiang 2017-04-17 18:04:30 +08:00
parent 56144ee1a9
commit 5ab787dff5
7 changed files with 79 additions and 22 deletions

View File

@ -52,6 +52,10 @@ func (task *Task) Create() (insertId int, err error) {
return return
} }
func (task *Task) UpdateBean(id int) (int64, error) {
return Db.UseBool("status").Update(task)
}
// 更新 // 更新
func (task *Task) Update(id int, data CommonMap) (int64, error) { func (task *Task) Update(id int, data CommonMap) (int64, error) {
return Db.Table(task).ID(id).Update(data) return Db.Table(task).ID(id).Update(data)
@ -89,7 +93,11 @@ func (task *Task) HostIdExist(hostId int16) (bool, error) {
} }
// 判断任务名称是否存在 // 判断任务名称是否存在
func (task *Task) NameExist(name string) (bool, error) { func (task *Task) NameExist(name string, id int) (bool, error) {
if id > 0 {
count, err := Db.Where("name = ? AND status = ? AND id != ?", name, Enabled, id).Count(task);
return count > 0, err
}
count, err := Db.Where("name = ? AND status = ?", name, Enabled).Count(task); count, err := Db.Where("name = ? AND status = ?", name, Enabled).Count(task);
return count > 0, err return count > 0, err

View File

@ -39,7 +39,6 @@ func Exec(sshConfig SSHConfig, cmd string) (output string, err error) {
var resultChan chan Result = make(chan Result) var resultChan chan Result = make(chan Result)
var timeoutChan chan bool = make(chan bool) var timeoutChan chan bool = make(chan bool)
go func() { go func() {
cmd += fmt.Sprintf(" & { sleep %d; eval 'kill $!' &> /dev/null; }", sshConfig.ExecTimeout)
output, err := session.CombinedOutput(cmd) output, err := session.CombinedOutput(cmd)
resultChan <- Result{string(output), err} resultChan <- Result{string(output), err}
}() }()

View File

@ -60,6 +60,7 @@ func Register(m *macaron.Macaron) {
m.Group("/task", func() { m.Group("/task", func() {
m.Get("/create", task.Create) m.Get("/create", task.Create)
m.Post("/store", binding.Bind(task.TaskForm{}), task.Store) m.Post("/store", binding.Bind(task.TaskForm{}), task.Store)
m.Get("/edit/:id", task.Edit)
m.Get("", task.Index) m.Get("", task.Index)
m.Get("/log", tasklog.Index) m.Get("/log", tasklog.Index)
m.Post("/log/clear", tasklog.Clear) m.Post("/log/clear", tasklog.Clear)

View File

@ -27,7 +27,31 @@ func Create(ctx *macaron.Context) {
if err != nil || len(hosts) == 0 { if err != nil || len(hosts) == 0 {
logger.Error(err) logger.Error(err)
} }
ctx.Data["Title"] = "任务管理" ctx.Data["Title"] = "添加任务"
ctx.Data["Hosts"] = hosts
if len(hosts) > 0 {
ctx.Data["FirstHostName"] = hosts[0].Name
ctx.Data["FirstHostId"] = hosts[0].Id
}
ctx.HTML(200, "task/task_form")
}
func Edit(ctx *macaron.Context) {
id := ctx.ParamsInt(":id")
hostModel := new(models.Host)
hosts, err := hostModel.List()
if err != nil || len(hosts) == 0 {
logger.Error(err)
}
taskModel := new(models.Task)
task, err := taskModel.Detail(id)
if err != nil {
logger.Errorf("编辑任务#获取任务详情失败#任务ID-%d#%s", id, err.Error())
ctx.Redirect("/task")
}
ctx.Data["TaskId"] = id
ctx.Data["Task"] = task
ctx.Data["Title"] = "编辑"
ctx.Data["Hosts"] = hosts ctx.Data["Hosts"] = hosts
if len(hosts) > 0 { if len(hosts) > 0 {
ctx.Data["FirstHostName"] = hosts[0].Name ctx.Data["FirstHostName"] = hosts[0].Name
@ -37,6 +61,7 @@ func Create(ctx *macaron.Context) {
} }
type TaskForm struct { type TaskForm struct {
Id int
Name string `binding:"Required;"` Name string `binding:"Required;"`
Spec string `binding:"Required;MaxSize(64)"` Spec string `binding:"Required;MaxSize(64)"`
Protocol models.TaskProtocol `binding:"In(1,2,3)"` Protocol models.TaskProtocol `binding:"In(1,2,3)"`
@ -44,18 +69,19 @@ type TaskForm struct {
Timeout int `binding:"Range(0,86400)"` Timeout int `binding:"Range(0,86400)"`
HostId int16 HostId int16
Remark string Remark string
Status models.Status `binding:"In(1,0)"` Status models.Status `binding:"In(1,2)"`
} }
// 保存任务 // 保存任务
func Store(ctx *macaron.Context, form TaskForm) string { func Store(ctx *macaron.Context, form TaskForm) string {
json := utils.JsonResponse{} json := utils.JsonResponse{}
taskModel := models.Task{} taskModel := models.Task{}
var id int = form.Id
_, err := cron.Parse(form.Spec) _, err := cron.Parse(form.Spec)
if err != nil { if err != nil {
return json.CommonFailure("crontab表达式解析失败", err) return json.CommonFailure("crontab表达式解析失败", err)
} }
nameExists, err := taskModel.NameExist(form.Name) nameExists, err := taskModel.NameExist(form.Name, form.Id)
if err != nil { if err != nil {
return json.CommonFailure(utils.FailureContent, err) return json.CommonFailure(utils.FailureContent, err)
} }
@ -74,15 +100,22 @@ func Store(ctx *macaron.Context, form TaskForm) string {
taskModel.HostId = form.HostId taskModel.HostId = form.HostId
taskModel.Remark = form.Remark taskModel.Remark = form.Remark
taskModel.Status = form.Status taskModel.Status = form.Status
if taskModel.Status != models.Enabled {
taskModel.Status = models.Disabled
}
taskModel.Spec = form.Spec taskModel.Spec = form.Spec
insertId, err := taskModel.Create() if id == 0 {
id, err = taskModel.Create()
} else {
_, err = taskModel.UpdateBean(id)
}
if err != nil { if err != nil {
return json.CommonFailure("保存失败", err) return json.CommonFailure("保存失败", err)
} }
// 任务处于激活状态,加入调度管理 // 任务处于激活状态,加入调度管理
if (taskModel.Status == models.Enabled) { if (taskModel.Status == models.Enabled) {
addTaskToTimer(insertId) addTaskToTimer(id)
} }
return json.Success("保存成功", nil) return json.Success("保存成功", nil)

View File

@ -62,7 +62,7 @@
</div> </div>
</div> </div>
<div class="ui primary submit button">提交</div> <div class="ui primary submit button">保存</div>
</form> </form>
</div> </div>
<!--the newDevice form--> <!--the newDevice form-->

View File

@ -39,6 +39,7 @@
<td>{{{.Remark}}}</td> <td>{{{.Remark}}}</td>
<td>{{{if eq .Status 1}}}<i class="large checkmark blue icon"></i> {{{else}}} <i class="large red minus icon"></i> {{{end}}}</td> <td>{{{if eq .Status 1}}}<i class="large checkmark blue icon"></i> {{{else}}} <i class="large red minus icon"></i> {{{end}}}</td>
<td> <td>
<a class="ui purple button" href="/task/edit/{{{.Id}}}">编辑</a>
{{{if eq .Status 1}}} {{{if eq .Status 1}}}
<button class="ui primary button" onclick="changeStatus({{{.Id}}},{{{.Status}}})">暂停</button> <button class="ui primary button" onclick="changeStatus({{{.Id}}},{{{.Status}}})">暂停</button>
{{{else}}} {{{else}}}

View File

@ -8,36 +8,41 @@
<h3 class="ui dividing header"> <h3 class="ui dividing header">
<i class="large add icon"></i> <i class="large add icon"></i>
<div class="content"> <div class="content">
添加任务 {{{.Title}}}
</div> </div>
</h3> </h3>
</div> </div>
</div> </div>
<form class="ui form fluid vertical segment"> <form class="ui form fluid vertical segment">
<input type="hidden" name="id" value="{{{.Task.Id}}}">
<div class="two fields"> <div class="two fields">
<div class="field"> <div class="field">
<label>任务名称</label> <label>任务名称</label>
<div class="ui small left icon input"> <div class="ui small left icon input">
<input type="text" placeholder="数据库备份" name="name"> <input type="text" placeholder="数据库备份" name="name" value="{{{.Task.Task.Name}}}">
</div> </div>
</div> </div>
</div> </div>
<div class="two fields"> <div class="two fields">
<div class="field"> <div class="field">
<label>crontab表达式 (每行一个表达式)</label> <label>crontab表达式 (每行一个表达式)</label>
<textarea rows="5" name="spec" placeholder="*/5 * * * * * *"></textarea> <textarea rows="5" name="spec" placeholder="*/5 * * * * * *">{{{.Task.Spec}}}</textarea>
</div> </div>
</div> </div>
<div class="three fields"> <div class="three fields">
<div class="field"> <div class="field">
<label>协议</label> <label>协议</label>
<div class="ui dropdown selection"> <div class="ui dropdown selection">
<input type="hidden" name="protocol" value="3"> {{{if .Task}}}
<input type="hidden" name="protocol" value="{{{if (gt .Task.Protocol 0)}}}{{{.Task.Protocol}}}{{{else}}}3{{{end}}}">
{{{else}}}
<input type="hidden" name="protocol" value="3">
{{{end}}}
<div class="default text">本地命令</div> <div class="default text">本地命令</div>
<i class="dropdown icon"></i> <i class="dropdown icon"></i>
<div class="menu"> <div class="menu">
<div class="item active" data-value="3">本地命令</div> <div class="item" data-value="3">本地命令</div>
<div class="item active" data-value="2">SSH</div> <div class="item" data-value="2">SSH</div>
<div class="item" data-value="1">HTTP</div> <div class="item" data-value="1">HTTP</div>
</div> </div>
</div> </div>
@ -49,7 +54,13 @@
{{{range $i, $v := .Hosts}}} {{{range $i, $v := .Hosts}}}
<div class="field"> <div class="field">
<div class="ui radio checkbox"> <div class="ui radio checkbox">
<input type="radio" name="host_id" tabindex="0" class="hidden" value="{{{.Id}}}"> {{{if $.Task}}}
<input type="radio" name="host_id" tabindex="0" class="hidden" value="{{{.Id}}}"
{{{if and .Task (eq $.TaskId .Id)}}} checked {{{end}}}
>
{{{else}}}
<input type="radio" name="host_id" tabindex="0" class="hidden">
{{{end}}}
<label>{{{.Alias}}}-{{{.Name}}}</label> <label>{{{.Alias}}}-{{{.Name}}}</label>
</div> </div>
</div> </div>
@ -58,23 +69,27 @@
</div> </div>
<div class="field"> <div class="field">
<label>命令(shell命令|URL地址, 多条shell命令";"分隔)</label> <label>命令(shell命令|URL地址, 多条shell命令";"分隔)</label>
<input type="text" name="command" placeholder="tail -n 10 /var/log/nginx/error.log"> <input type="text" name="command" placeholder="tail -n 10 /var/log/nginx/error.log" value="{{{.Task.Command}}}">
</div> </div>
<div class="three fields"> <div class="three fields">
<div class="field"> <div class="field">
<label>任务超时时间 (单位秒,0不限制,不能超过24小时)</label> <label>任务超时时间 (单位秒,0不限制,不能超过24小时)</label>
<input type="text" name="timeout" placeholder="0" value="180"> <input type="text" name="timeout" placeholder="0" value="{{{.Task.Timeout}}}">
</div> </div>
</div> </div>
<div class="three fields"> <div class="three fields">
<div class="field"> <div class="field">
<label>任务状态 (任务添加成功后,是否立即调度)</label> <label>任务状态 (任务添加成功后,是否立即调度)</label>
<div class="ui dropdown selection"> <div class="ui dropdown selection">
<input type="hidden" name="status" value="0"> {{{if .Task}}}
<div class="default text">激活</div> <input type="hidden" name="status" value="{{{if and .Task.Status (eq .Task.Status 1)}}}1{{{else}}}2{{{end}}}">
{{{else}}}
<input type="hidden" name="status" value="2">
{{{end}}}
<div class="default text">暂停</div>
<i class="dropdown icon"></i> <i class="dropdown icon"></i>
<div class="menu"> <div class="menu">
<div class="item active" data-value="0">暂停</div> <div class="item" data-value="2">暂停</div>
<div class="item" data-value="1">激活</div> <div class="item" data-value="1">激活</div>
</div> </div>
</div> </div>
@ -83,10 +98,10 @@
<div class="two field"> <div class="two field">
<div class="field"> <div class="field">
<label>备注</label> <label>备注</label>
<textarea rows="5" name="remark" placeholder="任务备注"></textarea> <textarea rows="5" name="remark" placeholder="任务备注">{{{.Task.Remark}}}</textarea>
</div> </div>
</div> </div>
<div class="ui primary submit button">提交</div> <div class="ui primary submit button">保存</div>
</form> </form>
</div> </div>
</div> </div>