Browse Source

更新插件仓库

main
蒋吉兆 3 years ago
parent
commit
b8a29fee4e
  1. 2
      README.md
  2. 154
      server/docs/docs.go
  3. 154
      server/docs/swagger.json
  4. 95
      server/docs/swagger.yaml
  5. 4
      server/go.mod
  6. 9
      server/initialize/plugin.go
  7. 74
      server/plugin/notify/README.MD
  8. 67
      server/plugin/notify/api/api.go
  9. 7
      server/plugin/notify/api/enter.go
  10. 7
      server/plugin/notify/config/dingding.go
  11. 5
      server/plugin/notify/global/global.go
  12. 28
      server/plugin/notify/main.go
  13. 21
      server/plugin/notify/model/response/notify.go
  14. 7
      server/plugin/notify/router/enter.go
  15. 18
      server/plugin/notify/router/router.go
  16. 7
      server/plugin/notify/service/enter.go
  17. 157
      server/plugin/notify/service/notify.go
  18. 1
      server/plugin/notify/utils/utils.go
  19. 2
      web/.env.development
  20. 160
      web/package-lock.json

2
README.md

@ -16,7 +16,7 @@
[github地址](https://github.com/flipped-aurora/gin-vue-admin): https://github.com/flipped-aurora/gin-vue-admin
[vue3版本分支地址](https://github.com/flipped-aurora/gin-vue-admin/tree/vue3Develop): https://github.com/flipped-aurora/gin-vue-admin/tree/vue3Develop
[插件仓库以及开发规范](https://github.com/flipped-aurora/gva-plugins):https://github.com/flipped-aurora/gva-plugins
[审批流分支](https://github.com/flipped-aurora/gin-vue-admin/tree/gva_workflow): https://github.com/flipped-aurora/gin-vue-admin/tree/gva_workflow

154
server/docs/docs.go

@ -24,108 +24,6 @@ var doc = `{
"host": "{{.Host}}",
"basePath": "{{.BasePath}}",
"paths": {
"/SimpleUploaderApi/checkFileMd5": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"produces": [
"application/json"
],
"tags": [
"SimpleUploader"
],
"summary": "断点续传插件版示例",
"parameters": [
{
"type": "string",
"description": "md5",
"name": "md5",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "{\"success\":true,\"data\":{},\"msg\":\"查询成功\"}",
"schema": {
"type": "string"
}
}
}
}
},
"/SimpleUploaderApi/mergeFileMd5": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"produces": [
"application/json"
],
"tags": [
"SimpleUploader"
],
"summary": "合并文件",
"parameters": [
{
"type": "string",
"description": "md5",
"name": "md5",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "{\"success\":true,\"data\":{},\"msg\":\"合并成功\"}",
"schema": {
"type": "string"
}
}
}
}
},
"/SimpleUploaderApi/upload": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"tags": [
"SimpleUploader"
],
"summary": "断点续传插件版示例",
"parameters": [
{
"type": "file",
"description": "断点续传插件版示例",
"name": "file",
"in": "formData",
"required": true
}
],
"responses": {
"200": {
"description": "{\"success\":true,\"data\":{},\"msg\":\"切片创建成功\"}",
"schema": {
"type": "string"
}
}
}
}
},
"/api/createApi": {
"post": {
"security": [
@ -1527,6 +1425,41 @@ var doc = `{
}
}
},
"/email/sendEmail": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"produces": [
"application/json"
],
"tags": [
"System"
],
"summary": "发送邮件",
"parameters": [
{
"description": "发送邮件必须的参数",
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/response.Email"
}
}
],
"responses": {
"200": {
"description": "{\"success\":true,\"data\":{},\"msg\":\"发送成功\"}",
"schema": {
"type": "string"
}
}
}
}
},
"/excel/downloadTemplate": {
"get": {
"security": [
@ -4376,6 +4309,23 @@ var doc = `{
}
}
},
"response.Email": {
"type": "object",
"properties": {
"body": {
"description": "邮件内容",
"type": "string"
},
"subject": {
"description": "邮件标题",
"type": "string"
},
"to": {
"description": "邮件发送给谁",
"type": "string"
}
}
},
"response.SysAuthorityCopyResponse": {
"type": "object",
"properties": {

154
server/docs/swagger.json

@ -8,108 +8,6 @@
},
"basePath": "/",
"paths": {
"/SimpleUploaderApi/checkFileMd5": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"produces": [
"application/json"
],
"tags": [
"SimpleUploader"
],
"summary": "断点续传插件版示例",
"parameters": [
{
"type": "string",
"description": "md5",
"name": "md5",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "{\"success\":true,\"data\":{},\"msg\":\"查询成功\"}",
"schema": {
"type": "string"
}
}
}
}
},
"/SimpleUploaderApi/mergeFileMd5": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"produces": [
"application/json"
],
"tags": [
"SimpleUploader"
],
"summary": "合并文件",
"parameters": [
{
"type": "string",
"description": "md5",
"name": "md5",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "{\"success\":true,\"data\":{},\"msg\":\"合并成功\"}",
"schema": {
"type": "string"
}
}
}
}
},
"/SimpleUploaderApi/upload": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"tags": [
"SimpleUploader"
],
"summary": "断点续传插件版示例",
"parameters": [
{
"type": "file",
"description": "断点续传插件版示例",
"name": "file",
"in": "formData",
"required": true
}
],
"responses": {
"200": {
"description": "{\"success\":true,\"data\":{},\"msg\":\"切片创建成功\"}",
"schema": {
"type": "string"
}
}
}
}
},
"/api/createApi": {
"post": {
"security": [
@ -1511,6 +1409,41 @@
}
}
},
"/email/sendEmail": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"produces": [
"application/json"
],
"tags": [
"System"
],
"summary": "发送邮件",
"parameters": [
{
"description": "发送邮件必须的参数",
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/response.Email"
}
}
],
"responses": {
"200": {
"description": "{\"success\":true,\"data\":{},\"msg\":\"发送成功\"}",
"schema": {
"type": "string"
}
}
}
}
},
"/excel/downloadTemplate": {
"get": {
"security": [
@ -4360,6 +4293,23 @@
}
}
},
"response.Email": {
"type": "object",
"properties": {
"body": {
"description": "邮件内容",
"type": "string"
},
"subject": {
"description": "邮件标题",
"type": "string"
},
"to": {
"description": "邮件发送给谁",
"type": "string"
}
}
},
"response.SysAuthorityCopyResponse": {
"type": "object",
"properties": {

95
server/docs/swagger.yaml

@ -567,6 +567,18 @@ definitions:
description: 每页大小
type: integer
type: object
response.Email:
properties:
body:
description: 邮件内容
type: string
subject:
description: 邮件标题
type: string
to:
description: 邮件发送给谁
type: string
type: object
response.SysAuthorityCopyResponse:
properties:
authority:
@ -930,68 +942,6 @@ info:
title: Swagger Example API
version: 0.0.1
paths:
/SimpleUploaderApi/checkFileMd5:
get:
parameters:
- description: md5
in: query
name: md5
required: true
type: string
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"查询成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 断点续传插件版示例
tags:
- SimpleUploader
/SimpleUploaderApi/mergeFileMd5:
get:
parameters:
- description: md5
in: query
name: md5
required: true
type: string
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"合并成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 合并文件
tags:
- SimpleUploader
/SimpleUploaderApi/upload:
post:
consumes:
- multipart/form-data
parameters:
- description: 断点续传插件版示例
in: formData
name: file
required: true
type: file
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"切片创建成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 断点续传插件版示例
tags:
- SimpleUploader
/api/createApi:
post:
consumes:
@ -1844,6 +1794,27 @@ paths:
summary: 发送测试邮件
tags:
- System
/email/sendEmail:
post:
parameters:
- description: 发送邮件必须的参数
in: body
name: data
required: true
schema:
$ref: '#/definitions/response.Email'
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"发送成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 发送邮件
tags:
- System
/excel/downloadTemplate:
get:
consumes:

4
server/go.mod

@ -3,12 +3,13 @@ module github.com/flipped-aurora/gin-vue-admin/server
go 1.16
require (
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
github.com/aliyun/aliyun-oss-go-sdk v2.1.6+incompatible
github.com/casbin/casbin/v2 v2.11.0
github.com/casbin/gorm-adapter/v3 v3.0.2
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/flipped-aurora/gva-plugins v0.0.0-20210828050649-287731daeddb
github.com/flipped-aurora/gva-plugins v0.0.0-20210828060501-fc8b729b9a4a // indirect
github.com/fsnotify/fsnotify v1.4.9
github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6
github.com/gin-gonic/gin v1.6.3
@ -17,6 +18,7 @@ require (
github.com/gookit/color v1.3.1
github.com/jordan-wright/email v0.0.0-20200824153738-3f5bafa1cd84
github.com/lestrrat-go/file-rotatelogs v2.3.0+incompatible
github.com/lestrrat-go/strftime v1.0.5 // indirect
github.com/mojocn/base64Captcha v1.3.1
github.com/qiniu/api.v7/v7 v7.4.1
github.com/robfig/cron/v3 v3.0.1

9
server/initialize/plugin.go

@ -2,7 +2,6 @@ package initialize
import (
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/notify"
email "github.com/flipped-aurora/gva-plugins/email" // 在线仓库模式go
//"github.com/flipped-aurora/gin-vue-admin/server/plugin/email" // 本地插件仓库地址模式
"github.com/flipped-aurora/gin-vue-admin/server/plugin/example_plugin"
@ -19,7 +18,8 @@ func PluginInit(group *gin.RouterGroup, Plugin ...plugin.Plugin) {
func InstallPlugin(PublicGroup *gin.RouterGroup, PrivateGroup *gin.RouterGroup) {
// 添加开放权限的插件 示例
PluginInit(PublicGroup, example_plugin.ExamplePlugin)
PluginInit(PublicGroup,
example_plugin.ExamplePlugin)
// 添加跟角色挂钩权限的插件 示例 本地示例模式于在线仓库模式注意上方的import 可以自行切换 效果相同
PluginInit(PrivateGroup, email.CreateEmailPlug(
@ -32,9 +32,4 @@ func InstallPlugin(PublicGroup *gin.RouterGroup, PrivateGroup *gin.RouterGroup)
global.GVA_CONFIG.Email.IsSSL,
))
// 钉钉通知,暂时开放权限
PluginInit(PublicGroup, notify.CreateDDPlug(
"https://oapi.dingtalk.com/robot/send",
"8ded23f91917dc4f6275f44ba5ef243e6ed1d2cc74de83f01a6f5f5f39905671",
"SECaecf452bd6e671ab0d47469c3ad933e32fcc47b335333049a1b8961606192f38"))
}

74
server/plugin/notify/README.MD

@ -1,74 +0,0 @@
## GVA 钉钉群通知插件
本插件用于向钉钉群推送消息
### 1. 使用场景
- 当服务运行异常时,可以向钉钉推送异常信息,便于及时发现解决问题
- 推送一些关键业务的运行日志等
### 2. 配置说明
钉钉 token 等相关信息的获取,请参考 [钉钉官网](https://developers.dingtalk.com/document/robots/custom-robot-access?spm=ding_open_doc.document.0.0.7f8710afbfzduV#topic-2026027)
在`plugin/notify/global/global.go` 文件中配置钉钉通知的URL ,Token 等
```go
// 在gin-vue-admin 主程序的initialize中的plugin的InstallPlugin 函数中写入如下代码
PluginInit(PublicGroup, notify.CreateDDPlug(
URL,
Token,
密钥))
}
```
### 3 参数说明
#### 3-1 全局参数说明
```go
Url string `mapstructure:"url" json:"url" yaml:"url"` // Url
Token string `mapstructure:"token" json:"token" yaml:"token"` // access_token
Secret string `mapstructure:"secret" json:"secret" yaml:"secret"` // 密钥
```
#### 3-2 请求入参说明
```go
```
### 3方法API(可调用方法)
```go
//content 发送的内容
//atMobiles 需要艾特的人的手机号
//isAtAll 是否艾特全体
SendTextMessage(content string,atMobiles []string,isAtAll bool)
//content 发送的内容
//title 内容标题
//picUrl 配图
//messageUrl 点击跳转路径
SendLinkMessage(content,title,picUrl,messageUrl string)
//content 发送的内容(markdown语法)
//title 内容标题
//atMobiles 需要艾特的人的手机号
//isAtAll 是否艾特全体
SendMarkdownMessage(content,title string,atMobiles []string,isAtAll bool)
```
### 4. 可直接调用接口
发送文字消息接口: /notify/sendTextMessage [post] 已配置swagger
发送图文链接消息接口: /notify/sendLinkMessage [post] 已配置swagger
发送markdown消息接口: /notify/sendMarkdownMessage [post] 已配置swagger
入参:
type Email struct {
To string `json:"to"` // 邮件发送给谁
Subject string `json:"subject"` // 邮件标题
Body string `json:"body"` // 邮件内容
}

67
server/plugin/notify/api/api.go

@ -1,67 +0,0 @@
package api
import (
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
notify_response "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/model/response"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/service"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
type Api struct {
}
// @Tags Notify
// @Summary 发送文字消息接口
// @Security ApiKeyAuth
// @Produce application/json
// @Param data body notify_response.TextNotify true "发送文字消息的参数"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"发送成功"}"
// @Router /notify/sendTextMessage [post]
func (s *Api) SendTextMessage(c *gin.Context) {
var textNotify notify_response.TextNotify
_ = c.ShouldBindJSON(&textNotify)
if err := service.ServiceGroupApp.SendTextMessage(textNotify.Content, textNotify.AtMobiles, textNotify.IsAtAll); err != nil {
global.GVA_LOG.Error("发送失败!", zap.Any("err", err))
response.FailWithMessage("发送失败", c)
} else {
response.OkWithData("发送成功", c)
}
}
// @Tags Notify
// @Summary 发送图文链接消息接口
// @Security ApiKeyAuth
// @Produce application/json
// @Param data body notify_response.LinkNotify true "发送图文链接消息的参数"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"发送成功"}"
// @Router /notify/sendLinkMessage [post]
func (s *Api) SendLinkMessage(c *gin.Context) {
var linkNotify notify_response.LinkNotify
_ = c.ShouldBindJSON(&linkNotify)
if err := service.ServiceGroupApp.SendLinkMessage(linkNotify.Content, linkNotify.Title, linkNotify.PicUrl, linkNotify.MessageUrl); err != nil {
global.GVA_LOG.Error("发送失败!", zap.Any("err", err))
response.FailWithMessage("发送失败", c)
} else {
response.OkWithData("发送成功", c)
}
}
// @Tags Notify
// @Summary 发送markdown消息接口
// @Security ApiKeyAuth
// @Produce application/json
// @Param data body notify_response.MarkdownNotify true "发送markdown消息的参数"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"发送成功"}"
// @Router /notify/sendMarkdownMessage [post]
func (s *Api) SendMarkdownMessage(c *gin.Context) {
var markdownNotify notify_response.MarkdownNotify
_ = c.ShouldBindJSON(&markdownNotify)
if err := service.ServiceGroupApp.SendMarkdownMessage(markdownNotify.Content, markdownNotify.Title, markdownNotify.AtMobiles, markdownNotify.IsAtAll); err != nil {
global.GVA_LOG.Error("发送失败!", zap.Any("err", err))
response.FailWithMessage("发送失败", c)
} else {
response.OkWithData("发送成功", c)
}
}

7
server/plugin/notify/api/enter.go

@ -1,7 +0,0 @@
package api
type ApiGroup struct {
Api
}
var ApiGroupApp = new(ApiGroup)

7
server/plugin/notify/config/dingding.go

@ -1,7 +0,0 @@
package config
type DingDing struct {
Url string `mapstructure:"url" json:"url" yaml:"url"` // Url
Token string `mapstructure:"token" json:"token" yaml:"token"` // access_token
Secret string `mapstructure:"secret" json:"secret" yaml:"secret"` // 密钥
}

5
server/plugin/notify/global/global.go

@ -1,5 +0,0 @@
package global
import "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/config"
var GlobalConfig_ = &config.DingDing{}

28
server/plugin/notify/main.go

@ -1,28 +0,0 @@
package notify
import (
"github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/global"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/router"
"github.com/gin-gonic/gin"
)
type ddPlugin struct {
Secret string
Token string
Url string
}
func CreateDDPlug(url, Token, Secret string) *ddPlugin {
global.GlobalConfig_.Url = url
global.GlobalConfig_.Token = Token
global.GlobalConfig_.Secret = Secret
return &ddPlugin{}
}
func (*ddPlugin) Register(group *gin.RouterGroup) {
router.RouterGroupApp.InitRouter(group)
}
func (*ddPlugin) RouterPath() string {
return "notify"
}

21
server/plugin/notify/model/response/notify.go

@ -1,21 +0,0 @@
package response
type TextNotify struct { // 文字信息
Content string `json:"content"` // 发送的内容
AtMobiles []string `json:"atMobiles"` // 需要艾特的人的手机号
IsAtAll bool `json:"isAtAll"` // 是否艾特全体
}
type LinkNotify struct { // 图文链接信息
Content string `json:"content"` // 发送的内容
Title string `json:"title"` // 内容标题
PicUrl string `json:"picUrl"` // 配图
MessageUrl string `json:"messageUrl"` // 点击跳转路径
}
type MarkdownNotify struct { // markdown信息
Title string `json:"title"` // 内容标题
Content string `json:"content"` // 发送的内容
AtMobiles []string `json:"atMobiles"` // 需要艾特的人的手机号
IsAtAll bool `json:"isAtAll"` // 是否艾特全体
}

7
server/plugin/notify/router/enter.go

@ -1,7 +0,0 @@
package router
type RouterGroup struct {
NotifyRouter
}
var RouterGroupApp = new(RouterGroup)

18
server/plugin/notify/router/router.go

@ -1,18 +0,0 @@
package router
import (
"github.com/flipped-aurora/gin-vue-admin/server/middleware"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/api"
"github.com/gin-gonic/gin"
)
type NotifyRouter struct {
}
func (s *NotifyRouter) InitRouter(Router *gin.RouterGroup) {
router := Router.Use(middleware.OperationRecord())
var SendTextMessage = api.ApiGroupApp.Api.SendTextMessage
{
router.POST("sendTextMessage", SendTextMessage)
}
}

7
server/plugin/notify/service/enter.go

@ -1,7 +0,0 @@
package service
type ServiceGroup struct {
NotifyService
}
var ServiceGroupApp = new(ServiceGroup)

157
server/plugin/notify/service/notify.go

@ -1,157 +0,0 @@
package service
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"fmt"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/global"
"io/ioutil"
"net/http"
"net/url"
"time"
)
type NotifyService struct {
}
//@author: [Espoir](https://github.com/nightsimon)
//@function: SendTextMessage
//@description: 发送钉钉文字信息
//@params content string发送的文字内容
//@params atMobiles []string 艾特的手机号
//@params isAtAll bool 是否艾特全体
//@return: err error
func (e *NotifyService) SendTextMessage(content string, atMobiles []string, isAtAll bool) (err error) {
msg := map[string]interface{}{
"msgtype": "text",
"text": map[string]string{
"content": content,
},
"at": map[string]interface{}{
"atMobiles": atMobiles,
"isAtAll": isAtAll,
},
}
return SendMessage(msg)
}
//@author: [Espoir](https://github.com/nightsimon)
//@function: SendLinkMessage
//@description: 发送钉钉图文链接信息
//@params content string 发送的文字内容
//@params title string 发送的标题
//@params picUrl string 艾特的手机号
//@params messageUrl string 是否艾特全体
//@return: err error
func (e *NotifyService) SendLinkMessage(content, title, picUrl, messageUrl string) (err error) {
msg := map[string]interface{}{
"msgtype": "link",
"link": map[string]string{
"text": content,
"title": title,
"picUrl": picUrl,
"messageUrl": messageUrl,
},
}
return SendMessage(msg)
}
//@author: [Espoir](https://github.com/nightsimon)
//@function: SendMarkdownMessage
//@description: 发送钉钉Markdown信息
//@params content 发送的文字内容
//@params title 发送的标题
//@params atMobiles []string 艾特的手机号
//@params isAtAll bool 是否艾特全体
//@return: err error
func (e *NotifyService) SendMarkdownMessage(content, title string, atMobiles []string, isAtAll bool) (err error) {
msg := map[string]interface{}{
"msgtype": "markdown",
"markdown": map[string]string{
"text": content,
"title": title,
},
"at": map[string]interface{}{
"atMobiles": atMobiles,
"isAtAll": isAtAll,
},
}
return SendMessage(msg)
}
func SendMessage(msg interface{}) error {
body := bytes.NewBuffer(nil)
err := json.NewEncoder(body).Encode(msg)
if err != nil {
return fmt.Errorf("msg json failed, msg: %v, err: %v", msg, err.Error())
}
value := url.Values{}
value.Set("access_token", global.GlobalConfig_.Token)
if global.GlobalConfig_.Secret != "" {
t := time.Now().UnixNano() / 1e6
value.Set("timestamp", fmt.Sprintf("%d", t))
value.Set("sign", sign(t, global.GlobalConfig_.Secret))
}
request, err := http.NewRequest(http.MethodPost, global.GlobalConfig_.Url, body)
if err != nil {
return fmt.Errorf("error request: %v", err.Error())
}
request.URL.RawQuery = value.Encode()
request.Header.Add("Content-Type", "application/json")
res, err := (&http.Client{}).Do(request)
if err != nil {
return fmt.Errorf("send dingTalk message failed, error: %v", err.Error())
}
defer func() { _ = res.Body.Close() }()
result, err := ioutil.ReadAll(res.Body)
if res.StatusCode != 200 {
return fmt.Errorf("send dingTalk message failed, %s", httpError(request, res, result, "http code is not 200"))
}
if err != nil {
return fmt.Errorf("send dingTalk message failed, %s", httpError(request, res, result, err.Error()))
}
type response struct {
ErrCode int `json:"errcode"`
}
var ret response
if err := json.Unmarshal(result, &ret); err != nil {
return fmt.Errorf("send dingTalk message failed, %s", httpError(request, res, result, err.Error()))
}
if ret.ErrCode != 0 {
return fmt.Errorf("send dingTalk message failed, %s", httpError(request, res, result, "errcode is not 0"))
}
return nil
}
func httpError(request *http.Request, response *http.Response, body []byte, error string) string {
return fmt.Sprintf(
"http request failure, error: %s, status code: %d, %s %s, body:\n%s",
error,
response.StatusCode,
request.Method,
request.URL.String(),
string(body),
)
}
func sign(t int64, secret string) string {
strToHash := fmt.Sprintf("%d\n%s", t, secret)
hmac256 := hmac.New(sha256.New, []byte(secret))
hmac256.Write([]byte(strToHash))
data := hmac256.Sum(nil)
return base64.StdEncoding.EncodeToString(data)
}
// 其余方法请参考 https://developers.dingtalk.com/document/robots/custom-robot-access?spm=ding_open_doc.document.0.0.7f8710afbfzduV#topic-2026027

1
server/plugin/notify/utils/utils.go

@ -1 +0,0 @@
package utils

2
web/.env.development

@ -3,4 +3,4 @@ ENV = 'development'
VUE_APP_CLI_PORT = 8080
VUE_APP_SERVER_PORT = 8888
VUE_APP_BASE_API = /api
VUE_APP_BASE_PATH = http://8.141.61.63
VUE_APP_BASE_PATH = http://127.0.0.1

160
web/package-lock.json

@ -1780,63 +1780,6 @@
"integrity": "sha1-/q7SVZc9LndVW4PbwIhRpsY1IPo=",
"dev": true
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"optional": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"optional": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"optional": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"optional": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"optional": true
},
"loader-utils": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
"dev": true,
"optional": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
}
},
"ssri": {
"version": "8.0.1",
"resolved": "https://registry.nlark.com/ssri/download/ssri-8.0.1.tgz",
@ -1845,28 +1788,6 @@
"requires": {
"minipass": "^3.1.1"
}
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"optional": true,
"requires": {
"has-flag": "^4.0.0"
}
},
"vue-loader-v16": {
"version": "npm:vue-loader@16.5.0",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.5.0.tgz",
"integrity": "sha512-WXh+7AgFxGTgb5QAkQtFeUcHNIEq3PGVQ8WskY5ZiFbWBkOwcCPRs4w/2tVyTbh2q6TVRlO3xfvIukUtjsu62A==",
"dev": true,
"optional": true,
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
}
}
}
},
@ -11623,6 +11544,87 @@
}
}
},
"vue-loader-v16": {
"version": "npm:vue-loader@16.5.0",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.5.0.tgz",
"integrity": "sha512-WXh+7AgFxGTgb5QAkQtFeUcHNIEq3PGVQ8WskY5ZiFbWBkOwcCPRs4w/2tVyTbh2q6TVRlO3xfvIukUtjsu62A==",
"dev": true,
"optional": true,
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"optional": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"optional": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"optional": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"optional": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"optional": true
},
"loader-utils": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
"dev": true,
"optional": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
}
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"optional": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"vue-particle-line": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/vue-particle-line/-/vue-particle-line-0.1.4.tgz",

Loading…
Cancel
Save