Merge pull request #30 from linxiaozhi/master

通知模板添加执行命令/错误输出变量
This commit is contained in:
George Hao
2019-03-28 21:47:54 +08:00
committed by GitHub
13 changed files with 113 additions and 50 deletions

View File

@@ -60,6 +60,17 @@ V1.x版本是一个简单的定时任务管理系统进入V1.0 https://git
- 运行 go build - 运行 go build
- 运行 ./run.sh start|stop - 运行 ./run.sh start|stop
mac
- 运行 ./package.sh -a amd64 -p darwin -v v2.x.0
linux
- 运行 ./package.sh -a 386 -p linux -v v2.x.0
- 运行 ./package.sh -a amd64 -p linux -v v2.x.0
windows
- 运行 ./package.sh -a amd64 -p windows -v v2.x.0
方法二、直接使用 方法二、直接使用
linux linux
@@ -79,9 +90,8 @@ mac
windows windows
- 进入 https://github.com/george518/PPGo_Job/releases - 进入 https://github.com/george518/PPGo_Job/releases
- 下载 ppgo_job-linux-2.x.0.zip 并解压 - 下载 ppgo_job-windows-2.x.0.zip 并解压
- 进入文件夹,设置好数据库(创建数据库导入ppgo_job2.sql)和配置文件(conf/app.conf) - 进入文件夹,设置好数据库(创建数据库导入ppgo_job2.sql)和配置文件(conf/app.conf)
- 运行 go build
- 运行 run.bat - 运行 run.bat
---- ----

View File

@@ -59,7 +59,7 @@ func (self *NotifyTplController) AjaxSave() {
notifyTpl.Type = models.NotifyTplTypeDefault notifyTpl.Type = models.NotifyTplTypeDefault
notifyTpl.Status, _ = self.GetInt("status") notifyTpl.Status, _ = self.GetInt("status")
if notifyTpl.TplType == 1 || notifyTpl.TplType == 3 { if notifyTpl.TplType == 1 || notifyTpl.TplType == 2 || notifyTpl.TplType == 3 {
m := make(map[string]string) m := make(map[string]string)
err := json.Unmarshal([]byte(notifyTpl.Content), &m) err := json.Unmarshal([]byte(notifyTpl.Content), &m)
if err != nil { if err != nil {
@@ -85,7 +85,7 @@ func (self *NotifyTplController) AjaxSave() {
notifyTpl.Content = strings.TrimSpace(self.GetString("content")) notifyTpl.Content = strings.TrimSpace(self.GetString("content"))
notifyTpl.Status, _ = self.GetInt("status") notifyTpl.Status, _ = self.GetInt("status")
if notifyTpl.TplType == 1 || notifyTpl.TplType == 3 { if notifyTpl.TplType == 1 || notifyTpl.TplType == 2 || notifyTpl.TplType == 3 {
m := make(map[string]string) m := make(map[string]string)
err := json.Unmarshal([]byte(notifyTpl.Content), &m) err := json.Unmarshal([]byte(notifyTpl.Content), &m)
if err != nil { if err != nil {

View File

@@ -26,6 +26,7 @@ type ServerController struct {
func (self *ServerController) List() { func (self *ServerController) List() {
self.Data["pageTitle"] = "资源管理" self.Data["pageTitle"] = "资源管理"
self.Data["serverGroup"] = serverGroupLists(self.serverGroups, self.userId)
self.display() self.display()
} }
@@ -368,6 +369,9 @@ func (self *ServerController) Table() {
if err != nil { if err != nil {
limit = 30 limit = 30
} }
serverGroupId, err := self.GetInt("serverGroupId")
serverName := strings.TrimSpace(self.GetString("serverName")) serverName := strings.TrimSpace(self.GetString("serverName"))
StatusText := []string{ StatusText := []string{
"正常", "正常",
@@ -390,16 +394,28 @@ func (self *ServerController) Table() {
//查询条件 //查询条件
filters := make([]interface{}, 0) filters := make([]interface{}, 0)
filters = append(filters, "status", 0) filters = append(filters, "status", 0)
groupsIds := make([]int, 0)
if self.userId != 1 { if self.userId != 1 {
groups := strings.Split(self.serverGroups, ",") groups := strings.Split(self.serverGroups, ",")
groupsIds := make([]int, 0)
for _, v := range groups { for _, v := range groups {
id, _ := strconv.Atoi(v) id, _ := strconv.Atoi(v)
groupsIds = append(groupsIds, id) if serverGroupId > 0 {
if id == serverGroupId {
groupsIds = append(groupsIds, id)
break
}
} else {
groupsIds = append(groupsIds, id)
}
} }
filters = append(filters, "group_id__in", groupsIds) filters = append(filters, "group_id__in", groupsIds)
} else if serverGroupId > 0 {
groupsIds = append(groupsIds, serverGroupId)
filters = append(filters, "group_id__in", groupsIds)
} }
if serverName != "" { if serverName != "" {
filters = append(filters, "server_name__icontains", serverName) filters = append(filters, "server_name__icontains", serverName)
} }

View File

@@ -240,28 +240,24 @@ func RemoteCommandJobByTelnetPassword(id int, name string, command string, serve
defer conn.Close() defer conn.Close()
buf := make([]byte, 4096) buf := make([]byte, 4096)
_, err = conn.Read(buf)
if err != nil { if _, err = conn.Read(buf); err != nil {
return "", "", err, false return "", "", err, false
} }
_, err = conn.Write([]byte(servers.ServerAccount + "\r\n")) if _, err = conn.Write([]byte(servers.ServerAccount + "\r\n")); err != nil {
if err != nil {
return "", "", err, false return "", "", err, false
} }
_, err = conn.Read(buf) if _, err = conn.Read(buf); err != nil {
if err != nil {
return "", "", err, false return "", "", err, false
} }
_, err = conn.Write([]byte(servers.Password + "\r\n")) if _, err = conn.Write([]byte(servers.Password + "\r\n")); err != nil {
if err != nil {
return "", "", err, false return "", "", err, false
} }
_, err = conn.Read(buf) if _, err = conn.Read(buf); err != nil {
if err != nil {
return "", "", err, false return "", "", err, false
} }
@@ -392,7 +388,7 @@ func (j *Job) Run() {
status := log.Status + 2 status := log.Status + 2
title, content := "", "" title, content, taskOutput, errOutput := "", "", "", ""
notifyTpl, err := models.NotifyTplGetById(j.task.NotifyTplId) notifyTpl, err := models.NotifyTplGetById(j.task.NotifyTplId)
if err != nil { if err != nil {
@@ -406,22 +402,31 @@ func (j *Job) Run() {
content = notifyTpl.Content content = notifyTpl.Content
} }
taskOutput = strings.Replace(log.Output, "\n", " ", -1)
taskOutput = strings.Replace(taskOutput, "\"", "\\\"", -1)
errOutput = strings.Replace(log.Error, "\n", " ", -1)
errOutput = strings.Replace(errOutput, "\"", "\\\"", -1)
if title != "" { if title != "" {
title = strings.Replace(title, "{{TaskId}}", strconv.Itoa(j.task.Id), -1) title = strings.Replace(title, "{{TaskId}}", strconv.Itoa(j.task.Id), -1)
title = strings.Replace(title, "{{TaskName}}", j.task.TaskName, -1) title = strings.Replace(title, "{{TaskName}}", j.task.TaskName, -1)
title = strings.Replace(title, "{{ExecuteCommand}}", j.task.Command, -1)
title = strings.Replace(title, "{{ExecuteTime}}", beego.Date(time.Unix(log.CreateTime, 0), "Y-m-d H:i:s"), -1) title = strings.Replace(title, "{{ExecuteTime}}", beego.Date(time.Unix(log.CreateTime, 0), "Y-m-d H:i:s"), -1)
title = strings.Replace(title, "{{ProcessTime}}", strconv.FormatFloat(float64(log.ProcessTime)/1000, 'f', 6, 64), -1) title = strings.Replace(title, "{{ProcessTime}}", strconv.FormatFloat(float64(log.ProcessTime)/1000, 'f', 6, 64), -1)
title = strings.Replace(title, "{{ExecuteStatus}}", TextStatus[status], -1) title = strings.Replace(title, "{{ExecuteStatus}}", TextStatus[status], -1)
title = strings.Replace(title, "{{TaskOutput}}", log.Error, -1) title = strings.Replace(title, "{{TaskOutput}}", taskOutput, -1)
title = strings.Replace(title, "{{ErrorOutput}}", errOutput, -1)
} }
if content != "" { if content != "" {
content = strings.Replace(content, "{{TaskId}}", strconv.Itoa(j.task.Id), -1) content = strings.Replace(content, "{{TaskId}}", strconv.Itoa(j.task.Id), -1)
content = strings.Replace(content, "{{TaskName}}", j.task.TaskName, -1) content = strings.Replace(content, "{{TaskName}}", j.task.TaskName, -1)
content = strings.Replace(content, "{{ExecuteCommand}}", j.task.Command, -1)
content = strings.Replace(content, "{{ExecuteTime}}", beego.Date(time.Unix(log.CreateTime, 0), "Y-m-d H:i:s"), -1) content = strings.Replace(content, "{{ExecuteTime}}", beego.Date(time.Unix(log.CreateTime, 0), "Y-m-d H:i:s"), -1)
content = strings.Replace(content, "{{ProcessTime}}", strconv.FormatFloat(float64(log.ProcessTime)/1000, 'f', 6, 64), -1) content = strings.Replace(content, "{{ProcessTime}}", strconv.FormatFloat(float64(log.ProcessTime)/1000, 'f', 6, 64), -1)
content = strings.Replace(content, "{{ExecuteStatus}}", TextStatus[status], -1) content = strings.Replace(content, "{{ExecuteStatus}}", TextStatus[status], -1)
content = strings.Replace(content, "{{TaskOutput}}", log.Error, -1) content = strings.Replace(content, "{{TaskOutput}}", taskOutput, -1)
content = strings.Replace(content, "{{ErrorOutput}}", errOutput, -1)
} }
if j.task.NotifyType == 0 && toEmail != "" { if j.task.NotifyType == 0 && toEmail != "" {
@@ -446,12 +451,20 @@ func (j *Job) Run() {
} }
} else if j.task.NotifyType == 2 && len(dingtalk) > 0 { } else if j.task.NotifyType == 2 && len(dingtalk) > 0 {
//钉钉 //钉钉
ok := notify.SendDingtalkToChan(dingtalk, content) param := make(map[string]interface{})
err := json.Unmarshal([]byte(content), &param)
if err != nil {
fmt.Println("发送钉钉错误", err)
return
}
ok := notify.SendDingtalkToChan(dingtalk, param)
if !ok { if !ok {
fmt.Println("发送钉钉错误", dingtalk) fmt.Println("发送钉钉错误", dingtalk)
} }
} else if j.task.NotifyType == 3 && len(wechat) > 0 { } else if j.task.NotifyType == 3 && len(wechat) > 0 {
//信 //
param := make(map[string]string) param := make(map[string]string)
err := json.Unmarshal([]byte(content), &param) err := json.Unmarshal([]byte(content), &param)
if err != nil { if err != nil {

View File

@@ -17,18 +17,9 @@ import (
"bytes" "bytes"
) )
type Msg struct {
MsgType string `json:"msgtype"`
Text *Text `json:"text"`
}
type Text struct {
Content string `json:"content"`
}
type Dingtalk struct { type Dingtalk struct {
Dingtalks map[string]string Dingtalks map[string]string
Content string Content map[string]interface{}
} }
var DingtalkChan chan *Dingtalk var DingtalkChan chan *Dingtalk
@@ -57,7 +48,7 @@ func init() {
} }
func SendDingtalkToChan(dingtalks map[string]string, content string) bool { func SendDingtalkToChan(dingtalks map[string]string, content map[string]interface{}) bool {
dingTalk := &Dingtalk{ dingTalk := &Dingtalk{
Dingtalks: dingtalks, Dingtalks: dingtalks,
Content: content, Content: content,
@@ -74,13 +65,7 @@ func SendDingtalkToChan(dingtalks map[string]string, content string) bool {
func (s *Dingtalk) SendDingtalk() error { func (s *Dingtalk) SendDingtalk() error {
for _, v := range s.Dingtalks { for _, v := range s.Dingtalks {
body, err := json.Marshal(s.Content)
msg := Msg{MsgType: "text"}
text := new(Text)
text.Content = s.Content
msg.Text = text
body, err := json.Marshal(msg)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
return err return err

View File

@@ -43,6 +43,13 @@ SUPPORT_ARCH=(386 amd64)
LDFLAGS='' LDFLAGS=''
# 需要打包的文件 # 需要打包的文件
INCLUDE_FILE=() INCLUDE_FILE=()
# linux需要打包的文件
INCLUDE_LINUX_FILE=()
# darwin需要打包的文件
INCLUDE_DARWIN_FILE=()
# windows需要打包的文件
INCLUDE_WINDOWS_FILE=()
# 打包文件生成目录 # 打包文件生成目录
PACKAGE_DIR='' PACKAGE_DIR=''
# 编译文件生成目录 # 编译文件生成目录
@@ -164,6 +171,22 @@ package_file() {
for item in "${INCLUDE_FILE[@]}"; do for item in "${INCLUDE_FILE[@]}"; do
cp -r ../${item} $1 cp -r ../${item} $1
done done
for OS in "${INPUT_OS[@]}";do
if [[ "${OS}" = "linux" ]];then
for item in "${INCLUDE_LINUX_FILE[@]}"; do
cp -r ../${item} $1
done
elif [[ "${OS}" = "darwin" ]];then
for item in "${INCLUDE_DARWIN_FILE[@]}"; do
cp -r ../${item} $1
done
elif [[ "${OS}" = "windows" ]];then
for item in "${INCLUDE_WINDOWS_FILE[@]}"; do
cp -r ../${item} $1
done
fi
done
} }
# 清理 # 清理
@@ -184,7 +207,10 @@ run() {
package_ppgo_job() { package_ppgo_job() {
BINARY_NAME='PPGo_Job' BINARY_NAME='PPGo_Job'
MAIN_FILE="./main.go" MAIN_FILE="./main.go"
INCLUDE_FILE=("conf" "static" "views" "ppgo_job2.sql" "run.sh" "run.bat") INCLUDE_FILE=("conf" "static" "views" "ppgo_job2.sql")
INCLUDE_LINUX_FILE=("run.sh")
INCLUDE_DARWIN_FILE=("run.sh")
INCLUDE_WINDOWS_FILE=("run.bat")
run run
} }

View File

@@ -312,10 +312,10 @@ CREATE TABLE `pp_notify_tpl` (
-- 转存表中的数据 `pp_notify_tpl` -- 转存表中的数据 `pp_notify_tpl`
-- --
BEGIN; BEGIN;
INSERT INTO `pp_notify_tpl` VALUES(1, 'system', '默认邮箱通知模板', 0, '定时任务异常:{{TaskName}}', 'Hello,定时任务出问题了:\r\n<p style=\"font-size:16px;\">任务执行详情:</p>\r\n<p style=\"display:block; padding:10px; background:#efefef;border:1px solid #e4e4e4\">\r\n任务 ID{{TaskId}}<br/>\r\n任务名称{{TaskName}}<br/>\r\n执行时间{{ExecuteTime}}<br/>\r\n执行耗时{{ProcessTime}}秒<br/>\r\n执行状态{{ExecuteStatus}}\r\n</p>\r\n<p style=\"font-size:16px;\">任务执行输出</p>\r\n<p style=\"display:block; padding:10px; background:#efefef;border:1px solid #e4e4e4\">\r\n{{TaskOutput}}\r\n</p>', 1, 1550255030, 1, 1550338305, 1); INSERT INTO `pp_notify_tpl` VALUES(1, 'system', '默认邮箱通知模板', 0, '定时任务异常:{{TaskName}}', 'Hello,定时任务出问题了:\r\n<p style=\"font-size:16px;\">任务执行详情:</p>\r\n<p style=\"display:block; padding:10px; background:#efefef;border:1px solid #e4e4e4\">\r\n任务 ID{{TaskId}}<br/>\r\n任务名称{{TaskName}}<br/>\r\n执行命令:{{ExecuteCommand}}<br/>\r\n执行时间:{{ExecuteTime}}<br/>\r\n执行耗时{{ProcessTime}}秒<br/>\r\n执行状态{{ExecuteStatus}}\r\n</p>\r\n<p style=\"font-size:16px;\">任务执行输出</p>\r\n<p style=\"display:block; padding:10px; background:#efefef;border:1px solid #e4e4e4\">\r\n{{TaskOutput}}\r\n</p>\r\n<p style=\"font-size:16px;\">错误输出</p>\r\n<p style=\"display:block; padding:10px; background:#efefef;border:1px solid #e4e4e4\">\r\n{{ErrorOutput}}\r\n</p>', 1, 1550255030, 1, 1553282382, 1);
INSERT INTO `pp_notify_tpl` VALUES(2, 'system', '默认短信通知模板', 1, '', '{\r\n \"task_id\": \"{{TaskId}}\",\r\n \"task_name\": \"{{TaskName}}\",\r\n \"execute_status\": \"{{ExecuteStatus}}\"\r\n}', 1, 1550255030, 1, 1550338215, 1); INSERT INTO `pp_notify_tpl` VALUES(2, 'system', '默认短信通知模板', 1, '', '{\r\n \"task_id\": \"{{TaskId}}\",\r\n \"task_name\": \"{{TaskName}}\",\r\n \"execute_command\": \"{{ExecuteCommand}}\",\r\n \"execute_status\": \"{{ExecuteStatus}}\"\r\n}', 1, 1550255030, 1, 1550338215, 1);
INSERT INTO `pp_notify_tpl` VALUES(3, 'system', '默认钉钉通知模板', 2, '', '任务执行异常详情:\r\n任务 ID{{TaskId}}\r\n任务名称{{TaskName}}\r\n执行时间{{ExecuteTime}}\r\n执行耗时{{ProcessTime}}秒\r\n执行状态{{ExecuteStatus}}\r\n任务执行输出\r\n{{TaskOutput}}', 1, 1550255030, 1, 1550338880, 1); INSERT INTO `pp_notify_tpl` VALUES(3, 'system', '默认钉钉通知模板', 2, '', '{\r\n \"msgtype\": \"text\",\r\n \"text\": {\r\n \"content\": \"任务执行异常详情:\\n任务 ID{{TaskId}}\\n任务名称{{TaskName}}\\n执行命令{{ExecuteCommand}}\\n执行时间{{ExecuteTime}}\\n执行耗时{{ProcessTime}}秒\\n执行状态{{ExecuteStatus}}\\n任务执行输出\\n{{TaskOutput}}\\n错误输出\\n{{ErrorOutput}}\"\r\n }\r\n}', 1, 1550255030, 1, 1553282245, 1);
INSERT INTO `pp_notify_tpl` VALUES(4, 'system', '默认微信通知模板', 3, '', '{\r\n \"task_id\": \"{{TaskId}}\",\r\n \"task_name\": \"{{TaskName}}\",\r\n \"execute_status\": \"{{ExecuteStatus}}\"\r\n}', 1, 1550347183, 1, 1550347201, 1); INSERT INTO `pp_notify_tpl` VALUES(4, 'system', '默认微信通知模板', 3, '', '{\r\n \"task_id\": \"{{TaskId}}\",\r\n \"task_name\": \"{{TaskName}}\",\r\n \"execute_command\": \"{{ExecuteCommand}}\",\r\n \"execute_status\": \"{{ExecuteStatus}}\"\r\n}', 1, 1550347183, 1, 1550347201, 1);
COMMIT; COMMIT;
BEGIN; BEGIN;

View File

@@ -40,14 +40,14 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">钉钉通知</label> <label class="layui-form-label">钉钉通知</label>
<div class="layui-input-inline"> <div class="layui-input-inline">
<input type="text" name="dingtalk" id="dingtalk" autocomplete="off" placeholder="钉钉通知" class="layui-input" value=""> <input type="text" name="dingtalk" id="dingtalk" autocomplete="off" placeholder="钉钉access_token" class="layui-input" value="">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">微信帐号</label> <label class="layui-form-label">微信帐号</label>
<div class="layui-input-inline"> <div class="layui-input-inline">
<input type="text" name="wechat" id="wechat" autocomplete="off" placeholder="微信帐号" class="layui-input" value=""> <input type="text" name="wechat" id="wechat" autocomplete="off" placeholder="微信openid" class="layui-input" value="">
</div> </div>
</div> </div>

View File

@@ -35,14 +35,14 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">钉钉通知</label> <label class="layui-form-label">钉钉通知</label>
<div class="layui-input-inline"> <div class="layui-input-inline">
<input type="text" name="dingtalk" id="dingtalk" autocomplete="off" placeholder="钉钉通知" class="layui-input" value="{{.admin.dingtalk}}"> <input type="text" name="dingtalk" id="dingtalk" autocomplete="off" placeholder="钉钉access_token" class="layui-input" value="{{.admin.dingtalk}}">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">微信帐号</label> <label class="layui-form-label">微信帐号</label>
<div class="layui-input-inline"> <div class="layui-input-inline">
<input type="text" name="wechat" id="wechat" autocomplete="off" placeholder="微信帐号" class="layui-input" value="{{.admin.wechat}}"> <input type="text" name="wechat" id="wechat" autocomplete="off" placeholder="微信openid" class="layui-input" value="{{.admin.wechat}}">
</div> </div>
</div> </div>

View File

@@ -41,10 +41,12 @@
{{"任务 ID {{TaskId}}"}} {{"任务 ID {{TaskId}}"}}
{{"任务名称 {{TaskName}}"}} {{"任务名称 {{TaskName}}"}}
{{"执行命令 {{ExecuteCommand}}"}}
{{"执行时间 {{ExecuteTime}}"}} {{"执行时间 {{ExecuteTime}}"}}
{{"执行耗时 {{ProcessTime}}"}} {{"执行耗时 {{ProcessTime}}"}}
{{"执行状态 {{ExecuteStatus}}"}} {{"执行状态 {{ExecuteStatus}}"}}
{{"任务输出 {{TaskOutput}}"}} {{"任务输出 {{TaskOutput}}"}}
{{"错误输出 {{ErrorOutput}}"}}
</pre> </pre>
</div> </div>

View File

@@ -42,10 +42,12 @@
{{"任务 ID {{TaskId}}"}} {{"任务 ID {{TaskId}}"}}
{{"任务名称 {{TaskName}}"}} {{"任务名称 {{TaskName}}"}}
{{"执行命令 {{ExecuteCommand}}"}}
{{"执行时间 {{ExecuteTime}}"}} {{"执行时间 {{ExecuteTime}}"}}
{{"执行耗时 {{ProcessTime}}"}} {{"执行耗时 {{ProcessTime}}"}}
{{"执行状态 {{ExecuteStatus}}"}} {{"执行状态 {{ExecuteStatus}}"}}
{{"任务输出 {{TaskOutput}}"}} {{"任务输出 {{TaskOutput}}"}}
{{"错误输出 {{ErrorOutput}}"}}
</pre> </pre>
</div> </div>

View File

@@ -9,6 +9,14 @@
<div class="layui-inline" style="width: 40%"> <div class="layui-inline" style="width: 40%">
<input class="layui-input" name="serverName" id="serverName" autocomplete="off" placeholder="资源名称" > <input class="layui-input" name="serverName" id="serverName" autocomplete="off" placeholder="资源名称" >
</div> </div>
<div class="layui-inline" style="width: 20%;text-align: left;">
<select name="serverGroupId" id="serverGroupId">
<option value="0">全部</option>
{{range $k, $v := .serverGroup}}
<option value="{{$k}}">{{$v}}</option>
{{end}}
</select>
</div>
<button class="layui-btn" data-type="reload">查询</button> <button class="layui-btn" data-type="reload">查询</button>
</div> </div>
</form> </form>
@@ -64,6 +72,7 @@
table.reload('listReload', { table.reload('listReload', {
where: { where: {
serverName: $('#serverName').val(), serverName: $('#serverName').val(),
serverGroupId:$('#serverGroupId').val(),
} }
}); });
} }

View File

@@ -36,14 +36,14 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">钉钉通知</label> <label class="layui-form-label">钉钉通知</label>
<div class="layui-input-inline"> <div class="layui-input-inline">
<input type="text" name="dingtalk" id="dingtalk" autocomplete="off" placeholder="钉钉通知" class="layui-input" value="{{.admin.dingtalk}}"> <input type="text" name="dingtalk" id="dingtalk" autocomplete="off" placeholder="钉钉access_token" class="layui-input" value="{{.admin.dingtalk}}">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">微信帐号</label> <label class="layui-form-label">微信帐号</label>
<div class="layui-input-inline"> <div class="layui-input-inline">
<input type="text" name="wechat" id="wechat" autocomplete="off" placeholder="微信帐号" class="layui-input" value="{{.admin.wechat}}"> <input type="text" name="wechat" id="wechat" autocomplete="off" placeholder="微信openid" class="layui-input" value="{{.admin.wechat}}">
</div> </div>
</div> </div>