Explorar o código

feat:
1、新增全局错误捕获中间件
2、新增swagger自动化文档生成

Roc %!s(int64=3) %!d(string=hai) anos
pai
achega
94f8b17a2d

+ 1 - 0
.gitignore

@@ -1,5 +1,6 @@
 /.idea/
 /log
+/docs
 latest_log
 /config/config.yaml
 .DS_Store

+ 2 - 1
config/config.go

@@ -11,7 +11,8 @@ type Config struct {
 type Serve struct {
 	Port     int    `mapstructure:"port" json:"port" yaml:"port" description:"gin开启监听http服务的端口"`
 	RunMode  string `mapstructure:"run-mode" json:"run-mode" yaml:"run-mode" description:"gin运行模式的默认,枚举值:debug,release"`
-	UseRedis bool   `mapstructure:"use-redis" json:"use-redis" yaml:"v" description:"是否使用redis"`
+	UseRedis bool   `mapstructure:"use-redis" json:"use-redis" yaml:"use-redis" description:"是否使用redis"`
+	AppName  string `mapstructure:"app-name" json:"app-name" yaml:"app-name" description:"项目名称"`
 }
 
 // Log 日志配置

+ 18 - 2
controller/activity/activity.go

@@ -13,7 +13,23 @@ import (
  * @param	*gin.Context
  * @return	json
  */
-func GetPageList(c *gin.Context)  {
+
+// GetPageList 活动列表
+// @Tags 活动模块
+// @Summary  活动列表
+// @Description 获取活动列表
+// @Security ApiKeyAuth
+// @Param Authorization	header string true "Bearer 31a165baebe6dec616b1f8f3207b4273"
+// @Accept  json
+// @Product json
+// @Param activity_name query string false "活动名称"
+// @Param activity_type_name query string false "活动类别"
+// @Param active_state query int false "活动状态"
+// @Param page query int false "当前页码"
+// @Param limit query int false "每页数量"
+// @Success 200 {object} []yb_activity.YbActivity
+// @Router /activity/getPageList [get]
+func GetPageList(c *gin.Context) {
 	where := _handleListQuery(c)
 	page, limit := _handlePageParam(c)
 	listData, err := activity.PageList(where, page, limit)
@@ -46,4 +62,4 @@ func _handlePageParam(c *gin.Context) (page int, limit int) {
 	page, _ = strconv.Atoi(c.Query("page"))
 	limit, _ = strconv.Atoi(c.Query("limit"))
 	return
-}
+}

+ 10 - 0
controller/user/user.go

@@ -11,6 +11,16 @@ import (
 )
 
 // Login 登录接口
+// @Tags 用户模块
+// @Summary  用户登录
+// @Description 用户手机号/邮箱登录
+// @Security ApiKeyAuth
+// @Param Authorization	header string true "Bearer 31a165baebe6dec616b1f8f3207b4273"
+// @Accept  json
+// @Product json
+// @Param	request	body user.LoginReq true "type json string"
+// @Success 200 {object}	user.LoginResp
+// @Router /user/login [post]
 func Login(c *gin.Context) {
 	var req user.LoginReq
 	if c.ShouldBind(&req) != nil {

+ 5 - 1
core/log.go

@@ -34,7 +34,11 @@ func init() {
 	//注册框架输出(日志文件)
 	fileWriter := registerFile(logConfig, &backends)
 	if fileWriter != nil {
-		gin.DefaultWriter = io.MultiWriter(fileWriter, os.Stdout)
+		if global.CONFIG.Serve.RunMode == "debug" {
+			gin.DefaultWriter = io.MultiWriter(fileWriter, os.Stdout)
+		} else {
+			gin.DefaultWriter = io.MultiWriter(fileWriter)
+		}
 	}
 	oplogging.SetBackend(backends...)
 	global.LOG = logger

+ 8 - 0
init_serve/router.go

@@ -2,6 +2,9 @@ package init_serve
 
 import (
 	"github.com/gin-gonic/gin"
+	"github.com/swaggo/gin-swagger"
+	"github.com/swaggo/gin-swagger/swaggerFiles"
+	_ "hongze/hongze_yb/docs"
 	"hongze/hongze_yb/global"
 	"hongze/hongze_yb/middleware"
 	"hongze/hongze_yb/routers"
@@ -14,6 +17,11 @@ func InitRouter() (r *gin.Engine) {
 	// 1.创建路由
 	r = gin.Default()
 	r.Use(middleware.Cors())
+	//r.Use(gin.Recovery())
+	r.Use(middleware.Recover())
+
+	//swagger界面访问地址
+	r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
 
 	// 2.绑定路由规则,执行的函数
 	// gin.Context,封装了request和response

+ 47 - 0
middleware/recover.go

@@ -0,0 +1,47 @@
+package middleware
+
+import (
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb/controller/response"
+	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/utils"
+	"net/http"
+	"runtime"
+	"time"
+)
+
+// Recover 异常处理
+func Recover() gin.HandlerFunc {
+	return func(c *gin.Context) {
+		defer func() {
+			if err := recover(); err != nil {
+				stack := ""
+
+				msg := fmt.Sprintf("The request url is  %v", c.Request.RequestURI)
+				stack += msg + "</br>"
+				global.LOG.Critical(msg)
+				msg = fmt.Sprintf("The request data is %v", c.Params)
+				stack += msg + "</br>"
+				global.LOG.Critical(msg)
+				msg = fmt.Sprintf("Handler crashed with error %v", err)
+				stack += msg + "</br>"
+				global.LOG.Critical(msg)
+				for i := 1; ; i++ {
+					_, file, line, ok := runtime.Caller(i)
+					if !ok {
+						break
+					}
+					global.LOG.Critical(fmt.Sprintf("%s:%d", file, line))
+					stack = stack + fmt.Sprintln(fmt.Sprintf("%s:%d</br>", file, line))
+				}
+				fmt.Println("stack:", stack)
+				response.Custom(http.StatusInternalServerError, "系统异常", c)
+				//c.JSON(http.StatusInternalServerError, Err)
+				go utils.SendEmail(utils.APPNAME+"崩了"+time.Now().Format("2006-01-02 15:04:05"), stack, utils.EmailSendToUsers)
+				return
+			}
+		}()
+		c.Next()
+	}
+}

+ 6 - 0
utils/constants.go

@@ -20,3 +20,9 @@ const (
 	RegularMobile = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0-9])|(17[0-9])|(16[0-9])|(19[0-9]))\\d{8}$" //手机号码
 	RegularEmail  = `\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*`                                             //匹配电子邮箱
 )
+
+const (
+	APPNAME = "弘则研报"
+	//EmailSendToUsers = "glji@hzinsights.com;pyan@hzinsights.com;cxzhang@hzinsights.com"
+	EmailSendToUsers = "pyan@hzinsights.com"
+)

+ 36 - 0
utils/email.go

@@ -0,0 +1,36 @@
+package utils
+
+import (
+	"fmt"
+	"gopkg.in/gomail.v2"
+	"hongze/hongze_yb/global"
+	"strings"
+)
+
+//发送邮件
+func SendEmail(title, content string, touser string) bool {
+	if global.CONFIG.Serve.RunMode == "debug" {
+		global.LOG.Info(fmt.Sprint(title, ";", content))
+		return false
+	}
+	var arr []string
+	sub := strings.Index(touser, ";")
+	if sub >= 0 {
+		spArr := strings.Split(touser, ";")
+		for _, v := range spArr {
+			arr = append(arr, v)
+		}
+	} else {
+		arr = append(arr, touser)
+	}
+	m := gomail.NewMessage()
+	m.SetHeader("From", "317699326@qq.com ")
+	m.SetHeader("To", arr...)
+	m.SetHeader("Subject", title+" "+GetRandString(16))
+	m.SetBody("text/html", content)
+	d := gomail.NewDialer("smtp.qq.com", 587, "317699326@qq.com", "oqdypwfcvruwcbea")
+	if err := d.DialAndSend(m); err != nil {
+		return false
+	}
+	return true
+}