前端重构#系统安装
parent
ac8936e238
commit
6606f64a4b
|
@ -1 +1,2 @@
|
||||||
.git
|
.git
|
||||||
|
nodu_modules
|
|
@ -1,7 +1,5 @@
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
|
|
||||||
MAINTAINER ouqiang <qiangqianludao@gmail.com>
|
|
||||||
|
|
||||||
WORKDIR /usr/local/gocron
|
WORKDIR /usr/local/gocron
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
|
@ -56,10 +56,12 @@
|
||||||
4. 浏览器访问 http://localhost:5920
|
4. 浏览器访问 http://localhost:5920
|
||||||
|
|
||||||
### 源码安装
|
### 源码安装
|
||||||
1. `go`语言版本1.9+
|
1. 安装Go 1.9+, Node.js, Yarn
|
||||||
2. `go get -d github.com/ouqiang/gocron`
|
2. `go get -d github.com/ouqiang/gocron`
|
||||||
3. 编译 `make`
|
3. 安装依赖 `make install-vue`
|
||||||
4. 启动
|
4. 前端打包 `make build-vue`
|
||||||
|
5. 编译Go代码 `make`
|
||||||
|
6. 启动
|
||||||
* gocron `./bin/gocron web`
|
* gocron `./bin/gocron web`
|
||||||
* gocron-node `./bin/gocron-node`
|
* gocron-node `./bin/gocron-node`
|
||||||
|
|
||||||
|
|
|
@ -11,11 +11,34 @@ type Setting struct {
|
||||||
Value string `xorm:"varchar(4096) notnull default '' "`
|
Value string `xorm:"varchar(4096) notnull default '' "`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const slackTemplate = `
|
||||||
|
任务ID: {{.TaskId}}\n
|
||||||
|
任务名称: {{.TaskName}}\n
|
||||||
|
状态: \n {{.Status}} \n
|
||||||
|
执行结果: {{.Result}}
|
||||||
|
`
|
||||||
|
const emailTemplate = `
|
||||||
|
任务ID: {{.TaskId}}<br>
|
||||||
|
任务名称: {{.TaskName}}<br>
|
||||||
|
状态: \n {{.Status}}<br>
|
||||||
|
执行结果: {{.Result}}
|
||||||
|
`
|
||||||
|
const webhookTemplate = `
|
||||||
|
{
|
||||||
|
"task_id": "{{.TaskId}}",
|
||||||
|
"task_name": "{{.TaskName}}",
|
||||||
|
"status": "{{.Status}}",
|
||||||
|
"result": "{{.Result}}"
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
const SlackCode = "slack"
|
const SlackCode = "slack"
|
||||||
const SlackUrlKey = "url"
|
const SlackUrlKey = "url"
|
||||||
|
const SlackTemplateKey = "template"
|
||||||
const SlackChannelKey = "channel"
|
const SlackChannelKey = "channel"
|
||||||
|
|
||||||
const MailCode = "mail"
|
const MailCode = "mail"
|
||||||
|
const MailTemplateKey = "template"
|
||||||
const MailServerKey = "server"
|
const MailServerKey = "server"
|
||||||
const MailUserKey = "user"
|
const MailUserKey = "user"
|
||||||
|
|
||||||
|
@ -23,11 +46,25 @@ const MailUserKey = "user"
|
||||||
func (setting *Setting) InitBasicField() {
|
func (setting *Setting) InitBasicField() {
|
||||||
setting.Code = SlackCode
|
setting.Code = SlackCode
|
||||||
setting.Key = SlackUrlKey
|
setting.Key = SlackUrlKey
|
||||||
|
setting.Value = ""
|
||||||
Db.Insert(setting)
|
Db.Insert(setting)
|
||||||
|
|
||||||
setting.Id = 0
|
setting.Id = 0
|
||||||
|
|
||||||
|
setting.Code = SlackCode
|
||||||
|
setting.Key = SlackTemplateKey
|
||||||
|
setting.Value = slackTemplate
|
||||||
|
Db.Insert(setting)
|
||||||
|
setting.Id = 0
|
||||||
|
|
||||||
setting.Code = MailCode
|
setting.Code = MailCode
|
||||||
setting.Key = MailServerKey
|
setting.Key = MailServerKey
|
||||||
|
setting.Value = ""
|
||||||
|
Db.Insert(setting)
|
||||||
|
setting.Id = 0
|
||||||
|
|
||||||
|
setting.Code = MailCode
|
||||||
|
setting.Key = MailTemplateKey
|
||||||
|
setting.Value = emailTemplate
|
||||||
Db.Insert(setting)
|
Db.Insert(setting)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +73,7 @@ func (setting *Setting) InitBasicField() {
|
||||||
type Slack struct {
|
type Slack struct {
|
||||||
Url string `json:"url"`
|
Url string `json:"url"`
|
||||||
Channels []Channel `json:"channels"`
|
Channels []Channel `json:"channels"`
|
||||||
|
Template string `json:"template"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Channel struct {
|
type Channel struct {
|
||||||
|
@ -46,7 +84,7 @@ type Channel struct {
|
||||||
func (setting *Setting) Slack() (Slack, error) {
|
func (setting *Setting) Slack() (Slack, error) {
|
||||||
list := make([]Setting, 0)
|
list := make([]Setting, 0)
|
||||||
err := Db.Where("code = ?", SlackCode).Find(&list)
|
err := Db.Where("code = ?", SlackCode).Find(&list)
|
||||||
slack := Slack{Url: "", Channels: make([]Channel, 0)}
|
slack := Slack{}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return slack, err
|
return slack, err
|
||||||
}
|
}
|
||||||
|
@ -58,15 +96,17 @@ func (setting *Setting) Slack() (Slack, error) {
|
||||||
|
|
||||||
func (setting *Setting) formatSlack(list []Setting, slack *Slack) {
|
func (setting *Setting) formatSlack(list []Setting, slack *Slack) {
|
||||||
for _, v := range list {
|
for _, v := range list {
|
||||||
if v.Key == SlackUrlKey {
|
switch v.Key {
|
||||||
|
case SlackUrlKey:
|
||||||
slack.Url = v.Value
|
slack.Url = v.Value
|
||||||
continue
|
case SlackTemplateKey:
|
||||||
}
|
slack.Template = v.Value
|
||||||
|
default:
|
||||||
slack.Channels = append(slack.Channels, Channel{
|
slack.Channels = append(slack.Channels, Channel{
|
||||||
v.Id, v.Value,
|
v.Id, v.Value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新slack webhook url
|
// 更新slack webhook url
|
||||||
|
@ -111,6 +151,7 @@ type Mail struct {
|
||||||
User string `json:"user"`
|
User string `json:"user"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
MailUsers []MailUser `json:"mail_users"`
|
MailUsers []MailUser `json:"mail_users"`
|
||||||
|
Template string `json:"template"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MailUser struct {
|
type MailUser struct {
|
||||||
|
|
|
@ -130,8 +130,8 @@ func RegisterMiddleware(m *macaron.Macaron) {
|
||||||
m.Use(toolbox.Toolboxer(m))
|
m.Use(toolbox.Toolboxer(m))
|
||||||
}
|
}
|
||||||
m.Use(macaron.Renderer())
|
m.Use(macaron.Renderer())
|
||||||
m.Use(ipAuth)
|
|
||||||
m.Use(checkAppInstall)
|
m.Use(checkAppInstall)
|
||||||
|
m.Use(ipAuth)
|
||||||
m.Use(userAuth)
|
m.Use(userAuth)
|
||||||
m.Use(urlAuth)
|
m.Use(urlAuth)
|
||||||
}
|
}
|
||||||
|
@ -140,10 +140,10 @@ func RegisterMiddleware(m *macaron.Macaron) {
|
||||||
|
|
||||||
/** 检测应用是否已安装 **/
|
/** 检测应用是否已安装 **/
|
||||||
func checkAppInstall(ctx *macaron.Context) {
|
func checkAppInstall(ctx *macaron.Context) {
|
||||||
if ctx.Req.URL.Path == "/install" {
|
if app.Installed {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if app.Installed {
|
if ctx.Req.URL.Path == "/install/store" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonResp := utils.JsonResponse{}
|
jsonResp := utils.JsonResponse{}
|
||||||
|
@ -154,6 +154,9 @@ func checkAppInstall(ctx *macaron.Context) {
|
||||||
|
|
||||||
// IP验证, 通过反向代理访问gocron,需设置Header X-Real-IP才能获取到客户端真实IP
|
// IP验证, 通过反向代理访问gocron,需设置Header X-Real-IP才能获取到客户端真实IP
|
||||||
func ipAuth(ctx *macaron.Context) {
|
func ipAuth(ctx *macaron.Context) {
|
||||||
|
if !app.Installed {
|
||||||
|
return
|
||||||
|
}
|
||||||
allowIpsStr := app.Setting.AllowIps
|
allowIpsStr := app.Setting.AllowIps
|
||||||
if allowIpsStr == "" {
|
if allowIpsStr == "" {
|
||||||
return
|
return
|
||||||
|
@ -173,6 +176,9 @@ func ipAuth(ctx *macaron.Context) {
|
||||||
|
|
||||||
// 用户认证
|
// 用户认证
|
||||||
func userAuth(ctx *macaron.Context) {
|
func userAuth(ctx *macaron.Context) {
|
||||||
|
if !app.Installed {
|
||||||
|
return
|
||||||
|
}
|
||||||
user.RestoreToken(ctx)
|
user.RestoreToken(ctx)
|
||||||
if user.IsLogin(ctx) {
|
if user.IsLogin(ctx) {
|
||||||
return
|
return
|
||||||
|
@ -181,7 +187,7 @@ func userAuth(ctx *macaron.Context) {
|
||||||
if strings.HasPrefix(uri, "/v1") {
|
if strings.HasPrefix(uri, "/v1") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
excludePaths := []string{"", "/install", "/user/login"}
|
excludePaths := []string{"", "/user/login"}
|
||||||
for _, path := range excludePaths {
|
for _, path := range excludePaths {
|
||||||
if uri == path {
|
if uri == path {
|
||||||
return
|
return
|
||||||
|
@ -195,6 +201,9 @@ func userAuth(ctx *macaron.Context) {
|
||||||
|
|
||||||
// URL权限验证
|
// URL权限验证
|
||||||
func urlAuth(ctx *macaron.Context) {
|
func urlAuth(ctx *macaron.Context) {
|
||||||
|
if !app.Installed {
|
||||||
|
return
|
||||||
|
}
|
||||||
if user.IsAdmin(ctx) {
|
if user.IsAdmin(ctx) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -225,6 +234,9 @@ func urlAuth(ctx *macaron.Context) {
|
||||||
|
|
||||||
/** API接口签名验证 **/
|
/** API接口签名验证 **/
|
||||||
func apiAuth(ctx *macaron.Context) {
|
func apiAuth(ctx *macaron.Context) {
|
||||||
|
if !app.Installed {
|
||||||
|
return
|
||||||
|
}
|
||||||
if !app.Setting.ApiSignEnable {
|
if !app.Setting.ApiSignEnable {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
4
makefile
4
makefile
|
@ -46,6 +46,10 @@ build-vue:
|
||||||
cd web/vue && yarn run build
|
cd web/vue && yarn run build
|
||||||
cp -r web/vue/dist/ web/public/
|
cp -r web/vue/dist/ web/public/
|
||||||
|
|
||||||
|
.PHONY: install-vue
|
||||||
|
install-vue:
|
||||||
|
cp web/vue && yarn install
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm bin/gocron
|
rm bin/gocron
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<app-nav-menu></app-nav-menu>
|
<app-nav-menu></app-nav-menu>
|
||||||
</el-header>
|
</el-header>
|
||||||
<el-main >
|
<el-main >
|
||||||
<div>
|
<div id="main-container">
|
||||||
<router-view/>
|
<router-view/>
|
||||||
</div>
|
</div>
|
||||||
</el-main>
|
</el-main>
|
||||||
|
@ -35,9 +35,26 @@ export default {
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
|
body {
|
||||||
|
margin:0;
|
||||||
|
}
|
||||||
.el-header {
|
.el-header {
|
||||||
padding:0;
|
padding:0;
|
||||||
margin:0;
|
margin:0;
|
||||||
}
|
}
|
||||||
|
.el-container {
|
||||||
|
padding:0;
|
||||||
|
margin:0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.el-main {
|
||||||
|
padding:0;
|
||||||
|
margin:0;
|
||||||
|
}
|
||||||
|
#main-container .el-main {
|
||||||
|
margin:20px 20px 0 20px;
|
||||||
|
}
|
||||||
|
.el-aside .el-menu {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -7,15 +7,28 @@
|
||||||
text-color="#fff"
|
text-color="#fff"
|
||||||
active-text-color="#ffd04b"
|
active-text-color="#ffd04b"
|
||||||
router>
|
router>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="2">
|
||||||
<el-menu-item index="/task">任务管理</el-menu-item>
|
<el-menu-item index="/task">任务管理</el-menu-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="2">
|
||||||
<el-menu-item index="/host">任务节点</el-menu-item>
|
<el-menu-item index="/host">任务节点</el-menu-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="2">
|
||||||
<el-menu-item v-if="this.$store.getters.user.isAdmin" index="/user">用户管理</el-menu-item>
|
<el-menu-item v-if="this.$store.getters.user.isAdmin" index="/user">用户管理</el-menu-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="2">
|
||||||
<el-menu-item v-if="this.$store.getters.user.isAdmin" index="/system">系统管理</el-menu-item>
|
<el-menu-item v-if="this.$store.getters.user.isAdmin" index="/system">系统管理</el-menu-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="16"></el-col>
|
||||||
|
<el-col :span="2" style="float:right;">
|
||||||
<el-submenu v-if="this.$store.getters.user.token" index="userStatus">
|
<el-submenu v-if="this.$store.getters.user.token" index="userStatus">
|
||||||
<template slot="title">{{this.$store.getters.user.username}}</template>
|
<template slot="title">{{this.$store.getters.user.username}}</template>
|
||||||
<el-menu-item index="/user/edit-my-password">修改密码</el-menu-item>
|
<el-menu-item index="/user/edit-my-password">修改密码</el-menu-item>
|
||||||
<el-menu-item @click="logout" index="/user/logout">退出</el-menu-item>
|
<el-menu-item @click="logout" index="/user/logout">退出</el-menu-item>
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -10,10 +10,6 @@ import store from './store/index'
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false
|
||||||
Vue.use(ElementUI)
|
Vue.use(ElementUI)
|
||||||
|
|
||||||
Vue.prototype.$refresh = function () {
|
|
||||||
router.go(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$appConfirm = function (callback) {
|
Vue.prototype.$appConfirm = function (callback) {
|
||||||
this.$confirm('确定执行此操作?', '提示', {
|
this.$confirm('确定执行此操作?', '提示', {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
|
|
|
@ -14,8 +14,14 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-button type="success" v-if="this.$store.getters.user.isAdmin" @click="toEdit(null)">新增</el-button>
|
<el-row type="flex" justify="end">
|
||||||
<el-button type="info" @click="refresh">刷新</el-button> <br><br>
|
<el-col :span="2">
|
||||||
|
<el-button type="primary" v-if="this.$store.getters.user.isAdmin" @click="toEdit(null)">新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="2">
|
||||||
|
<el-button type="info" @click="refresh">刷新</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
<el-pagination
|
<el-pagination
|
||||||
background
|
background
|
||||||
layout="prev, pager, next, sizes, total"
|
layout="prev, pager, next, sizes, total"
|
||||||
|
|
|
@ -1,14 +1,160 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<el-container>
|
||||||
安装页面
|
<el-main>
|
||||||
</div>
|
<el-form ref="form" :model="form" :rules="formRules" label-width="100px" style="width: 700px;">
|
||||||
|
<h3>数据库配置</h3>
|
||||||
|
<el-form-item label="数据库选择" prop="db_type">
|
||||||
|
<el-select v-model.trim="form.db_type">
|
||||||
|
<el-option
|
||||||
|
v-for="item in dbList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="主机名" prop="db_host">
|
||||||
|
<el-input v-model="form.db_host"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="端口" prop="db_port">
|
||||||
|
<el-input v-model.number="form.db_port"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="用户名" prop="db_username">
|
||||||
|
<el-input v-model="form.db_username"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="密码" prop="db_password">
|
||||||
|
<el-input v-model="form.db_password" type="password"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="数据库名称" prop="db_name">
|
||||||
|
<el-input v-model="form.db_name" placeholder="如果数据库不存在, 需提前创建"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="表前缀" prop="db_table_prefix">
|
||||||
|
<el-input v-model="form.db_table_prefix"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<h3>管理员账号配置</h3>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="账号" prop="admin_username">
|
||||||
|
<el-input v-model="form.admin_username"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="邮箱" prop="admin_email">
|
||||||
|
<el-input v-model="form.admin_email"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="密码" prop="admin_password">
|
||||||
|
<el-input v-model="form.admin_password" type="password"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="确认密码" prop="confirm_admin_password">
|
||||||
|
<el-input v-model="form.confirm_admin_password" type="password"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="submit()">安装</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import installService from '../../api/install'
|
||||||
export default {
|
export default {
|
||||||
name: 'index',
|
name: 'index',
|
||||||
data () {
|
data () {
|
||||||
return {}
|
return {
|
||||||
|
form: {
|
||||||
|
db_type: 'mysql',
|
||||||
|
db_host: '127.0.0.1',
|
||||||
|
db_port: 3306,
|
||||||
|
db_username: '',
|
||||||
|
db_password: '',
|
||||||
|
db_name: '',
|
||||||
|
db_table_prefix: '',
|
||||||
|
admin_username: '',
|
||||||
|
admin_password: '',
|
||||||
|
confirm_admin_password: '',
|
||||||
|
admin_email: ''
|
||||||
|
},
|
||||||
|
formRules: {
|
||||||
|
db_type: [
|
||||||
|
{required: true, message: '请选择数据库', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
db_host: [
|
||||||
|
{required: true, message: '请输入数据库主机名', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
db_port: [
|
||||||
|
{type: 'number', required: true, message: '请输入数据库端口', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
db_username: [
|
||||||
|
{required: true, message: '请输入数据库用户名', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
db_password: [
|
||||||
|
{required: true, message: '请输入数据库密码', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
db_name: [
|
||||||
|
{required: true, message: '请输入数据库名称', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
admin_username: [
|
||||||
|
{required: true, message: '请输入管理员账号', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
admin_email: [
|
||||||
|
{type: 'email', required: true, message: '请输入管理员邮箱', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
admin_password: [
|
||||||
|
{required: true, message: '请输入管理员密码', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
confirm_admin_password: [
|
||||||
|
{required: true, message: '请再次输入管理员密码', trigger: 'blur'}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
dbList: [
|
||||||
|
{
|
||||||
|
value: 'mysql',
|
||||||
|
label: 'MySQL'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
submit () {
|
||||||
|
this.$refs['form'].validate((valid) => {
|
||||||
|
if (!valid) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
this.save()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
save () {
|
||||||
|
installService.store(this.form, () => {
|
||||||
|
this.$router.push('/')
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
<template>
|
||||||
|
<el-container>
|
||||||
|
<system-sidebar></system-sidebar>
|
||||||
|
<el-main>
|
||||||
|
<notification-tab></notification-tab>
|
||||||
|
<el-form ref="form" :model="form" label-width="100px" style="width: 700px;">
|
||||||
|
<h3>邮件服务器配置</h3>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="SMTP服务器">
|
||||||
|
<el-input v-model="form.host"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="端口">
|
||||||
|
<el-input v-model="form.port"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="用户名">
|
||||||
|
<el-input v-model="form.user"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="密码">
|
||||||
|
<el-input v-model="form.password"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-form-item label="模板">
|
||||||
|
<el-input
|
||||||
|
type="textarea"
|
||||||
|
:rows="5"
|
||||||
|
placeholder=""
|
||||||
|
v-model="form.template">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<h3>邮箱用户</h3>
|
||||||
|
<el-tag
|
||||||
|
v-for="item in form.receivers"
|
||||||
|
:key="item.email"
|
||||||
|
closable>
|
||||||
|
{{item.username}}
|
||||||
|
</el-tag>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="submit()">保存</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import systemSidebar from '../sidebar'
|
||||||
|
import notificationTab from './tab'
|
||||||
|
export default {
|
||||||
|
name: 'notification-email',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
form: {
|
||||||
|
host: '',
|
||||||
|
port: 465,
|
||||||
|
user: '',
|
||||||
|
password: '',
|
||||||
|
template: '',
|
||||||
|
receivers: [
|
||||||
|
{
|
||||||
|
username: '欧强',
|
||||||
|
email: 'qingqianludao@gmail.com'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {notificationTab, systemSidebar},
|
||||||
|
methods: {
|
||||||
|
submit () {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,54 @@
|
||||||
|
<template>
|
||||||
|
<el-container>
|
||||||
|
<system-sidebar></system-sidebar>
|
||||||
|
<el-main>
|
||||||
|
<notification-tab></notification-tab>
|
||||||
|
<el-form ref="form" :model="form" label-width="180px" style="width: 700px;">
|
||||||
|
<el-form-item label="Slack Webhook URL">
|
||||||
|
<el-input v-model="form.url"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="模板">
|
||||||
|
<el-input
|
||||||
|
type="textarea"
|
||||||
|
:rows="5"
|
||||||
|
placeholder=""
|
||||||
|
v-model="form.template">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<h3>邮箱用户</h3>
|
||||||
|
<el-tag
|
||||||
|
v-for="item in form.channels"
|
||||||
|
:key="item"
|
||||||
|
closable>
|
||||||
|
{{item}}
|
||||||
|
</el-tag>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="submit()">保存</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import systemSidebar from '../sidebar'
|
||||||
|
import notificationTab from './tab'
|
||||||
|
export default {
|
||||||
|
name: 'notification-slack',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
form: {
|
||||||
|
url: '',
|
||||||
|
template: '',
|
||||||
|
channels: ['xiamen', 'taiwan']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {notificationTab, systemSidebar},
|
||||||
|
methods: {
|
||||||
|
submit () {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,30 @@
|
||||||
|
<template>
|
||||||
|
<el-tabs v-model="activeName" @tab-click="changeTab">
|
||||||
|
<el-tab-pane label="邮件" name="email"></el-tab-pane>
|
||||||
|
<el-tab-pane label="Slack" name="slack"></el-tab-pane>
|
||||||
|
<el-tab-pane label="Webhook" name="webhook"></el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'notification-tab',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
activeName: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
const segments = this.$route.path.split('/')
|
||||||
|
if (segments.length !== 4) {
|
||||||
|
return 'email'
|
||||||
|
}
|
||||||
|
this.activeName = segments[3]
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
changeTab (item) {
|
||||||
|
this.$router.push(`/system/notification/${item.name}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,46 @@
|
||||||
|
<template>
|
||||||
|
<el-container>
|
||||||
|
<system-sidebar></system-sidebar>
|
||||||
|
<el-main>
|
||||||
|
<notification-tab></notification-tab>
|
||||||
|
<el-form ref="form" :model="form" label-width="100px" style="width: 700px;">
|
||||||
|
<el-form-item label="URL">
|
||||||
|
<el-input v-model="form.url"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="模板">
|
||||||
|
<el-input
|
||||||
|
type="textarea"
|
||||||
|
:rows="5"
|
||||||
|
placeholder=""
|
||||||
|
v-model="form.template">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="submit()">保存</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import systemSidebar from '../sidebar'
|
||||||
|
import notificationTab from './tab'
|
||||||
|
export default {
|
||||||
|
name: 'notification-webhook',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
form: {
|
||||||
|
url: '',
|
||||||
|
template: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {notificationTab, systemSidebar},
|
||||||
|
methods: {
|
||||||
|
submit () {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,82 @@
|
||||||
|
<template>
|
||||||
|
<el-container>
|
||||||
|
<task-sidebar></task-sidebar>
|
||||||
|
<el-main>
|
||||||
|
<el-form ref="form" :model="form" label-width="80px">
|
||||||
|
<el-form-item label="任务名称">
|
||||||
|
<el-input v-model="form.name"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="活动区域">
|
||||||
|
<el-select v-model="form.region" placeholder="请选择活动区域">
|
||||||
|
<el-option label="区域一" value="shanghai"></el-option>
|
||||||
|
<el-option label="区域二" value="beijing"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="活动时间">
|
||||||
|
<el-col :span="11">
|
||||||
|
<el-date-picker type="date" placeholder="选择日期" v-model="form.date1" style="width: 100%;"></el-date-picker>
|
||||||
|
</el-col>
|
||||||
|
<el-col class="line" :span="2">-</el-col>
|
||||||
|
<el-col :span="11">
|
||||||
|
<el-time-picker type="fixed-time" placeholder="选择时间" v-model="form.date2" style="width: 100%;"></el-time-picker>
|
||||||
|
</el-col>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="即时配送">
|
||||||
|
<el-switch v-model="form.delivery"></el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="活动性质">
|
||||||
|
<el-checkbox-group v-model="form.type">
|
||||||
|
<el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
|
||||||
|
<el-checkbox label="地推活动" name="type"></el-checkbox>
|
||||||
|
<el-checkbox label="线下主题活动" name="type"></el-checkbox>
|
||||||
|
<el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
|
||||||
|
</el-checkbox-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="特殊资源">
|
||||||
|
<el-radio-group v-model="form.resource">
|
||||||
|
<el-radio label="线上品牌商赞助"></el-radio>
|
||||||
|
<el-radio label="线下场地免费"></el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="活动形式">
|
||||||
|
<el-input type="textarea" v-model="form.desc"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="onSubmit">立即创建</el-button>
|
||||||
|
<el-button>取消</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'task-edit',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
form: {
|
||||||
|
id: '',
|
||||||
|
name: '',
|
||||||
|
tag: '',
|
||||||
|
level: 1,
|
||||||
|
dependency_status: 1,
|
||||||
|
dependency_task_id: '',
|
||||||
|
spec: '',
|
||||||
|
protocol: 2,
|
||||||
|
http_method: 1,
|
||||||
|
command: '',
|
||||||
|
host_id: '',
|
||||||
|
timeout: 0,
|
||||||
|
multi: 2,
|
||||||
|
notify_status: 1,
|
||||||
|
notify_type: 1,
|
||||||
|
notify_receive_id: '',
|
||||||
|
retry_times: 0,
|
||||||
|
retry_interval: 0,
|
||||||
|
remark: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -53,8 +53,14 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-button type="success" v-if="this.$store.getters.user.isAdmin">新增</el-button>
|
<el-row type="flex" justify="end">
|
||||||
<el-button type="info" @click="refresh">刷新</el-button> <br> <br>
|
<el-col :span="2">
|
||||||
|
<el-button type="primary" v-if="this.$store.getters.user.isAdmin">新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="2">
|
||||||
|
<el-button type="info" @click="refresh">刷新</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
<el-pagination
|
<el-pagination
|
||||||
background
|
background
|
||||||
layout="prev, pager, next, sizes, total"
|
layout="prev, pager, next, sizes, total"
|
||||||
|
|
|
@ -32,10 +32,14 @@
|
||||||
<el-button type="primary" @click="search">搜索</el-button>
|
<el-button type="primary" @click="search">搜索</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<p>
|
<el-row type="flex" justify="end">
|
||||||
|
<el-col :span="3">
|
||||||
<el-button type="danger" v-if="this.$store.getters.user.isAdmin" @click="clearLog">清空日志</el-button>
|
<el-button type="danger" v-if="this.$store.getters.user.isAdmin" @click="clearLog">清空日志</el-button>
|
||||||
<el-button type="info" @click="refresh">刷新</el-button> <br> <br>
|
</el-col>
|
||||||
</p>
|
<el-col :span="2">
|
||||||
|
<el-button type="info" @click="refresh">刷新</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
<el-pagination
|
<el-pagination
|
||||||
background
|
background
|
||||||
layout="prev, pager, next, sizes, total"
|
layout="prev, pager, next, sizes, total"
|
||||||
|
@ -72,7 +76,8 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="name"
|
prop="name"
|
||||||
label="任务名称">
|
label="任务名称"
|
||||||
|
width="180">
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="protocol"
|
prop="protocol"
|
||||||
|
|
|
@ -55,7 +55,6 @@ export default {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
save () {
|
save () {
|
||||||
console.log(this.form)
|
|
||||||
userService.editPassword(this.form, () => {
|
userService.editPassword(this.form, () => {
|
||||||
this.$router.push('/user')
|
this.$router.push('/user')
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<el-container>
|
<el-container>
|
||||||
<el-main>
|
<el-main>
|
||||||
<el-button type="success" @click="toEdit(null)">新增</el-button>
|
<el-row type="flex" justify="end">
|
||||||
<el-button type="info" @click="refresh">刷新</el-button> <br><br>
|
<el-col :span="2">
|
||||||
|
<el-button type="primary" @click="toEdit(null)">新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="2">
|
||||||
|
<el-button type="info" @click="refresh">刷新</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
<el-pagination
|
<el-pagination
|
||||||
background
|
background
|
||||||
layout="prev, pager, next, sizes, total"
|
layout="prev, pager, next, sizes, total"
|
||||||
|
|
Loading…
Reference in New Issue