增加定时任务 处理异常

This commit is contained in:
2024-08-30 11:55:19 +08:00
parent aa3f9e8711
commit bfb284c4cc
30 changed files with 945 additions and 336 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
main.exe
go_build_energy_management_system.exe
.idea
log

View File

@@ -41,7 +41,7 @@ func (r *PeakValley) UpdatePeakValleyQuarter(c *gin.Context) {
func (r *PeakValley) PeakValleyQuarterEditDetail(c *gin.Context) {
var req form.PeakValleyQuarterEditDetailReq
id, err := strconv.Atoi(c.Param("id"))
exception.PanicMsgBool(err != nil, "参数有误")
exception.PBM(err != nil, "参数有误")
req.Id = id
respData := service.GroupServices.PeakValley.PeakValleyQuarterEditDetail(&req)
response.SuccessData(respData, c)
@@ -81,7 +81,7 @@ func (r *PeakValley) UpdatePeakValleyRule(c *gin.Context) {
func (r *PeakValley) PeakValleyRuleDetail(c *gin.Context) {
var req form.PeakValleyRuleDetailReq
id, err := strconv.Atoi(c.Param("id"))
exception.PanicMsgBool(err != nil, "参数有误")
exception.PBM(err != nil, "参数有误")
req.RuleId = id
respData := service.GroupServices.PeakValley.PeakValleyRuleDetail(&req)
response.SuccessData(respData, c)
@@ -90,7 +90,7 @@ func (r *PeakValley) PeakValleyRuleDetail(c *gin.Context) {
func (r *PeakValley) PeakValleyRuleEditDetail(c *gin.Context) {
var req form.PeakValleyRuleEditDetailReq
id, err := strconv.Atoi(c.Param("id"))
exception.PanicMsgBool(err != nil, "参数有误")
exception.PBM(err != nil, "参数有误")
req.RuleId = id
respData := service.GroupServices.PeakValley.PeakValleyRuleEditDetail(&req)
response.SuccessData(respData, c)

View File

@@ -2,6 +2,8 @@ package v1
import (
"energy-management-system/response"
"energy-management-system/utils"
"fmt"
"github.com/gin-gonic/gin"
)
@@ -13,6 +15,8 @@ func (r *TestApi) Test(c *gin.Context) {
}
func (r *TestApi) TestData(c *gin.Context) {
x, y, z, e := utils.GetMinutesFromTimeRange("00:00", "05:01")
fmt.Println(x, y, z, e)
response.SuccessData(gin.H{"userName": "iuu"}, c)
}

View File

@@ -1,3 +1,4 @@
is_debug: true
service:
http:
host: 0.0.0.0 # 默认localhost

View File

@@ -14,6 +14,7 @@ const (
)
type Config struct {
IsDebug bool `mapstructure:"is_debug" json:"is_debug" yaml:"is_debug"`
Db DbConf `mapstructure:"db" json:"db" yaml:"db"`
Service ServiceConf `mapstructure:"service" json:"service" yaml:"service"`
}

44
core/cron/crontab.go Normal file
View File

@@ -0,0 +1,44 @@
package cron
import (
"energy-management-system/utils"
"energy-management-system/utils/recovery"
"fmt"
"github.com/robfig/cron/v3"
"reflect"
"runtime"
)
var servers server
type server struct {
Cron []string
Func []func()
}
func (c *server) register(cron string, f func()) {
c.Cron = append(c.Cron, cron)
c.Func = append(c.Func, f)
}
func CronRun() {
c := cron.New()
for k, v := range servers.Cron {
eid, err := c.AddFunc(v, wrap(servers.Func[k]))
fmt.Println("定时任务:", eid, "添加成功")
utils.Exit(err, "添加定时器错误:")
}
c.Start()
}
func wrap(f func()) func() {
return func() {
defer recovery.CronRecovery(runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name())
f()
}
}
// Register 参数规则s m h d m w函数
func Register(rule string, f func()) {
servers.register(rule, f)
}

View File

@@ -1,8 +1,8 @@
package core
package gorm
import (
init_db_data "energy-management-system/core/init-db-data"
"energy-management-system/global"
"energy-management-system/model/init-db-data"
peak_valley "energy-management-system/model/peak-valley"
"fmt"
"gorm.io/driver/postgres"

91
core/logger/logger.go Normal file
View File

@@ -0,0 +1,91 @@
package logger
import (
"energy-management-system/global"
"fmt"
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
"github.com/sirupsen/logrus"
"runtime"
"strings"
"sync"
"time"
)
func InitLogger() *global.Logger {
L := logrus.New()
path := "./log/log"
file, _ := rotatelogs.New(
path+".%Y%m%d",
rotatelogs.WithLinkName(path),
rotatelogs.WithMaxAge(time.Duration(100*24)*time.Hour), //自动删除
rotatelogs.WithRotationTime(time.Duration(24*60)*time.Minute), //分割时间
)
L.SetOutput(file)
L.SetFormatter(&logrus.JSONFormatter{})
Log := &global.Logger{Logger: L, Heads: []string{}}
global.Log = Log
return Log
}
var errs = &errFunc{lock: new(sync.Mutex)}
func ErrorRegister(f func(string)) {
errs.register(f, false)
}
func ErrorRegisterOnly1(f func(string)) {
errs.register(f, true)
}
func ErrorWx(e ...string) {
errs.run(strings.Join(e, " "))
global.Log.Error(e)
}
type errFunc struct {
f []func(string)
lastTime int64
lock *sync.Mutex
}
func (e *errFunc) register(f func(string), only bool) {
if only {
e.f = []func(string){f}
} else {
e.f = append(e.f, f)
}
}
func (e *errFunc) run(logs string) {
if len(e.f) == 0 {
return
}
if time.Now().Unix()-e.lastTime > 1 {
e.lock.Lock()
e.lastTime = time.Now().Unix()
defer e.lock.Unlock()
for _, v := range e.f {
v(logs)
}
}
}
func StackSend(skip int, e string) {
e += "\n" + Stack(skip)
if global.AppConf.IsDebug {
fmt.Print(e)
}
errs.run(e)
}
func Stack(skip int) (re string) {
for i := skip; ; i++ {
_, file, line, ok := runtime.Caller(i)
if !ok {
break
}
if !strings.Contains(file, "local/go/src") && !strings.Contains(file, "/go/pkg") {
logs := fmt.Sprintf("%s:%d\n", file, line)
re += logs
}
}
return
}

View File

@@ -1,2 +0,0 @@
package core

View File

@@ -1,4 +1,4 @@
package core
package viper
import (
"energy-management-system/config"

14
global/logger.go Normal file
View File

@@ -0,0 +1,14 @@
package global
import "github.com/sirupsen/logrus"
type Logger struct {
*logrus.Logger
Heads []string
}
func (l *Logger) AddHead(args ...string) {
for _, v := range args {
l.Heads = append(l.Heads, v)
}
}

View File

@@ -11,6 +11,8 @@ var (
// Db 数据库
Db *gorm.DB
Log *Logger
// Trans 定义一个全局翻译器T
//Trans ut.Translator
//Validate *validator.Validate

15
go.mod
View File

@@ -5,7 +5,12 @@ go 1.22
require (
github.com/fsnotify/fsnotify v1.7.0
github.com/gin-gonic/gin v1.10.0
github.com/gookit/goutil v0.6.16
github.com/go-playground/locales v0.14.1
github.com/go-playground/universal-translator v0.18.1
github.com/go-playground/validator/v10 v10.20.0
github.com/gookit/color v1.5.4
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
github.com/sirupsen/logrus v1.9.3
github.com/spf13/viper v1.19.0
gorm.io/driver/postgres v1.5.9
gorm.io/gorm v1.25.11
@@ -18,11 +23,7 @@ require (
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.20.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/gookit/color v1.5.4 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
@@ -30,15 +31,19 @@ require (
github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/jonboulle/clockwork v0.4.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/lestrrat-go/strftime v1.1.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/robfig/cron/v3 v3.0.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect

17
go.sum
View File

@@ -35,8 +35,6 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
github.com/gookit/goutil v0.6.16 h1:9fRMCF4X9abdRD5+2HhBS/GwafjBlTUBjRtA5dgkvuw=
github.com/gookit/goutil v0.6.16/go.mod h1:op2q8AoPDFSiY2+qkHxcBWQMYxOLQ1GbLXqe7vrwscI=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
@@ -51,6 +49,8 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
@@ -63,6 +63,12 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4=
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA=
github.com/lestrrat-go/strftime v1.1.0 h1:gMESpZy44/4pXLO/m+sL0yBd1W6LjgjrrD4a68Gapyg=
github.com/lestrrat-go/strftime v1.1.0/go.mod h1:uzeIB52CeUJenCo1syghlugshMysrqUT51HlxphXVeI=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
@@ -76,15 +82,21 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/robfig/cron/v3 v3.0.0 h1:kQ6Cb7aHOHTSzNVNEhmp8EcWKLb4CbiMW9h9VyIhO4E=
github.com/robfig/cron/v3 v3.0.0/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
@@ -130,6 +142,7 @@ golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=

94
main.go
View File

@@ -2,9 +2,12 @@ package main
import (
"context"
"energy-management-system/core"
"energy-management-system/core/cron"
"energy-management-system/core/gorm"
"energy-management-system/core/logger"
"energy-management-system/core/viper"
"energy-management-system/global"
"energy-management-system/request"
"energy-management-system/request/validator"
"energy-management-system/router"
"errors"
"fmt"
@@ -16,19 +19,26 @@ import (
func init() {
// 配置
core.InitViper()
viper.InitViper()
// 日志
logger.InitLogger()
// 数据库
core.InitGorm()
gorm.InitGorm()
// gin验证器
request.InitTrans()
validator.InitTrans()
// 可选初始化表结构
core.AutoMigrate(global.Db)
gorm.AutoMigrate(global.Db)
// 可选初始化表数据
core.AutoInitDbData()
gorm.AutoInitDbData()
}
func main() {
cron.Register("0/1 * * * * ", func() {
fmt.Println(time.Now())
})
cron.CronRun()
r := router.InitRouter()
host := global.AppConf.Service.Http.Host
port := global.AppConf.Service.Http.Port
@@ -39,78 +49,8 @@ func main() {
// 优雅关闭
gracefulShutdown(srv)
//// 定义一个切片来接收查询结果
//var users []peaks_valleys.PeakValleyTimeBlock
//
//// 查询所有用户
//result := global.Db.Find(&users)
//if result.Error != nil {
// fmt.Println("Error:", result.Error)
//}
//
//// 打印查询结果
//for _, user := range users {
//
// if user.BlockIndex < 20 {
// global.Db.Create(&peaks_valleys.PeakValleyTimeBlockPrice{
// BlockId: user.BlockIndex,
// Price: 35,
// PeakValleyType: 5,
// })
// } else if user.BlockIndex < 40 {
// global.Db.Create(&peaks_valleys.PeakValleyTimeBlockPrice{
// BlockId: user.BlockIndex,
// Price: 45,
// PeakValleyType: 4,
// })
// } else if user.BlockIndex < 60 {
// global.Db.Create(&peaks_valleys.PeakValleyTimeBlockPrice{
// BlockId: user.BlockIndex,
// Price: 55,
// PeakValleyType: 3,
// })
// } else if user.BlockIndex < 80 {
// global.Db.Create(&peaks_valleys.PeakValleyTimeBlockPrice{
// BlockId: user.BlockIndex,
// Price: 65,
// PeakValleyType: 2,
// })
// } else if user.BlockIndex < 100 {
// global.Db.Create(&peaks_valleys.PeakValleyTimeBlockPrice{
// BlockId: user.BlockIndex,
// Price: 85,
// PeakValleyType: 1,
// })
// } else if user.BlockIndex <= 144 {
// global.Db.Create(&peaks_valleys.PeakValleyTimeBlockPrice{
// BlockId: user.BlockIndex,
// Price: 35,
// PeakValleyType: 5,
// })
// }
//
// //fmt.Printf("ID: %d, Name: %s, Email: %s\n", user.BlockIndex)
//}
}
//func loadConfig() (host, port string) {
// host = viper.GetString("service.http.host")
// if host == "" {
// host = "localhost"
// fmt.Println("Using default host:", host)
// }
//
// port = viper.GetString("service.http.port")
// if port == "" {
// port = "9999"
// fmt.Println("Using default port:", port)
// }
//
// return host, port
//}
func initServer(host, port string, handler http.Handler) *http.Server {
return &http.Server{
Addr: fmt.Sprintf("%s:%s", host, port),

57
middleware/log.go Normal file
View File

@@ -0,0 +1,57 @@
package middleware
import (
"bytes"
"energy-management-system/global"
"energy-management-system/utils/exception"
"github.com/gin-gonic/gin"
"io"
"net/url"
"strings"
"time"
)
func Log(c *gin.Context) {
// 开始时间
startTime := time.Now()
var body []byte
if c.Request.Method != "GET" {
if strings.Contains(c.GetHeader("Content-Type"), "application/json") {
var e error
if body, e = io.ReadAll(c.Request.Body); e == nil {
c.Request.Body = io.NopCloser(bytes.NewBuffer(body))
}
}
} // 处理请求
c.Next()
// 执行时间
latencyTime := time.Now().Sub(startTime).String()
// 日志格式
path, _ := url.PathUnescape(c.Request.RequestURI)
//
field := map[string]any{
"ip": c.ClientIP(),
"method": c.Request.Method,
"url": path,
"code": c.Writer.Status(),
"period": latencyTime,
"model": "gin",
}
if len(global.Log.Heads) > 0 {
for _, v := range global.Log.Heads {
field[v] = c.Request.Header.Get(v)
}
}
if err := c.Errors.Last(); err != nil {
if h, ok := err.Meta.(*exception.E); ok {
field["code"] = h.Code
field["errMsg"] = h.Msg
if h.Err != nil {
field["err"] = h.Err.Error()
}
}
global.Log.WithFields(field).Error(string(body))
} else {
global.Log.WithFields(field).Info(string(body))
}
}

View File

@@ -1,48 +1,2 @@
package middleware
import (
"energy-management-system/utils"
"energy-management-system/utils/exception"
"fmt"
"github.com/gin-gonic/gin"
"net"
"os"
"strings"
"time"
)
func Recovery() gin.HandlerFunc {
return func(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
var brokenPipe bool
if ne, ok := err.(*net.OpError); ok {
if se, ok := ne.Err.(*os.SyscallError); ok {
if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
brokenPipe = true
}
}
}
if brokenPipe {
c.Error(err.(error))
} else {
if h, ok := err.(*exception.Exception); ok {
exception.Panic(c, h)
c.Errors = append(c.Errors, &gin.Error{Meta: h})
} else if _, ok = err.(error); ok {
if gin.IsDebugging() {
fmt.Printf("[Recovery] %s : %s", utils.TimeFormat(time.Now()), err)
utils.Stack(3)
}
exception.Unknow(c)
} else {
fmt.Print(err)
exception.Server(c)
}
}
c.Abort()
}
}()
c.Next()
}
}

View File

@@ -2,104 +2,136 @@ package request
import (
"encoding/json"
req_validator "energy-management-system/request/validator"
"energy-management-system/utils/code"
"energy-management-system/utils/exception"
"errors"
"fmt"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/locales/en"
"github.com/go-playground/locales/zh"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
zhTranslations "github.com/go-playground/validator/v10/translations/zh"
"os"
"reflect"
"regexp"
"strconv"
"strings"
)
// Trans 定义一个全局翻译器T
var trans ut.Translator
var validate *validator.Validate
var ok bool
//var trans ut.Translator
//var validate *validator.Validate
//var ok bool
// InitTrans 初始化翻译器
func InitTrans(locale ...string) {
if len(locale) == 0 {
locale = []string{"zh"}
}
// 修改gin框架中的Validator引擎属性实现自定制
if validate, ok = binding.Validator.Engine().(*validator.Validate); ok {
//func InitTrans(locale ...string) {
// if len(locale) == 0 {
// locale = []string{"zh"}
// }
// // 修改gin框架中的Validator引擎属性实现自定制
// if validate, ok = binding.Validator.Engine().(*validator.Validate); ok {
//
// // zi
// //validate.SetTagName("ss")
//
// validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
// name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
// if name == "-" || name == "_" {
// return ""
// }
// return name
// })
//
// // 第一个参数是备用fallback的语言环境
// uni := ut.New(en.New(), zh.New())
// trans, _ = uni.FindTranslator(locale[0])
// // 注册翻译器
// err := zhTranslations.RegisterDefaultTranslations(validate, trans)
//
// // 注册自定义验证
// validate.RegisterValidation("mobile", func(fl validator.FieldLevel) bool {
// regRuler := "^1[3456789]{1}\\d{9}$"
// reg := regexp.MustCompile(regRuler)
// return reg.MatchString(fl.Field().String())
// })
//
// // 注册自定义验证的翻译
// validate.RegisterTranslation("mobile", trans, func(ut ut.Translator) error {
// return ut.Add("mobile", "手机号错误!", true)
// }, func(ut ut.Translator, fe validator.FieldError) string {
// t, _ := ut.T("mobile", fe.Field())
// return t
// })
//
// if err != nil {
// fmt.Printf("[-]自定义gin验证器失败: %s \n", err)
// os.Exit(0)
// }
// }
//}
// zi
//validate.SetTagName("ss")
//func BindJson(c *gin.Context, f interface{}) {
// dealWithError(c.ShouldBindJSON(f), "JSON")
//}
//func BindJsonWith(c *gin.Context, f interface{}) {
// dealWithError(c.ShouldBindBodyWith(f, binding.JSON), "JSON")
//}
//func BindParam(c *gin.Context, f interface{}) {
// dealWithError(c.ShouldBindQuery(f), "FORM")
//}
//
//func dealWithError(err error, t string) {
// if err != nil {
// var validationErrors validator.ValidationErrors
// var unmarshalTypeError *json.UnmarshalTypeError
// var numError *strconv.NumError
// switch {
// case errors.As(err, &validationErrors):
// exception.PanicMsg(removeTopStruct(err.(validator.ValidationErrors).Translate(trans)))
// case errors.As(err, &unmarshalTypeError):
// exception.PanicCodeMsg(code.PARAMETER_ERROR, err.(*json.UnmarshalTypeError).Field+": 类型错误")
// case errors.As(err, &numError):
// exception.PanicCodeMsg(code.PARAMETER_ERROR, err.(*strconv.NumError).Num+": 类型错误")
// default:
// exception.PanicCodeMsg(code.PARAMETER_ERROR, fmt.Sprintf("请将参数放于%s中传递: ", t)+err.Error())
// }
// }
//}
//
//func removeTopStruct(fields map[string]string) (re []string) {
// for _, err := range fields {
// re = append(re, err)
// }
// return
//}
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
if name == "-" || name == "_" {
return ""
}
return name
})
// 第一个参数是备用fallback的语言环境
uni := ut.New(en.New(), zh.New())
trans, _ = uni.FindTranslator(locale[0])
// 注册翻译器
err := zhTranslations.RegisterDefaultTranslations(validate, trans)
// 注册自定义验证
validate.RegisterValidation("mobile", func(fl validator.FieldLevel) bool {
regRuler := "^1[3456789]{1}\\d{9}$"
reg := regexp.MustCompile(regRuler)
return reg.MatchString(fl.Field().String())
})
// 注册自定义验证的翻译
validate.RegisterTranslation("mobile", trans, func(ut ut.Translator) error {
return ut.Add("mobile", "手机号错误!", true)
}, func(ut ut.Translator, fe validator.FieldError) string {
t, _ := ut.T("mobile", fe.Field())
return t
})
if err != nil {
fmt.Printf("[-]自定义gin验证器失败: %s \n", err)
os.Exit(0)
}
}
func BindJson(c *gin.Context, f any) {
err := c.ShouldBindJSON(f)
//if gin.IsDebugging() {
// c.Set("_req", f)
//doc.SetReq(c, f)
//}
DealValidError(err, "JSON")
}
func BindJsonWith(c *gin.Context, f any) {
DealValidError(c.ShouldBindBodyWith(f, binding.JSON), "JSON")
}
func BindParam(c *gin.Context, f any) {
err := c.ShouldBindQuery(f)
//doc.SetReq(c, f)
DealValidError(err, "FORM")
}
func BindJson(c *gin.Context, f interface{}) {
dealWithError(c.ShouldBindJSON(f), "JSON")
}
func BindJsonWith(c *gin.Context, f interface{}) {
dealWithError(c.ShouldBindBodyWith(f, binding.JSON), "JSON")
}
func BindParam(c *gin.Context, f interface{}) {
dealWithError(c.ShouldBindQuery(f), "FORM")
}
func dealWithError(err error, t string) {
func DealValidError(err error, t string) {
if err != nil {
var validationErrors validator.ValidationErrors
var unmarshalTypeError *json.UnmarshalTypeError
var numError *strconv.NumError
switch {
case errors.As(err, &validationErrors):
exception.PanicMsg(removeTopStruct(err.(validator.ValidationErrors).Translate(trans)))
case errors.As(err, &unmarshalTypeError):
exception.PanicCodeMsg(exception.PARAMETER_ERROR, err.(*json.UnmarshalTypeError).Field+": 类型错误")
case errors.As(err, &numError):
exception.PanicCodeMsg(exception.PARAMETER_ERROR, err.(*strconv.NumError).Num+": 类型错误")
switch err.(type) {
case validator.ValidationErrors:
exception.PM(RemoveTopStruct(err.(validator.ValidationErrors).Translate(req_validator.Trans)))
case *json.UnmarshalTypeError:
exception.PMC(err.(*json.UnmarshalTypeError).Field+": 类型错误", code.PARAMETER_ERROR)
case *strconv.NumError:
exception.PMC(err.(*strconv.NumError).Num+": 类型错误", code.PARAMETER_ERROR)
default:
exception.PanicCodeMsg(exception.PARAMETER_ERROR, fmt.Sprintf("请将参数放于%s中传递: ", t)+err.Error())
exception.PMC(fmt.Sprintf("请将参数放于%s中传递: ", t)+err.Error(), code.PARAMETER_ERROR)
}
}
}
func removeTopStruct(fields map[string]string) (re []string) {
func RemoveTopStruct(fields map[string]string) (re []string) {
for _, err := range fields {
re = append(re, err)
}

View File

@@ -0,0 +1,57 @@
package validator
import (
"fmt"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/locales/en"
"github.com/go-playground/locales/zh"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
zhTranslations "github.com/go-playground/validator/v10/translations/zh"
"os"
"reflect"
"regexp"
"strings"
)
// 定义一个全局翻译器T
var Trans ut.Translator
var Validate *validator.Validate
// InitTrans 初始化翻译器
func InitTrans(locale ...string) {
if len(locale) == 0 {
locale = []string{"zh"}
}
var ok bool
if Validate, ok = binding.Validator.Engine().(*validator.Validate); ok {
Validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
if name == "-" || name == "_" {
return ""
}
return name
})
uni := ut.New(en.New(), zh.New())
Trans, _ = uni.FindTranslator(locale[0])
err := zhTranslations.RegisterDefaultTranslations(Validate, Trans)
Validate.RegisterValidation("mobile", func(fl validator.FieldLevel) bool {
regRuler := "^1[3456789]{1}\\d{9}$"
reg := regexp.MustCompile(regRuler)
return reg.MatchString(fl.Field().String())
})
Validate.RegisterTranslation("mobile", Trans, func(ut ut.Translator) error {
return ut.Add("mobile", "手机号错误!", true)
}, func(ut ut.Translator, fe validator.FieldError) string {
t, _ := ut.T("mobile", fe.Field())
return t
})
if err != nil {
fmt.Printf("[-]自定义gin验证器失败: %s \n", err)
os.Exit(1)
}
}
}

View File

@@ -1,7 +1,7 @@
package response
import (
"energy-management-system/utils/exception"
"energy-management-system/utils/code"
"github.com/gin-gonic/gin"
"net/http"
)
@@ -22,9 +22,9 @@ func Success(c *gin.Context) {
}
func SuccessMsg(message string, c *gin.Context) {
Result(exception.SUCCESS, map[string]interface{}{}, message, c)
Result(code.SUCCESS, map[string]interface{}{}, message, c)
}
func SuccessData(data interface{}, c *gin.Context) {
Result(exception.SUCCESS, data, "操作成功", c)
Result(code.SUCCESS, data, "操作成功", c)
}

View File

@@ -2,18 +2,36 @@ package router
import (
v1 "energy-management-system/api/v1"
"energy-management-system/global"
"energy-management-system/middleware"
"energy-management-system/router/routes"
"energy-management-system/utils/code"
"energy-management-system/utils/exception"
"energy-management-system/utils/recovery"
"github.com/gin-gonic/gin"
"net/http"
)
func InitRouter() *gin.Engine {
gin.SetMode(gin.DebugMode)
if global.AppConf.IsDebug {
gin.SetMode(gin.DebugMode)
} else {
gin.SetMode("release")
}
r := gin.Default()
r.NoRoute(exception.NotFoundR)
r.NoMethod(exception.NotFoundM)
r.Use(middleware.Cors(), middleware.Recovery())
//r.NoRoute(exception.NotFoundR)
//r.NoMethod(exception.NotFoundM)
r.NoRoute(func(c *gin.Context) {
c.JSON(http.StatusForbidden, exception.E{Code: code.NOT_FOUND_ROUTE, Msg: "Not Found Route", Err: nil})
})
r.NoMethod(func(c *gin.Context) {
c.JSON(http.StatusForbidden, exception.E{Code: code.NOT_FOUND_METH, Msg: "Not Found Method"})
})
r.Use(middleware.Cors(), middleware.Log, recovery.GinRecovery)
api := r.Group("api")
{
controllersV1 := new(v1.Controller)

View File

@@ -20,7 +20,7 @@ type PeakValley struct{}
func (r *PeakValley) PeakValleyQuarterPage(req *form.PeakValleyQuarterListReq) map[string]interface{} {
count, list, err := repository.GroupRepositorys.PeakValley.GetPeakValleyQuarterPage(req)
if err != nil {
exception.PanicMsgErr(err, "获取列表失败")
exception.PEM(err, "获取列表失败")
//return
}
ListRsp := make(map[string]interface{})
@@ -32,7 +32,7 @@ func (r *PeakValley) PeakValleyQuarterPage(req *form.PeakValleyQuarterListReq) m
// PeakValleyQuarterEditDetail 获取季度详情-编辑使用
func (r *PeakValley) PeakValleyQuarterEditDetail(req *form.PeakValleyQuarterEditDetailReq) *peak_valley_model.PeakValleyQuarter {
pvq, err := repository.GroupRepositorys.PeakValley.GetOnePeakValleyQuarter(map[string]interface{}{"id": req.Id})
exception.PanicMsgBool(err != nil, "获取季度详情失败")
exception.PBM(err != nil, "获取季度详情失败")
return pvq
}
@@ -44,11 +44,11 @@ func (r *PeakValley) CreatePeakValleyQuarter(req *form.CreatePeakValleyQuarterRe
pvq.Rid = req.RuleId
startTime, err := time.Parse("2006-01-02", req.StartTime)
endTime, err := time.Parse("2006-01-02", req.EndTime)
exception.PanicMsgBool(err != nil, "时间解析失败")
exception.PBM(err != nil, "时间解析失败")
pvq.StartTime = startTime
pvq.EndTime = endTime
err = repository.GroupRepositorys.PeakValley.CreatePeakValleyQuarter(pvq)
exception.PanicMsgBool(err != nil, "创建季度失败")
exception.PBM(err != nil, "创建季度失败")
return
}
@@ -56,16 +56,16 @@ func (r *PeakValley) CreatePeakValleyQuarter(req *form.CreatePeakValleyQuarterRe
func (r *PeakValley) UpdatePeakValleyQuarter(req *form.UpdatePeakValleyQuarterReq) {
var err error
pvq, err := repository.GroupRepositorys.PeakValley.GetOnePeakValleyQuarter(map[string]interface{}{"id": req.Id})
exception.PanicMsgBool(err != nil, "修改季度失败")
exception.PBM(err != nil, "修改季度失败")
startTime, err := time.Parse("2006-01-02", req.StartTime)
endTime, err := time.Parse("2006-01-02", req.EndTime)
exception.PanicMsgBool(err != nil, "时间解析失败")
exception.PBM(err != nil, "时间解析失败")
pvq.QuarterName = req.QuarterName
pvq.Rid = req.RuleId
pvq.StartTime = startTime
pvq.EndTime = endTime
err = repository.GroupRepositorys.PeakValley.UpdatePeakValleyQuarter(pvq)
exception.PanicMsgBool(err != nil, "修改季度失败")
exception.PBM(err != nil, "修改季度失败")
return
}
@@ -90,15 +90,15 @@ func (r *PeakValley) CreatePeakValleyRule(req *form.CreatePeakValleyRuleReq) {
if rec := recover(); rec != nil {
tx.Rollback() // 如果发生错误,回滚事务
fmt.Println("事务回滚")
exception.PanicMsg(rec)
exception.PM(rec)
} else if err != nil {
tx.Rollback() // 错误时回滚事务
fmt.Println("事务回滚")
exception.PanicMsgErr(err, err.Error())
exception.PEM(err, err.Error())
} else {
err = tx.Commit().Error // 提交事务
if err != nil {
exception.PanicMsgErr(err, "事务提交失败")
exception.PEM(err, "事务提交失败")
}
}
}()
@@ -180,15 +180,15 @@ func (r *PeakValley) UpdatePeakValleyRule(req *form.UpdatePeakValleyRuleReq) {
if rec := recover(); rec != nil {
tx.Rollback() // 如果发生错误,回滚事务
fmt.Println("事务回滚1", rec)
exception.PanicMsg(rec)
exception.PM(rec)
} else if err != nil {
tx.Rollback() // 错误时回滚事务
fmt.Println("事务回滚2", err)
exception.PanicMsgErr(err, err.Error())
exception.PEM(err, err.Error())
} else {
err = tx.Commit().Error // 提交事务
if err != nil {
exception.PanicMsgErr(err, "事务提交失败")
exception.PEM(err, "事务提交失败")
}
}
}()
@@ -235,7 +235,7 @@ func (r *PeakValley) UpdatePeakValleyRule(req *form.UpdatePeakValleyRuleReq) {
return
}
timeBlockIds, err = repository.GroupRepositorys.PeakValley.GetTimeBlockIdsByTimeBlock(tx, uint(start), uint(end))
exception.PanicMsgBool(err != nil, "获取时间区块ID列表失败")
exception.PBM(err != nil, "获取时间区块ID列表失败")
timeBlockIdsMap[item.StartTime+item.EndTime] = timeBlockIds
}
if total < peak_valley_model.MinutesInADay {
@@ -273,7 +273,7 @@ func (r *PeakValley) UpdatePeakValleyRule(req *form.UpdatePeakValleyRuleReq) {
func (r *PeakValley) GetPeakValleyRulePage(req *form.PeakValleyRuleListReq) map[string]interface{} {
count, list, err := repository.GroupRepositorys.PeakValley.GetPeakValleyRulePage(req)
if err != nil {
exception.PanicMsgErr(err, "获取列表失败")
exception.PEM(err, "获取列表失败")
//return
}
ListRsp := make(map[string]interface{})
@@ -287,23 +287,23 @@ func (r *PeakValley) PeakValleyRuleDetail(req *form.PeakValleyRuleDetailReq) map
// 获取分了多少个时间段 以及每个时间段的自定义名称 峰谷类型
ruleTypes, err := repository.GroupRepositorys.PeakValley.GetPeakValleyRuleTypes(req.RuleId)
fmt.Println(ruleTypes)
exception.PanicMsgBool(err != nil, "获取规则区块类型失败1")
exception.PBM(err != nil, "获取规则区块类型失败1")
// 查询指定规则 指定峰谷类型的区块
for idx, ruleType := range ruleTypes {
// 查询当前类型的时间区块
typeBlockList, err := repository.GroupRepositorys.PeakValley.GetPeakValleyRulePriceByTypeAndRuleID(uint(req.RuleId), ruleType.PeakValleyType)
exception.PanicMsgBool(err != nil, "获取规则区块类型失败2")
exception.PBM(err != nil, "获取规则区块类型失败2")
// 根据连贯性 小区块 组合成大区块 (一个区块 或者多个区块)
blocks := utils.SplitIntoGroups(typeBlockList)
for _, block := range blocks {
maxBlockId, minBlockId, err := utils.GetSplitIntMaxMin(block)
exception.PanicMsgBool(err != nil, "获取规则区块类型失败3")
exception.PBM(err != nil, "获取规则区块类型失败3")
customName, err := repository.GroupRepositorys.PeakValley.GetPeakValleyRulePriceCustomName(minBlockId, uint(req.RuleId))
exception.PanicMsgBool(err != nil, "获取规则区块类型失败4")
exception.PBM(err != nil, "获取规则区块类型失败4")
startTime, err := repository.GroupRepositorys.PeakValley.GetBlockStartTime(minBlockId)
exception.PanicMsgBool(err != nil, "获取规则区块类型失败5")
exception.PBM(err != nil, "获取规则区块类型失败5")
endTime, err := repository.GroupRepositorys.PeakValley.GetBlockEndTime(maxBlockId)
exception.PanicMsgBool(err != nil, "获取规则区块类型失败6")
exception.PBM(err != nil, "获取规则区块类型失败6")
startTimeStr := fmt.Sprintf("%02d:%02d", startTime/60, startTime%60)
endTimeStr := fmt.Sprintf("%02d:%02d", endTime/60, endTime%60)
ruleTimeBlock := peak_valley_model.RuleTimeBlock{
@@ -326,21 +326,21 @@ func (r *PeakValley) PeakValleyRuleDetail(req *form.PeakValleyRuleDetailReq) map
// PeakValleyRuleEditDetail 获取规则详情-编辑使用
func (r *PeakValley) PeakValleyRuleEditDetail(req *form.PeakValleyRuleEditDetailReq) map[string]interface{} {
pvr, err := repository.GroupRepositorys.PeakValley.GetOnePeakValleyRule(map[string]interface{}{"rule_id": req.RuleId})
exception.PanicMsgBool(err != nil, "获取规则详情失败")
exception.PBM(err != nil, "获取规则详情失败")
// 获取分了多少个时间段 以及每个时间段的自定义名称 峰谷类型
customNames, err := repository.GroupRepositorys.PeakValley.GetPeakValleyRuleCustomName(req.RuleId)
exception.PanicMsgBool(err != nil, "获取规则区块类型失败1")
exception.PBM(err != nil, "获取规则区块类型失败1")
// 查询指定规则 指定峰谷类型的区块
for idx, customName := range customNames {
// 查询当前类型的时间区块
customNameBlockList, err := repository.GroupRepositorys.PeakValley.GetPeakValleyRulePriceByCustomNameAndRuleID(uint(req.RuleId), customName.CustomName)
exception.PanicMsgBool(err != nil, "获取规则区块类型失败2")
exception.PBM(err != nil, "获取规则区块类型失败2")
maxBlockId, minBlockId, err := utils.GetSplitIntMaxMin(customNameBlockList)
exception.PanicMsgBool(err != nil, "获取规则区块类型失败3")
exception.PBM(err != nil, "获取规则区块类型失败3")
startTime, err := repository.GroupRepositorys.PeakValley.GetBlockStartTime(minBlockId)
exception.PanicMsgBool(err != nil, "获取规则区块类型失败4")
exception.PBM(err != nil, "获取规则区块类型失败4")
endTime, err := repository.GroupRepositorys.PeakValley.GetBlockEndTime(maxBlockId)
exception.PanicMsgBool(err != nil, "获取规则区块类型失败5")
exception.PBM(err != nil, "获取规则区块类型失败5")
startTimeStr := fmt.Sprintf("%02d:%02d", startTime/60, startTime%60)
endTimeStr := fmt.Sprintf("%02d:%02d", endTime/60, endTime%60)
//dump.P(customNameBlockList)

View File

@@ -1,4 +1,4 @@
package exception
package code
const (
SUCCESS = 1 // 操作成功
@@ -23,25 +23,3 @@ const (
DB_ERRROR = 10027 // 数据库错误
SENSITIVE = 10028 // 敏感词语
)
const (
//用户
NOT_FOUND_USER = 20001 // 未查询到用户
EXIST_USER = 20002 // 用户已存在
NO_BELONG_ACTION = 20003 // 越权操作
NO_PHONE = 20004 // 未验证手机号
//订单
ORDER_ERROR = 20100 // 订单统用错误
NO_ORDER = 20101 // 订单不存在
NO_PAID_ORDER = 20102 // 订单未支付
PAID_ORDER = 20103 // 订单已支付
EXPIRE_ORDER = 20104 // 订单超时
DONE_ORDER = 20105 // 订单已完结
NO_BELONG_ORDER = 20106 // 不属于自己的订单
//积分
SIGNED = 20200 // 已签到
NO_ENOUGH_POINT = 20201 // 积分不足
NO_ILLEGAL_CHANNEL = 20202 // 渠道非法
NO_ILLEGAL_SIGN = 20203 // 渠道非签到
)

View File

@@ -1,81 +1,164 @@
package exception
import (
"energy-management-system/utils"
"net/http"
"energy-management-system/utils/code"
"fmt"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"net/http"
)
type Exception struct {
HttpCode int `json:"-"`
Code int `json:"code"`
Msg interface{} `json:"msg"`
Err error `json:"err"`
type E struct {
Code int `json:"code"`
Msg any `json:"msg"`
Err error `json:"-"`
}
type ExceptionResponse struct {
Code int `json:"code"`
Msg interface{} `json:"msg"`
Path string `json:"path"`
}
func (r *Exception) Error() interface{} {
return r.Msg
}
func NotFoundR(c *gin.Context) {
c.JSON(http.StatusForbidden, ExceptionResponse{NOT_FOUND_ROUTE, "Not Found Route", utils.GetReqPath(c)})
}
func NotFoundM(c *gin.Context) {
c.JSON(http.StatusForbidden, ExceptionResponse{NOT_FOUND_METH, "Not Found Method", utils.GetReqPath(c)})
}
func Panic(c *gin.Context, e *Exception) {
c.JSON(e.HttpCode, ExceptionResponse{e.Code, e.Msg, utils.GetReqPath(c)})
}
func Unknow(c *gin.Context) {
c.JSON(http.StatusForbidden, ExceptionResponse{UNKNOW_ERROR, "未知错误", utils.GetReqPath(c)})
}
func Server(c *gin.Context) {
c.JSON(http.StatusInternalServerError, ExceptionResponse{SERVER_ERROR, "服务器错误", utils.GetReqPath(c)})
}
// FailMsg 主动抛出错误Exception类型
func FailMsg(msg interface{}) *Exception {
return &Exception{http.StatusOK, ERROR, msg, nil}
}
func FailCodeMsg(code int, msg string) *Exception {
return &Exception{http.StatusOK, code, msg, nil}
}
func PanicMsg(msg interface{}) {
PanicMsgBool(true, msg)
}
func PanicCodeMsg(code int, msg string) {
PanicCodeMsgBool(true, code, msg)
}
func PanicMsgBool(flag bool, msg interface{}) {
if flag {
panic(&Exception{http.StatusOK, ERROR, msg, nil})
}
}
func PanicCodeMsgBool(flag bool, code int, msg string) {
if flag {
panic(&Exception{http.StatusOK, code, msg, nil})
func (r E) Error() string {
if r.Err != nil {
return fmt.Sprintf(`{\"code\":%d;\"msg\":\"%v\",\"err\":\"%s\"}`, r.Code, r.Msg, r.Err.Error())
} else {
return fmt.Sprintf(`{\"code\":%d;\"msg\":\"%v\"}`, r.Code, r.Msg)
}
}
func PanicMsgErr(err error, msg interface{}) {
func (r E) Return(c *gin.Context) {
c.JSON(http.StatusOK, r)
}
func NE(msg any) error {
return NEC(msg, code.ERROR)
}
func NEC(msg any, code int) error {
return &E{
Msg: msg,
Code: code,
}
}
func NEE(err error, msg string) error {
return NEEC(err, msg, code.ERROR)
}
func NEEC(err error, msg string, code int) error {
if err != nil {
panic(&Exception{http.StatusOK, ERROR, msg, err})
return &E{
Msg: msg,
Code: code,
Err: err,
}
}
return nil
}
func PM(msg any) {
panic(&E{code.ERROR, msg, nil})
}
func PMC(msg any, code int) {
panic(&E{code, msg, nil})
}
func PBM(flag bool, msg any) {
if flag {
panic(&E{code.ERROR, msg, nil})
}
}
func PanicCodeMsgErr(err error, code int, msg string) {
func PBMC(flag bool, msg any, code int) {
if flag {
panic(&E{code, msg, nil})
}
}
func PEM(err error, msg any) {
if err != nil {
panic(&Exception{http.StatusOK, code, msg, err})
panic(&E{code.ERROR, msg, err})
}
}
func PEMC(err error, msg any, code int) {
if err != nil {
panic(&E{code, msg, err})
}
}
func PDM(db *gorm.DB, msgs ...string) {
if db.Error != nil {
msg := "未查询到"
if len(msgs) > 0 {
msg = msgs[0]
}
panic(&E{code.ERROR, msg, db.Error})
}
}
//type Exception struct {
// HttpCode int `json:"-"`
// Code int `json:"code"`
// Msg interface{} `json:"msg"`
// Err error `json:"err"`
//}
//
//type ExceptionResponse struct {
// Code int `json:"code"`
// Msg interface{} `json:"msg"`
// Path string `json:"path"`
//}
//
//func (r *Exception) Error() interface{} {
// return r.Msg
//}
//
//func NotFoundR(c *gin.Context) {
// c.JSON(http.StatusForbidden, ExceptionResponse{NOT_FOUND_ROUTE, "Not Found Route", utils.GetReqPath(c)})
//}
//
//func NotFoundM(c *gin.Context) {
// c.JSON(http.StatusForbidden, ExceptionResponse{NOT_FOUND_METH, "Not Found Method", utils.GetReqPath(c)})
//}
//
//func Panic(c *gin.Context, e *Exception) {
// c.JSON(e.HttpCode, ExceptionResponse{e.Code, e.Msg, utils.GetReqPath(c)})
//}
//func Unknow(c *gin.Context) {
// c.JSON(http.StatusForbidden, ExceptionResponse{UNKNOW_ERROR, "未知错误", utils.GetReqPath(c)})
//}
//func Server(c *gin.Context) {
// c.JSON(http.StatusInternalServerError, ExceptionResponse{SERVER_ERROR, "服务器错误", utils.GetReqPath(c)})
//}
//
//// FailMsg 主动抛出错误Exception类型
//func FailMsg(msg interface{}) *Exception {
// return &Exception{http.StatusOK, ERROR, msg, nil}
//}
//
//func FailCodeMsg(code int, msg string) *Exception {
// return &Exception{http.StatusOK, code, msg, nil}
//}
//
//func PanicMsg(msg interface{}) {
// PanicMsgBool(true, msg)
//}
//func PanicCodeMsg(code int, msg string) {
// PanicCodeMsgBool(true, code, msg)
//}
//
//func PanicMsgBool(flag bool, msg interface{}) {
// if flag {
// panic(&Exception{http.StatusOK, ERROR, msg, nil})
// }
//}
//func PanicCodeMsgBool(flag bool, code int, msg string) {
// if flag {
// panic(&Exception{http.StatusOK, code, msg, nil})
// }
//}
//
//func PanicMsgErr(err error, msg interface{}) {
// if err != nil {
// panic(&Exception{http.StatusOK, ERROR, msg, err})
// }
//}
//func PanicCodeMsgErr(err error, code int, msg string) {
// if err != nil {
// panic(&Exception{http.StatusOK, code, msg, err})
// }
//}

View File

@@ -0,0 +1,36 @@
package recovery
import (
"energy-management-system/core/logger"
"energy-management-system/global"
"energy-management-system/utils/code"
"energy-management-system/utils/exception"
"fmt"
)
func CronRecovery(name string) {
if err := recover(); err != nil {
var codes int
var msg any
var er error
if h, ok := err.(*exception.E); ok {
codes = h.Code
msg = h.Msg
er = h.Err
} else if e, ok := err.(error); ok {
msg = fmt.Sprint("未知错误:", e.Error())
logger.StackSend(5, e.Error())
codes = code.UNKNOW_ERROR
} else {
msg = fmt.Sprint("服务器错误:", err)
logger.StackSend(5, err.(string))
codes = code.SERVER_ERROR
}
global.Log.WithFields(map[string]any{
"code": codes,
"model": "task",
"func": name,
"err": er,
}).Error(msg)
}
}

View File

@@ -0,0 +1,86 @@
package recovery
import (
"energy-management-system/core/logger"
"energy-management-system/global"
"energy-management-system/utils"
"energy-management-system/utils/code"
"energy-management-system/utils/exception"
"github.com/gin-gonic/gin"
"net"
"net/http"
"os"
"strings"
)
func GinRecovery(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
var brokenPipe bool
if ne, ok := err.(*net.OpError); ok {
if se, ok := ne.Err.(*os.SyscallError); ok {
if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
brokenPipe = true
}
}
}
if brokenPipe {
c.Error(err.(error))
} else {
if req, ok := c.Get("_req"); ok {
global.Log.Errorln("获取参数:", utils.String(req))
}
if h, ok := err.(*exception.E); ok {
h.Return(c)
c.Errors = append(c.Errors, &gin.Error{Meta: h})
} else if e, ok := err.(error); ok {
global.Log.Errorln("未知错误:", err)
logger.StackSend(3, e.Error())
c.JSON(http.StatusForbidden, exception.E{code.UNKNOW_ERROR, "未知错误", nil})
} else {
global.Log.Errorln("服务器错误:", err)
logger.StackSend(3, err.(string))
c.JSON(http.StatusForbidden, exception.E{code.SERVER_ERROR, "服务器错误", nil})
}
}
c.Abort()
}
}()
c.Next()
}
//func GinRecovery() gin.HandlerFunc {
// return func(c *gin.Context) {
// defer func() {
// if err := recover(); err != nil {
// var brokenPipe bool
// if ne, ok := err.(*net.OpError); ok {
// if se, ok := ne.Err.(*os.SyscallError); ok {
// if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
// brokenPipe = true
// }
// }
// }
// if brokenPipe {
// c.Error(err.(error))
// } else {
// if h, ok := err.(*exception.Exception); ok {
// exception.Panic(c, h)
// c.Errors = append(c.Errors, &gin.Error{Meta: h})
// } else if _, ok = err.(error); ok {
// if gin.IsDebugging() {
// fmt.Printf("[Recovery] %s : %s", utils.TimeFormat(time.Now()), err)
// utils.Stack(3)
// }
// exception.Unknow(c)
// } else {
// fmt.Print(err)
// exception.Server(c)
// }
// }
// c.Abort()
// }
// }()
// c.Next()
// }
//}

179
utils/string.go Normal file
View File

@@ -0,0 +1,179 @@
package utils
import (
"encoding/json"
"fmt"
"reflect"
"regexp"
"strconv"
"strings"
"time"
"unicode"
)
func ReplaceDownLine(req string) (res string) {
for _, v := range req {
if 64 < v && v < 91 {
res = res + "_" + string(v+32)
} else {
res += string(v)
}
}
return strings.TrimRight(strings.TrimLeft(res, "_"), "_")
}
func String(data any) string {
if data == nil {
return ""
}
switch value := data.(type) {
case int:
return strconv.Itoa(value)
case int8:
return strconv.Itoa(int(value))
case int16:
return strconv.Itoa(int(value))
case int32:
return strconv.Itoa(int(value))
case int64:
return strconv.FormatInt(value, 10)
case uint:
return strconv.FormatUint(uint64(value), 10)
case uint8:
return strconv.FormatUint(uint64(value), 10)
case uint16:
return strconv.FormatUint(uint64(value), 10)
case uint32:
return strconv.FormatUint(uint64(value), 10)
case uint64:
return strconv.FormatUint(value, 10)
case float32:
return strconv.FormatFloat(float64(value), 'f', -1, 32)
case float64:
return strconv.FormatFloat(value, 'f', -1, 64)
case bool:
return strconv.FormatBool(value)
case string:
return value
case []byte:
return string(value)
case time.Time:
if value.IsZero() {
return ""
}
return value.String()
case *time.Time:
if value == nil {
return ""
}
return value.String()
default:
// Empty checks.
if value == nil {
return ""
}
var (
rv = reflect.ValueOf(value)
kind = rv.Kind()
)
switch kind {
case reflect.Chan,
reflect.Map,
reflect.Slice,
reflect.Func,
reflect.Ptr,
reflect.Interface,
reflect.UnsafePointer:
if rv.IsNil() {
return ""
}
case reflect.String:
return rv.String()
}
if kind == reflect.Ptr {
return String(rv.Elem().Interface())
}
// Finally, we use json.Marshal to convert.
jsonContent, err := json.Marshal(value)
if err != nil {
return fmt.Sprint(value)
} else {
return string(jsonContent)
}
}
}
func IsNumber(s string) bool {
_, err := strconv.ParseFloat(s, 64)
return err == nil
}
func ContainChinese(str string) bool {
for _, r := range str {
if unicode.Is(unicode.Scripts["Han"], r) || (regexp.MustCompile("[\u3002\uff1b\uff0c\uff1a\u201c\u201d\uff08\uff09\u3001\uff1f\u300a\u300b]").MatchString(string(r))) {
return true
}
}
return false
}
func Contains(ids []string, id string) bool {
for _, v := range ids {
if strings.Compare(v, id) == 0 {
return true
}
}
return false
}
// contain one of subs
func ContainSub(str string, subs ...string) bool {
for _, sub := range subs {
if strings.Contains(str, sub) {
return true
}
}
return false
}
// must contain all subs
func ContainSubs(str string, subs ...string) bool {
for _, sub := range subs {
if strings.Contains(str, sub) {
continue
} else {
return false
}
}
return true
}
func Duplicate(slc []string) []string {
result := make([]string, 0)
tempMap := make(map[string]bool, len(slc))
for _, e := range slc {
if tempMap[e] == false {
tempMap[e] = true
result = append(result, e)
}
}
return result
}
func Capitalize(str string) string {
var upperStr string
vv := []rune(str)
for i := 0; i < len(vv); i++ {
if i == 0 {
if vv[i] >= 97 && vv[i] <= 122 {
vv[i] -= 32 // string的码表相差32位
upperStr += string(vv[i])
} else {
return str
}
} else {
upperStr += string(vv[i])
}
}
return upperStr
}

View File

@@ -13,6 +13,21 @@ import (
"time"
)
func Exit(err any, str string) {
switch arg := err.(type) {
case error:
if arg != nil {
fmt.Println(str, arg.Error())
os.Exit(1)
}
case bool:
if arg {
fmt.Println(str, err)
os.Exit(1)
}
}
}
func GetReqPath(c *gin.Context) string {
return c.Request.Method + " " + c.Request.URL.String()
}