Commit 6ccf677b by swh

支持template

parent 1a0f2f41
...@@ -3,21 +3,52 @@ package main ...@@ -3,21 +3,52 @@ package main
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"errors"
"flag" "flag"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"os" "os"
"path"
"path/filepath"
"regexp" "regexp"
"runtime"
"strings" "strings"
) )
var sqlAddr = flag.String("sql", "", "sql file path") var sqlAddr = flag.String("sql", "", "sql file path")
var targetAddr = flag.String("dir", "", "model produced path") var action = flag.String("a", "", "action")
var name = flag.String("name", "", "project name")
var targetAddr = flag.String("dir", "", "code produced path")
func main() { func main() {
flag.Parse() flag.Parse()
if *sqlAddr == "" || !checkFileIsExist(*sqlAddr){ switch *action {
case "model":
model()
case "template":
template()
default:
fmt.Println("action miss")
}
}
func getCurrentPath() string {
var abPath string
_, filename, _, ok := runtime.Caller(0)
if ok {
abPath = path.Dir(filename)
}
return abPath + "/"
}
func template() {
CopyDir(getCurrentPath() + "template", *targetAddr, *name)
fmt.Println("项目创建成功")
}
func model() {
if *sqlAddr == "" || !checkFileIsExist(*sqlAddr) {
fmt.Println("sql路径不存在") fmt.Println("sql路径不存在")
return return
} }
...@@ -26,26 +57,43 @@ func main() { ...@@ -26,26 +57,43 @@ func main() {
fmt.Println("请输入文件生成地址") fmt.Println("请输入文件生成地址")
return return
} }
//判断文件生成地址是否存在
if b, _ := pathExists(*targetAddr); !b {
err := os.Mkdir(*targetAddr, os.ModePerm)
if err != nil {
fmt.Println(err)
return
}
}
bt, _ := os.ReadFile(*sqlAddr) bt, _ := os.ReadFile(*sqlAddr)
arr := strings.Split(string(bt), ";") arr := strings.Split(string(bt), ";")
funcTemplateByte, err := ioutil.ReadFile(getCurrentPath() + "model.tpl")
funcTemplateStr := string(funcTemplateByte)
if err != nil {
fmt.Println(err)
return
}
for _, v := range arr { for _, v := range arr {
if v != "" && v != "\n" && v != "\r\n" { if v != "" && v != "\n" && v != "\r\n" {
sqlName := regexpData(v, "CREATE TABLE `(.*?)` ") sqlName := regexpData(v, "CREATE TABLE `(.*?)` ")
dir := *targetAddr dir := *targetAddr
dir = strings.TrimRight(dir, "/") dir = strings.TrimRight(dir, "/")
filename := dir + "/" + Case2Camel(sqlName) + ".go" filename := dir + "/" + Case2Camel(sqlName) + ".go"
if !checkFileIsExist(filename) { //如果文件存在 if !checkFileIsExist(filename) { //如果文件存在
var result struct{ var result struct {
Data string `json:"data"` Data string `json:"data"`
Error string `json:"error"` Error string `json:"error"`
} }
res, _ := Request("https://www.printlove.cn/api/sql2gorm", map[string]interface{}{ res, _ := Request("https://www.printlove.cn/api/sql2gorm", map[string]interface{}{
"ddl" : v + ";", "ddl": v + ";",
}, map[string]interface{}{}, "POST", "form") }, map[string]interface{}{}, "POST", "form")
json.Unmarshal(res, &result) json.Unmarshal(res, &result)
structName := regexpData(result.Data, "type (.*?) struct") structName := regexpData(result.Data, "type (.*?) struct")
funcTemplateStr := Temp() funcTemplateStrCopy := funcTemplateStr
funcTemplateStr = strings.Replace(funcTemplateStr, "Template", Case2Camel(structName), -1) funcTemplateStrCopy = strings.Replace(funcTemplateStrCopy, "Template", Case2Camel(structName), -1)
arr1 := strings.Split(result.Data, "\n") arr1 := strings.Split(result.Data, "\n")
importIndex := 2 importIndex := 2
hasImport := false hasImport := false
...@@ -72,9 +120,9 @@ func main() { ...@@ -72,9 +120,9 @@ func main() {
arr1 = append(arr1, insertArr...) arr1 = append(arr1, insertArr...)
} }
result.Data = strings.Join(arr1, "\n") result.Data = strings.Join(arr1, "\n")
err := ioutil.WriteFile(filename, []byte(result.Data + "\n" + funcTemplateStr), 0644) err := ioutil.WriteFile(filename, []byte(result.Data+"\n"+funcTemplateStrCopy), 0644)
if err != nil { if err != nil {
fmt.Println("model文件生成失败,原因:"+ err.Error()) fmt.Println("model文件生成失败,原因:" + err.Error())
} }
fmt.Println("文件生成成功") fmt.Println("文件生成成功")
} else { } else {
...@@ -84,10 +132,6 @@ func main() { ...@@ -84,10 +132,6 @@ func main() {
} }
} }
func Temp() string {
return "func (m *Template) Create(Db *gorm.DB) error {\n err := Db.Model(&m).Create(&m).Error\n return err\n}\n\nfunc (m *Template) Update(Db *gorm.DB, field ...string) error {\n sql := Db.Model(&m)\n if len(field) > 0 {\n sql = sql.Select(field)\n }\n err := sql.Where(\"id\", m.Id).Updates(m).Error\n return err\n}\n\nfunc (m *Template) GetInfo(Db *gorm.DB) error {\n sql := Db.Model(m).Where(\"id = ? \", m.Id)\n err := sql.First(&m).Error\n return err\n}\n"
}
func regexpData(str string, pattern string) string { func regexpData(str string, pattern string) string {
reg2 := regexp.MustCompile(pattern) reg2 := regexp.MustCompile(pattern)
result2 := reg2.FindAllStringSubmatch(str, -1) result2 := reg2.FindAllStringSubmatch(str, -1)
...@@ -108,7 +152,6 @@ func checkFileIsExist(filename string) bool { ...@@ -108,7 +152,6 @@ func checkFileIsExist(filename string) bool {
return true return true
} }
func Request(url string, data map[string]interface{}, header map[string]interface{}, method string, stype string) (body []byte, err error) { func Request(url string, data map[string]interface{}, header map[string]interface{}, method string, stype string) (body []byte, err error) {
url = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(url, "\n", ""), " ", ""), "\r", "") url = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(url, "\n", ""), " ", ""), "\r", "")
param := []byte("") param := []byte("")
...@@ -149,3 +192,103 @@ func Request(url string, data map[string]interface{}, header map[string]interfac ...@@ -149,3 +192,103 @@ func Request(url string, data map[string]interface{}, header map[string]interfac
} }
return return
} }
/**
* 拷贝文件夹,同时拷贝文件夹中的文件
* @param srcPath 需要拷贝的文件夹路径: D:/test
* @param destPath 拷贝到的位置: D:/backup/
*/
func CopyDir(srcPath, destPath, name string) error {
//检测目录正确性
if srcInfo, err := os.Stat(srcPath); err != nil {
fmt.Println(err.Error())
return err
} else {
if !srcInfo.IsDir() {
e := errors.New("srcPath不是一个正确的目录!")
fmt.Println(e.Error())
return e
}
}
if b, _ := pathExists(destPath); !b {
err := os.Mkdir(destPath, os.ModePerm)
if err != nil {
return err
}
}
if destInfo, err := os.Stat(destPath); err != nil {
fmt.Println(err.Error())
return err
} else {
if !destInfo.IsDir() {
e := errors.New("destInfo不是一个正确的目录!")
fmt.Println(e.Error())
return e
}
}
//加上拷贝时间:不用可以去掉
err := filepath.Walk(srcPath, func(path string, f os.FileInfo, err error) error {
if f == nil {
return err
}
if !f.IsDir() {
path = strings.Replace(path, "\\", "/", -1)
destNewPath := strings.Replace(path, srcPath, destPath, -1)
copyFile(path, destNewPath, name)
}
return nil
})
if err != nil {
fmt.Printf(err.Error())
}
return err
}
//生成目录并拷贝文件
func copyFile(src, dest, name string) error {
srcFile, err := os.Open(src)
if err != nil {
fmt.Println(err.Error())
return err
}
defer srcFile.Close()
//分割path目录
destSplitPathDirs := strings.Split(dest, "/")
//检测时候存在目录
destSplitPath := ""
for index, dir := range destSplitPathDirs {
if index < len(destSplitPathDirs)-1 {
destSplitPath = destSplitPath + dir + "/"
b, _ := pathExists(destSplitPath)
if b == false {
fmt.Println("创建目录:" + destSplitPath)
//创建目录
err := os.Mkdir(destSplitPath, os.ModePerm)
if err != nil {
fmt.Println(err)
}
}
}
}
fileContentByte, _ := os.ReadFile(src)
fileContent := strings.ReplaceAll(string(fileContentByte), "TEMPLATE", name)
return ioutil.WriteFile(dest, []byte(fileContent), 0644)
}
//检测文件夹路径时候存在
func pathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
.idea
logs
*.yaml
package v1
import (
"TEMPLATE/types/request"
"TEMPLATE/types/response"
"github.com/gin-gonic/gin"
"github.com/zjswh/go-tool/utils"
)
func CreateCoupon(c *gin.Context) {
var createStruct request.CreateCouponStruct
err := c.ShouldBind(&createStruct)
if err != nil {
response.ParamError("参数缺失", c)
return
}
response.Success(1, c)
return
}
func UpdateCoupon(c *gin.Context) {
id := utils.DefaultIntFormValue("couponId", 0, c)
if id == 0 {
response.ParamError("参数缺失", c)
return
}
response.Success("修改成功", c)
return
}
func DeleteCoupon(c *gin.Context) {
id := utils.DefaultIntFormValue("couponId", 0, c)
if id == 0 {
response.ParamError("参数缺失", c)
return
}
response.Success("删除成功", c)
return
}
func CouponInfo(c *gin.Context) {
id := utils.DefaultIntParam("id", 0, c)
if id == 0 {
response.ParamError("参数缺失", c)
return
}
response.Success("", c)
return
}
func GetCouponList(c *gin.Context) {
//page := utils.DefaultIntParam("page", 1, c)
//num := utils.DefaultIntParam("num", 10, c)
//name := c.DefaultQuery("name", "")
//status := utils.DefaultIntParam("status", -1, c)
//startTime := utils.DefaultIntParam("startTime", 0, c)
//endTime := utils.DefaultIntParam("endTime", 0, c)
response.Success(gin.H{
"list": "",
"count": 0,
}, c)
return
}
package config
import (
"fmt"
"github.com/fsnotify/fsnotify"
"github.com/go-redis/redis"
"github.com/spf13/viper"
"github.com/zjswh/go-tool/nacos"
"gorm.io/gorm"
"os"
)
var configFilePath = "config"
var systemConfigFilePath = "system"
var (
GVA_CONFIG Server
GVA_SYSTEM_CONFIG SysTemConfig
GVA_VP *viper.Viper
GVA_DB *gorm.DB
GVA_REDIS *redis.Client
GVA_REDIS_MASTER *redis.Client
)
type UserInfo struct {
AccountId int `json:"accountId"`
Aid int `json:"aid"`
Uin int `json:"uin"`
Name string `json:"name"`
}
type SysTemConfig struct {
AppIp string `mapstructure:"appIp" json:"appIp" yaml:"appIp"`
AppPort uint64 `mapstructure:"appPort" json:"appPort" yaml:"appPort"`
NacosIp string `mapstructure:"nacosIp" json:"nacosIp" yaml:"nacosIp"`
NacosPort uint64 `mapstructure:"nacosPort" json:"nacosPort" yaml:"nacosPort"`
ServerName string `mapstructure:"ServerName" json:"ServerName" yaml:"ServerName"`
Mode string `mapstructure:"mode" json:"mode" yaml:"mode"`
ConfigId string `mapstructure:"configId" json:"configId" yaml:"configId"`
}
type Server struct {
Mysql Mysql `json:"mysql"`
Redis Redis `json:"redis"`
RedisMaster RedisMaster `json:"redisMaster"`
System System `json:"system"`
Jwt JWT `json:"jwt"`
Log Log `json:"log"`
Email Email `json:"email"`
Param Param `json:"param"`
}
type Mysql struct {
Username string `mapstructure:"username" json:"username" yaml:"username"`
Password string `mapstructure:"password" json:"password" yaml:"password"`
Path string `mapstructure:"path" json:"path" yaml:"path"`
Dbname string `mapstructure:"db-name" json:"dbname" yaml:"db-name"`
Config string `mapstructure:"config" json:"config" yaml:"config"`
MaxIdleConns int `mapstructure:"max-idle-conns" json:"maxIdleConns" yaml:"max-idle-conns"`
MaxOpenConns int `mapstructure:"max-open-conns" json:"maxOpenConns" yaml:"max-open-conns"`
LogMode bool `mapstructure:"log-mode" json:"logMode" yaml:"log-mode"`
}
type Redis struct {
Addr string `mapstructure:"addr" json:"addr" yaml:"addr"`
Password string `mapstructure:"password" json:"password" yaml:"password"`
DB int `mapstructure:"db" json:"db" yaml:"db"`
}
type RedisMaster struct {
Addr string `mapstructure:"addr" json:"addr" yaml:"addr"`
Password string `mapstructure:"password" json:"password" yaml:"password"`
DB int `mapstructure:"db" json:"db" yaml:"db"`
}
type System struct {
Env string `mapstructure:"env" json:"env" yaml:"env"`
Addr int `mapstructure:"addr" json:"addr" yaml:"addr"`
DbType string `mapstructure:"db-type" json:"dbType" yaml:"db-type"`
}
type JWT struct {
SigningKey string `mapstructure:"signing-key" json:"signingKey" yaml:"signing-key"`
}
type Log struct {
Path string `mapstructure:"path" json:"path" yaml:"path"`
Name string `mapstructure:"name" json:"name" yaml:"name"`
}
type Email struct {
User string `mapstructure:"user" json:"user" yaml:"user"`
Host string `mapstructure:"host" json:"host" yaml:"host"`
Port int `mapstructure:"port" json:"port" yaml:"port"`
Pass string `mapstructure:"pass" json:"pass" yaml:"pass"`
AdminUser string `mapstructure:"admin-user" json:"admin-user" yaml:"admin-user"`
}
type Param struct {
WebHost string `mapstructure:"web-host" json:"web-host" yaml:"web-host"`
ActivityHost string `mapstructure:"activity-host" json:"activity-host" yaml:"activity-host"`
CouponHost string `mapstructure:"coupon-host" json:"coupon-host" yaml:"coupon-host"`
ProjectHost string `mapstructure:"project-host" json:"project-host" yaml:"project-host"`
CronHost string `mapstructure:"cron-host" json:"cron-host" yaml:"cron-host"`
MessageHost string `mapstructure:"message-host" json:"message-host" yaml:"message-host"`
EsHost string `mapstructure:"es-host" json:"es-host" yaml:"es-host"`
BGatewayHost string `mapstructure:"b-gateway-host" json:"b-gateway-host" yaml:"b-gateway-host"`
XCaStage string `mapstructure:"x-ca-stage" json:"x-ca-stage" yaml:"x-ca-stage"`
}
func SetUp() {
//读取环境变量
args := os.Args
//判断环境变量是否存在
environment := os.Getenv("environment")
if len(args) > 1 {
configFilePath = configFilePath + "." + args[1]
} else if environment != "" {
configFilePath = configFilePath + "." + environment
}
configFilePath = configFilePath + ".yaml"
//判断配置文件是否已存在 不存在则去环境变量中读取
if _, err := os.Stat(configFilePath); os.IsNotExist(err) {
config, er := nacos.GetConfig(GVA_SYSTEM_CONFIG.ConfigId)
if er != nil {
fmt.Println(er)
return
}
f, er := os.OpenFile(configFilePath, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0600)
defer f.Close()
if er == nil {
f.Write([]byte(config))
}
}
v := viper.New()
v.SetConfigFile(configFilePath)
err := v.ReadInConfig()
if err != nil {
panic(fmt.Errorf("Fatal error config file: %s \n", err))
}
v.WatchConfig()
v.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("config file changed:", e.Name)
if err := v.Unmarshal(&GVA_CONFIG); err != nil {
fmt.Println(err)
}
})
if err := v.Unmarshal(&GVA_CONFIG); err != nil {
fmt.Println(err)
}
GVA_VP = v
}
func SystemSetUp() {
//读取环境变量
args := os.Args
//判断环境变量是否存在
environment := os.Getenv("environment")
if len(args) > 1 {
systemConfigFilePath = systemConfigFilePath + "." + args[1]
} else if environment != "" {
systemConfigFilePath = systemConfigFilePath + "." + environment
}
systemConfigFilePath = systemConfigFilePath + ".yaml"
//判断配置文件是否已存在 不存在则去环境变量中读取
if _, err := os.Stat(systemConfigFilePath); os.IsNotExist(err) {
config := os.Getenv("config")
f, er := os.OpenFile(systemConfigFilePath, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0600)
defer f.Close()
if er == nil {
f.Write([]byte(config))
}
}
v := viper.New()
v.SetConfigFile(systemConfigFilePath)
err := v.ReadInConfig()
if err != nil {
panic(fmt.Errorf("Fatal error config file: %s \n", err))
}
v.WatchConfig()
v.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("config file changed:", e.Name)
if err := v.Unmarshal(&GVA_SYSTEM_CONFIG); err != nil {
fmt.Println(err)
}
})
if err := v.Unmarshal(&GVA_SYSTEM_CONFIG); err != nil {
fmt.Println(err)
}
GVA_VP = v
}
module TEMPLATE
go 1.13
require (
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/fsnotify/fsnotify v1.4.9
github.com/gin-gonic/gin v1.7.4
github.com/go-redis/redis v6.15.9+incompatible
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/onsi/ginkgo v1.14.1 // indirect
github.com/onsi/gomega v1.10.2 // indirect
github.com/satori/go.uuid v1.2.0 // indirect
github.com/sirupsen/logrus v1.6.0
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 // indirect
github.com/spf13/viper v1.7.1
github.com/stretchr/testify v1.7.0 // indirect
github.com/xinliangnote/go-util v0.0.0-20200323134426-527984dc34bf
github.com/zjswh/go-tool v0.1.1
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect
golang.org/x/text v0.3.5 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect
gorm.io/driver/mysql v1.0.4
gorm.io/gorm v1.20.12
)
This diff is collapsed. Click to expand it.
package initialize
import (
"TEMPLATE/config"
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"gorm.io/gorm/schema"
"os"
)
func Mysql() {
conf := config.GVA_CONFIG.Mysql
link := conf.Username + ":" + conf.Password + "@(" + conf.Path + ")/" + conf.Dbname + "?" + conf.Config
if db, err := gorm.Open(mysql.Open(link), &gorm.Config{
NamingStrategy: schema.NamingStrategy{
SingularTable: true, // 使用单数表名,启用该选项后,`User` 表将是`user`
},
Logger: logger.Default.LogMode(logger.Info),
}); err != nil {
fmt.Println("mysql connect failed", err.Error())
os.Exit(0)
} else {
config.GVA_DB = db
sqlDb, _ := db.DB()
sqlDb.SetMaxIdleConns(conf.MaxIdleConns)
sqlDb.SetMaxOpenConns(conf.MaxOpenConns)
//config.GVA_DB.SingularTable(true)
}
}
func DBTables() {
//config.GVA_DB.AutoMigrate(
// model.User{},
// )
}
package initialize
import (
"TEMPLATE/config"
"fmt"
"github.com/go-redis/redis"
)
func Redis() {
conf := config.GVA_CONFIG.Redis
fmt.Println("redis")
client := redis.NewClient(&redis.Options{
Addr: conf.Addr,
Password: conf.Password,
DB: conf.DB,
})
pong, err := client.Ping().Result()
if err != nil {
fmt.Println("redis连接失败")
} else{
fmt.Println("redis connect result is:", pong)
config.GVA_REDIS = client
}
confMaster := config.GVA_CONFIG.RedisMaster
fmt.Println("redisMaster")
clientMaster := redis.NewClient(&redis.Options{
Addr: confMaster.Addr,
Password: confMaster.Password,
DB: confMaster.DB,
})
pongMaster, err := clientMaster.Ping().Result()
if err != nil {
fmt.Println("redis连接失败")
} else{
fmt.Println("redis connect result is:", pongMaster)
config.GVA_REDIS_MASTER = clientMaster
}
}
package initialize
import (
"TEMPLATE/config"
"TEMPLATE/middleware"
"TEMPLATE/router"
"TEMPLATE/types/response"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"time"
)
func RunServer() {
gin.SetMode(config.GVA_SYSTEM_CONFIG.Mode)
//加载路由
router := Routers()
address := fmt.Sprintf(":%d", config.GVA_CONFIG.System.Addr)
//http
s := &http.Server{
Addr: address,
Handler: router,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
s.ListenAndServe()
}
func Routers() *gin.Engine {
Router := gin.Default()
//处理跨域
Router.Use(cors())
//日记记录
Router.Use(middleware.RequestId(), middleware.LoggerToFile()) //, middleware.Exception()
ApiGroup := Router.Group("v1/coupon/market")
router.InitRouter(ApiGroup) //注册用户相关接口路由
//处理404
Router.NoMethod(HandleNotFind)
Router.NoRoute(HandleNotFind)
return Router
}
//处理404
func HandleNotFind(c *gin.Context) {
response.Result(4, "api不存在", "", c)
}
//跨域
func cors() gin.HandlerFunc {
return func(c *gin.Context) {
method := c.Request.Method
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token, x-ca-stage")
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
c.Header("Access-Control-Allow-Credentials", "true")
//过滤options请求
if method == "OPTIONS" {
c.AbortWithStatus(http.StatusNoContent)
}
//处理请求
c.Next()
}
}
package main
import (
"TEMPLATE/config"
"TEMPLATE/initialize"
"github.com/zjswh/go-tool/nacos"
)
func main() {
config.SystemSetUp()
systemConfig := config.GVA_SYSTEM_CONFIG
nacos.Setup(systemConfig.NacosIp, systemConfig.NacosPort, systemConfig.AppIp, systemConfig.AppPort, systemConfig.ServerName)
config.SetUp()
//加载数据库
initialize.Mysql()
//加载redis
initialize.Redis()
initialize.RunServer()
}
package middleware
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/xinliangnote/go-util/mail"
"TEMPLATE/config"
"TEMPLATE/types/response"
"runtime/debug"
"strings"
"time"
)
func Exception() gin.HandlerFunc {
return func(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
DebugStack := ""
for _, v := range strings.Split(string(debug.Stack()), "\n") {
DebugStack += v + "<br>"
}
subject := "【重要错误】项目出错了!"
body := strings.ReplaceAll(MailTemplate, "{ErrorMsg}", fmt.Sprintf("%s", err))
body = strings.ReplaceAll(body, "{RequestTime}", time.Now().Format("2006-01-02 15:04:05"))
body = strings.ReplaceAll(body, "{RequestURL}", c.Request.Method + " " + c.Request.Host + c.Request.RequestURI)
body = strings.ReplaceAll(body, "{RequestUA}", c.Request.UserAgent())
body = strings.ReplaceAll(body, "{RequestIP}", c.ClientIP())
body = strings.ReplaceAll(body, "{DebugStack}", DebugStack)
options := &mail.Options{
MailHost : config.GVA_CONFIG.Email.Host,
MailPort : config.GVA_CONFIG.Email.Port,
MailUser : config.GVA_CONFIG.Email.User,
MailPass : config.GVA_CONFIG.Email.Pass,
MailTo : config.GVA_CONFIG.Email.AdminUser,
Subject : subject,
Body : body,
}
_ = mail.Send(options)
response.SystemError("系统异常", c)
}
}()
c.Next()
}
}
package middleware
import (
"TEMPLATE/config"
"TEMPLATE/types/request"
"errors"
"github.com/dgrijalva/jwt-go"
)
type JWT struct {
SigningKey []byte
}
var (
TokenExpired = errors.New("登录过期,请重试")
TokenNotValidYet = errors.New("登录信息失效")
TokenMalformed = errors.New("登录凭证异常")
TokenInvalid = errors.New("登录凭证异常")
)
func NewJwt() *JWT {
return &JWT{[]byte(config.GVA_CONFIG.Jwt.SigningKey)}
}
func JwtAuth(token string) string {
if token == "" {
return ""
}
newJwt := NewJwt()
claims, err := newJwt.ParseToken(token)
if err != nil {
return ""
}
return claims.Token
}
func CreateToken(claims request.UserClaims) (string, error) {
newJwt := NewJwt()
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString(newJwt.SigningKey)
}
func (j *JWT) ParseToken(tokenString string) (*request.UserClaims, error) {
token, err := jwt.ParseWithClaims(tokenString, &request.UserClaims{}, func(token *jwt.Token) (i interface{}, err error) {
return j.SigningKey, nil
})
if err != nil {
if ve, ok := err.(*jwt.ValidationError); ok {
if ve.Errors&jwt.ValidationErrorMalformed != 0 {
return nil, TokenMalformed
} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
// Token is expired
return nil, TokenExpired
} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
return nil, TokenNotValidYet
} else {
return nil, TokenInvalid
}
}
}
if token != nil {
if claims, ok := token.Claims.(*request.UserClaims); ok && token.Valid {
return claims, nil
}
return nil, TokenInvalid
} else {
return nil, TokenInvalid
}
}
package middleware
import (
"TEMPLATE/config"
"fmt"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"os"
"path"
"time"
)
func LoggerToFile() gin.HandlerFunc {
logFilePath := config.GVA_CONFIG.Log.Path
logFileName := config.GVA_CONFIG.Log.Name
fileName := path.Join(logFilePath, logFileName)
//创建文件夹
if _, err := os.Stat(logFilePath); os.IsNotExist(err) {
// 必须分成两步:先创建文件夹、再修改权限
os.Mkdir(logFilePath, os.ModePerm)
os.Chmod(logFilePath, os.ModePerm)
}
src, err := os.OpenFile(fileName, os.O_CREATE|os.O_APPEND|os.O_WRONLY , os.ModeAppend)
if err != nil {
fmt.Println("err:", err.Error())
}
logger := logrus.New()
//设置日志输出
logger.Out = src
//设置日记级别
logger.SetLevel(logrus.DebugLevel)
//设置日志格式
logger.SetFormatter(&logrus.JSONFormatter{
TimestampFormat: "2006-01-02 15:04:05",
})
return func(c *gin.Context) {
startTime := time.Now()
c.Next()
endTime := time.Now()
latencyTime := endTime.Sub(startTime)
reqMethod := c.Request.Method
reqUri := c.Request.RequestURI
status := c.Writer.Status()
clientIp := c.ClientIP()
logger.WithFields(logrus.Fields{
"status" : status ,
"latencyTime" : latencyTime ,
"clientIp" : clientIp ,
"reqMethod" : reqMethod ,
"reqUri" : reqUri ,
}).Info()
}
}
package middleware
import (
"github.com/gin-gonic/gin"
"github.com/zjswh/go-tool/utils"
)
func RequestId() gin.HandlerFunc {
return func(c *gin.Context) {
headerName := "X-Request-Id"
requestUid := c.Request.Header.Get(headerName)
if requestUid == "" {
requestUid = utils.GenUUID()
}
c.Set(headerName, requestUid)
c.Writer.Header().Set(headerName, requestUid)
c.Next()
}
}
package router
import (
v1 "TEMPLATE/api/v1"
"TEMPLATE/service"
"github.com/gin-gonic/gin"
)
func InitRouter(Router *gin.RouterGroup) {
userRouter := Router.Group("User").
Use(service.CheckLogin())
{
userRouter.POST("create", v1.CreateCoupon)
userRouter.POST("update", v1.UpdateCoupon)
userRouter.POST("delete", v1.DeleteCoupon)
userRouter.GET("info", v1.CouponInfo)
userRouter.GET("getList", v1.GetCouponList)
}
}
package service
import (
"TEMPLATE/config"
"TEMPLATE/middleware"
"TEMPLATE/types/response"
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"github.com/zjswh/go-tool/utils"
)
type UserInfo struct {
AccountId int `json:"accountId"`
Aid int `json:"aid"`
Uin int `json:"uin"`
Name string `json:"name"`
}
type CUserInfo struct {
Uin int `json:"uin"`
Id int `json:"id"`
IsSafe int `json:"isSafe"`
Phone string `json:"phone"`
UserNick string `json:"userNick"`
LoginType string `json:"loginType"`
UserHeadImg string `json:"userHeadImg"`
UserIp string `json:"userIp"`
}
func CheckLogin() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader("token")
if token == "" {
token = c.Query("token")
}
if token == "" {
response.Result(1, "", "未登录", c)
c.Abort()
return
}
realToken := middleware.JwtAuth(token)
if realToken == "" {
response.Result(1, "", "登录过期", c)
c.Abort()
return
}
url := config.GVA_CONFIG.Param.BGatewayHost + "/v1/Passport/Index/getLoginInfo"
url = fmt.Sprintf("%s?token=%s&path=/%s&method=%s", url, token, c.FullPath(), c.Request.Method)
res, _ := utils.Request(url, map[string]interface{}{}, map[string]interface{}{
"X-CA-STAGE": config.GVA_CONFIG.Param.XCaStage,
},"GET", "")
var result response.Response
json.Unmarshal(res, &result)
if result.Code != 200 || result.ErrorCode != 0 {
response.Result(result.ErrorCode, "", result.ErrorMessage, c)
c.Abort()
return
}
userInfo, _ := json.Marshal(result.Data)
c.Set("userInfo", string(userInfo))
c.Next()
}
}
func GetCUserInfo(c *gin.Context) CUserInfo {
userInfo := CUserInfo{}
token := c.GetHeader("token")
if token == "" {
return userInfo
}
realToken := middleware.JwtAuth(token)
if realToken == "" {
return userInfo
}
info, _ := config.GVA_REDIS_MASTER.Get(realToken).Result()
json.Unmarshal([]byte(info), &userInfo)
return userInfo
}
package appConst
const (
//redis
CouponInfoKey = "new_live_coupon_info"
RecordInfoKey = "coupon_record_info"
DefaultTimeFormat = "2006-01-02 15:04:05"
)
var ApiMap = map[string][]string{
"/v1/coupon/market/Discount/create": []string{"创建优惠券", "活动管理-优惠券"},
"/v1/coupon/market/Discount/update": []string{"修改优惠券", "活动管理-优惠券"},
"/v1/coupon/market/Discount/delete": []string{"删除优惠券", "活动管理-优惠券"},
"/v1/coupon/market/Discount/saveInclude": []string{"配置优惠券", "活动管理-优惠券"},
"/v1/coupon/market/DiscountDetail/writeOff": []string{"核销优惠券", "活动管理-优惠券"},
}
package request
type WxParam struct {
Content WxContent `json:"content"`
State int `json:"state"`
}
type WxContent struct {
Guide int `json:"guide"`
Pic string `json:"pic"`
}
type Banner struct {
Pic string `json:"pic"`
Src string `json:"src"`
Type string `json:"type"`
LiveId int `json:"liveId"`
LiveName string `json:"liveName"`
}
type Navigation struct {
Id int `json:"id"`
State int `json:"state"`
Pic string `json:"pic"`
Name string `json:"name"`
Type string `json:"type"`
Msg string `json:"msg"`
}
type WxConfig struct {
Id int `form:"id"`
State int `form:"state"`
Content struct {
Guide int `form:"guide"`
Pic string `form:"pic"`
} `form:"content"`
}
type ShareConfig struct {
Id int `form:"id" binding:"required"`
Title string `form:"title" binding:"required"`
SubTitle string `form:"subTitle" binding:"required"`
Thumb string `form:"thumb" binding:"required"`
}
type ViewCountConfig struct {
ID int `form:"id" binding:"required"`
IsDisplayWatchNum int `form:"isDisplayWatchNum"`
CustomWatchTrendNumMin int `form:"customWatchTrendNumMin"`
CustomWatchTrendNumMax int `form:"customWatchTrendNumMax"`
CustomWatchLimitMax int `form:"customWatchLimitMax"`
CustomWatchNum int `form:"customWatchNum"`
}
type NavigationConfig struct {
ID int `form:"id" binding:"required"`
Navigationstate int `form:"navigationState"`
Navigationstyle int `form:"navigationStyle"`
Content string `form:"content"`
}
type NavInfo struct {
ID int `json:"id"`
State int `json:"state"`
Pic string `json:"pic"`
Name string `json:"name"`
Type string `json:"type"`
Msg interface{} `json:"msg"`
Url string `json:"url"`
}
type MenuInfo struct {
ID int `json:"id"`
MenuId int `json:"menuId"`
Name string `json:"name"`
Type string `json:"type"`
Sort int `json:"sort"`
Content interface{} `json:"content"`
}
type MenuConfig struct {
ID int `json:"id"`
Aid int `json:"aid"`
Name string `json:"name"`
Type string `json:"type"`
Multilevel int `json:"multilevel"`
Status int `json:"status"`
Sort int `json:"sort"`
Content interface{} `json:"content"`
}
type SourceInfo struct {
SourceId int `json:"sourceId"`
IsSelect int `json:"isSelect"`
Type string `json:"type"`
Style int `json:"style"`
Name string `json:"name"`
Logo string `json:"logo"`
CreateTime string `json:"createTime"`
ID int `json:"id"`
}
package request
type CreateCouponStruct struct {
Name string `form:"name" binding:"required"`
WaiverAmount float32 `form:"waiverAmount" binding:"required"`
Condition float32 `form:"condition"`
ConditionType int `form:"conditionType"`
Type int `form:"type" binding:"required"`
CouponType int `form:"couponType"`
Num int `form:"num" binding:"required"`
Intro string `form:"intro"`
StartTime int64 `form:"startTime" binding:"required"`
EndTime int64 `form:"endTime" binding:"required"`
}
package request
import "github.com/dgrijalva/jwt-go"
type UserClaims struct {
Token string
jwt.StandardClaims
}
package request
type LoginStruct struct {
Phone string `json:"phone"`
Password string `json:"password"`
}
type RegisterStruct struct {
Phone string `json:"phone"`
Username string `json:"username"`
Avatar string `json:"avatar"`
Password string `json:"password"`
}
type GetInfoStruct struct {
Id int `json:"id"`
Phone string `json:"phone"`
Username string `json:"username"`
}
type PageInfo struct {
Page int `json:"page"`
Num int `json:"num"`
}
type ProgrammeStruct struct {
Id int `json:"id"`
Name string `json:"name"`
MssUrl string `json:"mssUrl"`
StartTime string `json:"startTime"`
EndTime string `json:"endTime"`
ChannelId int `json:"channelId"`
Uin int64 `json:"uin"`
Type int `json:"type"`
Week int `json:"week"`
STaskId int `json:"sTaskId"`
ETaskId int `json:"eTaskId"`
}
package request
type CreateVoteStruct struct {
Topic string `json:"topic"`
VoteIntro string `json:"vote_intro"`
VoteType int `json:"vote_type"`
Banner string `json:"banner"`
VoteWay int `json:"vote_way"`
RefreshStatus int `json:"refresh_status"`
VoteOption int `json:"vote_option"`
VoteChooseNum int `json:"vote_choose_num"`
StartTime int64 `json:"start_time"`
EndTime int64 `json:"end_time"`
IsRank int `json:"is_rank"`
Content []VoteContentStruct `json:"content"`
}
type VoteInfoStruct struct {
ID int `form:"id"`
Topic string `form:"topic"`
Banner string `form:"banner"`
AccessId int `form:"access_id"`
Aid int `form:"aid"`
Url string `form:"url"`
StartTime string `form:"start_time"`
EndTime string `form:"end_time"`
IsRank int `form:"is_rank"`
VoteChooseNum int `form:"vote_choose_num"`
VoteIntro string `form:"vote_intro"`
VoteOption int `form:"vote_option"`
VoteType int `form:"vote_type"`
VoteWay int `form:"vote_way"`
RefreshStatus int `form:"refresh_status"`
Content string `form:"content"`
}
type VoteContentStruct struct {
Id int `json:"id"`
Title string `json:"title"`
Intro string `json:"intro"`
VoteId int `json:"vote_id"`
Pic string `json:"pic"`
VideoUrl string `json:"videoUrl"`
VideoCoverImg string `json:"videoCoverImg"`
}
type VoteOption struct {
OptionId int `form:"optionId"`
UserId int `form:"userId"`
Type string `form:"type"`
Num int `form:"num"`
Page int `form:"page"`
Phone string `form:"phone"`
Name string `form:"name"`
StartTime string `form:"startTime"`
EndTime string `form:"endTime"`
Filename string `form:"filename"`
}
package response
import (
"TEMPLATE/config"
"TEMPLATE/types/appConst"
"github.com/gin-gonic/gin"
"github.com/zjswh/go-tool/logOperation"
"net/http"
)
type Response struct {
Code int `json:"code"`
Data interface{} `json:"data"`
ErrorMessage string `json:"errorMessage"`
ErrorCode int `json:"errorCode"`
}
type GdyAPiResult struct {
Code int `json:"code"`
ErrorCode int `json:"errorCode"`
ErrorMessage string `json:"errorMessage"`
Data map[string][]LiveList `json:"data"`
}
type LiveList struct {
Id int `json:"id"`
Name string `json:"name"`
Logo string `json:"logo"`
CreateTime string `json:"createTime"`
Type string `json:"type"`
WatchNum int `json:"watchNum"`
IsSelect int `json:"isSelect"`
}
func Success(data interface{}, c *gin.Context) {
Result(0, data, "", c)
}
func Result(code int, data interface{}, msg string, c *gin.Context) {
result := Response{
200,
data,
msg,
code,
}
go logOperation.Push(c, config.GVA_CONFIG.Param.XCaStage, appConst.ApiMap, result)
c.JSON(http.StatusOK, result)
}
func SystemError(msg string, c *gin.Context) {
// 开始时间
c.JSON(http.StatusInternalServerError, Response{
http.StatusInternalServerError,
"",
msg,
0,
})
c.Abort()
}
func ParamError(message string, c *gin.Context) {
Result(2, "", message, c)
}
func DbError(message string, c *gin.Context) {
Result(3, "", message, c)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment