优化首页内容
This commit is contained in:
30
README.md
30
README.md
@@ -1,12 +1,15 @@
|
||||
PPGo_Job定时任务管理系统 V2.x
|
||||
PPGo_Job定时任务管理系统
|
||||
====
|
||||
|
||||

|
||||
|
||||
PPGo_Job是一款定时任务可视化的、多人多权限的管理系统,采用golang开发,安装方便,资源消耗少,支持大并发,可同时管理多台服务器上的定时任务。
|
||||
##说明
|
||||
PPGo_Job是一款轻量级定时任务管理系统,go语言开发,部署超级简单,资源消耗少,运行稳定。
|
||||
支持定时任务可视化管理、多人多权限的管理,支持大并发,可同时管理多台服务器上的定时任务。
|
||||
|
||||
PPGo_Job从v1.0开源以来,得到众多技术朋友的支持和欢迎,已应用在多个公司的生产环境,同时也
|
||||
吸收使用者的建议和意见,不断改进和优化,目前已经上线了20余个版本,9个稳定版本(生产环境部署完成后才发布新版本)。
|
||||
|
||||
前言:PPGo_Job V1.x版本开源两年多了,不少朋友的公司都在用,反响还不错,当然,也有好多朋友提了不少合理的意见和建议,所以这次干脆重构了一下,连UI也重新编码。目前V2.x版本
|
||||
已经用于生产环境。
|
||||
|
||||
码云地址:https://gitee.com/georgehao/PPGo_Job
|
||||
Github地址:https://github.com/george518/PPGo_Job
|
||||
@@ -14,11 +17,15 @@ Github地址:https://github.com/george518/PPGo_Job
|
||||
文档地址:http://www.haodaquan.com/topics/1###
|
||||
Wiki:https://github.com/george518/PPGo_Job/wiki
|
||||
|
||||
##架构
|
||||
|
||||
V1.x版本是一个简单的定时任务管理系统,进入V1.0 :https://github.com/george518/PPGo_Job/releases/tag/v1.2.1
|
||||
相对于V1.x版本,V2.0新增以下功能和特性:
|
||||

|
||||
|
||||
- 1、全新UI,基于LayUI2.3构建全新页面,后端模板手工搭建,让操作更加人性化。后台模板地址:https://github.com/george518/PP_admin-template
|
||||
##特性
|
||||
|
||||
V2.x新增以下功能和特性:
|
||||
|
||||
- 1、全新UI,基于LayUI构建全新页面,后端模板手工搭建,让操作更加人性化。后台模板地址:https://github.com/george518/PP_admin-template
|
||||
- 2、新增权限管理功能,根据菜单权限、操作权限和数据权限进行划分,方便多用户多权限管理定时任务。
|
||||
- 3、新增服务器复制功能,让服务器资源添加更加方便。
|
||||
- 4、新增定时任务详情页面,将任务相关操作更加集中起来操作。
|
||||
@@ -29,13 +36,16 @@ V1.x版本是一个简单的定时任务管理系统,进入V1.0 :https://git
|
||||
- 9、支持windows系统运行定时系统,不歧视windows,也要支持。
|
||||
- 10、提醒信息新增钉钉和微信通知功能,并支持编辑通知模版功能。让提醒内容个性化,不再死板。
|
||||
- 11、新增创建、启动、关闭任务的API,通过接口的方式控制定时任务,猜你喜欢。
|
||||
- 12、**新增任务执行器agent,可以通过ssh,telnet或者agent的方式分发任务**
|
||||
|
||||
总之,管理定时任务,使用PPGo_Job吧,节省出来的时间,或皮或浪,随你,哈哈。
|
||||
总之,管理定时任务,使用PPGo_Job吧,节省出来的时间,或皮或浪,随你。
|
||||
|
||||
感觉不错的话,给个星星吧 :)
|
||||
|
||||
也可以请我喝水
|
||||
|
||||
##支持
|
||||
----
|
||||
####1、给项目一个star
|
||||
####2、请我喝瓶水
|
||||

|
||||
|
||||
先看效果
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
package main
|
||||
|
||||
//任务执行器
|
||||
//
|
||||
|
||||
func main() {
|
||||
|
||||
}
|
||||
BIN
agent/agent
Executable file
BIN
agent/agent
Executable file
Binary file not shown.
@@ -6,19 +6,18 @@ Version = 1.0.0
|
||||
LogLevel = ALL
|
||||
# 执行器配置
|
||||
# auto-自动起名,或者自己起名
|
||||
ServerName = agent-10.32.40.165-1564
|
||||
ServerName = agent-192.168.1.101-1564
|
||||
# 启动后回写
|
||||
ServerId = 7
|
||||
ServerId = 4
|
||||
# 端口,必须配置!!
|
||||
TcpPort = 1564
|
||||
# auto-自动获取
|
||||
TcpIp = 10.32.40.165
|
||||
TcpIp = 192.168.1.101
|
||||
# Ip地址是外网还是内网,1-外网,0-内网,若填写TcpIp则本项配置无意义
|
||||
IpType = 0
|
||||
# 添加的执行器属于分组Id,默认为1
|
||||
GroupId = 1
|
||||
|
||||
# 以下配置必填,地址格式:http://yourdomain/server/apisave
|
||||
RegisterUrl = http://localhost:8081/server/apisave
|
||||
UpdateStatusUrl = http://localhost:8081/server/apistatus
|
||||
RegisterUrl = http://localhost:8080/server/apisave
|
||||
UpdateStatusUrl = http://localhost:8080/server/apistatus
|
||||
|
||||
|
||||
@@ -80,8 +80,8 @@ func ResetCommandJob(id int, serverId int, name string, command string) *Job {
|
||||
err, isTimeout := runCmdWithTimeout(cmd, timeout)
|
||||
|
||||
jobResult = new(JobResult)
|
||||
jobResult.ErrMsg = libs.GbkAsUtf8(bufErr.String())
|
||||
jobResult.OutMsg = libs.GbkAsUtf8(bufOut.String())
|
||||
jobResult.ErrMsg = bufErr.String()
|
||||
jobResult.OutMsg = bufOut.String()
|
||||
jobResult.IsOk = true
|
||||
if err != nil {
|
||||
jobResult.IsOk = false
|
||||
|
||||
15
agent/test/sqls/ts.go
Normal file
15
agent/test/sqls/ts.go
Normal file
@@ -0,0 +1,15 @@
|
||||
/************************************************************
|
||||
** @Description: ts
|
||||
** @Author: george hao
|
||||
** @Date: 2019-07-04 17:23
|
||||
** @Last Modified by: george hao
|
||||
** @Last Modified time: 2019-07-04 17:23
|
||||
*************************************************************/
|
||||
package main
|
||||
|
||||
import "github.com/george518/PPGo_Job/models"
|
||||
|
||||
func main() {
|
||||
|
||||
models.TaskTotalRunNum()
|
||||
}
|
||||
BIN
assets/screenshot/ppgo.png
Normal file
BIN
assets/screenshot/ppgo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 120 KiB |
@@ -1,9 +1,9 @@
|
||||
AppName = PPGo_Job2
|
||||
HTTPPort = 8081
|
||||
HTTPPort = 8080
|
||||
RunMode = dev
|
||||
SessionOn = true
|
||||
|
||||
version= V2.7
|
||||
version= V2.8
|
||||
|
||||
# 允许同时运行的任务数
|
||||
jobs.pool = 1000
|
||||
@@ -19,7 +19,7 @@ db.host = 127.0.0.1
|
||||
db.user = root
|
||||
db.password = "123456"
|
||||
db.port = 3306
|
||||
db.name = cron
|
||||
db.name = ppgo_job3
|
||||
db.prefix = pp_
|
||||
db.timezone = Asia/Shanghai
|
||||
|
||||
|
||||
@@ -13,6 +13,9 @@ import (
|
||||
"github.com/george518/PPGo_Job/libs"
|
||||
"github.com/george518/PPGo_Job/models"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
//"strconv"
|
||||
"time"
|
||||
)
|
||||
@@ -34,9 +37,47 @@ func (self *HomeController) Help() {
|
||||
}
|
||||
|
||||
func (self *HomeController) Start() {
|
||||
|
||||
//总任务数量
|
||||
_, count := models.TaskGetList(1, 10)
|
||||
self.Data["totalJob"] = count
|
||||
|
||||
//日志总量
|
||||
_, totalLog := models.TaskLogGetList(1, 10)
|
||||
self.Data["totalLog"] = totalLog
|
||||
|
||||
//待审核任务数量
|
||||
_, totalAuditTask := models.TaskGetList(1, 10, "status", 2)
|
||||
self.Data["totalAuditTask"] = totalAuditTask
|
||||
|
||||
//失败
|
||||
errorNum, err := models.GetLogNum(-1)
|
||||
if err != nil {
|
||||
errorNum = 0
|
||||
}
|
||||
self.Data["errorNum"] = errorNum
|
||||
|
||||
//成功
|
||||
successNum, err := models.GetLogNum(0)
|
||||
if err != nil {
|
||||
successNum = 0
|
||||
}
|
||||
self.Data["successNum"] = successNum
|
||||
|
||||
//用户数
|
||||
_, userNum := models.AdminGetList(1, 10, "status", 1)
|
||||
self.Data["userNum"] = userNum
|
||||
|
||||
//累计运行总次数
|
||||
n, err := models.TaskTotalRunNum()
|
||||
if err != nil {
|
||||
n = 0
|
||||
}
|
||||
self.Data["TaskTotalRunNum"] = n
|
||||
|
||||
groups_map := serverGroupLists(self.serverGroups, self.userId)
|
||||
//计算总任务数量
|
||||
_, count := models.TaskGetList(1, 300)
|
||||
|
||||
// 即将执行的任务
|
||||
entries := jobs.GetEntries(30)
|
||||
jobList := make([]map[string]interface{}, len(entries))
|
||||
@@ -53,35 +94,10 @@ func (self *HomeController) Start() {
|
||||
startJob++
|
||||
}
|
||||
|
||||
// 最近执行的日志
|
||||
logs, _ := models.TaskLogGetList(1, 20)
|
||||
recentLogs := make([]map[string]interface{}, len(logs))
|
||||
failJob := 0 //最近失败的数量
|
||||
okJob := 0 //最近成功的数量
|
||||
for k, v := range logs {
|
||||
task, err := models.TaskGetById(v.TaskId)
|
||||
taskName := ""
|
||||
if err == nil {
|
||||
taskName = task.TaskName
|
||||
}
|
||||
row := make(map[string]interface{})
|
||||
row["task_name"] = taskName
|
||||
row["id"] = v.Id
|
||||
row["start_time"] = beego.Date(time.Unix(v.CreateTime, 0), "Y-m-d H:i:s")
|
||||
row["process_time"] = float64(v.ProcessTime) / 1000
|
||||
row["ouput_size"] = libs.SizeFormat(float64(len(v.Output)))
|
||||
row["output"] = beego.Substr(v.Output, 0, 100)
|
||||
row["status"] = v.Status
|
||||
recentLogs[k] = row
|
||||
if v.Status != 0 {
|
||||
failJob++
|
||||
} else {
|
||||
okJob++
|
||||
}
|
||||
}
|
||||
self.Data["recentLogs"] = jobList
|
||||
|
||||
// 最近执行失败的日志
|
||||
logs, _ = models.TaskLogGetList(1, 20, "status__lt", 0)
|
||||
logs, _ := models.TaskLogGetList(1, 30, "status__lt", 0)
|
||||
errLogs := make([]map[string]interface{}, len(logs))
|
||||
|
||||
for k, v := range logs {
|
||||
@@ -102,15 +118,61 @@ func (self *HomeController) Start() {
|
||||
errLogs[k] = row
|
||||
|
||||
}
|
||||
|
||||
self.Data["errLogs"] = errLogs
|
||||
self.Data["startJob"] = startJob
|
||||
self.Data["okJob"] = okJob
|
||||
self.Data["failJob"] = failJob
|
||||
self.Data["totalJob"] = count
|
||||
|
||||
self.Data["recentLogs"] = recentLogs
|
||||
// this.Data["errLogs"] = errLogs
|
||||
self.Data["jobs"] = jobList
|
||||
|
||||
//折线图
|
||||
okRun := models.SumByDays(30, "0")
|
||||
errRun := models.SumByDays(30, "-1")
|
||||
expiredRun := models.SumByDays(30, "-2")
|
||||
|
||||
days := []string{}
|
||||
okNum := []int64{}
|
||||
errNum := []int64{}
|
||||
expiredNum := []int64{}
|
||||
|
||||
type kv struct {
|
||||
Key string
|
||||
Value int64
|
||||
}
|
||||
|
||||
//排序
|
||||
var ss []kv
|
||||
for k, v := range okRun {
|
||||
i, _ := strconv.ParseInt(v.(string), 10, 64)
|
||||
ss = append(ss, kv{k, i})
|
||||
}
|
||||
|
||||
sort.Slice(ss, func(i, j int) bool {
|
||||
|
||||
return ss[i].Key < ss[j].Key
|
||||
})
|
||||
|
||||
for _, v := range ss {
|
||||
|
||||
days = append(days, v.Key)
|
||||
okNum = append(okNum, v.Value)
|
||||
|
||||
if _, ok := errRun[v.Key]; ok {
|
||||
i, _ := strconv.ParseInt(errRun[v.Key].(string), 10, 64)
|
||||
errNum = append(errNum, i)
|
||||
} else {
|
||||
errNum = append(errNum, 0)
|
||||
}
|
||||
|
||||
if _, ok := expiredRun[v.Key]; ok {
|
||||
i, _ := strconv.ParseInt(expiredRun[v.Key].(string), 10, 64)
|
||||
expiredNum = append(expiredNum, i)
|
||||
} else {
|
||||
expiredNum = append(expiredNum, 0)
|
||||
}
|
||||
}
|
||||
|
||||
self.Data["days"] = days
|
||||
self.Data["okNum"] = okNum
|
||||
self.Data["errNum"] = errNum
|
||||
self.Data["expiredNum"] = expiredNum
|
||||
self.Data["cpuNum"] = runtime.NumCPU()
|
||||
|
||||
//系统运行信息
|
||||
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"fmt"
|
||||
|
||||
"strconv"
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
@@ -53,6 +55,7 @@ func (self *ServerGroupController) AjaxSave() {
|
||||
|
||||
servergroup_id, _ := self.GetInt("id")
|
||||
|
||||
fmt.Println(servergroup_id)
|
||||
if servergroup_id == 0 {
|
||||
//新增
|
||||
servergroup.CreateTime = time.Now().Unix()
|
||||
|
||||
@@ -223,7 +223,7 @@ func (self *TaskController) Detail() {
|
||||
//任务分组
|
||||
groupName := "默认分组"
|
||||
if task.GroupId > 0 {
|
||||
group, err := models.TaskGroupGetById(task.GroupId)
|
||||
group, err := models.GroupGetById(task.GroupId)
|
||||
if err == nil {
|
||||
groupName = group.GroupName
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ func (self *TaskLogController) Detail() {
|
||||
//任务分组
|
||||
groupName := "默认分组"
|
||||
if task.GroupId > 0 {
|
||||
group, err := models.TaskGroupGetById(task.GroupId)
|
||||
group, err := models.GroupGetById(task.GroupId)
|
||||
if err == nil {
|
||||
groupName = group.GroupName
|
||||
}
|
||||
|
||||
@@ -192,8 +192,8 @@ func NewCommandJob(id int, serverId int, name string, command string) *Job {
|
||||
cmd.Start()
|
||||
err, isTimeout := runCmdWithTimeout(cmd, timeout)
|
||||
jobresult = new(JobResult)
|
||||
jobresult.OutMsg = libs.GbkAsUtf8(bufOut.String())
|
||||
jobresult.ErrMsg = libs.GbkAsUtf8(bufErr.String())
|
||||
jobresult.OutMsg = bufOut.String()
|
||||
jobresult.ErrMsg = bufErr.String()
|
||||
|
||||
jobresult.IsOk = true
|
||||
if err != nil {
|
||||
|
||||
@@ -79,5 +79,5 @@ func GbkAsUtf8(str string) string {
|
||||
|
||||
//任务识别码
|
||||
func JobKey(taskId, serverId int) int {
|
||||
return taskId*10000000 + serverId
|
||||
return taskId*100000 + serverId
|
||||
}
|
||||
|
||||
1
main.go
1
main.go
@@ -21,7 +21,6 @@ func init() {
|
||||
var StartTime = time.Now().Unix()
|
||||
models.Init(StartTime)
|
||||
jobs.InitJobs()
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
@@ -9,6 +9,7 @@ package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/astaxie/beego/orm"
|
||||
@@ -116,3 +117,25 @@ func TaskDel(id int) (int64, error) {
|
||||
//_, err := orm.NewOrm().QueryTable(TableName("task")).Filter("id", id).Delete()
|
||||
//return err
|
||||
}
|
||||
|
||||
//运行总次数
|
||||
func TaskTotalRunNum() (int64, error) {
|
||||
|
||||
res := make(orm.Params)
|
||||
_, err := orm.NewOrm().Raw("select sum(execute_times) as num,task_name from pp_task").RowsToMap(&res, "num", "task_name")
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
for k, _ := range res {
|
||||
i64, err := strconv.ParseInt(k, 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return i64, nil
|
||||
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -71,8 +71,22 @@ func TaskLogDelByTaskId(taskId int) (int64, error) {
|
||||
return orm.NewOrm().QueryTable(TableName("task_log")).Filter("task_id", taskId).Delete()
|
||||
}
|
||||
|
||||
// func GetTodaySuccessNum() (num, error) {
|
||||
// o := orm.NewOrm()
|
||||
// var r RawSeter
|
||||
// r = o.Raw("SELECT COUNT(*) AS num WHERE create_time>=? AND status<0", "")
|
||||
// }
|
||||
func GetLogNum(status int) (int64, error) {
|
||||
return orm.NewOrm().QueryTable(TableName("task_log")).Filter("status", status).Count()
|
||||
}
|
||||
|
||||
type SumDays struct {
|
||||
Day string
|
||||
Sum int
|
||||
}
|
||||
|
||||
func SumByDays(limit int, status string) orm.Params {
|
||||
res := make(orm.Params)
|
||||
_, err := orm.NewOrm().Raw("SELECT FROM_UNIXTIME(create_time,'%Y-%m-%d') days,COUNT(id) count FROM pp_task_log WHERE status in(?) GROUP BY days ORDER BY days DESC limit ?;",
|
||||
status, limit).RowsToMap(&res, "days", "count")
|
||||
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -331,15 +331,15 @@ ALTER TABLE `pp_task_server` ADD `connection_type` TINYINT(1) NOT NULL DEFAULT '
|
||||
COMMIT;
|
||||
|
||||
BEGIN;
|
||||
ALTER TABLE `ppgo_job2`.`pp_task` CHANGE COLUMN `server_id` `server_ids` varchar(200) NOT NULL DEFAULT '0' COMMENT '服务器id字符串,英文都好隔开';
|
||||
ALTER TABLE `pp_task` CHANGE COLUMN `server_id` `server_ids` varchar(200) NOT NULL DEFAULT '0' COMMENT '服务器id字符串,英文都好隔开';
|
||||
COMMIT;
|
||||
|
||||
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`;
|
||||
ALTER TABLE `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 `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`;
|
||||
COMMIT;
|
||||
|
||||
BEGIN;
|
||||
ALTER TABLE `ppgo_job2`.`pp_task` CHANGE COLUMN `is_notify` ` is_notify` tinyint(1) UNSIGNED NOT NULL DEFAULT '0' COMMENT '0-不通知,1-通知', ADD COLUMN `server_type` tinyint(1) UNSIGNED NOT NULL DEFAULT '1' COMMENT '执行策略:0-同时执行,1-轮询执行' AFTER `update_id`;
|
||||
ALTER TABLE `pp_task` CHANGE COLUMN `is_notify` `is_notify` tinyint(1) UNSIGNED NOT NULL DEFAULT '0' COMMENT '0-不通知,1-通知', ADD COLUMN `server_type` tinyint(1) UNSIGNED NOT NULL DEFAULT '1' COMMENT '执行策略:0-同时执行,1-轮询执行' AFTER `update_id`;
|
||||
COMMIT;
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
|
||||
13
static/echarts/echarts.min.js
vendored
Normal file
13
static/echarts/echarts.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1,9 +1,10 @@
|
||||
<div class="layui-row ml20" >
|
||||
<style>
|
||||
.info-box {
|
||||
height: 85px;
|
||||
background-color: white;
|
||||
background-color: #ecf0f5;
|
||||
height: 60px;
|
||||
background-color: #f2f2f2;
|
||||
border: 1px solid #f2f2f2;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -14,34 +15,40 @@
|
||||
border-bottom-left-radius: 2px;
|
||||
display: block;
|
||||
float: left;
|
||||
height: 85px;
|
||||
width: 85px;
|
||||
height: 60px;
|
||||
width: 60px;
|
||||
text-align: center;
|
||||
font-size: 45px;
|
||||
line-height: 85px;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
font-size: 40px;
|
||||
line-height: 60px;
|
||||
/*background: rgba(0, 0, 0, 0.2);*/
|
||||
background-color:#efefef !important;
|
||||
}
|
||||
|
||||
.info-box .info-box-content {
|
||||
padding: 5px 10px;
|
||||
margin-left: 85px;
|
||||
padding: 1px 5px;
|
||||
margin-left: 60px;
|
||||
}
|
||||
|
||||
.info-box-content .info-box-text{
|
||||
font-size: 18px;
|
||||
width: 100%;
|
||||
font-size: 16px;
|
||||
width: 80%;
|
||||
display: block;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
margin: 10px auto;
|
||||
color: #888;
|
||||
margin: 3px auto;
|
||||
}
|
||||
|
||||
.info-box-content .info-box-number{
|
||||
font-size: 24px;
|
||||
font-size: 20px;
|
||||
width: 100%;
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.inner-icon{
|
||||
font-size:24px;
|
||||
color: #efefef !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="layui-row">
|
||||
@@ -51,153 +58,347 @@
|
||||
<div class="layui-row layui-col-space15">
|
||||
<div class="layui-col-md3">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon" style="background-color:#00a65a !important;color:white;"><i class="fa fa-check" aria-hidden="true"></i></span>
|
||||
{{/*<span class="info-box-icon" style="background-color:#f39c12 !important;color:white;"><i class="fa fa-hourglass" aria-hidden="true"></i></span>*/}}
|
||||
<span class="fa-stack fa-lg info-box-icon" >
|
||||
<i class="fa fa-circle fa-stack-1x" style="color:#fff !important;">
|
||||
<i class="fa fa-hourglass fa-inverse fa-stack-1x inner-icon" ></i>
|
||||
</i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">最近执行成功</span>
|
||||
<span class="info-box-number">{{.okJob}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon" style="background-color:#dd4b39 !important;color:white;"><i class="fa fa-exclamation" aria-hidden="true"></i></span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">最近执行失败</span>
|
||||
<span class="info-box-number">{{.failJob}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon" style="background-color:#f39c12 !important;color:white;"><i class="fa fa-hourglass" aria-hidden="true"></i></span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">即将执行的任务</span>
|
||||
<span class="info-box-text">即将执行的任务</span>
|
||||
<span class="info-box-number">{{.startJob}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-col-md3">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon" style="background-color:#00c0ef !important;color:white;"><i class="fa fa-database" aria-hidden="true"></i></span>
|
||||
<span class="fa-stack fa-lg info-box-icon" >
|
||||
<i class="fa fa-circle fa-stack-1x" style="color:#fff !important;">
|
||||
<i class="fa fa-question fa-inverse fa-stack-1x inner-icon" ></i>
|
||||
</i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">待审核任务数量</span>
|
||||
<span class="info-box-number">{{.totalAuditTask}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="info-box">
|
||||
<span class="fa-stack fa-lg info-box-icon" >
|
||||
<i class="fa fa-circle fa-stack-1x" style="color:#fff !important;">
|
||||
<i class="fa fa-check fa-inverse fa-stack-1x inner-icon" ></i>
|
||||
</i>
|
||||
</span>
|
||||
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">近期执行成功</span>
|
||||
<span class="info-box-number">{{.successNum}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="info-box">
|
||||
<span class="fa-stack fa-lg info-box-icon" >
|
||||
<i class="fa fa-circle fa-stack-1x" style="color:#fff !important;">
|
||||
<i class="fa fa-exclamation fa-inverse fa-stack-1x inner-icon" ></i>
|
||||
</i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">近期执行失败</span>
|
||||
<span class="info-box-number">{{.errorNum}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-col-md3">
|
||||
<div class="info-box">
|
||||
<span class="fa-stack fa-lg info-box-icon" >
|
||||
<i class="fa fa-circle fa-stack-1x" style="color:#fff !important;">
|
||||
<i class="fa fa-user fa-inverse fa-stack-1x inner-icon" ></i>
|
||||
</i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">当前用户总数</span>
|
||||
<span class="info-box-number">{{.userNum}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="info-box">
|
||||
<span class="fa-stack fa-lg info-box-icon" >
|
||||
<i class="fa fa-circle fa-stack-1x" style="color:#fff !important;">
|
||||
<i class="fa fa-tasks fa-inverse fa-stack-1x inner-icon" ></i>
|
||||
</i>
|
||||
</span>
|
||||
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">定时任务总数量</span>
|
||||
<span class="info-box-number">{{.totalJob}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="layui-col-md3">
|
||||
<div class="info-box">
|
||||
<span class="fa-stack fa-lg info-box-icon" >
|
||||
<i class="fa fa-circle fa-stack-1x" style="color:#fff !important;">
|
||||
<i class="fa fa-calculator fa-inverse fa-stack-1x inner-icon" ></i>
|
||||
</i>
|
||||
</span>
|
||||
|
||||
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">累计运行次数</span>
|
||||
<span class="info-box-number">{{.TaskTotalRunNum}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="info-box">
|
||||
<span class="fa-stack fa-lg info-box-icon" >
|
||||
<i class="fa fa-circle fa-stack-1x" style="color:#fff !important;">
|
||||
<i class="fa fa-sticky-note fa-inverse fa-stack-1x inner-icon" ></i>
|
||||
</i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">当前日志总量</span>
|
||||
<span class="info-box-number">{{.totalLog}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md4">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">最近执行的任务</div>
|
||||
<div class="layui-card-body" style="height: 465px; padding-bottom: 10px; overflow: auto">
|
||||
<table class="layui-table" lay-size="sm">
|
||||
<colgroup>
|
||||
<col width="50">
|
||||
<col >
|
||||
<col >
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>序号</th>
|
||||
<th>任务名称</th>
|
||||
<th>开始时间</th>
|
||||
<th>执行结果</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range $k, $v := .recentLogs}}
|
||||
<tr>
|
||||
<td>{{$k}}</td>
|
||||
<td><a href="{{urlfor "TaskLogController.Detail" "id" $v.id}}" class="news-item-title">
|
||||
{{$v.task_name}} # {{$v.id}}
|
||||
</a></td>
|
||||
<td>{{$v.start_time}}</td>
|
||||
<td>{{if eq $v.status 0}}
|
||||
正常
|
||||
{{else if eq $v.status -1}}
|
||||
<span style="color:red">异常</span>
|
||||
{{else}}
|
||||
<span style="color:red">超时</span>
|
||||
{{end}}</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
<tr>
|
||||
<td colspan="3">暂无信息</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md4">
|
||||
<div class="layui-card" style="background: #fff">
|
||||
<div class="layui-card-header">即将执行的任务</div>
|
||||
<div class="layui-card-body" style="height: 465px; padding-bottom: 10px; overflow: auto">
|
||||
<table class="layui-table" lay-size="sm">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>任务名称</th>
|
||||
<th>执行时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{{range $k, $v := .jobs}}
|
||||
<tr>
|
||||
<td><a href="{{urlfor "TaskController.Logs" "id" $v.task_id}}" class="news-item-title">{{$v.task_name}}-{{$v.task_group}} # {{$v.task_id}}</a></td>
|
||||
<td>{{$v.next_time}}</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
<tr>
|
||||
<td colspan="2">暂无信息</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md4">
|
||||
<div class="layui-card" style="background: #fff">
|
||||
<div class="layui-card-header">系统概况</div>
|
||||
<div class="layui-card-body" style="height: 465px; padding-bottom: 10px; overflow: auto">
|
||||
<table class="layui-table" lay-size="sm">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>参数</th>
|
||||
<th>值</th>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-row">
|
||||
<div class="layui-col-md12">
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-tab">
|
||||
<ul class="layui-tab-title">
|
||||
<li class="layui-this">系统概况</li>
|
||||
<li>即将开始的任务</li>
|
||||
<li>最近失败的任务</li>
|
||||
</ul>
|
||||
<div class="layui-tab-content">
|
||||
<div class="layui-tab-item layui-show">
|
||||
<div class="layui-col-md8" id="charts-box">
|
||||
{{/*图表*/}}
|
||||
<div id="main" style=" height: 528px;"></div>
|
||||
</div>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range $k, $v := .sysInfo}}
|
||||
<tr>
|
||||
<td># {{$k}} </td>
|
||||
<td>{{$v}}</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
<tr>
|
||||
<td colspan="2">暂无信息</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="layui-col-md4" >
|
||||
{{/*系统概况*/}}
|
||||
<div class="layui-card" style="background: #fff" id="sys">
|
||||
<div class="layui-card-header">系统概况</div>
|
||||
<div class="layui-card-body" style="height: 465px; padding-bottom: 10px; overflow: auto">
|
||||
<table class="layui-table" lay-size="sm">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>参数</th>
|
||||
<th>值</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range $k, $v := .sysInfo}}
|
||||
<tr>
|
||||
<td># {{$k}} </td>
|
||||
<td>{{$v}}</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
<tr>
|
||||
<td colspan="2">暂无信息</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-tab-item">
|
||||
<div class="layui-card" style="background: #fff">
|
||||
<div class="layui-card-header">即将执行的任务</div>
|
||||
<div class="layui-card-body" style="height: 465px; padding-bottom: 10px; overflow: auto">
|
||||
<table class="layui-table" lay-size="sm">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>任务名称</th>
|
||||
<th>执行时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range $k, $v := .jobs}}
|
||||
<tr>
|
||||
<td><a href="{{urlfor "TaskController.Logs" "id" $v.task_id}}" class="news-item-title">{{$v.task_name}}-{{$v.task_group}} # {{$v.task_id}}</a></td>
|
||||
<td>{{$v.next_time}}</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
<tr>
|
||||
<td colspan="2">暂无信息</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-tab-item">
|
||||
{{/*执行失败的任务*/}}
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">最近执行的任务</div>
|
||||
<div class="layui-card-body" style="height: 465px; padding-bottom: 10px; overflow: auto">
|
||||
<table class="layui-table" lay-size="sm">
|
||||
<colgroup>
|
||||
<col width="50">
|
||||
<col >
|
||||
<col >
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>序号</th>
|
||||
<th>任务名称</th>
|
||||
<th>开始时间</th>
|
||||
<th>执行结果</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range $k, $v := .errLogs}}
|
||||
<tr>
|
||||
<td>{{$k}}</td>
|
||||
<td><a href="javascript:;" onclick="logDetail({{$v.id}});" class="news-item-title">
|
||||
{{$v.task_name}} # {{$v.id}}
|
||||
</a></td>
|
||||
<td>{{$v.start_time}}</td>
|
||||
<td>{{if eq $v.status 0}}
|
||||
正常
|
||||
{{else if eq $v.status -1}}
|
||||
<span style="color:red">异常</span>
|
||||
{{else}}
|
||||
<span style="color:red">超时</span>
|
||||
{{end}}</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
<tr>
|
||||
<td colspan="3">暂无信息</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/echarts/echarts.min.js"></script>
|
||||
<script src="/static/layui/layui.js"></script>
|
||||
<script>
|
||||
var $;
|
||||
//注意:选项卡 依赖 element 模块,否则无法进行功能性操作
|
||||
layui.use('element', function(){
|
||||
var element = layui.element;
|
||||
|
||||
$ = layui.$;
|
||||
resizeChartbox();
|
||||
window.onresize = function(){
|
||||
resizeChartbox();
|
||||
}
|
||||
function resizeChartbox()
|
||||
{
|
||||
height = $("#sys").height();
|
||||
width = $("#charts-box").width();
|
||||
$("#main").width(width-200);
|
||||
$("#main").height(height);
|
||||
}
|
||||
element.render();
|
||||
//…
|
||||
});
|
||||
|
||||
function logDetail(id){
|
||||
window.parent.openTab("/tasklog/detail?id="+id,id+' 日志详情',"admin_log_detail-"+id,'');
|
||||
}
|
||||
|
||||
|
||||
// 基于准备好的dom,初始化echarts实例
|
||||
var myChart = echarts.init(document.getElementById('main'));
|
||||
|
||||
|
||||
// 指定图表的配置项和数据
|
||||
var option = {
|
||||
title: {
|
||||
text: '运行概况'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis'
|
||||
},
|
||||
legend: {
|
||||
data:['任务执行失败','任务执行超时','任务执行成功']
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
toolbox: {
|
||||
feature: {
|
||||
saveAsImage: {}
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: {{.days}}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name:'任务执行失败',
|
||||
type:'line',
|
||||
stack: '总量',
|
||||
data:{{.errNum}}
|
||||
},
|
||||
{
|
||||
name:'任务执行超时',
|
||||
type:'line',
|
||||
stack: '总量',
|
||||
data:{{.expiredNum}}
|
||||
},
|
||||
{
|
||||
name:'任务执行成功',
|
||||
type:'line',
|
||||
stack: '总量',
|
||||
data:{{.okNum}}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// 使用刚指定的配置项和数据显示图表。
|
||||
myChart.setOption(option);
|
||||
</script>
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
,url: '/task/table?status=2'
|
||||
,cols: [[
|
||||
{checkbox: true, fixed: true},
|
||||
{field:'id', title: 'ID', align:'center',sort: true, width:100}
|
||||
{field:'id', title: 'ID', align:'center',sort: true, width:80}
|
||||
,{field:'task_name',title: '任务名称'}
|
||||
,{field:'cron_spec',title: '执行时间', width:150}
|
||||
,{field:'pre_time', width:170,title: '上次执行时间'}
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
{{/*<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="status">启|停</a>*/}}
|
||||
{{/*<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>*/}}
|
||||
<a class="layui-btn layui-btn-xs " lay-event="detail">详细</a>
|
||||
{{/*<a class="layui-btn layui-btn-warm layui-btn-xs" lay-event="run">测试</a>*/}}
|
||||
<a class="layui-btn layui-btn-warm layui-btn-xs" lay-event="run">测试</a>
|
||||
<a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="log">日志</a>
|
||||
</script>
|
||||
</div>
|
||||
@@ -58,13 +58,13 @@
|
||||
,url: '/task/table'
|
||||
,cols: [[
|
||||
{checkbox: true, fixed: true},
|
||||
{field:'id', title: 'ID', align:'center', width:100,sort: true}
|
||||
{field:'id', title: 'ID', align:'center', width:80,sort: true}
|
||||
,{field:'task_name', title: '任务名称'}
|
||||
,{field:'cron_spec',title: '时间表达式', width:150}
|
||||
,{field:'cron_spec',title: '时间表达式', width:100}
|
||||
,{field:'next_time', width:170,title: '下次执行时间'}
|
||||
,{field:'pre_time', title: '上次执行时间',width:170,}
|
||||
,{field:'execute_times', title: '次数',width:100}
|
||||
,{width:120, align:'center', title:'操作', toolbar: '#bar'}
|
||||
,{width:180, align:'center', title:'操作', toolbar: '#bar'}
|
||||
]]
|
||||
,id: 'listReload'
|
||||
,page: true
|
||||
|
||||
Reference in New Issue
Block a user