支持多台服务器同时执行任务+优化页面

一个定时任务可以允许多台服务器同时执行任务,优化页面关闭并刷新列表页
This commit is contained in:
georgehao
2019-04-16 23:40:07 +08:00
parent 07aff7ee72
commit 830d49ee1c
24 changed files with 391 additions and 137 deletions

View File

@@ -9,11 +9,11 @@ package controllers
import (
"github.com/astaxie/beego"
"github.com/axgle/mahonia"
"github.com/george518/PPGo_Job/libs"
"github.com/george518/PPGo_Job/models"
"strconv"
"strings"
"github.com/axgle/mahonia"
)
const (
@@ -361,4 +361,9 @@ func gbkAsUtf8(str string) string {
resStr := srcDecoder.ConvertString(str)
_, resBytes, _ := desDecoder.Translate([]byte(resStr), true)
return string(resBytes)
}
}
//任务识别码
func jobKey(taskId, serverId int) int {
return taskId*10000 + serverId
}

View File

@@ -8,6 +8,7 @@
package controllers
import (
"fmt"
"strconv"
"strings"
"time"
@@ -78,6 +79,15 @@ func (self *TaskController) Edit() {
self.Data["notify_user_ids"] = notifyUserIds
server_ids := strings.Split(task.ServerIds, ",")
var server_ids_arr []int
for _, sv := range server_ids {
i, _ := strconv.Atoi(sv)
server_ids_arr = append(server_ids_arr, i)
}
self.Data["service_ids"] = server_ids_arr
notifyTplList, _, err := models.NotifyTplGetByTplTypeList(task.NotifyType)
tplList := make([]map[string]interface{}, len(notifyTplList))
@@ -145,13 +155,28 @@ func (self *TaskController) Detail() {
// 分组列表
self.Data["taskGroup"] = taskGroupLists(self.taskGroups, self.userId)
serverName := "本地服务器"
if task.ServerId == 0 {
serverName := ""
if task.ServerIds == "0" {
serverName = "本地服务器"
} else {
server, err := models.TaskServerGetById(task.ServerId)
if err == nil {
serverName = server.ServerName
serverIdSli := strings.Split(task.ServerIds, ",")
for _, v := range serverIdSli {
if v == "0" {
serverName = "本地服务器 "
}
}
servers, n := models.TaskServerGetByIds(task.ServerIds)
if n > 0 {
for _, server := range servers {
fmt.Println(server.Status)
if server.Status != 0 {
serverName += server.ServerName + "【无效】 "
} else {
serverName += server.ServerName + " "
}
}
} else {
serverName += "服务器异常!!"
}
}
@@ -212,7 +237,7 @@ func (self *TaskController) AjaxSave() {
task.TaskName = strings.TrimSpace(self.GetString("task_name"))
task.Description = strings.TrimSpace(self.GetString("description"))
task.Concurrent, _ = self.GetInt("concurrent")
task.ServerId, _ = self.GetInt("server_id")
task.ServerIds = strings.TrimSpace(self.GetString("server_ids"))
task.CronSpec = strings.TrimSpace(self.GetString("cron_spec"))
task.Command = strings.TrimSpace(self.GetString("command"))
task.Timeout, _ = self.GetInt("timeout")
@@ -258,7 +283,7 @@ func (self *TaskController) AjaxSave() {
task.Description = strings.TrimSpace(self.GetString("description"))
task.GroupId, _ = self.GetInt("group_id")
task.Concurrent, _ = self.GetInt("concurrent")
task.ServerId, _ = self.GetInt("server_id")
task.ServerIds = strings.TrimSpace(self.GetString("server_ids"))
task.CronSpec = strings.TrimSpace(self.GetString("cron_spec"))
task.Command = strings.TrimSpace(self.GetString("command"))
task.Timeout, _ = self.GetInt("timeout")
@@ -291,8 +316,6 @@ func (self *TaskController) AjaxSave() {
self.ajaxMsg("", MSG_OK)
}
//检查是否含有禁用命令
func checkCommand(command string) (string, bool) {
@@ -332,8 +355,6 @@ func (self *TaskController) AjaxNopass() {
self.ajaxMsg("", MSG_OK)
}
func (self *TaskController) AjaxStart() {
taskId, _ := self.GetInt("id")
if taskId == 0 {
@@ -349,15 +370,19 @@ func (self *TaskController) AjaxStart() {
self.ajaxMsg("任务状态有误", MSG_ERR)
}
job, err := jobs.NewJobFromTask(task)
jobArr, err := jobs.NewJobFromTask(task)
if err != nil {
self.ajaxMsg("创建任务失败", MSG_ERR)
}
if jobs.AddJob(task.CronSpec, job) {
task.Status = 1
task.Update()
for _, job := range jobArr {
if jobs.AddJob(task.CronSpec, job) {
task.Status = 1
task.Update()
}
}
self.ajaxMsg("", MSG_OK)
}
@@ -372,9 +397,18 @@ func (self *TaskController) AjaxPause() {
self.ajaxMsg("查不到该任务", MSG_ERR)
}
jobs.RemoveJob(taskId)
//移出任务
TaskServerIdsArr := strings.Split(task.ServerIds, ",")
for _, server_id := range TaskServerIdsArr {
server_id_int, _ := strconv.Atoi(server_id)
jobKey := jobKey(task.Id, server_id_int)
jobs.RemoveJob(jobKey)
}
task.Status = 0
task.Update()
self.ajaxMsg("", MSG_OK)
}
@@ -387,11 +421,14 @@ func (self *TaskController) AjaxRun() {
self.ajaxMsg(err.Error(), MSG_ERR)
}
job, err := jobs.NewJobFromTask(task)
jobArr, err := jobs.NewJobFromTask(task)
if err != nil {
self.ajaxMsg(err.Error(), MSG_ERR)
}
job.Run()
for _, job := range jobArr {
job.Run()
}
self.ajaxMsg("", MSG_OK)
}
@@ -408,9 +445,12 @@ func (self *TaskController) AjaxBatchStart() {
}
if task, err := models.TaskGetById(id); err == nil {
job, err := jobs.NewJobFromTask(task)
jobArr, err := jobs.NewJobFromTask(task)
if err == nil {
jobs.AddJob(task.CronSpec, job)
for _, job := range jobArr {
jobs.AddJob(task.CronSpec, job)
}
task.Status = 1
task.Update()
}
@@ -430,9 +470,17 @@ func (self *TaskController) AjaxBatchPause() {
if id < 1 {
continue
}
jobs.RemoveJob(id)
if task, err := models.TaskGetById(id); err == nil {
task, err := models.TaskGetById(id)
//移出任务
TaskServerIdsArr := strings.Split(task.ServerIds, ",")
for _, server_id := range TaskServerIdsArr {
server_id_int, _ := strconv.Atoi(server_id)
jobKey := jobKey(task.Id, server_id_int)
jobs.RemoveJob(jobKey)
}
if err == nil {
task.Status = 0
task.Update()
}
@@ -451,9 +499,19 @@ func (self *TaskController) AjaxBatchDel() {
if id < 1 {
continue
}
task, _ := models.TaskGetById(id)
//移出任务
TaskServerIdsArr := strings.Split(task.ServerIds, ",")
for _, server_id := range TaskServerIdsArr {
server_id_int, _ := strconv.Atoi(server_id)
jobKey := jobKey(task.Id, server_id_int)
jobs.RemoveJob(jobKey)
}
models.TaskDel(id)
models.TaskLogDelByTaskId(id)
jobs.RemoveJob(id)
}
self.ajaxMsg("", MSG_OK)
}
@@ -661,12 +719,12 @@ func (self *TaskController) ApiTask() {
task_id, _ := self.GetInt("id")
if task_id == 0 {
task := new(models.Task)
task.CreateId,_ = self.GetInt("create_id")
task.CreateId, _ = self.GetInt("create_id")
task.GroupId, _ = self.GetInt("group_id")
task.TaskName = strings.TrimSpace(self.GetString("task_name"))
task.Description = strings.TrimSpace(self.GetString("description"))
task.Concurrent, _ = self.GetInt("concurrent")
task.ServerId, _ = self.GetInt("server_id")
task.ServerIds = strings.TrimSpace(self.GetString("server_ids"))
task.CronSpec = strings.TrimSpace(self.GetString("cron_spec"))
task.Command = strings.TrimSpace(self.GetString("command"))
task.Timeout, _ = self.GetInt("timeout")
@@ -716,7 +774,7 @@ func (self *TaskController) ApiTask() {
task.Description = strings.TrimSpace(self.GetString("description"))
task.GroupId, _ = self.GetInt("group_id")
task.Concurrent, _ = self.GetInt("concurrent")
task.ServerId, _ = self.GetInt("server_id")
task.ServerIds = strings.TrimSpace(self.GetString("server_ids"))
task.CronSpec = strings.TrimSpace(self.GetString("cron_spec"))
task.Command = strings.TrimSpace(self.GetString("command"))
task.Timeout, _ = self.GetInt("timeout")
@@ -724,7 +782,7 @@ func (self *TaskController) ApiTask() {
task.NotifyType, _ = self.GetInt("notify_type")
task.NotifyTplId, _ = self.GetInt("notify_tpl_id")
task.NotifyUserIds = strings.TrimSpace(self.GetString("notify_user_ids"))
task.UpdateId , _ = self.GetInt("update_id")
task.UpdateId, _ = self.GetInt("update_id")
task.Status = 0 //接口不需要
if task.IsNotify == 1 && task.NotifyTplId <= 0 {
@@ -761,15 +819,18 @@ func (self *TaskController) ApiStart() {
self.ajaxMsg("任务状态有误", MSG_ERR)
}
job, err := jobs.NewJobFromTask(task)
jobArr, err := jobs.NewJobFromTask(task)
if err != nil {
self.ajaxMsg("创建任务失败", MSG_ERR)
}
if jobs.AddJob(task.CronSpec, job) {
task.Status = 1
task.Update()
for _, job := range jobArr {
if jobs.AddJob(task.CronSpec, job) {
task.Status = 1
task.Update()
}
}
self.ajaxMsg("", MSG_OK)
}
@@ -784,11 +845,17 @@ func (self *TaskController) ApiPause() {
self.ajaxMsg("查不到该任务", MSG_ERR)
}
jobs.RemoveJob(taskId)
//移出任务
TaskServerIdsArr := strings.Split(task.ServerIds, ",")
for _, server_id := range TaskServerIdsArr {
server_id_int, _ := strconv.Atoi(server_id)
jobKey := jobKey(task.Id, server_id_int)
jobs.RemoveJob(jobKey)
}
task.Status = 0
task.Update()
self.ajaxMsg("", MSG_OK)
}

View File

@@ -8,6 +8,7 @@
package controllers
import (
"fmt"
"github.com/astaxie/beego"
"github.com/george518/PPGo_Job/libs"
"github.com/george518/PPGo_Job/models"
@@ -74,9 +75,12 @@ func (self *TaskLogController) Table() {
for k, v := range result {
row := make(map[string]interface{})
row["id"] = v.Id
row["task_id"] = v.TaskId
row["task_id"] = jobKey(v.TaskId, v.ServerId)
row["start_time"] = beego.Date(time.Unix(v.CreateTime, 0), "Y-m-d H:i:s")
row["process_time"] = float64(v.ProcessTime) / 1000
row["server_id"] = v.ServerId
row["server_name"] = v.ServerName + "#" + strconv.Itoa(v.ServerId)
if v.Status == 0 {
row["output_size"] = libs.SizeFormat(float64(len(v.Output)))
} else {
@@ -99,6 +103,8 @@ func (self *TaskLogController) Detail() {
//日志内容
id, _ := self.GetInt("id")
tasklog, err := models.TaskLogGetById(id)
fmt.Println(tasklog)
if err != nil {
self.Ctx.WriteString("日志不存在")
return
@@ -119,6 +125,8 @@ func (self *TaskLogController) Detail() {
row["output_size"] = libs.SizeFormat(float64(len(tasklog.Error)))
}
row["server_name"] = tasklog.ServerName
row["output"] = tasklog.Output
row["error"] = tasklog.Error
@@ -149,15 +157,31 @@ func (self *TaskLogController) Detail() {
// 分组列表
self.Data["taskGroup"] = taskGroupLists(self.taskGroups, self.userId)
serverName := "本地服务器"
if task.ServerId == 0 {
serverName := ""
if task.ServerIds == "0" {
serverName = "本地服务器"
} else {
server, err := models.TaskServerGetById(task.ServerId)
if err == nil {
serverName = server.ServerName
serverIdSli := strings.Split(task.ServerIds, ",")
for _, v := range serverIdSli {
if v == "0" {
serverName = "本地服务器 "
}
}
servers, n := models.TaskServerGetByIds(task.ServerIds)
if n > 0 {
for _, server := range servers {
if server.Status != 0 {
serverName += server.ServerName + "【无效】 "
} else {
serverName += server.ServerName + " "
}
}
} else {
serverName = "服务器异常!! "
}
}
self.Data["serverName"] = serverName
//任务分组

View File

@@ -32,7 +32,7 @@ func AddJob(spec string, job *Job) bool {
lock.Lock()
defer lock.Unlock()
if GetEntryById(job.id) != nil {
if GetEntryById(job.jobKey) != nil {
return false
}
err := mainCron.AddJob(spec, job)
@@ -40,13 +40,14 @@ func AddJob(spec string, job *Job) bool {
beego.Error("AddJob: ", err.Error())
return false
}
//fmt.Println(job)
return true
}
func RemoveJob(id int) {
func RemoveJob(jobKey int) {
mainCron.RemoveJob(func(e *cron.Entry) bool {
if v, ok := e.Job.(*Job); ok {
if v.id == id {
if v.jobKey == jobKey {
return true
}
}
@@ -54,11 +55,11 @@ func RemoveJob(id int) {
})
}
func GetEntryById(id int) *cron.Entry {
func GetEntryById(jobKey int) *cron.Entry {
entries := mainCron.Entries()
for _, e := range entries {
if v, ok := e.Job.(*Job); ok {
if v.id == id {
if v.jobKey == jobKey {
return e
}
}

View File

@@ -18,12 +18,16 @@ import (
func InitJobs() {
list, _ := models.TaskGetList(1, 1000000, "status", 1)
for _, task := range list {
job, err := NewJobFromTask(task)
jobs, err := NewJobFromTask(task)
if err != nil {
beego.Error("InitJobs:", err.Error())
continue
}
AddJob(task.CronSpec, job)
for _, job := range jobs {
AddJob(task.CronSpec, job)
}
}
}

View File

@@ -20,19 +20,22 @@ import (
"strconv"
"strings"
"encoding/json"
"github.com/astaxie/beego"
"github.com/axgle/mahonia"
"github.com/george518/PPGo_Job/models"
"github.com/george518/PPGo_Job/notify"
"golang.org/x/crypto/ssh"
"encoding/json"
"github.com/axgle/mahonia"
"github.com/pkg/errors"
"github.com/linxiaozhi/go-telnet"
"github.com/pkg/errors"
"golang.org/x/crypto/ssh"
)
type Job struct {
id int // 任务ID
jobKey int // jobId = id*10000+serverId
id int // taskID
logId int64 // 日志记录ID
serverId int //服务器信息
serverName string //服务器名称
name string // 任务名称
task *models.Task // 任务对象
runFunc func(time.Duration) (string, string, error, bool) // 执行函数
@@ -40,51 +43,79 @@ type Job struct {
Concurrent bool // 同一个任务是否允许并行执行
}
func NewJobFromTask(task *models.Task) (*Job, error) {
func NewJobFromTask(task *models.Task) ([]*Job, error) {
if task.Id < 1 {
return nil, fmt.Errorf("ToJob: 缺少id")
}
//本地程序执行
if task.ServerId == 0 {
job := NewCommandJob(task.Id, task.TaskName, task.Command)
job.task = task
job.Concurrent = task.Concurrent == 1
return job, nil
if task.ServerIds == "" {
return nil, fmt.Errorf("任务执行失败,找不到执行的服务器")
}
server, _ := models.TaskServerGetById(task.ServerId)
if server.ConnectionType == 0 {
if server.Type == 0 {
//密码验证登录服务器
job := RemoteCommandJobByPassword(task.Id, task.TaskName, task.Command, server)
job.task = task
job.Concurrent = task.Concurrent == 1
return job, nil
}
TaskServerIdsArr := strings.Split(task.ServerIds, ",")
job := RemoteCommandJob(task.Id, task.TaskName, task.Command, server)
job.task = task
job.Concurrent = task.Concurrent == 1
return job, nil
} else if server.ConnectionType == 1 {
if server.Type == 0 {
//密码验证登录服务器
job := RemoteCommandJobByTelnetPassword(task.Id, task.TaskName, task.Command, server)
jobArr := make([]*Job, 0)
for _, server_id := range TaskServerIdsArr {
if server_id == "0" {
//本地执行
job := NewCommandJob(task.Id, 0, task.TaskName, task.Command)
job.task = task
job.Concurrent = task.Concurrent == 1
return job, nil
job.serverId = 0
job.serverName = "本地服务器"
jobArr = append(jobArr, job)
} else {
server_id_int, _ := strconv.Atoi(server_id)
//远程执行
server, _ := models.TaskServerGetById(server_id_int)
if server.Status == 1 {
fmt.Println("服务器已禁用")
continue
}
if server.ConnectionType == 0 {
if server.Type == 0 {
//密码验证登录服务器
job := RemoteCommandJobByPassword(task.Id, server_id_int, task.TaskName, task.Command, server)
job.task = task
job.Concurrent = task.Concurrent == 1
job.serverId = server_id_int
job.serverName = server.ServerName
jobArr = append(jobArr, job)
} else {
job := RemoteCommandJob(task.Id, server_id_int, task.TaskName, task.Command, server)
job.task = task
job.Concurrent = task.Concurrent == 1
job.serverId = server_id_int
job.serverName = server.ServerName
jobArr = append(jobArr, job)
}
} else if server.ConnectionType == 1 {
if server.Type == 0 {
//密码验证登录服务器
job := RemoteCommandJobByTelnetPassword(task.Id, server_id_int, task.TaskName, task.Command, server)
job.task = task
job.Concurrent = task.Concurrent == 1
job.serverId = server_id_int
job.serverName = server.ServerName
jobArr = append(jobArr, job)
}
}
}
}
return nil, fmt.Errorf("未知ConnectionType")
return jobArr, nil
}
func NewCommandJob(id int, name string, command string) *Job {
func NewCommandJob(id int, serverId int, name string, command string) *Job {
job := &Job{
id: id,
name: name,
}
job.jobKey = jobKey(id, serverId)
job.runFunc = func(timeout time.Duration) (string, string, error, bool) {
bufOut := new(bytes.Buffer)
bufErr := new(bytes.Buffer)
@@ -106,11 +137,15 @@ func NewCommandJob(id int, name string, command string) *Job {
}
//远程执行任务 密钥验证
func RemoteCommandJob(id int, name string, command string, servers *models.TaskServer) *Job {
func RemoteCommandJob(id int, serverId int, name string, command string, servers *models.TaskServer) *Job {
job := &Job{
id: id,
name: name,
id: id,
name: name,
serverId: serverId,
}
job.jobKey = jobKey(id, serverId)
job.runFunc = func(timeout time.Duration) (string, string, error, bool) {
key, err := ioutil.ReadFile(servers.PrivateKeySrc)
@@ -166,7 +201,7 @@ func RemoteCommandJob(id int, name string, command string, servers *models.TaskS
return job
}
func RemoteCommandJobByPassword(id int, name string, command string, servers *models.TaskServer) *Job {
func RemoteCommandJobByPassword(id int, serverId int, name string, command string, servers *models.TaskServer) *Job {
var (
auth []ssh.AuthMethod
addr string
@@ -177,9 +212,11 @@ func RemoteCommandJobByPassword(id int, name string, command string, servers *mo
)
job := &Job{
id: id,
name: name,
id: id,
name: name,
serverId: serverId,
}
job.jobKey = jobKey(id, serverId)
job.runFunc = func(timeout time.Duration) (string, string, error, bool) {
// get auth method
auth = make([]ssh.AuthMethod, 0)
@@ -223,12 +260,15 @@ func RemoteCommandJobByPassword(id int, name string, command string, servers *mo
return job
}
func RemoteCommandJobByTelnetPassword(id int, name string, command string, servers *models.TaskServer) *Job {
func RemoteCommandJobByTelnetPassword(id int, serverId int, name string, command string, servers *models.TaskServer) *Job {
job := &Job{
id: id,
name: name,
id: id,
name: name,
serverId: serverId,
}
job.jobKey = jobKey(id, serverId)
job.runFunc = func(timeout time.Duration) (string, string, error, bool) {
addr := fmt.Sprintf("%s:%d", servers.ServerIp, servers.Port)
@@ -309,7 +349,7 @@ func (j *Job) GetLogId() int64 {
func (j *Job) Run() {
if !j.Concurrent && j.status > 0 {
beego.Warn(fmt.Sprintf("任务[%d]上一次执行尚未结束,本次被忽略。", j.id))
beego.Warn(fmt.Sprintf("任务[%d]上一次执行尚未结束,本次被忽略。", j.jobKey))
return
}
@@ -326,7 +366,7 @@ func (j *Job) Run() {
}()
}
beego.Debug(fmt.Sprintf("开始执行任务: %d", j.id))
beego.Debug(fmt.Sprintf("开始执行任务: %d", j.jobKey))
j.status++
defer func() {
@@ -344,6 +384,8 @@ func (j *Job) Run() {
// 插入日志
log := new(models.TaskLog)
log.TaskId = j.id
log.ServerId = j.serverId
log.ServerName = j.serverName
log.Output = cmdOut
log.Error = cmdErr
log.ProcessTime = int(ut)
@@ -536,3 +578,8 @@ func gbkAsUtf8(str string) string {
_, resBytes, _ := desDecoder.Translate([]byte(resStr), true)
return string(resBytes)
}
//任务识别码
func jobKey(taskId, serverId int) int {
return taskId*10000 + serverId
}

View File

@@ -9,6 +9,8 @@ package models
import (
"fmt"
"strconv"
"strings"
"github.com/astaxie/beego/orm"
)
@@ -95,6 +97,22 @@ func TaskServerGetById(id int) (*TaskServer, error) {
return obj, nil
}
//
func TaskServerGetByIds(ids string) ([]*TaskServer, int64) {
serverFilters := make([]interface{}, 0)
//serverFilters = append(serverFilters, "status", 1)
TaskServerIdsArr := strings.Split(ids, ",")
TaskServerIds := make([]int, 0)
for _, v := range TaskServerIdsArr {
id, _ := strconv.Atoi(v)
TaskServerIds = append(TaskServerIds, id)
}
serverFilters = append(serverFilters, "id__in", TaskServerIds)
return TaskServerGetList(1, 1000, serverFilters...)
}
func TaskServerDelById(id int) error {
_, err := orm.NewOrm().QueryTable(TableName("task_server")).Filter("id", id).Delete()
return err

View File

@@ -23,7 +23,7 @@ const (
type Task struct {
Id int
GroupId int
ServerId int
ServerIds string
TaskName string
Description string
CronSpec string

View File

@@ -14,6 +14,8 @@ import (
type TaskLog struct {
Id int
TaskId int
ServerId int
ServerName string
Output string
Error string
Status int

View File

@@ -330,4 +330,13 @@ BEGIN;
ALTER TABLE `pp_task_server` ADD `connection_type` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '连接类型 0:SSH;1:Telnet;' AFTER `group_id`;
COMMIT;
BEGIN;
ALTER TABLE `ppgo_job2`.`pp_task` CHANGE COLUMN `server_id` `server_ids` varchar(200) NOT NULL DEFAULT '0' COMMENT '服务器id字符串英文都好隔开';
BEGIN;
BEGIN;
ALTER TABLE `ppgo_job2`.`pp_task_log` ADD COLUMN `server_id` int(11) NOT NULL DEFAULT '-1' COMMENT '服务器ID-1异常' AFTER `task_id`, CHANGE COLUMN `output` `output` mediumtext NOT NULL COMMENT '任务输出' AFTER `server_id`, CHANGE COLUMN `error` `error` text NOT NULL COMMENT '错误信息' AFTER `output`, CHANGE COLUMN `status` `status` tinyint(4) NOT NULL COMMENT '状态' AFTER `error`, CHANGE COLUMN `process_time` `process_time` int(11) NOT NULL DEFAULT '0' COMMENT '消耗时间/毫秒' AFTER `status`, CHANGE COLUMN `create_time` `create_time` int(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '创建时间' AFTER `process_time`;
ALTER TABLE `ppgo_job2`.`pp_task_log` ADD COLUMN `server_name` varchar(60) NOT NULL DEFAULT '\"\"' COMMENT '服务器名称' AFTER `server_id`, CHANGE COLUMN `output` `output` mediumtext NOT NULL COMMENT '任务输出' AFTER `server_name`, CHANGE COLUMN `error` `error` text NOT NULL COMMENT '错误信息' AFTER `output`, CHANGE COLUMN `status` `status` tinyint(4) NOT NULL COMMENT '状态' AFTER `error`, CHANGE COLUMN `process_time` `process_time` int(11) NOT NULL DEFAULT '0' COMMENT '消耗时间/毫秒' AFTER `status`, CHANGE COLUMN `create_time` `create_time` int(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '创建时间' AFTER `process_time`;
BEGIN;
SET FOREIGN_KEY_CHECKS = 1;

View File

@@ -106,7 +106,7 @@ var $;
$.post('{{urlfor "AdminController.AjaxSave"}}', form_data, function (out) {
if (out.status == 0) {
layer.msg("操作成功",{icon: 1,shade:0.3,time:1000},function () {
window.location.reload()
window.parent.deleteCurrentTab();
})
} else {
layer.msg(out.message)

View File

@@ -113,7 +113,7 @@ var $;
$.post('{{urlfor "AdminController.AjaxSave"}}', form_data, function (out) {
if (out.status == 0) {
layer.msg("操作成功",{icon: 1,shade:0.3,time:1000},function () {
window.location.reload()
window.parent.deleteCurrentTab();
})
} else {
layer.msg(out.message)

View File

@@ -89,8 +89,7 @@
$.post('{{urlfor "NotifyTplController.AjaxSave"}}', form_data, function (out) {
if (out.status == 0) {
layer.msg("操作成功", {icon: 1, shade: 0.3, time: 1000}, function () {
// window.history.go(-1)//
window.location.reload()
window.parent.deleteCurrentTab();
})
} else {
layer.msg(out.message)

View File

@@ -89,8 +89,7 @@
$.post('{{urlfor "NotifyTplController.AjaxSave"}}', form_data, function (out) {
if (out.status == 0) {
layer.msg("操作成功", {icon: 1, shade: 0.3, time: 1000}, function () {
// window.history.go(-1)
window.location.reload()
window.parent.deleteCurrentTab();
})
} else {
layer.msg(out.message)

View File

@@ -26,7 +26,7 @@
{{.pageTitle}}
</div>
<div class="tr fr">
<button class="layui-btn layui-btn-radius layui-btn-primary layui-btn-xs" onclick="javascript:window.location.reload();"><i class="fa fa-refresh" aria-hidden="true"></i></button>
<button class="layui-btn layui-btn-radius layui-btn-primary layui-btn-xs" onclick="javascript:window.location.reload();"><i class="fa fa-refresh" aria-hidden="true" id="reload"></i></button>
</div>
</div>
<!-- 公共头部 end-->

View File

@@ -106,6 +106,29 @@
return str;
}
//新页面编辑或者新增,完成后关闭本页并刷新上一页
function deleteCurrentTab(){
//关闭
var lay_id = $(parent.document).find("ul.layui-tab-title").children("li.layui-this").find(".layui-tab-close");
lay_id.click();
//刷新
var currents =$(parent.document).find("div.layui-tab-content").find("div.layui-show").find("iframe").contents();
$(currents[0]).find("body").find("#reload").click();
}
function getCheckboxValue(name)
{
var arr = new Array();
$("input:checkbox[name="+name+"]:checked").each(function(){
console.log($(this).val());
arr.push($(this).val());
});
return arr.join(",");
}
function openTab(url,title,id,icon){
if (!url || !title || !id) {
@@ -235,6 +258,9 @@
layer.tips($(this).attr('data-title'), $(this),{time:1000});
});
element.render();
// $("#default_tab").html('<i class="fa fa-home back_space1"></i>系统首页');

View File

@@ -156,7 +156,7 @@
if (out.status == 0) {
layer.msg("操作成功",{icon: 1,shade:0.3,time:1000},function () {
// window.history.go(-1)//
window.location.reload()
window.parent.deleteCurrentTab();
})
} else {
layer.msg(out.message)

View File

@@ -154,7 +154,7 @@
if (out.status == 0) {
layer.msg("操作成功",{icon: 1,shade:0.3,time:1000},function () {
//window.location.href = "/server/list"
windwo.location.reload();
window.parent.deleteCurrentTab();
})
} else {
layer.msg(out.message)

View File

@@ -155,7 +155,9 @@
if (out.status == 0) {
layer.msg("操作成功",{icon: 1,shade:0.3,time:1000},function () {
// window.history.go(-1)
window.location.reload()
// window.location.reload()
window.parent.deleteCurrentTab();
})
} else {
layer.msg(out.message)

View File

@@ -27,19 +27,22 @@
<div class="layui-form-item">
<label class="layui-form-label mw200">服务器资源</label>
<div class="layui-inline">
<div class="layui-input-inline">
<select name="server_id">
<option value="0">本地服务器</option>
{{range $k, $v := .serverGroup}}
<optgroup label="{{$v.GroupName}}">
{{range $kk, $vv := $v.Servers}}
<option value="{{$kk}}">{{$vv}}</option>
<div class="layui-block">
<div class="layui-col-md3"></div>
<div class="layui-col-md9">
<div style="margin-bottom: 20px;">
<input type="checkbox" name="server_id" lay-skin="primary" title="本地服务器" value="0">
</div>
<div class="layui-row layui-col-space10">
{{range $k, $v := .serverGroup}}
<div class="layui-col-md12" style="background: #efefef;">{{$v.GroupName}}</div>
{{range $kk, $vv := $v.Servers}}
<div class="layui-col-md4">
<input type="checkbox" name="server_id" lay-skin="primary" title="{{$vv}}" value="{{$kk}}">
</div>
{{end}}
{{end}}
</optgroup>
{{end}}
</select>
</div>
</div>
</div>
</div>
@@ -129,7 +132,7 @@
<input type="checkbox" name="notify_user" lay-filter="notify_user" title="{{$v.RealName}}"
value="{{$v.Id}}" lay-skin="primary">
{{end}}
<input type="hidden" name="notify_user_ids" id="notify_user_ids" value="">
</div>
<div class="layui-form-mid layui-word-aux"></div>
</div>
@@ -159,7 +162,7 @@
layer.tips('设为的话如果该任务在上一个时间点还没执行完则略过不执行', '#des', {
tips: [1, '#0FA6D8'] //还可配置颜色
});
})
});
var notify_user_ids = [];
@@ -176,6 +179,7 @@
}
$("#notify_user_ids").val(notify_user_ids.join(","));
});
form.on('radio(is_notify)', function (data) {
if (data.value == 1) {
$(".notify").show()
@@ -185,12 +189,36 @@
});
form.on('submit(sub)', function (data) {
var form_data = data.field;
var server_arr = new Array();
$("input:checkbox[name=server_id]:checked").each(function(){
server_arr.push($(this).val());
});
form_data.server_ids = server_arr.join(",");
if (form_data.server_ids==="" || form_data.server_ids===null){
layer.msg("请选择服务器资源");
return false;
}
var notify_user_arr = new Array();
$("input:checkbox[name=notify_user]:checked").each(function(){
notify_user_arr.push($(this).val());
});
form_data.notify_user_ids = notify_user_arr.join(",");
if (form_data.is_notify==1 && form_data.notify_user_ids==="") {
layer.msg("请选择通知用户");
return false;
}
$.post('{{urlfor "TaskController.AjaxSave"}}', form_data, function (out) {
if (out.status == 0) {
layer.msg("操作成功", {icon: 1, shade: 0.3, time: 1000}, function () {
// window.history.go(-1)
window.location.reload();
window.parent.deleteCurrentTab();
})
} else {

View File

@@ -175,7 +175,7 @@
if (out.status == 0) {
layer.msg("复制成功!,请到列表中查看",{icon: 1,shade:0.3,time:1000},function () {
//self.location=document.referrer;
window.location.reload();
window.parent.deleteCurrentTab();
})
} else {
layer.msg(out.message)

View File

@@ -26,20 +26,24 @@
<div class="layui-form-item">
<label class="layui-form-label mw200">服务器资源</label>
<div class="layui-inline">
<div class="layui-input-inline">
<select name="server_id">
<option value="0">本地服务器</option>
{{range $k, $v := .serverGroup}}
<optgroup label="{{$v.GroupName}}">
{{range $kk, $vv := $v.Servers}}
<option value="{{$kk}}" {{if eq $kk $.task.ServerId}}selected{{end}} >{{$vv}}</option>
<div class="layui-block">
<div class="layui-col-md3"></div>
<div class="layui-col-md9">
<div style="margin-bottom: 20px;">
<input type="checkbox" name="server_id" lay-skin="primary" title="本地服务器" value="0" {{range $ks,$vs:=$.service_ids}} {{if eq 0 $vs}}checked{{end}}{{end}}>
</div>
<div class="layui-row layui-col-space10">
{{range $k, $v := .serverGroup}}
<div class="layui-col-md12" style="background: #efefef;">{{$v.GroupName}}</div>
{{range $kk, $vv := $v.Servers}}
<div class="layui-col-md4">
<input type="checkbox" name="server_id" lay-skin="primary" title="{{$vv}}" value="{{$kk}}" {{range $ks,$vs:=$.service_ids}} {{if eq $kk $vs}}checked{{end}}{{end}}>
</div>
{{end}}
{{end}}
</optgroup>
{{end}}
</select>
</div>
</div>
</div>
</div>
@@ -182,6 +186,7 @@
$("#notify_user_ids").val(notify_user_ids.join(","));
});
form.on('submit(sub)', function(data){
var isAdmin = "{{.isAdmin}}";
var msg = "编辑任务需要重新审核,是否确认需要编辑?";
@@ -193,15 +198,26 @@
}
layer.confirm(msg, {icon: 3, title:'提示'}, function(index){
layer.load();
var form_data = data.field;
var ids = [];
$("input[name=server_id][type=checkbox]").each(function() {
if ($(this).prop("checked")) {
ids.push($(this).val());
}
});
if (ids.length<1){
layer.msg("请选择服务资源");
return false;
}
form_data.server_ids = ids.join(",");
$.post('{{urlfor "TaskController.AjaxSave"}}', form_data, function (out) {
if (out.status == 0) {
layer.msg(okmsg,{icon: 1,shade:0.3,time:1000},function () {
// self.location=document.referrer;
window.location.reload();
window.parent.deleteCurrentTab();
})
} else {
layer.msg(out.message)
return

View File

@@ -50,6 +50,12 @@
<td>{{.taskLog.status|str2html}}</td>
<td></td>
</tr>
<tr>
<td>运行服务器</td>
<td>{{.taskLog.server_name}}</td>
<td></td>
</tr>
</tbody>
</table>

View File

@@ -46,12 +46,13 @@
,url: "/tasklog/table?task_id={{.task_id}}"
,cols: [[
{checkbox: true, fixed: true}
,{field:'id', title: 'ID', align:'center',sort: true, width:150}
,{field:'task_id', title: '任务ID', align:'center',sort: true, width:150}
// ,{field:'id', title: 'ID', align:'center',sort: true, width:150}
,{field:'task_id', title: '任务ID', align:'center',width:100}
,{field:'server_name', title: '服务器', width:150}
,{field:'start_time',title: '开始时间'}
,{field:'process_time',width:100, title: '执行时间'}
,{field:'output_size',title: '输出'}
,{field:'status', width:170,title: '状态'}
,{field:'status', width:100,title: '状态'}
,{fixed: 'right', align:'center', title:'操作', toolbar: '#bar'}
]]
,id: 'listReload'