支持旧版本升级

develop
ouqiang 2018-05-20 15:24:31 +08:00
parent 4f7a5cfbde
commit 0e023bd3fa
43 changed files with 78 additions and 2282 deletions

View File

@ -14,7 +14,8 @@ RUN make install-vue \
FROM alpine:3.7
RUN addgroup -S app \
RUN apk add --no-cache ca-certificates \
&& addgroup -S app \
&& adduser -S -g app app
WORKDIR /app
@ -27,4 +28,4 @@ EXPOSE 5920
USER app
ENTRYPOINT ["/app/gocron", "web"]
ENTRYPOINT ["/app/gocron", "web"]

View File

@ -223,6 +223,7 @@ func (m *Migration) upgradeFor150(session *xorm.Session) error {
return err
}
settingModel.Id = 0
settingModel.Code = WebhookCode
settingModel.Key = WebhookUrlKey
settingModel.Value = ""
@ -231,6 +232,7 @@ func (m *Migration) upgradeFor150(session *xorm.Session) error {
return err
}
settingModel.Id = 0
settingModel.Code = WebhookCode
settingModel.Key = WebhookTemplateKey
settingModel.Value = webhookTemplate

View File

@ -22,8 +22,6 @@ var (
ConfDir string // 配置目录
// LogDir 日志目录
LogDir string // 日志目录
// DataDir 数据目录
DataDir string // 存放session等
// AppConfig 配置文件
AppConfig string // 应用配置文件
// Installed 应用是否已安装
@ -46,10 +44,9 @@ func InitEnv(versionString string) {
}
ConfDir = filepath.Join(AppDir, "/conf")
LogDir = filepath.Join(AppDir, "/log")
DataDir = filepath.Join(AppDir, "/data")
AppConfig = filepath.Join(ConfDir, "/app.ini")
VersionFile = filepath.Join(ConfDir, "/.version")
createDirIfNotExists(ConfDir, LogDir, DataDir)
createDirIfNotExists(ConfDir, LogDir)
Installed = IsInstalled()
VersionId = ToNumberVersion(versionString)
}
@ -107,7 +104,7 @@ func GetCurrentVersionId() int {
// ToNumberVersion 把字符串版本号a.b.c转换为整数版本号abc
func ToNumberVersion(versionString string) int {
if strings.HasPrefix("v", versionString) {
if strings.HasPrefix(versionString, "v") {
versionString = versionString[1:]
}
v := strings.Replace(versionString, ".", "", -1)

View File

@ -27,10 +27,10 @@ import (
_ "github.com/ouqiang/gocron/internal/statik"
)
// URL前缀
const urlPrefix = "/api"
var staticDir = "public"
const (
urlPrefix = "/api"
staticDir = "public"
)
var statikFS http.FileSystem
@ -42,7 +42,7 @@ func init() {
}
}
// 路由注册
// Register 路由注册
func Register(m *macaron.Macaron) {
m.SetURLPrefix(urlPrefix)
// 所有GET方法自动注册HEAD方法
@ -54,6 +54,7 @@ func Register(m *macaron.Macaron) {
ctx.WriteHeader(http.StatusInternalServerError)
return
}
io.Copy(ctx.Resp, file)
})

View File

@ -50,7 +50,7 @@ func Index(ctx *macaron.Context) string {
// 解析查询参数
func parseQueryParams(ctx *macaron.Context) models.CommonMap {
var params models.CommonMap = models.CommonMap{}
params := models.CommonMap{}
base.ParsePageAndPageSize(ctx, params)
return params
@ -65,6 +65,9 @@ func Detail(ctx *macaron.Context) string {
logger.Error(err)
}
jsonResp := utils.JsonResponse{}
if userModel.Id == 0 {
return jsonResp.Success(utils.SuccessContent, nil)
}
return jsonResp.Success(utils.SuccessContent, userModel)
}

View File

@ -120,7 +120,7 @@ func (task Task) Initialize() {
for page < maxPage {
taskList, err := taskModel.ActiveList(page, pageSize)
if err != nil {
logger.Fatalf("定时任务初始化#获取任务列表错误-", err.Error())
logger.Fatalf("定时任务初始化#获取任务列表错误: %s", err)
}
if len(taskList) == 0 {
break

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,3 @@
.PHONY: build
build: gocron node
@ -41,6 +39,10 @@ enable-race:
package: build-vue statik
bash ./package.sh
.PHONY: package-all
package-all: build-vue statik
bash ./package.sh -p 'linux darwin windows'
.PHONY: build-vue
build-vue:
cd web/vue && yarn run build

View File

@ -103,8 +103,8 @@ init() {
GIT_COMMIT_ID=`git_latest_commit`
LDFLAGS="-w -X 'main.AppVersion=${VERSION}' -X 'main.BuildDate=`date '+%Y-%m-%d %H:%M:%S'`' -X 'main.GitCommit=${GIT_COMMIT_ID}'"
PACKAGE_DIR=${BINARY_NAME}_package
BUILD_DIR=${BINARY_NAME}_build
PACKAGE_DIR=${BINARY_NAME}-package
BUILD_DIR=${BINARY_NAME}-build
if [[ -d ${BUILD_DIR} ]];then
rm -rf ${BUILD_DIR}
@ -178,7 +178,7 @@ run() {
package_gocron() {
BINARY_NAME='gocron'
MAIN_FILE="./cmd/gocron/gocron.go"
INCLUDE_FILE=(Dockerfile-release README.md)
INCLUDE_FILE=()
run

View File

@ -1,25 +0,0 @@
</div>
<footer>
<div id="copyrights">
<div class="inset">
<div class="bigcontainer">
<div class="fl">
<p>&copy; 2017 gocron
<i class="Github Alternate icon"></i><a href="https://github.com/ouqiang/gocron" target="_blank">
GitHub
</a>
</p>
</div>
</div>
</div>
</div>
</footer>
<script>
$(
function(){
$('.ui.dropdown').dropdown();
}
);
</script>
</body>
</html>

View File

@ -1,72 +0,0 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="renderer" content="webkit">
<title>{%.Title%}</title>
<link type="text/css" rel="stylesheet" href="/resource/css/framework.css" />
<link type="text/css" rel="stylesheet" href="/resource/css/main.css" />
<link type="text/css" rel="stylesheet" href="/resource/sweetalert/sweetalert.css" />
<script type="text/javascript" src="/resource/javascript/jquery.min.js"></script>
<script type="text/javascript" src="/resource/javascript/framework.js"></script>
<script type="text/javascript" src="/resource/javascript/form.min.js"></script>
<script type="text/javascript" src="/resource/sweetalert/sweetalert.min.js"></script>
<script type="text/javascript" src="/resource/javascript/vue.min.js"></script>
<script type="text/javascript" src="/resource/javascript/handlebars-v4.0.5.js"></script>
<script type="text/javascript" src="/resource/javascript/main.js"></script>
<style type="text/css">
body {
overflow-x: hidden;
}
select {
height: 40px;
}
.fields.search > .field {
margin-right: 5px;
}
</style>
</head>
<body>
<div class="page">
{%if not .DisableNav%}
<!--header begin-->
<header>
<div class="bigcontainer">
<div id="logo">
{%.AppName%}
</div>
<div class="user">
<div class="ui inline labeled icon top right pointing dropdown">
{%if not .LoginUsername%}
<i class="dropdown icon"></i>
<div class="menu">
<a class="item" href="/user/login"><i class="sign in icon"></i></a>
</div>
{%else%}
{%.LoginUsername%}
<i class="dropdown icon"></i>
<div class="menu">
<a href="/user/editMyPassword" class="item"><i class="edit icon"></i></a>
<a class="item" href="/user/logout"><i class="sign out icon"></i>退</a>
</div>
{%end%}
</div>
</div>
</div>
</header>
<!-- the main menu-->
<div class="ui teal inverted menu">
<div class="bigcontainer">
<div class="right menu">
<a class="item {%if or (eq .Controller "task") (eq .Controller "delaytask")%}active{%end%}" href="/task"><i class="tasks icon"></i></a>
<a class="item {%if eq .Controller "host"%}active{%end%}" href="/host"><i class="linux icon"></i></a>
{%if .IsAdmin%}
<a class="item {%if eq .Controller "user"%}active{%end%}" href="/user"><i class="user icon"></i></a>
<a class="item {%if eq .Controller "manage"%}active{%end%}" href="/manage/slack/edit"><i class="settings icon"></i></a>
{%end%}
</div>
</div>
</div>
{%end%}

View File

@ -1,41 +0,0 @@
{%if gt .Pagination.Total 0%}
<div class="ui pagination menu">
{%if not .Pagination.IsFirst%}
<a class="item" href="{%.URI%}?{% .Params.PageParams%}&page=1">
</a>
{%end%}
{%if .Pagination.HasPrevious%}
<a class="icon item" href="{%.URI%}?{% .Params.PageParams%}&page={%.Pagination.Previous%}">
<i class="icon left arrow"></i>
</a>
{%end%}
{%range .Pagination.Pages%}
{%if eq .Num -1%}
<div class="disabled item">
...
</div>
{%else%}
<a class="icon {%if .IsCurrent%}active{%end%} item" href="{%$.URI%}?{% $.Params.PageParams%}&page={%.Num%}">
{%.Num%}
</a>
{%end%}
{%end%}
{%if .Pagination.HasNext%}
<a class="icon item" href="{%.URI%}?{% .Params.PageParams%}&page={%.Pagination.Next%}">
<i class="icon right arrow"></i>
</a>
{%end%}
{%if not .Pagination.IsLast%}
<a class="icon item" href="{%.URI%}?{% .Params.PageParams%}&page={%.Pagination.TotalPages%}">
</a>
{%end%}
<div class="item">{%.Pagination.Total%}/{%.Pagination.TotalPages%}</div>
</div>
{%end%}

View File

@ -1,12 +0,0 @@
{% template "common/header" . %}
<script>
swal({
title: "404 - NOT FOUND",
text: "您访问的页面不存在",
type: "warning"
},
function(){
location.href = "/"
});
</script>
{% template "common/footer" . %}

View File

@ -1,11 +0,0 @@
{% template "common/header" . %}
<script>
swal({
title: "500 - INTERNAL SERVER ERROR",
text: "网站暂时无法访问, 请稍后再试.",
type: "warning",
confirmButtonColor: "#DD6B55",
confirmButtonText: "确定"
});
</script>
{% template "common/footer" . %}

View File

@ -1,3 +0,0 @@
{% template "common/header" . %}
{% template "common/footer" . %}

View File

@ -1,116 +0,0 @@
{% template "common/header" . %}
<div class="ui grid">
{% template "host/menu" . %}
<div class="twelve wide column">
<div class="pageHeader">
<div class="segment">
<h3 class="ui dividing header">
<div class="content">
</div>
</h3>
</div>
</div>
<form class="ui form fluid vertical segment">
<input type="hidden" name="id" value="{%.Host.Id%}">
<div class="four fields">
<div class="field">
<label></label>
<div class="ui small input">
<input type="text" name="name" value="{%.Host.Name%}" placeholder="127.0.0.1">
</div>
</div>
<div class="field">
<label></label>
<div class="ui small input">
<input type="text" name="port" value="{%.Host.Port%}" placeholder="5921">
</div>
</div>
<div class="field">
<label></label>
<div class="ui small input">
<input type="text" name="alias" value="{%.Host.Alias%}"
placeholder="节点名称如web">
</div>
</div>
</div>
<div class="two fields">
<div class="field">
<label></label>
<div class="ui small input">
<textarea rows="7" name="remark" >{%.Host.Remark%}</textarea>
</div>
</div>
</div>
<div class="ui primary submit button"></div>
<a class="ui button" onclick="location.href='/host';"></a>
</form>
</div>
</div>
<script type="text/javascript">
var $uiForm = $('.ui.form');
$($uiForm).form(
{
onSuccess: function(event, fields) {
util.post('/host/store', fields, function(code, message) {
location.href = "/host"
});
return false;
},
fields: {
name: {
identifier : 'name',
rules: [
{
type : 'empty',
prompt : ''
},
{
type : 'maxLength[64]',
prompt : '64'
}
]
},
alias: {
identifier : 'alias',
rules: [
{
type : 'empty',
prompt : ''
},
{
type : 'maxLength[32]',
prompt : '32'
}
]
},
port: {
identifier : 'port',
rules: [
{
type : 'integer[1..65535]',
prompt : ''
}
]
},
remark: {
identifier : 'remark',
rules: [
{
type : 'maxLength[100]',
prompt : '100'
}
]
}
},
inline : true
});
</script>
{% template "common/footer" . %}

View File

@ -1,86 +0,0 @@
{% template "common/header" . %}
<div class="ui grid">
{% template "host/menu" . %}
<div class="twelve wide column">
{%if .IsAdmin%}
<div class="pageHeader">
<div class="segment">
<h3 class="ui dividing header">
<a href="/host/create">
<i class="large add icon"></i>
<div class="content">
</div>
</a>
</h3>
</div>
</div>
{%end%}
<form class="ui form">
<div class="three fields">
<div class="field">
<input type="text" placeholder="ID" name="id" value="{%if gt .Params.Id 0%}{%.Params.Id%}{%end%}">
</div>
<div class="field">
<input type="text" placeholder="主机名" name="name" value="{%.Params.Name%}">
</div>
<div class="field">
<button class="ui linkedin submit button"></button>
</div>
</div>
</form>
<table class="ui celled table">
<thead>
<tr>
<th>ID</th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{%range $i, $v := .Hosts%}
<tr>
<td>{%.Id%}</td>
<td>{%.Name%}</td>
<td>{%.Alias%}</td>
<td>{%.Port%}</td>
<td>{%.Remark%}</td>
<td class="operation">
{%if $.IsAdmin%}
<a class="ui purple button" href="/host/edit/{%.Id%}"></a>
<button class="ui positive button" onclick="util.removeConfirm('/host/remove/{%.Id%}')"></button><br>
{%end%}
<div style="margin-top: 5px;">
<a class="ui twitter button" href="/task?host_id={%.Id%}"></a>
{%if $.IsAdmin%}
<button class="ui blue button" @click="ping({%.Id%})"></button>
{%end%}
</div>
</td>
</tr>
{%end%}
</tbody>
</table>
{% template "common/pagination" .%}
</div>
</div>
<script type="text/javascript">
var Vue = new Vue({
el: '.ui.celled.table',
methods: {
ping: function(id) {
util.get("/host/ping/" + id, function(code, message) {
swal('', '', 'success');
})
}
}
});
</script>
{% template "common/footer" . %}

View File

@ -1,9 +0,0 @@
<div class="four wide column">
<div class="verticalMenu">
<div class="ui vertical pointing menu fluid">
<a class="{%if eq .URI "/host"%}active teal{%end%} item" href="/host">
<i class="linux icon"></i>
</a>
</div>
</div>
</div>

View File

@ -1,189 +0,0 @@
{% template "common/header" . %}
<div class="ui grid">
{% template "install/menu" . %}
<div class="ten wide column">
<form class="ui form">
<div class="ui blue center aligned segment">
<p></p>
</div>
<br>
<div class="three fields">
<div class="field">
<label>(MySQL)</label>
<div class="ui dropdown selection">
<input type="hidden" name="db_type" value="mysql">
<div class="default text">MySQL</div>
<i class="dropdown icon"></i>
<div class="menu">
<div class="item active" data-value="mysql">MySQL</div>
</div>
</div>
</div>
</div>
<div class="three fields">
<div class="field">
<label></label>
<input type="text" name="db_host" value="127.0.0.1">
</div>
<div class="field">
<label></label>
<input type="text" name="db_port" value="3306">
</div>
</div>
<div class="three fields">
<div class="field">
<label></label>
<input type="text" name="db_username">
</div>
<div class="field">
<label></label>
<input type="password" name="db_password">
</div>
</div>
<div class="three fields">
<div class="field">
<label></label>
<input type="text" name="db_name">
</div>
<div class="field">
<label></label>
<input type="text" name="db_table_prefix" value="cron_">
</div>
</div>
<div class="ui divider"></div>
<div class="ui blue center aligned segment">
<p></p>
</div>
<br>
<div class="three fields">
<div class="field">
<label></label>
<input type="text" name="admin_username">
</div>
</div>
<div class="three fields">
<div class="field">
<label></label>
<input type="password" name="admin_password">
</div>
</div>
<div class="three fields">
<div class="field">
<label></label>
<input type="password" name="confirm_admin_password">
</div>
</div>
<div class="three fields">
<div class="field">
<label></label>
<input type="text" name="admin_email">
</div>
</div>
<div class="ui blue submit button"></div>
</form>
</div>
</div>
<script type="text/javascript">
// 表单验证规则
$('.ui.form').form(
{
onSuccess: function(event, fields) {
util.post('/install/store', fields, function(code, message) {
swal('');
setTimeout(function() {
location.href = "/";
}, 2000)
});
return false;
},
fields: {
dbHost: {
identifier : 'db_host',
rules: [
{
type : 'empty',
prompt : ''
}
]
},
dbPort: {
identifier : 'db_port',
rules: [
{
type : 'integer',
prompt : ''
}
]
},
dbUsername: {
identifier : 'db_username',
rules: [
{
type : 'empty',
prompt : ''
}
]
},
dbPassword: {
identifier : 'db_password',
rules: [
{
type : 'empty',
prompt : ''
}
]
},
dbName: {
identifier : 'db_name',
rules: [
{
type : 'empty',
prompt : ''
}
]
},
adminUsername: {
identifier : 'admin_username',
rules: [
{
type : 'minLength[3]',
prompt : '3'
}
]
},
adminPassword: {
identifier : 'admin_password',
rules: [
{
type : 'minLength[6]',
prompt : '6'
}
]
},
confirmAdminPassword: {
identifier : 'confirm_admin_password',
rules: [
{
type : 'match[admin_password]',
prompt : ''
}
]
},
adminEmail: {
identifier : 'admin_email',
rules: [
{
type : 'email',
prompt : ''
}
]
}
},
inline : true
});
</script>
{% template "common/footer" . %}

View File

@ -1,9 +0,0 @@
<div class="four wide column">
<div class="verticalMenu">
<div class="ui vertical pointing menu fluid">
<a class="active teal item" href="/install">
<i class="chevron right icon"></i>
</a>
</div>
</div>
</div>

View File

@ -1,39 +0,0 @@
{% template "common/header" . %}
<div class="ui grid">
{% template "manage/menu" . %}
<div class="twelve wide column">
<div class="pageHeader">
<div class="segment">
<h3 class="ui dividing header">
<div class="content">
</div>
</h3>
</div>
</div>
<table class="ui striped table">
<thead>
<tr>
<th></th>
<th>IP</th>
<th></th>
</tr>
</thead>
<tbody>
{%range $i, $v := .LoginLogs%}
<tr>
<td>{%.Username%}</td>
<td>{%.Ip%}</td>
<td>{%.Created%}</td>
</tr>
{%end%}
</tbody>
</table>
{% template "common/pagination" .%}
</div>
</div>
{% template "common/footer" . %}

View File

@ -1,201 +0,0 @@
{% template "common/header" . %}
<div class="ui grid">
{%template "manage/menu" .%}
<div class="twelve wide column">
<div class="pageHeader">
<div class="segment">
<h3 class="ui dividing header">
<div class="content">
{%.Title%}
</div>
</h3>
</div>
</div>
<form class="ui form fluid vertical segment mail-server">
<div class="content"></div><br>
<div class="four fields">
<div class="field">
<label>
SMTP
</label>
<div class="ui small input">
<input type="text" name="host" value="{%.Mail.Host%}">
</div>
</div>
<div class="field">
<label>
</label>
<div class="ui small input">
<input type="text" name="port" value="{%if gt .Mail.Port 0%}{%.Mail.Port%}{%end%}">
</div>
</div>
<div class="field">
<label>
</label>
<div class="ui small input">
<input type="text" name="user" value="{%.Mail.User%}">
</div>
</div>
<div class="field">
<label>
</label>
<div class="ui small input">
<input type="text" name="password" value="{%.Mail.Password%}">
</div>
</div>
</div>
<button class="ui primary button"></button>
{%if .Mail.Host%}
<a class="ui green button" onclick="clearMailServer()"></a>
{%end%}
<br><br><br>
<div>
<div class="content"></div><p></p>
<div class="fields">
{%range $i, $v := .Mail.MailUsers%}
<div class="field">
<div class="ui segment">
{%.Username%}-{%.Email%}&nbsp;&nbsp;&nbsp;<div class="ui blue button" onclick="removeMailUser({%.Id%})"></div>
</div>
</div>
{%end%}
</div>
</div>
</form>
<div class="ui facebook button" onclick="createMailUser();"></div>
</div>
</div>
<div class="ui small modal">
<div class="header"></div>
<div class="content">
<form class="ui form mail-user">
<div class="two fields">
<div class="field">
<label>
</label>
<div class="ui small input">
<input type="text" name="username">
</div>
</div>
<div class="field">
<label>
</label>
<div class="ui small input">
<input type="text" name="email">
</div>
</div>
</div>
<button class="ui primary button"></button>
</form>
</div>
</div>
<script type="text/javascript">
$('.mail-server').form(
{
onSuccess: function(event, fields) {
util.post('/manage/mail/server',
fields,
function(code, message) {
location.reload();
}
);
return false;
},
fields: {
host: {
identifier : 'host',
rules: [
{
type : 'empty',
prompt : ''
}
]
},
port: {
identifier : 'port',
rules: [
{
type : 'integer[1..65535]',
prompt : ''
}
]
},
user: {
identifier : 'user',
rules: [
{
type : 'email',
prompt : ''
}
]
},
password: {
identifier : 'password',
rules: [
{
type : 'empty',
prompt : ''
}
]
}
},
inline : true
});
$('.mail-user').form(
{
onSuccess: function(event, fields) {
util.post('/manage/mail/user',
fields,
function(code, message) {
util.alertSuccess();
location.reload();
}
);
return false;
},
fields: {
username: {
identifier : 'username',
rules: [
{
type : 'empty',
prompt : ''
}
]
},
email: {
identifier : 'email',
rules: [
{
type : 'email',
prompt : ''
}
]
}
},
inline : true
});
function createMailUser() {
$('.ui.modal').modal('show');
}
function removeMailUser(id) {
util.post('/manage/mail/user/remove/' + id, {}, function(code, message) {
location.reload();
});
}
function clearMailServer() {
util.post('/manage/mail/server/clear', {}, function(code, message) {
location.reload();
});
}
</script>
{% template "common/footer" . %}

View File

@ -1,15 +0,0 @@
<div class="three wide column">
<div class="verticalMenu">
<div class="ui vertical pointing menu fluid">
<a class="{%if eq .URI "/manage/slack/edit"%}active teal{%end%} item" href="/manage/slack/edit">
<i class="slack icon"></i> Slack
</a>
<a class="{%if eq .URI "/manage/mail/edit"%}active teal{%end%} item" href="/manage/mail/edit">
<i class="slack icon"></i>
</a>
<a class="{%if eq .URI "/manage/login-log"%}active teal{%end%} item" href="/manage/login-log">
<i class="slack icon"></i>
</a>
</div>
</div>
</div>

View File

@ -1,88 +0,0 @@
{% template "common/header" . %}
<div class="ui grid">
{%template "manage/menu" .%}
<div class="twelve wide column">
<div class="pageHeader">
<div class="segment">
<h3 class="ui dividing header">
<div class="content">
{%.Title%}
</div>
</h3>
</div>
</div>
<form class="ui form fluid vertical segment">
<div class="field">
<label>
<div class="content">Slack WebHook URL</div>
</label>
<div class="ui small input">
<input type="text" id="url" value="{%.Slack.Url%}">
</div>
</div>
<div class="ui primary button" @click="updateUrl"></div>
<br><br><br>
<div>
<div class="content">Slack Channel(Channel)</div><p></p>
<div class="fields">
{%range $i, $v := .Slack.Channels%}
<div class="field">
<div class="ui segment">
{%.Name%}&nbsp;&nbsp;&nbsp;<div class="ui blue button" @click="removeChannel({%.Id%})"></div>
</div>
</div>
{%end%}
</div>
</div>
<div class="ui facebook button" @click="createChannel">Channel</div>
</form>
</div>
</div>
<script type="text/javascript">
new Vue({
el: '.ui.form',
methods: {
updateUrl: function() {
var url = $('#url').val();
util.post('/manage/slack/url', {"url": url}, function(code, message) {
util.alertSuccess();
});
},
createChannel: function() {
swal({
title: "新增Channel",
type: "input",
showCancelButton: true,
closeOnConfirm: false,
animation: "slide-from-top"
},
function(inputValue){
if (inputValue === false) return false;
if (inputValue === "") {
swal.showInputError("请输入Channel");
return false
}
util.post('/manage/slack/channel',
{"channel": inputValue},
function(code, message) {
util.alertSuccess();
location.reload();
}
);
});
},
removeChannel: function(id) {
util.post('/manage/slack/channel/remove/' + id, {}, function(code, message) {
location.reload();
});
}
}
});
</script>
{% template "common/footer" . %}

View File

@ -1,242 +0,0 @@
{% template "common/header" . %}
<div class="ui grid">
{%template "task/menu" .%}
<div class="twelve wide column">
{%if .IsAdmin%}
<div class="pageHeader">
<div class="segment">
<h3 class="ui dividing header">
<a href="/task/create">
<i class="large add icon"></i>
<div class="content">
</div>
</a>
</h3>
</div>
</div>
{%end%}
<form class="ui form">
<div class="six fields search">
<div class="one wide field">
<input type="text" placeholder="任务ID" name="id" value="{%if gt .Params.Id 0%}{%.Params.Id%}{%end%}">
</div>
<div class="field">
<input type="text" placeholder="任务名称" name="name" value="{%.Params.Name%}">
</div>
<div class="field">
<input type="text" placeholder="标签名称" name="tag" value="{%.Params.Tag%}">
</div>
</div>
<div class="six fields search">
<div class="field">
<select name="host_id" id="hostId">
<option value=""></option>
{%range $i, $v := .Hosts%}
<option value="{%.Id%}" {%if eq $.Params.HostId .Id %} selected {%end%} >{%.Alias%}-{%.Name%}</option>
{%end%}
</select>
</div>
<div class="field">
<select name="protocol" id="protocol">
<option value="0"></option>
<option value="2" {%if eq .Params.Protocol 2%}selected{%end%} data-match="host_id" data-validate-type="selectProtocol">SHELL</option>
<option value="1" {%if eq .Params.Protocol 1%}selected{%end%}>HTTP</option>
</select>
</div>
<div class="field">
<select name="status">
<option value="0"></option>
<option value="1" {%if eq .Params.Status 0%}selected{%end%} ></option>
<option value="2" {%if eq .Params.Status 1%}selected{%end%}></option>
</select>
</div>
<div class="field">
<button class="ui linkedin submit button"></button>
</div>
</div>
</form>
{%if .IsAdmin%}
<div class="field">
<select id="batch-operation">
<option value="0"></option>
<option value="1"></option>
<option value="2"></option>
<option value="3"></option>
</select>
</div>
{%end%}
<br>
<table class="ui celled table task-list">
<thead>
<tr>
{%if .IsAdmin%}
<th>
<input type="checkbox" onclick="checkAll(this)" style="width:25px;height: 25px;">
</th>
{%end%}
<th>ID</th>
<th></th>
<th></th>
<th></th>
<th>cron</th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{%range $i, $v := .Tasks%}
<tr>
{%if $.IsAdmin%}
<td>
<input type="checkbox"
class="sub-check"
data-id="{%.Id%}"
style="width:25px;height: 25px;">
</td>
{%end%}
<td>{%.Id%}</td>
<td>{%.Name%}</td>
<td>{%if eq .Level 1%}{%else%}{%end%}</td>
<td>{%.Tag%}</td>
<td>{%.Spec%}</td>
<td>{%if eq .Protocol 1%} HTTP {%else if eq .Protocol 2%} SHELL {%end%}</td>
<td>{%if eq .Timeout -1%}{%else if gt .Timeout 0%}{%.Timeout%}{%else%}{%end%}</td>
<td>{%.RetryTimes%}</td>
<td>{%if gt .Multi 0%}{%else%}{%end%}</td>
<td>
{%range $k, $h := .Hosts%}
{%$h.Alias%}<br>
{%end%}
</td>
<td>
{%if eq .Level 1%}
{%if eq .Status 1%}<span><i class="checkmark big icon"></i></span>{%else%}<span><i class="minus big icon"></i><span>{%end%}
{%end%}
</td>
<td>
<div class="ui buttons operation">
{%if $.IsAdmin%}
<a href="/task/edit/{%.Id%}" ><i class="edit big icon" title="编辑"></i></a>&nbsp;&nbsp;&nbsp;&nbsp;
{%if eq .Level 1%}
{%if eq .Status 1%}
<a href="javascript:void(0);" @click="changeStatus({%.Id%},{%.Status%})"><i class="pause circle big icon" title="停止"></i></a>&nbsp;&nbsp;
{%else%}
<a href="javascript:void(0);" @click="changeStatus({%.Id%},{%.Status%})"><i class="play big icon" title="激活"></i></a>&nbsp;&nbsp;
{%end%}
{%end%}
<a href="javascript:void(0);" @click="remove({%.Id%})"><i class="remove big icon" title="删除"></i></a>
<a href="javascript:void(0);" @click="run({%.Id%})"><i class="rocket big icon" title="手动执行"></i></a>&nbsp;&nbsp;
{%end%}
<a href="/task/log?task_id={%.Id%}"><i class="bar chart icon big" title="查看日志"></i></a>
</div>
</td>
</tr>
{%end%}
</tbody>
</table>
{% template "common/pagination" .%}
</div>
</div>
<script type="text/javascript">
$('.ui.checkbox').checkbox();
$('#batch-operation').change(function() {
var type = $(this).val();
if (type == 0) {
return;
}
var ids = [];
$('.sub-check:checked').each(function() {
ids.push($(this).data('id'));
});
if (ids.length == 0) {
swal('', '', 'warning');
return;
}
util.confirm("确定要执行此操作吗", function () {
$.ajaxSetup({
async: false
});
switch (type) {
case "1":
for (i in ids) {
changeStatus(ids[i], false, true);
}
break;
case "2":
for (i in ids) {
changeStatus(ids[i], true, true);
}
break;
case "3":
for (i in ids) {
remove(ids[i], true);
}
break;
}
location.reload();
});
});
var vue = new Vue(
{
el: '.task-list',
methods: {
changeStatus: changeStatus,
remove: remove,
run: function(id) {
util.get("/task/run/" + id, function(code, message) {
swal('', message, 'success');
})
}
}
}
);
function checkAll(ele) {
if ($(ele).is(":checked")) {
$('.sub-check').prop("checked", true);
} else {
$('.sub-check').prop("checked", false);
}
}
function remove(id, stopReload) {
var url = '/task/remove/' + id;
if (stopReload === undefined) {
util.removeConfirm(url);
return;
}
util.post(url, {}, function () {
if (stopReload === undefined) {
location.reload();
}
});
}
function changeStatus(id ,status, stopReload) {
var url = '';
if (status) {
url = '/task/disable';
} else {
url = '/task/enable';
}
url += '/' + id;
util.post(url,{}, function() {
if (stopReload === undefined) {
location.reload();
}
});
}
</script>
{% template "common/footer" . %}

View File

@ -1,174 +0,0 @@
{% template "common/header" . %}
<style type="text/css">
pre {
white-space: pre-wrap;
word-wrap: break-word;
padding:10px;
background-color: #4C4C4C;
color: white;
}
</style>
<div class="ui grid">
<!--the vertical menu-->
{% template "task/menu" . %}
<div class="twelve wide column">
{%if .IsAdmin%}
<div class="pageHeader">
<div class="segment">
<h3 class="ui dividing header">
<div class="content">
<button class="ui small teal button" onclick="clearLog()"></button>
</div>
</h3>
</div>
</div>
{%end%}
<form class="ui form">
<div class="six fields search">
<div class="field">
<input type="text" placeholder="任务ID" name="task_id" value="{%if gt .Params.TaskId 0%}{%.Params.TaskId%}{%end%}">
</div>
<div class="field">
<select name="protocol" id="protocol">
<option value="0"></option>
<option value="2" {%if eq .Params.Protocol 2%}selected{%end%} data-match="host_id" data-validate-type="selectProtocol">SHELL</option>
<option value="1" {%if eq .Params.Protocol 1%}selected{%end%}>HTTP</option>
</select>
</div>
<div class="field">
<select name="status">
<option value="0"></option>
<option value="1" {%if eq .Params.Status 0%}selected{%end%} ></option>
<option value="2" {%if eq .Params.Status 1%}selected{%end%}></option>
<option value="3" {%if eq .Params.Status 2%}selected{%end%}></option>
<option value="4" {%if eq .Params.Status 3%}selected{%end%}></option>
</select>
</div>
<div class="field">
<button class="ui linkedin submit button"></button>
</div>
</div>
</form>
<table class="ui celled table">
<thead>
<tr>
<th>ID</th>
<th></th>
<th>cron</th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{%range $i, $v := .Logs%}
<tr>
<td><a href="/task?id={%.TaskId%}">{%.TaskId%}</a></td>
<td>{%.Name%}</td>
<td>{%.Spec%}</td>
<td>{%if eq .Protocol 1%} HTTP {%else if eq .Protocol 2%} SHELL {%end%}</td>
<td>{%.RetryTimes%}</td>
<td>{%unescape .Hostname%}</td>
<td>
{%if and (ne .Status 3) (ne .Status 4)%}
{%if gt .TotalTime 0%}{%.TotalTime%}{%else%}1{%end%}<br>
: {%.StartTime.Format "2006-01-02 15:04:05" %}<br>
{%if ne .Status 1%}
: {%.EndTime.Format "2006-01-02 15:04:05" %}
{%end%}
{%end%}
</td>
<td>
{%if eq .Status 2%}
{%else if eq .Status 1%}
<span style="color:green"></span>
{%else if eq .Status 0%}
<span style="color:red"></span>
{%else if eq .Status 3%}
<span style="color:#4499EE"></span>
{%end%}
</td>
<td>
{%if or (eq .Status 2) (eq .Status 0)%}
<button class="ui small primary button"
onclick="showResult('{%.Name%}', '{%.Command%}', '{%.Result%}')"
>
</button>
{%end%}
{%if $.IsAdmin%}
{%if and (eq .Status 1) (eq .Protocol 2) %}
<button class="ui small blue button" onclick="stopTask({%.Id%}, {%.TaskId%})"></button>
{%end%}
{%end%}
</td>
</tr>
{%end%}
</tbody>
</table>
{% template "common/pagination" .%}
</div>
</div>
<div class="message">
<result></result>
</div>
<script type="text/x-vue-template" id="task-result">
<div class="ui modal">
<i class="close icon"></i>
<div class="header">
{{name}}
</div>
<div>
<pre style="background-color:#04477C;color:lightslategray">{{command}}</pre>
</div>
<div>
<pre>{{result}}</pre>
</div>
</div>
</script>
<script type="text/javascript">
function showResult(name, command,result) {
$('.message').html($('#task-result').html());
new Vue(
{
el: '.message',
data: {
result: result.replace(/\\n/,"<br>"),
name: name,
command: command
}
}
);
$('.ui.modal.transition').remove();
$('.ui.modal').modal({
detachable: false,
observeChanges: true
}).modal('refresh').modal('show');
}
function stopTask(id, taskId) {
util.confirm("确定要停止任务吗", function () {
util.post("/task/log/stop/", {id: id, task_id:taskId}, function (code, message) {
swal('', message, 'info');
});
});
}
function clearLog() {
util.confirm("确定要删除所有日志吗?", function() {
util.post("/task/log/clear",{}, function() {
location.reload();
});
});
}
</script>
{% template "common/footer" . %}

View File

@ -1,12 +0,0 @@
<div class="three wide column">
<div class="verticalMenu">
<div class="ui vertical pointing menu fluid">
<a class="{%if eq .URI "/task"%}active teal{%end%} item" href="/task">
<i class="tasks icon"></i>
</a>
<a class="item {%if eq .URI "/task/log"%}active teal{%end%} " href="/task/log">
<i class="bar chart icon"></i>
</a>
</div>
</div>
</div>

View File

@ -1,468 +0,0 @@
{% template "common/header" . %}
<div class="ui grid">
{%template "task/menu" .%}
<div class="twelve wide column">
<div class="pageHeader">
<div class="segment">
<h3 class="ui dividing header">
<div class="content">
{%.Title%}
</div>
</h3>
</div>
</div>
<form class="ui form fluid vertical segment">
<input type="hidden" name="id" value="{%.Task.Id%}">
<div class="two fields">
<div class="field">
<label>
<div class="content"></div>
</label>
<div class="ui small input">
<input type="text" name="name" placeholder="任务名称" value="{%.Task.Name%}">
</div>
</div>
<div class="field">
<label>
<div class="content"></div>
</label>
<div class="ui small input">
<input type="text" name="tag" placeholder="标签用于任务分类" value="{%.Task.Tag%}">
</div>
</div>
</div>
<div class="two fields">
<div class="field">
<label>
<div class="content"></div>
<div class="ui message">
, <br>
</div>
</label>
<select name="level" id="level" {%if .Task%}disabled="disabled"{%end%}>
<option value="1" {%if .Task%} {%if eq .Task.Level 1%}selected{%end%} {%end%}></option>
<option value="2" {%if .Task%} {%if eq .Task.Level 2%}selected{%end%} {%end%}></option>
</select>
</div>
</div>
<div id="parent-task">
<div class="two fields">
<div class="field">
<label>
<div class="content"></div>
<div class="ui message">
: <br>
:
</div>
</label>
<select name="dependency_status" id="dependency_status">
<option value="1" {%if .Task%} {%if eq .Task.DependencyStatus 1%}selected{%end%} {%end%}></option>
<option value="2" {%if .Task%} {%if eq .Task.DependencyStatus 2%}selected{%end%} {%end%}></option>
</select>
</div>
<div class="field">
<label>
<div class="content">ID</div>
<div class="ui message">
ID <br>
</div>
</label>
<div class="ui small input">
<input type="text" name="dependency_task_id" placeholder="可选" value="{%.Task.DependencyTaskId%}">
</div>
</div>
</div>
<div class="two fields">
<div class="field">
<label>
<div class="content">
crontab
</div>
</label>
<div class="ui small input">
<input type="text" name="spec" value="{%.Task.Spec%}" placeholder="秒 分 时 天 月 周"/>
</div>
</div>
</div>
</div>
<div class="three fields">
<div class="field">
<label></label>
<select name="protocol" id="protocol">
<option value="2" {%if .Task%} {%if eq .Task.Protocol 2%}selected{%end%} {%end%}
data-validate-type="selectProtocol">SHELL</option>
<option value="1" {%if .Task%} {%if eq .Task.Protocol 1%}selected{%end%} {%end%}>HTTP</option>
</select>
</div>
</div>
<div class="fields" id="hostField">
<div class="field">
<label></label>
<div id="hostId">
{%range $i, $v := .Hosts%}
<label>
<input type="checkbox" value="{%.Id%}" {%if $.Task%}{%if $v.Selected%} checked {%end%}{%end%} style="width:25px;height: 25px;">{%.Alias%}-{%.Name%}
{%if (HostFormat $i) %}<br>{%end%}
</label>
{%end%}
</div> &nbsp; <br> <a class="ui blue button" href="/host/create" target="_blank"></a>
</div>
</div>
<div class="two fields" id="http-method" style="display: none">
<div class="field">
<label></label>
<select name="http_method">
<option value="1" {%if .Task%} {%if eq .Task.HttpMethod 1%}selected{%end%} {%end%}>GET</option>
<option value="2" {%if .Task%} {%if eq .Task.HttpMethod 2%}selected{%end%} {%end%}
data-validate-type="selectProtocol">POST</option>
</select>
</div>
</div>
<div class="two fields">
<div class="field">
<label></label>
<textarea rows="5" name="command" placeholder="请输入系统命令" id="command">{%.Task.Command%}</textarea>
</div>
</div>
<div class="two fields">
<div class="field">
<label>(, 0-86400)</label>
<input type="text" name="timeout" placeholder="默认0, 不限制" value="{%if .Task%} {%.Task.Timeout%} {%else%}0{%end%}">
</div>
<div class="field">
<label></label>
<select name="multi">
<option value="2" {%if .Task%} {%if eq .Task.Multi 0%}selected{%end%} {%end%}></option>
<option value="1"{%if .Task%} {%if eq .Task.Multi 1%}selected{%end%} {%end%}></option>
</select>
</div>
</div>
<div class="two fields">
<div class="field">
<label> (0-10)</label>
<input type="text" name="retry_times" placeholder="默认0, 不重试" value="{%if .Task%} {%.Task.RetryTimes%} {%else%}0{%end%}">
</div>
<div class="field">
<label> (, 0-3600)</label>
<input type="text" name="retry_interval" placeholder="默认0, 执行默认重试策略" value="{%if .Task%} {%.Task.RetryInterval%} {%else%}0{%end%}">
</div>
</div>
<div class="three fields">
<div class="field">
<label></label>
<select name="notify_status" id="task-status">
<option value="1"{%if .Task%} {%if eq .Task.NotifyStatus 0%}selected{%end%} {%end%}></option>
<option value="2" {%if .Task%} {%if eq .Task.NotifyStatus 1%}selected{%end%} {%end%}></option>
<option value="3" {%if .Task%} {%if eq .Task.NotifyStatus 2%}selected{%end%} {%end%}></option>
</select>
</div>
</div>
<div class="two fields" style="display: none" id="task-notify-type">
<div class="field" >
<label></label>
<select name="notify_type">
<option value="1"{%if .Task%} {%if eq .Task.NotifyType 0%}selected{%end%} {%end%}></option>
<option value="2" {%if .Task%} {%if eq .Task.NotifyType 1%}selected{%end%} {%end%}></option>
<option value="3" {%if .Task%} {%if eq .Task.NotifyType 2%}selected{%end%} {%end%}>Slack</option>
</select>
</div>
</div>
<div class="inline fields" style="display: none" id="receiver-id"></div>
<div class="two fields">
<div class="field">
<label></label>
<textarea rows="5" name="remark" placeholder="任务备注信息">{%.Task.Remark%}</textarea>
</div>
</div>
<div class="ui primary submit button"></div> <a class="ui button" onclick="location.href='/task';"></a>
</form>
</div>
</div>
<script type="x-handlerbar-template" id="mail-template">
{{#each MailUsers}}
<div class="field">
<div class="ui checkbox">
<input type="checkbox" name="receiver[]" {{#if checked}}checked{{/if}} value="{{Id}}" />
<label>{{Username}}-{{Email}}</label>
</div>
</div>
{{else}}
<a class="ui blue button" href="/manage/mail/edit" target="_blank"></a><br><br>
{{/each}}
</script>
<script type="x-handlervar-template" id="slack-template">
{{#each Channels}}
<div class="field">
<div class="ui checkbox">
<input type="checkbox" name="receiver[]" {{#if checked}}checked{{/if}} value="{{Id}}" />
<label>{{Name}}</label>
</div>
</div>
{{else}}
<a class="ui blue button" href="/manage/slack/edit" target="_blank">Slack</a>
{{/each}}
</script>
<script type="text/javascript">
$(function() {
changeCommandPlaceholder();
changeLevel();
changeProtocol();
showNotify();
});
$('#protocol').change(function() {
changeCommandPlaceholder();
changeProtocol();
});
$('#level').change(function() {
changeLevel();
});
$('#task-status').change(function() {
var selected = $(this).val();
if (selected == 1) {
$('#task-notify-type').hide();
$('#receiver-id').hide();
$('#task-notify-type').find('select').val('1');
return;
}
$('#task-notify-type').show();
});
$('#task-notify-type').change(function() {
changeNotify();
});
function changeCommandPlaceholder() {
var selectedId = $('#protocol').val();
switch (selectedId) {
case '1':
$('#command').attr('placeholder', 'URL');
break;
case '2':
$('#command').attr('placeholder', 'shell');
break;
}
}
function showNotify() {
var notifyStatus = {%.Task.NotifyStatus%};
if (notifyStatus > 0) {
$('#task-notify-type').show();
}
var notifyReceiverIds = '{%.Task.NotifyReceiverId%}'.split(',');
changeNotify(notifyReceiverIds);
}
function changeNotify(notifyReceiverIds) {
var selectedId = $('#task-notify-type').find('select').val();
if (selectedId == 1) {
$('#receiver-id').hide();
$('#receiver-id').html('');
return;
}
if (selectedId == 2) {
showMail(notifyReceiverIds);
} else if (selectedId == 3) {
showSlack(notifyReceiverIds);
}
$('#receiver-id').show();
}
function showMail(notifyReceiverIds) {
util.get("/manage/mail", function(code, message, data) {
renderReceiver(notifyReceiverIds, $('#mail-template'), data, 'MailUsers');
})
}
function showSlack(notifyReceiverIds) {
util.get("/manage/slack", function(code, message, data) {
renderReceiver(notifyReceiverIds, $('#slack-template'), data, 'Channels');
})
}
function renderReceiver(notifyReceiverIds, $element, data, key) {
if (notifyReceiverIds !== undefined && notifyReceiverIds) {
console.log(data[key]);
for (i in data[key]) {
if ($.inArray(data[key][i].Id + '', notifyReceiverIds) != -1) {
data[key][i].checked = true;
}
}
}
var html = util.renderTemplate($($element), data);
$('#receiver-id').html(html);
$('.ui.checkbox').checkbox();
}
function changeProtocol() {
var protocol = $('#protocol').val();
if (protocol == 2) {
$('#hostField').show();
$('#http-method').hide();
return;
}
$('#hostField').hide();
$('#http-method').show();
}
$('.ui.checkbox')
.checkbox()
;
function validateNotify() {
var selectedId = $('#task-status').val();
if (selectedId == 1) {
return true;
}
var checkedLength = $('#receiver-id input:checked').length;
if (checkedLength == 0) {
return false;
}
return true;
}
function parseNotifyReceiver() {
var receivers = [];
$('#receiver-id input:checked').each(function() {
receivers.push($(this).val());
});
return receivers.join(",");
}
function parseHostId() {
var hostIds = [];
$('#hostId input:checked').each(function () {
hostIds.push($(this).val());
});
return hostIds.join(",");
}
function changeLevel() {
var selected = $('#level').val();
if (selected == 1) {
// 主任务
$('#parent-task').show();
$('#child-task').hide();
} else {
// 子任务
$('#parent-task').hide();
$('#child-task').show();
}
}
var $uiForm = $('.ui.form');
registerSelectFormValidation("selectProtocol", $uiForm, $('#protocol'), 'protocol');
$($uiForm).form(
{
onSuccess: function(event, fields) {
if (!validateNotify()) {
swal('', '', 'error');
return false;
}
fields.notify_receiver_id = parseNotifyReceiver();
fields.host_id = parseHostId();
if (fields.protocol == 2 && fields.host_id == "") {
swal('', '');
return false;
}
util.post('/task/store', fields, function(code, message) {
location.href = "/task"
});
return false;
},
fields: {
name: {
identifier : 'name',
rules: [
{
type : 'empty',
prompt : ''
},
{
type : 'maxLength[32]',
prompt : '32'
}
]
},
command: {
identifier : 'command',
rules: [
{
type : 'empty',
prompt : ''
},
{
type : 'maxLength[256]',
prompt : '256'
}
]
},
hosts: {
identifier : 'host_id',
rules: [
{
type : 'selectProtocol',
prompt : ''
}
]
},
timeout: {
identifier : 'timeout',
rules: [
{
type : 'integer[0..86400]',
prompt : '0-86400'
}
]
},
retryTimes: {
identifier : 'retry_times',
rules: [
{
type : 'integer[0..10]',
prompt : '0-10'
}
]
},
retryInterval: {
identifier : 'retry_interval',
rules: [
{
type : 'integer[0..3600]',
prompt : '0-3600'
}
]
},
remark: {
identifier : 'remark',
rules: [
{
type : 'maxLength[100]',
prompt : '100'
}
]
}
},
inline : true
});
</script>
{% template "common/footer" . %}

View File

@ -1,73 +0,0 @@
{% template "common/header" . %}
<div class="ui small modal">
<div class="header"></div>
<div class="content">
<form class="ui form">
<div class="two fields">
<div class="field">
<label></label>
<input class="small input" type="password" name="old_password" placeholder="原密码">
</div>
</div>
<div class="two fields">
<div class="field">
<label></label>
<input type="password" name="new_password" placeholder="新密码">
</div>
</div>
<div class="two fields">
<div class="field">
<label></label>
<input type="password" name="confirm_new_password" placeholder="确认新密码">
</div>
</div>
<button class="ui button primary button" ></button>
</form>
</div>
</div>
<script type="text/javascript">
$('.ui.modal').modal('setting', 'closable', false).modal('show');
$('.ui.form').form(
{
onSuccess: function(event, fields) {
util.post('/user/editMyPassword', fields, function(code, message) {
swal("操作成功", '', 'success');
location.href = "/task"
});
return false;
},
fields: {
oldPassword: {
identifier : 'old_password',
rules: [
{
type : 'empty',
prompt : ''
}
]
},
newPassword: {
identifier : 'new_password',
rules: [
{
type : 'empty',
prompt : ''
}
]
},
confirmNewPassword: {
identifier : 'confirm_new_password',
rules: [
{
type : 'match[new_password]',
prompt : ''
}
]
}
},
inline : true
});
</script>
{% template "common/footer" . %}

View File

@ -1,58 +0,0 @@
{% template "common/header" . %}
<div class="ui small modal">
<div class="header"></div>
<div class="content">
<form class="ui form">
<div class="two fields">
<div class="field">
<label></label>
<input type="password" name="new_password" placeholder="新密码">
</div>
</div>
<div class="two fields">
<div class="field">
<label></label>
<input type="password" name="confirm_new_password" placeholder="确认新密码">
</div>
</div>
<button class="ui button primary button" ></button>
</form>
</div>
</div>
<script type="text/javascript">
$('.ui.modal').modal('setting', 'closable', false).modal('show');
$('.ui.form').form(
{
onSuccess: function(event, fields) {
util.post('/user/editPassword/{%.Id%}', fields, function(code, message) {
swal("操作成功", '', 'success');
location.href = "/user"
});
return false;
},
fields: {
newPassword: {
identifier : 'new_password',
rules: [
{
type : 'empty',
prompt : ''
}
]
},
confirmNewPassword: {
identifier : 'confirm_new_password',
rules: [
{
type : 'match[new_password]',
prompt : ''
}
]
}
},
inline : true
});
</script>
{% template "common/footer" . %}

View File

@ -1,73 +0,0 @@
{% template "common/header" . %}
<div class="ui grid">
{% template "user/menu" . %}
<div class="twelve wide column">
<div class="pageHeader">
<div class="segment">
<h3 class="ui dividing header">
<a href="/user/create">
<i class="large add icon"></i>
<div class="content">
</div>
</a>
</h3>
</div>
</div>
<table class="ui celled table">
<thead>
<tr>
<th>ID</th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{%range $i, $v := .Users%}
<tr>
<td>{%.Id%}</td>
<td>{%.Name%}</td>
<td>{%.Email%}</td>
<td>{%if .IsAdmin%}{%else%}{%end%}</td>
<td>{%if .Status%}{%else%}{%end%}</td>
<td class="operation">
<a class="ui purple button" href="/user/edit/{%.Id%}"></a>
{%if eq .Status 1%}
<button class="ui button red" onclick="changeStatus({%.Id%},{%.Status%})"></button>&nbsp;&nbsp;
{%else%}
<button class="ui button twitter" onclick="changeStatus({%.Id%},{%.Status%})"></button>&nbsp;&nbsp;
{%end%}
<a href="/user/editPassword/{%.Id%}">
<button class="ui button facebook"></button>
</a>
<button class="ui positive button" onclick="util.removeConfirm('/user/remove/{%.Id%}')"></button>
</td>
</tr>
{%end%}
</tbody>
</table>
{% template "common/pagination" .%}
</div>
</div>
<script type="text/javascript">
function changeStatus(id ,status) {
var url = '';
if (status) {
url = '/user/disable';
} else {
url = '/user/enable';
}
url += '/' + id;
util.post(url,{}, function() {
location.reload();
});
}
</script>
{% template "common/footer" . %}

View File

@ -1,74 +0,0 @@
{% template "common/header" . %}
<div class="ui small modal">
<div class="header"></div>
<div class="content">
<form class="ui form">
<div class="two fields">
<div class="field">
<input class="small input" type="text" name="username" placeholder="用户名或邮箱">
</div>
</div>
<div class="two fields">
<div class="field">
<input type="password" name="password" placeholder="密码">
</div>
</div>
<div class="two fields">
<div class="field">
{%.Captcha.CreateHtml%}
<input type="text" name="captcha" placeholder="验证码">
</div>
</div>
<button class="ui button primary button" ></button>
</form>
</div>
</div>
<script type="text/javascript">
$('.ui.modal').modal('setting', 'closable', false).modal('show');
$('.ui.form').form(
{
onSuccess: function(event, fields) {
util.post('/user/login', fields, function(code, message) {
location.href = "/"
}, function (code, message) {
if (code == 5) {
$('.captcha-img').trigger('click');
}
});
return false;
},
fields: {
username: {
identifier : 'username',
rules: [
{
type : 'empty',
prompt : ''
}
]
},
Password: {
identifier : 'password',
rules: [
{
type : 'empty',
prompt : ''
}
]
},
Captcha: {
identifier : 'captcha',
rules: [
{
type : 'empty',
prompt : ''
}
]
}
},
inline : true
});
</script>
{% template "common/footer" . %}

View File

@ -1,9 +0,0 @@
<div class="four wide column">
<div class="verticalMenu">
<div class="ui vertical pointing menu fluid">
<a class="{%if eq .URI "/user"%}active teal{%end%} item" href="/user">
<i class="user icon"></i>
</a>
</div>
</div>
</div>

View File

@ -1,142 +0,0 @@
{% template "common/header" . %}
<div class="ui grid">
{% template "user/menu" . %}
<div class="twelve wide column">
<div class="pageHeader">
<div class="segment">
<h3 class="ui dividing header">
<div class="content">
</div>
</h3>
</div>
</div>
<form class="ui form fluid vertical segment">
<input type="hidden" name="id" value="{%.User.Id%}">
<div class="three fields">
<div class="field">
<label></label>
<div class="ui small input">
<input type="text" name="name" value="{%.User.Name%}" placeholder="请输入用户名">
</div>
</div>
<div class="field">
<label></label>
<div class="ui small input">
<input type="text" name="email" value="{%.User.Email%}" placeholder="请输入邮箱">
</div>
</div>
</div>
{%if eq .User.Id 0%}
<div class="three fields">
<div class="field">
<label></label>
<input type="password" name="password" placeholder="请输入密码">
</div>
<div class="field">
<label></label>
<input type="password" name="confirm_password" placeholder="请再次输入密码">
</div>
</div>
{%end%}
<div class="three fields">
<div class="field">
<label></label>
<input type="radio" name="is_admin" value="0" {%if eq .User.IsAdmin 0%}checked{%end%}>
<input type="radio" name="is_admin" value="1" {%if eq .User.IsAdmin 1%}checked{%end%}>
</div>
<div class="field">
<label></label>
<input type="radio" name="status" value="1" {%if eq .User.Status 1%}checked{%end%}>
<input type="radio" name="status" value="0"
{%if eq .User.Status 0%}checked{%end%}
>
</div>
</div>
<div class="ui primary submit button"></div>
<a class="ui button" onclick="location.href='/user';"></a>
</form>
</div>
</div>
<script type="text/javascript">
var $uiForm = $('.ui.form');
$($uiForm).form(
{
onSuccess: function(event, fields) {
util.post('/user/store', fields, function(code, message) {
location.href = "/user"
});
return false;
},
fields: {
name: {
identifier : 'name',
rules: [
{
type : 'empty',
prompt : ''
},
{
type : 'minLength[3]',
prompt : '3'
},
{
type : 'maxLength[32]',
prompt : '32'
}
]
},
password: {
identifier : 'password',
rules: [
{
type : 'empty',
prompt : ''
},
{
type : 'minLength[6]',
prompt : '6'
}
]
},
confirmPassword: {
identifier : 'confirm_password',
rules: [
{
type : 'empty',
prompt : ''
},
{
type : 'match[password]',
prompt : ''
}
]
},
email: {
identifier : 'email',
rules: [
{
type : 'empty',
prompt : ''
},
{
type : 'email',
prompt : ''
}
]
}
},
inline : true
});
</script>
{% template "common/footer" . %}

View File

@ -16,7 +16,7 @@
</template>
<script>
import installService from './api/install'
import appHeader from './components/common/header.vue'
import appNavMenu from './components/common/navMenu.vue'
import appFooter from './components/common/footer.vue'
@ -26,7 +26,9 @@ export default {
data () {
return {}
},
created () {
installService.store({})
},
components: {
appHeader,
appNavMenu,

View File

@ -9,7 +9,7 @@ export default {
httpClient.post('/task/log/clear', {}, callback)
},
stop (id, callback) {
httpClient.post('/task/log/stop', {id}, callback)
stop (id, taskId, callback) {
httpClient.post('/task/log/stop', {id, task_id: taskId}, callback)
}
}

View File

@ -102,10 +102,13 @@ export default {
this.searchParams.page_size = pageSize
this.search()
},
search () {
search (callback = null) {
hostService.list(this.searchParams, (data) => {
this.hosts = data.data
this.hostTotal = data.total
if (callback) {
callback()
}
})
},
remove (item) {
@ -128,7 +131,9 @@ export default {
this.$router.push(path)
},
refresh () {
this.search()
this.search(() => {
this.$message.success('刷新成功')
})
}
}
}

View File

@ -283,11 +283,14 @@ export default {
this.searchParams.page_size = pageSize
this.search()
},
search () {
search (callback = null) {
taskService.list(this.searchParams, (tasks, hosts) => {
this.tasks = tasks.data
this.taskTotal = tasks.total
this.hosts = hosts.data
if (callback) {
callback()
}
})
},
runTask (item) {
@ -308,7 +311,9 @@ export default {
this.$router.push(`/task/log?task_id=${item.id}`)
},
refresh () {
this.search()
this.search(() => {
this.$message.success('刷新成功')
})
},
toEdit (item) {
let path = ''

View File

@ -111,7 +111,7 @@
</el-table-column>
<el-table-column
label="执行结果"
width="120">
width="120" v-if="this.isAdmin">
<template slot-scope="scope">
<el-button type="success"
v-if="scope.row.status === 2"
@ -120,11 +120,23 @@
v-if="scope.row.status === 0"
@click="showTaskResult(scope.row)" >查看结果</el-button>
<el-button type="danger"
v-if="this.isAdmin && scope.row.status === 1 && scope.row.protocol === 2"
v-if="scope.row.status === 1 && scope.row.protocol === 2"
@click="stopTask(scope.row)">停止任务
</el-button>
</template>
</el-table-column>
<el-table-column
label="执行结果"
width="120" v-else>
<template slot-scope="scope">
<el-button type="success"
v-if="scope.row.status === 2"
@click="showTaskResult(scope.row)">查看结果</el-button>
<el-button type="warning"
v-if="scope.row.status === 0"
@click="showTaskResult(scope.row)" >查看结果</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog title="任务执行结果" :visible.sync="dialogVisible">
<div>
@ -213,10 +225,14 @@ export default {
this.searchParams.page_size = pageSize
this.search()
},
search () {
search (callback = null) {
taskLogService.list(this.searchParams, (data) => {
this.logs = data.data
this.logTotal = data.total
if (callback) {
callback()
}
})
},
clearLog () {
@ -228,7 +244,7 @@ export default {
})
},
stopTask (item) {
taskLogService.stop(item.id, () => {
taskLogService.stop(item.id, item.task_id, () => {
this.search()
})
},
@ -238,7 +254,9 @@ export default {
this.currentTaskResult.result = item.result
},
refresh () {
this.search()
this.search(() => {
this.$message.success('刷新成功')
})
}
}
}

View File

@ -54,7 +54,6 @@ export default {
})
},
save () {
console.log(this.form)
userService.editMyPassword(this.form, () => {
this.$router.back()
})

View File

@ -109,10 +109,13 @@ export default {
this.searchParams.page_size = pageSize
this.search()
},
search () {
search (callback = null) {
userService.list(this.searchParams, (data) => {
this.users = data.data
this.userTotal = data.total
if (callback) {
callback()
}
})
},
remove (item) {
@ -132,7 +135,9 @@ export default {
this.$router.push(path)
},
refresh () {
this.search()
this.search(() => {
this.$message.success('刷新成功')
})
},
editPassword (item) {
this.$router.push(`/user/edit-password/${item.id}`)

View File

@ -5,7 +5,8 @@
:visible.sync="dialogVisible"
:close-on-click-modal="false"
:show-close="false"
:close-on-press-escape="false">
:close-on-press-escape="false"
width="40%">
<el-form ref="form" :model="form" label-width="80px"
:rules="formRules">
<el-form-item label="用户名" prop="username" >

View File

@ -160,10 +160,6 @@ router.beforeEach((to, from, next) => {
next()
return
}
if (to.fullPath === '/task') {
next()
return
}
if (store.getters.user.token) {
if ((store.getters.user.isAdmin || to.meta.noNeedAdmin)) {
next()