From 4a1e66339645051f61f35d7b3d8764dd21e6f012 Mon Sep 17 00:00:00 2001 From: engigu Date: Mon, 1 Jan 2024 12:03:56 +0800 Subject: [PATCH] feat: complete settings --- README_ZH.md | 99 +------------------ main.go | 11 +-- middleware/log.go | 80 +++++++++++++++ models/models.go | 3 +- models/send_tasks.go | 8 ++ pkg/logging/logger.go | 33 ++++++- routers/api/v1/send_task.go | 35 ++++++- routers/router.go | 6 +- service/send_ins_service/send_ins.go | 2 +- service/send_message_service/send_message.go | 39 +++++++- service/send_task_service/send_task.go | 4 + web/src/util/viewApi.js | 4 +- .../views/tabsTools/sendTasks/sendTasks.vue | 10 +- .../sendTasks/{ => view}/addTaskPopUp.vue | 5 +- .../sendTasks/{ => view}/editTaskPopUp.vue | 36 +++---- .../sendTasks/{ => view}/viewTaskAPIPopUp.vue | 0 web/src/views/tabsTools/sendWays/sendWays.vue | 10 +- .../sendWays/{ => view}/addWayPopUp.vue | 6 +- .../sendWays/{ => view}/editWayPopUp.vue | 6 +- 19 files changed, 242 insertions(+), 155 deletions(-) create mode 100644 middleware/log.go rename web/src/views/tabsTools/sendTasks/{ => view}/addTaskPopUp.vue (98%) rename web/src/views/tabsTools/sendTasks/{ => view}/editTaskPopUp.vue (89%) rename web/src/views/tabsTools/sendTasks/{ => view}/viewTaskAPIPopUp.vue (100%) rename web/src/views/tabsTools/sendWays/{ => view}/addWayPopUp.vue (96%) rename web/src/views/tabsTools/sendWays/{ => view}/editWayPopUp.vue (97%) diff --git a/README_ZH.md b/README_ZH.md index f4286e4..5ecb468 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -1,30 +1,7 @@ -# Go Gin Example [![rcard](https://goreportcard.com/badge/github.com/EDDYCJY/go-gin-example)](https://goreportcard.com/report/github.com/EDDYCJY/go-gin-example) [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://godoc.org/github.com/EDDYCJY/go-gin-example) [![License](http://img.shields.io/badge/license-mit-blue.svg?style=flat-square)](https://raw.githubusercontent.com/EDDYCJY/go-gin-example/master/LICENSE) +# Message Nest `gin` 的一个例子,包含许多有用特性 -## 目录 - -本项目提供 [Gin实践](https://segmentfault.com/a/1190000013297625) 的连载示例代码 - -1. [Gin实践 连载一 Golang介绍与环境安装](https://book.eddycjy.com/golang/gin/install.html) -2. [Gin实践 连载二 搭建Blog API's(一)](https://book.eddycjy.com/golang/gin/api-01.html) -3. [Gin实践 连载三 搭建Blog API's(二)](https://book.eddycjy.com/golang/gin/api-02.html) -4. [Gin实践 连载四 搭建Blog API's(三)](https://book.eddycjy.com/golang/gin/api-03.html) -5. [Gin实践 连载五 使用JWT进行身份校验](https://book.eddycjy.com/golang/gin/jwt.html) -6. [Gin实践 连载六 编写一个简单的文件日志](https://book.eddycjy.com/golang/gin/log.html) -7. [Gin实践 连载七 Golang优雅重启HTTP服务](https://book.eddycjy.com/golang/gin/reload-http.html) -8. [Gin实践 连载八 为它加上Swagger](https://book.eddycjy.com/golang/gin/swagger.html) -9. [Gin实践 连载九 将Golang应用部署到Docker](https://book.eddycjy.com/golang/gin/golang-docker.html) -10. [Gin实践 连载十 定制 GORM Callbacks](https://book.eddycjy.com/golang/gin/gorm-callback.html) -11. [Gin实践 连载十一 Cron定时任务](https://book.eddycjy.com/golang/gin/cron.html) -12. [Gin实践 连载十二 优化配置结构及实现图片上传](https://book.eddycjy.com/golang/gin/config-upload.html) -13. [Gin实践 连载十三 优化你的应用结构和实现Redis缓存](https://book.eddycjy.com/golang/gin/application-redis.html) -14. [Gin实践 连载十四 实现导出、导入 Excel](https://book.eddycjy.com/golang/gin/excel.html) -15. [Gin实践 连载十五 生成二维码、合并海报](https://book.eddycjy.com/golang/gin/image.html) -16. [Gin实践 连载十六 在图片上绘制文字](https://book.eddycjy.com/golang/gin/font.html) -17. [Gin实践 连载十七 用 Nginx 部署 Go 应用](https://book.eddycjy.com/golang/gin/nginx.html) -18. [Gin实践 番外 Golang交叉编译](https://book.eddycjy.com/golang/gin/cgo.html) -19. [Gin实践 番外 请入门 Makefile](https://book.eddycjy.com/golang/gin/makefile.html) ## 安装 ``` @@ -34,83 +11,15 @@ $ go get github.com/EDDYCJY/go-gin-example ## 如何运行 ### 必须 - - Mysql -- Redis ### 准备 -创建一个 `blog` 数据库,并且导入建表的 [SQL](https://message-nest/blob/master/docs/sql/blog.sql) + ### 配置 -你应该修改 `conf/app.ini` 配置文件 - -``` -[database] -Type = mysql -User = root -Password = rootroot -Host = 127.0.0.1:3306 -Name = blog -TablePrefix = blog_ - -[redis] -Host = 127.0.0.1:6379 -Password = -MaxIdle = 30 -MaxActive = 30 -IdleTimeout = 200 -... -``` +[main.go](main.go) -### 运行 -``` -$ cd $GOPATH/src/go-gin-example - -$ go run main.go -``` - -项目的运行信息和已存在的 API's - -``` -[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production. - - using env: export GIN_MODE=release - - using code: gin.SetMode(gin.ReleaseMode) - -[GIN-debug] GET /auth --> message-nest/routers/api.GetAuth (3 handlers) -[GIN-debug] GET /swagger/*any --> message-nest/vendor/github.com/swaggo/gin-swagger.WrapHandler.func1 (3 handlers) -[GIN-debug] GET /api/v1/tags --> message-nest/routers/api/v1.GetTags (4 handlers) -[GIN-debug] POST /api/v1/tags --> message-nest/routers/api/v1.AddTag (4 handlers) -[GIN-debug] PUT /api/v1/tags/:id --> message-nest/routers/api/v1.EditTag (4 handlers) -[GIN-debug] DELETE /api/v1/tags/:id --> message-nest/routers/api/v1.DeleteTag (4 handlers) -[GIN-debug] GET /api/v1/articles --> message-nest/routers/api/v1.GetArticles (4 handlers) -[GIN-debug] GET /api/v1/articles/:id --> message-nest/routers/api/v1.GetArticle (4 handlers) -[GIN-debug] POST /api/v1/articles --> message-nest/routers/api/v1.AddArticle (4 handlers) -[GIN-debug] PUT /api/v1/articles/:id --> message-nest/routers/api/v1.EditArticle (4 handlers) -[GIN-debug] DELETE /api/v1/articles/:id --> message-nest/routers/api/v1.DeleteArticle (4 handlers) - -Listening port is 8000 -Actual pid is 4393 -``` -Swagger 文档 - -![image](https://i.imgur.com/bVRLTP4.jpg) - -## 特性 - -- RESTful API -- Gorm -- Swagger -- logging -- Jwt-go -- Gin -- Graceful restart or stop (fvbock/endless) -- App configurable -- Cron -- Redis - -## 联系我 - -![image](https://image.eddycjy.com/7074be90379a121746146bc4229819f8.jpg) +### 运行[main.go](main.go) diff --git a/main.go b/main.go index f3ce58f..892795f 100644 --- a/main.go +++ b/main.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "log" "message-nest/pkg/table" "message-nest/service/cron_service" "message-nest/service/env_service" @@ -27,12 +26,6 @@ func init() { cron_service.Setup() } -// @title Golang Gin API -// @version 1.0 -// @description An example of gin -// @termsOfService https://github.com/EDDYCJY/go-gin-example -// @license.name MIT -// @license.url https://message-nest/blob/master/LICENSE func main() { gin.SetMode(setting.ServerSetting.RunMode) @@ -50,10 +43,10 @@ func main() { MaxHeaderBytes: maxHeaderBytes, } - log.Printf("[info] start http server listening http://0.0.0.0%s", endPoint) + logging.Logger.Info("start http server listening http://0.0.0.0", endPoint) err := server.ListenAndServe() if err != nil { - log.Printf("Server err: %v", err) + logging.Logger.Error("Server err: ", err) } } diff --git a/middleware/log.go b/middleware/log.go new file mode 100644 index 0000000..15940c6 --- /dev/null +++ b/middleware/log.go @@ -0,0 +1,80 @@ +package middleware + +import ( + "fmt" + "github.com/gin-gonic/gin" + "message-nest/pkg/logging" + "time" +) + +const ( + status200 = 42 + status404 = 43 + status500 = 41 + + methodGET = 44 +) + +func formatDuration(duration time.Duration) string { + seconds := duration.Seconds() + switch { + case seconds >= 1: + return fmt.Sprintf("%.2fs", seconds) + default: + return fmt.Sprintf("%.3fms", float64(duration.Milliseconds())) + //default: + // return fmt.Sprintf("%dns", duration.Nanoseconds()) + //case duration.Milliseconds() >= 1: + // return fmt.Sprintf("%.2fms", float64(duration.Milliseconds())) + //default: + // return fmt.Sprintf("%dns", duration.Nanoseconds()) + } +} + +func LogMiddleware() gin.HandlerFunc { + return func(c *gin.Context) { + start := time.Now() + path := c.Request.URL.Path + raw := c.Request.URL.RawQuery + + // Process request + c.Next() + + // Log only when path is not being skipped + + // Stop timer + end := time.Now() + timeSub := end.Sub(start) + dr := formatDuration(timeSub) + clientIP := c.ClientIP() + method := c.Request.Method + statusCode := c.Writer.Status() + //bodySize := c.Writer.Size() + if raw != "" { + path = path + "?" + raw + } + + var statusColor string + switch statusCode { + case 200: + statusColor = fmt.Sprintf("\033[%dm %d \033[0m", status200, statusCode) + case 500: + statusColor = fmt.Sprintf("\033[%dm %d \033[0m", status500, statusCode) + default: + statusColor = fmt.Sprintf("\033[%dm %d \033[0m", status404, statusCode) + } + + var methodColor string + methodColor = fmt.Sprintf("\033[%dm %s \033[0m", methodGET, method) + + logging.Logger.Infof("[GIN]|%s|%s|%s|%s| %s", + //start.Format("2006-01-02 15:04:06"), + statusColor, + dr, + clientIP, + methodColor, + path, + ) + + } +} diff --git a/models/models.go b/models/models.go index ac6aca0..c46378b 100644 --- a/models/models.go +++ b/models/models.go @@ -47,7 +47,7 @@ func Setup() { return setting.DatabaseSetting.TablePrefix + defaultTableName } - db.LogMode(true) + //db.LogMode(true) db.SingularTable(true) db.Callback().Create().Replace("gorm:update_time_stamp", updateTimeStampForCreateCallback) db.Callback().Update().Replace("gorm:update_time_stamp", updateTimeStampForUpdateCallback) @@ -65,7 +65,6 @@ func CloseDB() { func updateTimeStampForCreateCallback(scope *gorm.Scope) { if !scope.HasError() { nowTime := time.Now() - fmt.Printf("fyyyyyynowTime %s", nowTime) if createTimeField, ok := scope.FieldByName("CreatedOn"); ok { if createTimeField.IsBlank { diff --git a/models/send_tasks.go b/models/send_tasks.go index 834389a..d1e0a12 100644 --- a/models/send_tasks.go +++ b/models/send_tasks.go @@ -162,3 +162,11 @@ func DeleteMsgTask(id string) error { tx.Commit() return nil } + +func EditSendTask(id string, data interface{}) error { + if err := db.Model(&SendTasks{}).Where("id = ? ", id).Updates(data).Error; err != nil { + return err + } + + return nil +} diff --git a/pkg/logging/logger.go b/pkg/logging/logger.go index 18b26a3..80da478 100644 --- a/pkg/logging/logger.go +++ b/pkg/logging/logger.go @@ -1,15 +1,44 @@ package logging import ( + "bytes" + "fmt" "github.com/sirupsen/logrus" "os" + "path/filepath" ) var Logger = logrus.New() +type MyFormatter struct{} + +func (m *MyFormatter) Format(entry *logrus.Entry) ([]byte, error) { + var b *bytes.Buffer + if entry.Buffer != nil { + b = entry.Buffer + } else { + b = &bytes.Buffer{} + } + + timestamp := entry.Time.Format("2006-01-02 15:04:05") + var newLog string + + //HasCaller()为true才会有调用信息 + if entry.HasCaller() { + fName := filepath.Base(entry.Caller.File) + newLog = fmt.Sprintf("[%s] [%s] [%s:%d %s] %s\n", + timestamp, entry.Level, fName, entry.Caller.Line, entry.Caller.Function, entry.Message) + } else { + newLog = fmt.Sprintf("[%s] [%s] %s\n", timestamp, entry.Level, entry.Message) + } + + b.WriteString(newLog) + return b.Bytes(), nil +} + func Setup() { - Logger := logrus.New() - Logger.SetFormatter(&logrus.JSONFormatter{}) + Logger.SetReportCaller(true) + Logger.SetFormatter(&MyFormatter{}) Logger.SetOutput(os.Stdout) Logger.SetLevel(logrus.InfoLevel) } diff --git a/routers/api/v1/send_task.go b/routers/api/v1/send_task.go index f068b4f..4297a7c 100644 --- a/routers/api/v1/send_task.go +++ b/routers/api/v1/send_task.go @@ -69,7 +69,7 @@ func GetMsgSendTaskList(c *gin.Context) { } type AddMsgSendTaskReq struct { - Name string `json:"name" validate:"required,max=100,min=1" label:"任务任务名"` + Name string `json:"name" validate:"required,max=100,min=1" label:"任务名"` } // AddMsgSendTask 添加发送任务 @@ -101,3 +101,36 @@ func AddMsgSendTask(c *gin.Context) { appG.CResponse(http.StatusOK, "添加任务任务成功!", nil) } + +type EditMsgSendTaskReq struct { + ID string `json:"id" validate:"required,len=36" label:"任务id"` + TaskName string `json:"name" validate:"required,max=100,min=1" label:"任务任务名"` +} + +// EditMsgSendTask 编辑消息任务 +func EditMsgSendTask(c *gin.Context) { + var ( + appG = app.Gin{C: c} + req EditMsgSendTaskReq + ) + + errCode, errMsg := app.BindJsonAndPlayValid(c, &req) + if errCode != e.SUCCESS { + appG.CResponse(errCode, errMsg, nil) + return + } + + MsgSendTaskService := send_task_service.SendTaskService{ + ID: req.ID, + } + + var data = map[string]string{} + data["name"] = req.TaskName + err := MsgSendTaskService.Edit(data) + if err != nil { + appG.CResponse(http.StatusBadRequest, "编辑发信任务失败!", nil) + return + } + + appG.CResponse(http.StatusOK, "编辑发信任务成功!", nil) +} diff --git a/routers/router.go b/routers/router.go index 609f11b..f4c6a42 100644 --- a/routers/router.go +++ b/routers/router.go @@ -3,7 +3,6 @@ package routers import ( "github.com/gin-gonic/gin" "message-nest/middleware" - "message-nest/routers/api" "message-nest/routers/api/v1" ) @@ -11,7 +10,9 @@ import ( // InitRouter initialize routing information func InitRouter() *gin.Engine { r := gin.New() - r.Use(gin.Logger()) + r.Use(middleware.LogMiddleware()) + //gin.DefaultWriter = logging.Logger.Out + //gin.DefaultErrorWriter = logging.Logger.Out r.Use(gin.Recovery()) r.Use(middleware.Cors()) @@ -32,6 +33,7 @@ func InitRouter() *gin.Engine { apiv1.GET("/sendtasks/list", v1.GetMsgSendTaskList) apiv1.POST("/sendtasks/add", v1.AddMsgSendTask) apiv1.POST("/sendtasks/delete", v1.DeleteMsgSendTask) + apiv1.POST("/sendtasks/edit", v1.EditMsgSendTask) // sendtasks/ins apiv1.POST("/sendtasks/ins/addmany", v1.AddManyTasksIns) diff --git a/service/send_ins_service/send_ins.go b/service/send_ins_service/send_ins.go index 22c55c2..352724b 100644 --- a/service/send_ins_service/send_ins.go +++ b/service/send_ins_service/send_ins.go @@ -30,7 +30,7 @@ func (sw *SendTaskInsService) ValidateDiffIns(ins models.SendTasksIns) (string, _, Msg := app.CommonPlaygroundValid(emailConfig) return Msg, emailConfig } - return "", empty + return "未知的渠道的config校验", empty } func (st *SendTaskInsService) ManyAdd(taskIns []models.SendTasksIns) string { diff --git a/service/send_message_service/send_message.go b/service/send_message_service/send_message.go index ed45035..55313d0 100644 --- a/service/send_message_service/send_message.go +++ b/service/send_message_service/send_message.go @@ -5,6 +5,7 @@ import ( "message-nest/models" "message-nest/pkg/logging" "message-nest/pkg/message" + "message-nest/service/send_ins_service" "message-nest/service/send_task_service" "message-nest/service/send_way_service" "strings" @@ -56,7 +57,7 @@ func (sm *SendMessageService) Send() string { // 邮箱类型的实例 emailAuth, ok := msgObj.(send_way_service.WayDetailEmail) if ok { - errMsg := sm.SendTaskEmail(emailAuth) + errMsg := sm.SendTaskEmail(emailAuth, ins.SendTasksIns) sm.MarkStatus(errMsg, &status) logOutput = append(logOutput, sm.TransError(errMsg)) continue @@ -119,11 +120,39 @@ func (sm *SendMessageService) TransError(err string) string { } } +// GetSendMsg +func (sm *SendMessageService) GetSendMsg(ins models.SendTasksIns) string { + data := map[string]string{} + data["text"] = sm.Text + data["html"] = sm.HTML + data["markdown"] = sm.MarkDown + content, ok := data[ins.ContentType] + if !ok || len(content) == 0 { + content, ok := data["text"] + if !ok { + logging.Logger.Error("text节点数据为空!") + return "" + } else { + return content + } + } else { + return content + } +} + // SendTaskEmail 执行发送邮件 -func (sm *SendMessageService) SendTaskEmail(auth send_way_service.WayDetailEmail) string { +func (sm *SendMessageService) SendTaskEmail(auth send_way_service.WayDetailEmail, ins models.SendTasksIns) string { + insService := send_ins_service.SendTaskInsService{} + errStr, c := insService.ValidateDiffIns(ins) + if errStr != "" { + return errStr + } + config, ok := c.(models.InsEmailConfig) + if !ok { + return "邮箱config校验失败" + } var emailer message.EmailMessage emailer.Init(auth.Server, auth.Port, auth.Account, auth.Passwd) - //errMsg := emailer.SendTextMessage("sayheya@qq.com", "test", "This is a test email from message-nest.") - //return errMsg - return "" + errMsg := emailer.SendTextMessage(config.ToAccount, config.Title, sm.GetSendMsg(ins)) + return errMsg } diff --git a/service/send_task_service/send_task.go b/service/send_task_service/send_task.go index ea1a428..f917933 100644 --- a/service/send_task_service/send_task.go +++ b/service/send_task_service/send_task.go @@ -27,6 +27,10 @@ func (st *SendTaskService) Delete() error { return models.DeleteMsgTask(st.ID) } +func (st *SendTaskService) Edit(data map[string]string) error { + return models.EditSendTask(st.ID, data) +} + func (st *SendTaskService) GetTaskWithIns() (models.TaskIns, error) { return models.GetTasksIns(st.ID) } diff --git a/web/src/util/viewApi.js b/web/src/util/viewApi.js index f80ce39..02905d9 100644 --- a/web/src/util/viewApi.js +++ b/web/src/util/viewApi.js @@ -16,9 +16,9 @@ class ApiStrGenerate { if (options.markdown) { data.html = '** Hello World! **'; } - let dataStr = JSON.stringify(data, null, 4) + let dataStr = JSON.stringify(data, null, 4); let example = `curl -X POST --location '${gethttpOrigin()}/api/v1/message/send' \\ - --header 'Accept: application/json' \\ + --header 'Content-Type: application/json' \\ --data '${dataStr}'`; return example; } diff --git a/web/src/views/tabsTools/sendTasks/sendTasks.vue b/web/src/views/tabsTools/sendTasks/sendTasks.vue index 3ea7f5f..e7cde69 100644 --- a/web/src/views/tabsTools/sendTasks/sendTasks.vue +++ b/web/src/views/tabsTools/sendTasks/sendTasks.vue @@ -44,11 +44,11 @@