diff --git a/go_fabric/.idea/.gitignore b/go_fabric/.idea/.gitignore
new file mode 100644
index 0000000..35410ca
--- /dev/null
+++ b/go_fabric/.idea/.gitignore
@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/go_fabric/.idea/go_fabric.iml b/go_fabric/.idea/go_fabric.iml
new file mode 100644
index 0000000..5e764c4
--- /dev/null
+++ b/go_fabric/.idea/go_fabric.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/go_fabric/.idea/modules.xml b/go_fabric/.idea/modules.xml
new file mode 100644
index 0000000..74a6653
--- /dev/null
+++ b/go_fabric/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/go_fabric/.idea/vcs.xml b/go_fabric/.idea/vcs.xml
new file mode 100644
index 0000000..6c0b863
--- /dev/null
+++ b/go_fabric/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/go_fabric/api/v1/common.go b/go_fabric/api/v1/common.go
new file mode 100644
index 0000000..e93ddc3
--- /dev/null
+++ b/go_fabric/api/v1/common.go
@@ -0,0 +1,21 @@
+package v1
+
+import (
+ "encoding/json"
+ "go_fabric/serializer"
+)
+
+func ErrorResponse(err error) serializer.Response {
+ if _, ok := err.(*json.UnmarshalTypeError); ok {
+ return serializer.Response{
+ Status: 400,
+ Msg: "JSON类型不匹配",
+ Error: err.Error(),
+ }
+ }
+ return serializer.Response{
+ Status: 400,
+ Msg: "参数错误",
+ Error: err.Error(),
+ }
+}
diff --git a/go_fabric/api/v1/poem.go b/go_fabric/api/v1/poem.go
new file mode 100644
index 0000000..5cbf3a7
--- /dev/null
+++ b/go_fabric/api/v1/poem.go
@@ -0,0 +1,20 @@
+package v1
+
+import (
+ "go_fabric/pkg/util"
+ "go_fabric/service"
+ "net/http"
+
+ "github.com/gin-gonic/gin"
+)
+
+func PoemGet(c *gin.Context) {
+ var userRegister service.UserService
+ if err := c.ShouldBind(&userRegister); err == nil {
+ res := userRegister.Register(c.Request.Context())
+ c.JSON(http.StatusOK, res)
+ } else {
+ c.JSON(http.StatusBadRequest, ErrorResponse(err)) //400参数错误
+ util.LoggerObj.Error(err)
+ }
+}
diff --git a/go_fabric/api/v1/user.go b/go_fabric/api/v1/user.go
new file mode 100644
index 0000000..d170b96
--- /dev/null
+++ b/go_fabric/api/v1/user.go
@@ -0,0 +1,80 @@
+package v1
+
+import (
+ "go_fabric/pkg/util"
+ "go_fabric/service"
+ "net/http"
+
+ "github.com/gin-gonic/gin"
+)
+
+func UserRegister(c *gin.Context) {
+ var userRegister service.UserService
+ if err := c.ShouldBind(&userRegister); err == nil {
+ res := userRegister.Register(c.Request.Context())
+ c.JSON(http.StatusOK, res)
+ } else {
+ c.JSON(http.StatusBadRequest, ErrorResponse(err)) //400参数错误
+ util.LoggerObj.Error(err)
+ }
+}
+
+func UserLogin(c *gin.Context) {
+ var userLogin service.UserService
+ if err := c.ShouldBind(&userLogin); err == nil {
+ res := userLogin.Login(c.Request.Context())
+ c.JSON(http.StatusOK, res)
+ } else {
+ c.JSON(http.StatusBadRequest, ErrorResponse(err)) //400参数错误
+ util.LoggerObj.Error(err)
+ }
+}
+
+func UserUpdate(c *gin.Context) {
+ var userUpdate service.UserService
+ claims, _ := util.ParseToken(c.GetHeader("Authorization"))
+ if err := c.ShouldBind(&userUpdate); err == nil {
+ res := userUpdate.Update(c.Request.Context(), claims.ID)
+ c.JSON(http.StatusOK, res)
+ } else {
+ c.JSON(http.StatusBadRequest, ErrorResponse(err)) //400参数错误
+ util.LoggerObj.Error(err)
+ }
+}
+
+func UpdateAvatar(c *gin.Context) {
+ file, fileHeader, _ := c.Request.FormFile("file")
+ fileSize := fileHeader.Size
+ var updateAvatar service.UserService
+ claims, _ := util.ParseToken(c.GetHeader("Authorization"))
+ if err := c.ShouldBind(&updateAvatar); err == nil {
+ res := updateAvatar.Post(c.Request.Context(), claims.ID, file, fileSize)
+ c.JSON(http.StatusOK, res)
+ } else {
+ c.JSON(http.StatusBadRequest, ErrorResponse(err)) //400参数错误
+ util.LoggerObj.Error(err)
+ }
+}
+
+func SendEmail(c *gin.Context) {
+ var sendEmail service.SendEmailService
+ claims, _ := util.ParseToken(c.GetHeader("Authorization"))
+ if err := c.ShouldBind(&sendEmail); err == nil {
+ res := sendEmail.Send(c.Request.Context(), claims.ID)
+ c.JSON(http.StatusOK, res)
+ } else {
+ c.JSON(http.StatusBadRequest, ErrorResponse(err)) //400参数错误
+ util.LoggerObj.Error(err)
+ }
+}
+
+func ValidEmail(c *gin.Context) {
+ var validEmail service.ValidEmailService
+ if err := c.ShouldBind(&validEmail); err == nil {
+ res := validEmail.Valid(c.Request.Context(), c.GetHeader("Authorization"))
+ c.JSON(http.StatusOK, res)
+ } else {
+ c.JSON(http.StatusBadRequest, ErrorResponse(err)) //400参数错误
+ util.LoggerObj.Error(err)
+ }
+}
diff --git a/go_fabric/cache/commen.go b/go_fabric/cache/commen.go
new file mode 100644
index 0000000..5bb97f4
--- /dev/null
+++ b/go_fabric/cache/commen.go
@@ -0,0 +1,47 @@
+package cache
+
+import (
+ "fmt"
+ "strconv"
+
+ "github.com/go-redis/redis"
+ "gopkg.in/ini.v1"
+)
+
+var (
+ RedisClient *redis.Client
+ RedisDb string
+ RedisAddr string
+ RedisPw string
+ RedisDbName string
+)
+
+func Init() {
+ file, err := ini.Load("C:/Users/801028/Desktop/marketv1.2/go_fabric/conf/config.ini")
+ if err != nil {
+ fmt.Println("redis config err", err)
+ }
+ LoadRedisData(file)
+ Redis()
+}
+
+func LoadRedisData(file *ini.File) {
+ RedisDb = file.Section("redis").Key("RedisDb").String()
+ RedisAddr = file.Section("redis").Key("RedisAddr").String()
+ RedisPw = file.Section("redis").Key("RedisPw").String()
+ RedisDbName = file.Section("redis").Key("RedisDbName").String()
+}
+
+func Redis() {
+ db, _ := strconv.ParseUint(RedisDbName, 10, 64)
+ client := redis.NewClient(&redis.Options{
+ Addr: RedisAddr,
+ //Password
+ DB: int(db),
+ })
+ _, err := client.Ping().Result()
+ if err != nil {
+ panic(err)
+ }
+ RedisClient = client
+}
diff --git a/go_fabric/cache/key.go b/go_fabric/cache/key.go
new file mode 100644
index 0000000..150689b
--- /dev/null
+++ b/go_fabric/cache/key.go
@@ -0,0 +1,14 @@
+package cache
+
+import (
+ "fmt"
+ "strconv"
+)
+
+const (
+ RankKey = "rank" //排名
+)
+
+func ProductViewKey(id uint) string{
+ return fmt.Sprintf("view:product:%s",strconv.Itoa(int(id)))
+}
\ No newline at end of file
diff --git a/go_fabric/cmd/mian.go b/go_fabric/cmd/mian.go
new file mode 100644
index 0000000..7b67a91
--- /dev/null
+++ b/go_fabric/cmd/mian.go
@@ -0,0 +1,14 @@
+package main
+
+import (
+ // "go_fabric/cache"
+ "go_fabric/conf"
+ "go_fabric/routes"
+)
+
+func main() {
+ conf.Init()
+ // cache.Init()
+ r := routes.NewRouter()
+ _ = r.Run(conf.HttpPort)
+}
diff --git a/go_fabric/conf/config.go b/go_fabric/conf/config.go
new file mode 100644
index 0000000..6af96d7
--- /dev/null
+++ b/go_fabric/conf/config.go
@@ -0,0 +1,86 @@
+package conf
+
+import (
+ "go_fabric/dao"
+ "strings"
+
+ "gopkg.in/ini.v1"
+)
+
+var (
+ AppModel string
+ HttpPort string
+
+ Db string
+ DbHost string
+ DbPort string
+ DbUser string
+ DbPassword string
+ DbName string
+
+ RedisDb string
+ RedisAddr string
+ RedisPw string
+ RedisDbName string
+
+ ValidEmail string
+ SmtpHost string
+ SmtpEmail string
+ SmtpPass string
+
+ Host string
+ ProductPath string
+ AvatarPath string
+)
+
+func Init() {
+ //从本地文件读取环境变量
+ file, err := ini.Load("C:/Users/801028/Desktop/marketv1.2/go_fabric/conf/config.ini")
+ if err != nil {
+ panic(err)
+ }
+ LoadServer(file)
+ LoadMySql(file)
+ LoadRedis(file)
+ LoadEmail(file)
+ // mysql读
+ LoadPhotoPath(file)
+ PathRead := strings.Join([]string{DbUser, ":", DbPassword, "@tcp(", DbHost, ":", DbPort, ")/", DbName, "?charset=utf8mb4&parseTime=true&loc=Local"}, "")
+ //写
+ PathWrite := strings.Join([]string{DbUser, ":", DbPassword, "@tcp(", DbHost, ":", DbPort, ")/", DbName, "?charset=utf8mb4&parseTime=true&loc=Local"}, "")
+ dao.Database(PathRead, PathWrite)
+}
+
+func LoadServer(file *ini.File) {
+ AppModel = file.Section("service").Key("AppMode").String()
+ HttpPort = file.Section("service").Key("HttpPort").String()
+}
+
+func LoadMySql(file *ini.File) {
+ Db = file.Section("mysql").Key("DB").String()
+ DbHost = file.Section("mysql").Key("DbHost").String()
+ DbPort = file.Section("mysql").Key("DbPort").String()
+ DbUser = file.Section("mysql").Key("DbUser").String()
+ DbPassword = file.Section("mysql").Key("DbPassword").String()
+ DbName = file.Section("mysql").Key("DbName").String()
+}
+
+func LoadRedis(file *ini.File) {
+ RedisDb = file.Section("redis").Key("RedisDb").String()
+ RedisAddr = file.Section("redis").Key("RedisAddr").String()
+ RedisPw = file.Section("redis").Key("RedisPw").String()
+ RedisDbName = file.Section("redis").Key("RedisDbName").String()
+}
+
+func LoadEmail(file *ini.File) {
+ ValidEmail = file.Section("email").Key("ValidEmail").String()
+ SmtpHost = file.Section("email").Key("SmtpHost").String()
+ SmtpEmail = file.Section("email").Key("SmtpEmail").String()
+ SmtpPass = file.Section("email").Key("SmtpPass").String()
+}
+
+func LoadPhotoPath(file *ini.File) {
+ Host = file.Section("path").Key("Host").String()
+ ProductPath = file.Section("path").Key("ProductPath").String()
+ AvatarPath = file.Section("path").Key("AvatarPath").String()
+}
diff --git a/go_fabric/conf/config.ini b/go_fabric/conf/config.ini
new file mode 100644
index 0000000..ce7dfb6
--- /dev/null
+++ b/go_fabric/conf/config.ini
@@ -0,0 +1,36 @@
+[service]
+AppMode = debug
+HttpPort = :3000
+
+[mysql]
+DB = mysql
+DbHost = 127.0.0.1
+DbPort = 3306
+DbUser = root
+DbPassword = 240011@rbb
+DbName = poem
+
+[redis]
+RedisDb = redis
+RedisAddr = 127.0.0.1:6379
+RedisPw =
+RedisDbName = 2
+
+[qiniu]
+AccessKey =
+SecretKey =
+Bucket =
+QiniuServer =
+
+[email]
+ValidEmail = http://localhost:8080/#/vaild/email/
+SmtpHost = smtp.qq.com
+SmtpEmail = 1065109019@qq.com
+; 管理员邮箱
+SmtpPass = coziejecpksvbbcf
+; 授权码
+
+[path]
+Host = http://127.0.0.1
+ProductPath =C:/Users/801028/Desktop/marketv1.2/go_fabric/static/imags/Product/
+AvatarPath =C:/Users/801028/Desktop/marketv1.2/static/imags/avatar/
diff --git a/go_fabric/dao/init.go b/go_fabric/dao/init.go
new file mode 100644
index 0000000..21fb482
--- /dev/null
+++ b/go_fabric/dao/init.go
@@ -0,0 +1,61 @@
+package dao
+
+import (
+ "context"
+ "time"
+
+ "github.com/gin-gonic/gin"
+ "gorm.io/driver/mysql"
+ "gorm.io/gorm"
+ "gorm.io/gorm/logger"
+ "gorm.io/gorm/schema"
+ "gorm.io/plugin/dbresolver"
+)
+
+var _db *gorm.DB
+
+func Database(connRead, connWrite string) {
+ var ormLogger logger.Interface
+ if gin.Mode() == "debug" {
+ ormLogger = logger.Default.LogMode(logger.Info)
+ } else {
+ ormLogger = logger.Default
+ }
+
+ db, err := gorm.Open(mysql.New(mysql.Config{
+ DSN: connRead,
+ DefaultStringSize: 256, //string类型字段默认长度
+ DisableDatetimePrecision: true, //禁止datatime精度
+ DontSupportRenameIndex: true, //重命名索引,需要先删除索引再重建
+ DontSupportRenameColumn: true, //用change重命名列,mysql 8之前不支持
+ SkipInitializeWithVersion: false,
+ }), &gorm.Config{
+ Logger: ormLogger,
+ NamingStrategy: schema.NamingStrategy{
+ SingularTable: true,
+ },
+ })
+ if err != nil {
+ return
+ }
+ sqlDB, _ := db.DB()
+ sqlDB.SetMaxOpenConns(20) //设置连接池
+ sqlDB.SetMaxOpenConns(100) //打开连接数
+ sqlDB.SetConnMaxLifetime(time.Second * 30)
+ _db = db
+
+ // 主从配置
+ _ = _db.Use(dbresolver.
+ Register(dbresolver.Config{
+ Sources: []gorm.Dialector{mysql.Open(connWrite)}, //写操作
+ Replicas: []gorm.Dialector{mysql.Open(connRead), mysql.Open(connRead)}, //读操作
+ Policy: dbresolver.RandomPolicy{},
+ }))
+ //数据库迁移
+ migration()
+}
+
+func NewDBClient(ctx context.Context) *gorm.DB {
+ db := _db
+ return db.WithContext(ctx)
+}
diff --git a/go_fabric/dao/migration.go b/go_fabric/dao/migration.go
new file mode 100644
index 0000000..a3fbbde
--- /dev/null
+++ b/go_fabric/dao/migration.go
@@ -0,0 +1,17 @@
+package dao
+
+import (
+ "fmt"
+ "go_fabric/model"
+)
+
+func migration() {
+ err := _db.Set("gorm:table_options", "charset=utf8mb4").
+ AutoMigrate(
+ &model.Poem{},
+ )
+ if err != nil {
+ fmt.Println("err", err)
+ }
+ return
+}
diff --git a/go_fabric/dao/poem.go b/go_fabric/dao/poem.go
new file mode 100644
index 0000000..e5e1eaa
--- /dev/null
+++ b/go_fabric/dao/poem.go
@@ -0,0 +1,64 @@
+package dao
+
+import (
+ "context"
+ "go_fabric/model"
+
+ "gorm.io/gorm"
+)
+
+type UserDao struct {
+ *gorm.DB
+}
+
+func NewUserDao(ctx context.Context) *UserDao {
+ return &UserDao{NewDBClient(ctx)}
+}
+
+func NewUserDaoDB(db *gorm.DB) *UserDao {
+ return &UserDao{db}
+}
+
+// 是否存在该用户名用户
+func (dao *UserDao) ExistOrNotByUserName(userName string) (user *model.User, exist bool, err error) {
+ var count int64
+ err = dao.DB.Model(&model.User{}).Where("user_name=?", userName).Find(&user).Count(&count).Error
+ if count == 0 {
+ return nil, false, err
+ }
+ return user, true, nil
+}
+
+// 添加用户
+func (dao *UserDao) CreateUser(user *model.User) error {
+ return dao.DB.Model(&model.User{}).Create(&user).Error
+}
+
+// 根据Id寻找用户
+func (dao *UserDao) GetUserById(id uint) (user *model.User, err error) {
+ err = dao.DB.Model(&model.User{}).Where("id=?", id).First(&user).Error
+ return
+}
+
+// 查询所有用户 列表
+// offset表示偏移量,pageSize表示每页数据量,pageNum表示当前查询的页码数
+func (dao *UserDao) ListUser(pageNum int, pageSize int) (users []model.User, err error) {
+ offset := (pageNum - 1) * pageSize
+ err = dao.DB.Model(&model.User{}).Offset(offset).Limit(pageSize).Find(&users).Error
+ return
+}
+
+// 根据id修改用户信息
+func (dao *UserDao) UpdateUserById(uId uint, user *model.User) error {
+ return dao.DB.Model(&model.User{}).Where("id=?", uId).Updates(&user).Error
+}
+
+// 根据用户名删除用户
+func (dao *UserDao) DeleteByUserName(user *model.User) error {
+ return dao.DB.Delete(&user).Error
+}
+
+// 封禁用户
+func (dao *UserDao) PassiveByUserName(uId uint) error {
+ return dao.DB.Model(&model.User{}).Where("id=?", uId).Update("status", "passive").Error
+}
diff --git a/go_fabric/go.mod b/go_fabric/go.mod
new file mode 100644
index 0000000..3fc6b34
--- /dev/null
+++ b/go_fabric/go.mod
@@ -0,0 +1,44 @@
+module go_fabric
+
+go 1.20
+
+require github.com/gin-gonic/gin v1.9.1
+
+require (
+ github.com/bytedance/sonic v1.9.2 // indirect
+ github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
+ github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
+ github.com/gabriel-vasile/mimetype v1.4.2 // 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.14.1 // indirect
+ github.com/go-redis/redis v6.15.9+incompatible // indirect
+ github.com/go-sql-driver/mysql v1.7.0 // indirect
+ github.com/goccy/go-json v0.10.2 // indirect
+ github.com/jinzhu/inflection v1.0.0 // indirect
+ github.com/jinzhu/now v1.1.5 // indirect
+ github.com/json-iterator/go v1.1.12 // indirect
+ github.com/klauspost/cpuid/v2 v2.2.5 // indirect
+ github.com/leodido/go-urn v1.2.4 // indirect
+ github.com/mattn/go-isatty v0.0.19 // 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.0.8 // indirect
+ github.com/sirupsen/logrus v1.9.3 // indirect
+ github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
+ github.com/ugorji/go/codec v1.2.11 // indirect
+ golang.org/x/arch v0.4.0 // indirect
+ golang.org/x/crypto v0.11.0 // indirect
+ golang.org/x/net v0.12.0 // indirect
+ golang.org/x/sys v0.10.0 // indirect
+ golang.org/x/text v0.11.0 // indirect
+ google.golang.org/protobuf v1.31.0 // indirect
+ gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
+ gopkg.in/ini.v1 v1.67.0 // indirect
+ gopkg.in/mail.v2 v2.3.1 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
+ gorm.io/driver/mysql v1.5.1 // indirect
+ gorm.io/gorm v1.25.2 // indirect
+ gorm.io/plugin/dbresolver v1.4.1 // indirect
+)
diff --git a/go_fabric/go.sum b/go_fabric/go.sum
new file mode 100644
index 0000000..398395c
--- /dev/null
+++ b/go_fabric/go.sum
@@ -0,0 +1,109 @@
+github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
+github.com/bytedance/sonic v1.9.2 h1:GDaNjuWSGu09guE9Oql0MSTNhNCLlWwO8y/xM5BzcbM=
+github.com/bytedance/sonic v1.9.2/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
+github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
+github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
+github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
+github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
+github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
+github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
+github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
+github.com/go-playground/validator/v10 v10.14.1 h1:9c50NUPC30zyuKprjL3vNZ0m5oG+jU0zvx4AqHGnv4k=
+github.com/go-playground/validator/v10 v10.14.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
+github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
+github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
+github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
+github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
+github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
+github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+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=
+github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
+github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
+github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
+github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
+github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
+github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
+github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
+github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
+github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
+github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc=
+golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
+golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
+golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
+golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
+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.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
+golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
+golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
+gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
+gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk=
+gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/driver/mysql v1.4.3/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c=
+gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw=
+gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o=
+gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
+gorm.io/gorm v1.24.3/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
+gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
+gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho=
+gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
+gorm.io/plugin/dbresolver v1.4.1 h1:Ug4LcoPhrvqq71UhxtF346f+skTYoCa/nEsdjvHwEzk=
+gorm.io/plugin/dbresolver v1.4.1/go.mod h1:CTbCtMWhsjXSiJqiW2R8POvJ2cq18RVOl4WGyT5nhNc=
+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
diff --git a/go_fabric/middleware/cors.go b/go_fabric/middleware/cors.go
new file mode 100644
index 0000000..46f33a9
--- /dev/null
+++ b/go_fabric/middleware/cors.go
@@ -0,0 +1,45 @@
+package middleware
+
+import (
+ "fmt"
+ "net/http"
+ "strings"
+
+ "github.com/gin-gonic/gin"
+)
+
+// 跨域
+func Cors() gin.HandlerFunc {
+ return func(c *gin.Context) {
+ method := c.Request.Method //请求方法
+ origin := c.Request.Header.Get("Origin") //请求头部
+ var headerKeys []string // 声明请求头keys
+ for k := range c.Request.Header {
+ headerKeys = append(headerKeys, k)
+ }
+ headerStr := strings.Join(headerKeys, ", ")
+ if headerStr != "" {
+ headerStr = fmt.Sprintf("access-control-allow-origin, access-control-allow-headers, %s", headerStr)
+ } else {
+ headerStr = "access-control-allow-origin, access-control-allow-headers"
+ }
+ if origin != "" {
+ c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
+ c.Header("Access-Control-Allow-Origin", "*") // 这是允许访问所有域
+ c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE") //服务器支持的所有跨域请求的方法,为了避免浏览次请求的多次'预检'请求
+ // header的类型
+ c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,X_Requested_With,Accept, Origin, Host, Connection, Accept-Encoding, Accept-Language,DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Pragma")
+ // 允许跨域设置 可以返回其他子段
+ c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar") // 跨域关键设置 让浏览器可以解析
+ c.Header("Access-Control-Max-Age", "172800") // 缓存请求信息 单位为秒
+ c.Header("Access-Control-Allow-Credentials", "false") // 跨域请求是否需要带cookie信息 默认设置为true
+ c.Set("content-type", "application/json") // 设置返回格式是json
+ }
+ //放行所有OPTIONS方法
+ if method == "OPTIONS" {
+ c.JSON(http.StatusOK, "Options Request!")
+ }
+ // 处理请求
+ c.Next() // 处理请求
+ }
+}
diff --git a/go_fabric/middleware/jwt.go b/go_fabric/middleware/jwt.go
new file mode 100644
index 0000000..640bb07
--- /dev/null
+++ b/go_fabric/middleware/jwt.go
@@ -0,0 +1,36 @@
+package middleware
+
+import (
+ "github.com/gin-gonic/gin"
+ "go_fabric/pkg/e"
+ "go_fabric/pkg/util"
+ "time"
+)
+
+func JWT() gin.HandlerFunc {
+ return func(c *gin.Context) {
+ var code int
+ //var data interface{}
+ code = 200
+ token := c.GetHeader("Authorization")
+ if token == "" {
+ code = 404
+ } else {
+ claims, err := util.ParseToken(token)
+ if err != nil {
+ code = e.ErrorToken
+ } else if time.Now().Unix() > claims.ExpiresAt {
+ code = e.ErrorCheckTokenTimeOut
+ }
+ }
+ if code != e.Success {
+ c.JSON(200, gin.H{
+ "status": code,
+ "msg": e.GetMsg(code),
+ })
+ c.Abort()
+ return
+ }
+ c.Next()
+ }
+}
diff --git a/go_fabric/model/poem.go b/go_fabric/model/poem.go
new file mode 100644
index 0000000..66af1a4
--- /dev/null
+++ b/go_fabric/model/poem.go
@@ -0,0 +1,9 @@
+package model
+
+import "gorm.io/gorm"
+
+type Poem struct {
+ gorm.Model
+ Id uint `gorm:"not null"`
+ Content string
+}
diff --git a/go_fabric/pkg/e/code.go b/go_fabric/pkg/e/code.go
new file mode 100644
index 0000000..f757908
--- /dev/null
+++ b/go_fabric/pkg/e/code.go
@@ -0,0 +1,29 @@
+package e
+
+const (
+ Success = 200
+ Error = 500
+ InvalidParams = 400
+
+ //user模块错误
+ ErrorExistUser = 30001
+ ErrorFailEncryption = 30002
+ NullPassword = 30003
+ UserNotFind = 30004
+ ErrorPassword = 30005
+ ErrorToken = 30006
+ ErrorCheckTokenTimeOut = 30007
+ ErrorUploadFail = 30008
+ ErrorSendEmail = 30009
+ ErrorNotActive = 30010
+
+ //product模块错误
+ ErrorProductImgUpload = 40001
+ ProductNotFind = 40002
+ ErrorBossForProduct = 40003
+ ErrorNotSale = 40004
+ ErrorProductNum = 40005
+
+ //收藏夹模块
+ ErrorFavoriteExist = 50001
+)
diff --git a/go_fabric/pkg/e/msg.go b/go_fabric/pkg/e/msg.go
new file mode 100644
index 0000000..e43917d
--- /dev/null
+++ b/go_fabric/pkg/e/msg.go
@@ -0,0 +1,39 @@
+package e
+
+var MsgFlags = map[int]string{
+ Success: "ok",
+ Error: "fail",
+ InvalidParams: "参数错误",
+
+ //user模块错误
+ ErrorExistUser: "用户已存在",
+ NullPassword: "密码不能为空",
+ ErrorFailEncryption: "密码加密失败",
+ UserNotFind: "用户不存在",
+ ErrorPassword: "密码错误",
+ ErrorToken: "token验证失败",
+ ErrorCheckTokenTimeOut: "token过期",
+ ErrorUploadFail: "图片上传失败",
+ ErrorSendEmail: "邮件发送失败",
+ ErrorNotActive: "用户未激活",
+
+ //product模块错误
+ ErrorProductImgUpload: "商品图片上传失败",
+ ProductNotFind: "商品不存在",
+ ErrorBossForProduct: "商品与商户不匹配",
+ ErrorNotSale: "商品不在售",
+ ErrorProductNum: "商品数量错误",
+
+ //收藏夹模块
+ ErrorFavoriteExist: "收藏夹已存在",
+}
+
+// GetMsg 获取状态码对应信息
+func GetMsg(code int) string {
+ msg, ok := MsgFlags[code]
+ if !ok {
+ return MsgFlags[Error]
+ } else {
+ return msg
+ }
+}
diff --git a/go_fabric/pkg/util/enceypt.go b/go_fabric/pkg/util/enceypt.go
new file mode 100644
index 0000000..7f8ac75
--- /dev/null
+++ b/go_fabric/pkg/util/enceypt.go
@@ -0,0 +1,88 @@
+package util
+
+import (
+ "bytes"
+ "crypto/aes"
+ "encoding/base64"
+ "errors"
+)
+
+var Encrypt *Encryption
+
+// AES 加密算法
+type Encryption struct {
+ key string
+}
+
+func init() {
+ Encrypt = NewEncryption()
+}
+
+func NewEncryption() *Encryption {
+ return &Encryption{}
+}
+
+// 填充密码长度
+func PadPwd(srcByte []byte, blockSize int) []byte {
+ padNum := blockSize - len(srcByte)%blockSize
+ ret := bytes.Repeat([]byte{byte(padNum)}, padNum)
+ srcByte = append(srcByte, ret...)
+ return srcByte
+}
+
+// 加密
+func (k *Encryption) AesEncoding(src string) string {
+ srcByte := []byte(src)
+ block, err := aes.NewCipher([]byte(k.key))
+ if err != nil {
+ return src
+ }
+ // 密码填充
+ NewSrcByte := PadPwd(srcByte, block.BlockSize()) //由于字节长度不够,所以要进行字节的填充
+ dst := make([]byte, len(NewSrcByte))
+ block.Encrypt(dst, NewSrcByte)
+ // base64 编码
+ pwd := base64.StdEncoding.EncodeToString(dst)
+ return pwd
+}
+
+// 去掉填充的部分
+func UnPadPwd(dst []byte) ([]byte, error) {
+ if len(dst) <= 0 {
+ return dst, errors.New("长度有误")
+ }
+ // 去掉的长度
+ unpadNum := int(dst[len(dst)-1])
+ strErr := "error"
+ op := []byte(strErr)
+ if len(dst) < unpadNum {
+ return op, nil
+ }
+ str := dst[:(len(dst) - unpadNum)]
+ return str, nil
+}
+
+// 解密
+func (k *Encryption) AesDecoding(pwd string) string {
+ pwdByte := []byte(pwd)
+ pwdByte, err := base64.StdEncoding.DecodeString(pwd)
+ if err != nil {
+ return pwd
+ }
+ block, errBlock := aes.NewCipher([]byte(k.key))
+ if errBlock != nil {
+ return pwd
+ }
+ dst := make([]byte, len(pwdByte))
+ block.Decrypt(dst, pwdByte)
+ dst, err = UnPadPwd(dst) // 填充的要去掉
+ if err != nil {
+ return "0"
+ }
+ return string(dst)
+}
+
+// set方法
+func (k *Encryption) SetKey(key string) {
+ k.key = key
+}
diff --git a/go_fabric/pkg/util/jwt.go b/go_fabric/pkg/util/jwt.go
new file mode 100644
index 0000000..b5ca521
--- /dev/null
+++ b/go_fabric/pkg/util/jwt.go
@@ -0,0 +1,87 @@
+package util
+
+import (
+ "github.com/dgrijalva/jwt-go"
+ "time"
+)
+
+var jwtSecret = []byte("test")
+
+// 用户唯一token信息类
+type Claims struct {
+ ID uint `json:"id"`
+ UserName string `json:"user_name"`
+ Authority int `json:"authority"` //权限
+ jwt.StandardClaims
+}
+
+// token分发
+func GenerateToken(id uint, userName string, authority int) (string, error) {
+ nowTime := time.Now()
+ endTime := nowTime.Add(24 * time.Hour)
+ claims := Claims{
+ ID: id,
+ UserName: userName,
+ Authority: authority,
+ StandardClaims: jwt.StandardClaims{
+ ExpiresAt: endTime.Unix(),
+ Issuer: "test-mall",
+ },
+ }
+ tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) //哈希256加密
+ token, err := tokenClaims.SignedString(jwtSecret) //数字签名
+ return token, err
+}
+
+// token验证
+func ParseToken(token string) (*Claims, error) {
+ tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
+ return jwtSecret, nil
+ })
+ if tokenClaims != nil {
+ if claims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid {
+ return claims, nil
+ }
+ }
+ return nil, err
+}
+
+type EmailClaims struct {
+ UserID uint `json:"user_id"`
+ Email string `json:"email"`
+ Password string `json:"password"`
+ OperationType uint `json:"operation_type"`
+ jwt.StandardClaims
+}
+
+// 签发email token
+func GenerateEmailToken(userId, Operation uint, email, password string) (string, error) {
+ nowTime := time.Now()
+ endTime := nowTime.Add(24 * time.Hour)
+ claims := EmailClaims{
+ UserID: userId,
+ Email: email,
+ Password: password,
+ OperationType: Operation,
+ StandardClaims: jwt.StandardClaims{
+ ExpiresAt: endTime.Unix(),
+ Issuer: "test-mall",
+ },
+ }
+ tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) //哈希256加密
+ token, err := tokenClaims.SignedString(jwtSecret) //数字签名
+ return token, err
+}
+
+// 解密email token
+func ParseEmailToken(token string) (*EmailClaims, error) {
+ tokenClaims, err := jwt.ParseWithClaims(token, &EmailClaims{}, func(token *jwt.Token) (interface{}, error) {
+ return jwtSecret, nil
+ })
+ if tokenClaims != nil {
+ if claims, ok := tokenClaims.Claims.(*EmailClaims); ok && tokenClaims.Valid {
+ return claims, nil
+ }
+ }
+ return nil, err
+}
diff --git a/go_fabric/pkg/util/logger.go b/go_fabric/pkg/util/logger.go
new file mode 100644
index 0000000..5572a33
--- /dev/null
+++ b/go_fabric/pkg/util/logger.go
@@ -0,0 +1,59 @@
+package util
+
+import (
+ "github.com/sirupsen/logrus"
+ "log"
+ "os"
+ "path"
+ "time"
+)
+
+// 日志打印
+var LoggerObj *logrus.Logger
+
+func init() {
+ src, _ := setOutPutFile()
+ if LoggerObj != nil {
+ LoggerObj.Out = src
+ return
+ }
+ //实例化
+ logger := logrus.New()
+ logger.Out = src //设置输出
+ logger.SetLevel(logrus.DebugLevel) //设置日志级别
+ logger.SetFormatter(&logrus.TextFormatter{
+ TimestampFormat: "2006-01-02 15:04:05",
+ })
+ LoggerObj = logger
+}
+
+func setOutPutFile() (*os.File, error) {
+ now := time.Now()
+ logFilePath := ""
+ if dir, err := os.Getwd(); err == nil { //工作目录下
+ logFilePath = dir + "/logs/"
+ }
+ _, err := os.Stat(logFilePath)
+ if os.IsNotExist(err) {
+ if err = os.MkdirAll(logFilePath, 0777); err != nil {
+ log.Println(err.Error())
+ return nil, err
+ }
+ }
+ logFileName := now.Format("2006-1-02") + ".log"
+ //日志文件
+ fileName := path.Join(logFilePath, logFileName)
+ _, err = os.Stat(fileName)
+ if os.IsNotExist(err) {
+ if err = os.MkdirAll(fileName, 0777); err != nil {
+ log.Println(err.Error())
+ return nil, err
+ }
+ }
+ // 写入文件
+ src, err := os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY, os.ModeAppend)
+ if err != nil {
+ return nil, err
+ }
+ return src, nil
+}
diff --git a/go_fabric/routes/router.go b/go_fabric/routes/router.go
new file mode 100644
index 0000000..e78c592
--- /dev/null
+++ b/go_fabric/routes/router.go
@@ -0,0 +1,40 @@
+package routes
+
+import (
+ api "go_fabric/api/v1"
+ "go_fabric/middleware"
+ "net/http"
+
+ "github.com/gin-gonic/gin"
+)
+
+func NewRouter() *gin.Engine {
+ r := gin.Default()
+
+ r.Use(middleware.Cors())
+ r.StaticFS("/static", http.Dir("C:/Users/801028/Desktop/marketv1.2/go_fabric/static/"))
+ // jr.StaticFile("/avatar.jpg", "/GOCODE/go_fabric/static/imags/avatar/avatar.jpg")
+ v1 := r.Group("api/v1")
+ {
+ v1.GET("ping", func(ctx *gin.Context) {
+ ctx.JSON(200, "success")
+ })
+ //获取诗词
+ v1.GET("poem/gain", api.PoemGet)
+
+ //用户操作
+ v1.POST("user/register", api.UserRegister)
+ v1.POST("user/login", api.UserLogin)
+
+ authed := v1.Group("/") //登录保护
+ authed.Use(middleware.JWT())
+ {
+ // 用户操作
+ authed.PUT("user", api.UserUpdate) //用户信息更新
+ authed.POST("avatar", api.UpdateAvatar) //用户上传头像
+ authed.POST("user/send-email", api.SendEmail) //发送验证邮件
+ authed.POST("user/valid-email", api.ValidEmail) //绑定邮箱
+ }
+ }
+ return r
+}
diff --git a/go_fabric/serializer/common.go b/go_fabric/serializer/common.go
new file mode 100644
index 0000000..9bbb90d
--- /dev/null
+++ b/go_fabric/serializer/common.go
@@ -0,0 +1,39 @@
+package serializer
+
+type Response struct {
+ Status int `json:"status"`
+ Data interface{} `json:"data"`
+ Msg string `json:"msg"`
+ Error string `json:"error"`
+}
+
+type TokenData struct {
+ User interface{} `json:"user"`
+ Token string `json:"tokens"`
+}
+
+type AdminToken struct {
+ Admin interface{} `json:"admin"`
+ Token string `json:"tokens"`
+}
+
+type BossToken struct {
+ Boss interface{} `json:"boss"`
+ Token string `json:"tokens"`
+}
+
+type DataList struct {
+ Item interface{} `json:"item"`
+ Total uint `json:"total"`
+}
+
+func BuildListResponse(items interface{}, total uint) Response {
+ return Response{
+ Status: 200,
+ Data: DataList{
+ Item: items,
+ Total: total,
+ },
+ Msg: "ok",
+ }
+}
diff --git a/go_fabric/serializer/poem.go b/go_fabric/serializer/poem.go
new file mode 100644
index 0000000..3be7958
--- /dev/null
+++ b/go_fabric/serializer/poem.go
@@ -0,0 +1,26 @@
+package serializer
+
+import (
+ "go_fabric/model"
+)
+
+// Vo 向前端展示
+type PoemVo struct {
+ Id uint `json:"id"`
+ Content string `json:"content"`
+}
+
+func BuildUser(poem *model.Poem) PoemVo {
+ return PoemVo{
+ Id: poem.Id,
+ Content: poem.Content,
+ }
+}
+
+func BuildUsers(items []model.Poem) (users []PoemVo) {
+ for _, item := range items {
+ poem := BuildUser(&item)
+ poems = append(poems, poem)
+ }
+ return poems
+}
diff --git a/go_fabric/service/poem.go b/go_fabric/service/poem.go
new file mode 100644
index 0000000..cc72525
--- /dev/null
+++ b/go_fabric/service/poem.go
@@ -0,0 +1,379 @@
+package service
+
+import (
+ "context"
+ "fmt"
+ "go_fabric/conf"
+ "go_fabric/dao"
+ "go_fabric/model"
+ "go_fabric/pkg/e"
+ "go_fabric/pkg/util"
+ "go_fabric/serializer"
+ "mime/multipart"
+ "strings"
+ "time"
+
+ "gopkg.in/mail.v2"
+)
+
+type UserService struct {
+ NickName string `json:"nick_name" form:"nick_name"`
+ UserName string `json:"user_name" form:"user_name"`
+ Password string `json:"password" form:"password"`
+ Key string `json:"key" form:"key"` //加密密钥
+}
+
+type SendEmailService struct {
+ Email string `json:"email" form:"email"`
+ Password string `json:"password"`
+ OperationType uint `json:"operation_type" form:"operation_type"` // 1.绑定邮箱 2.解绑邮箱 3.更改密码
+}
+
+type ValidEmailService struct {
+}
+
+// 注册
+func (service *UserService) Register(ctx context.Context) serializer.Response {
+ var user model.User
+ code := e.Success
+ if service.Key == "" || len(service.Key) != 6 {
+ code = e.Error
+ return serializer.Response{
+ Status: code,
+ Data: nil,
+ Msg: e.GetMsg(code),
+ Error: "密钥长度不符",
+ }
+ }
+ util.Encrypt.SetKey(service.Key)
+
+ userDao := dao.NewUserDao(ctx)
+ _, exist, err := userDao.ExistOrNotByUserName(service.UserName)
+ if err != nil {
+ util.LoggerObj.Error(err)
+ code = e.Error
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ }
+ }
+ if exist {
+ code = e.ErrorExistUser
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ }
+ }
+ user = model.User{
+ UserName: service.UserName,
+ NickName: service.NickName,
+ Avatar: "avatar.JPG",
+ Status: model.Active,
+ Money: "1000",
+ Vip: 0,
+ }
+ //密码是否为空
+ if service.Password == "" {
+ code = e.NullPassword
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ }
+ }
+ //密码加密
+ if err = user.SetPassword(service.Password); err != nil {
+ util.LoggerObj.Error(err)
+ code = e.ErrorFailEncryption
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ }
+ }
+ //创建用户
+ err = userDao.CreateUser(&user)
+ if err != nil {
+ util.LoggerObj.Error(err)
+ code = e.Error
+ }
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ }
+}
+
+// 登录
+func (service *UserService) Login(ctx context.Context) serializer.Response {
+ var user *model.User
+ code := e.Success
+ userDao := dao.NewUserDao(ctx)
+ //检查用户是否存在
+ user, exist, err := userDao.ExistOrNotByUserName(service.UserName)
+ if !exist || err != nil {
+ util.LoggerObj.Error(err)
+ code = e.UserNotFind
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ Data: "用户不存在,请先注册",
+ }
+ }
+ //验证密码是否正确
+ if user.CheckPassword(service.Password) == false {
+ code = e.ErrorPassword
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ Data: "密码错误,请重新输入",
+ }
+ }
+ //分发token
+ token, err := util.GenerateToken(user.ID, service.UserName, 0)
+ if err != nil {
+ util.LoggerObj.Error(err)
+ code = e.ErrorToken
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ Data: "token验证失败",
+ }
+ }
+ return serializer.Response{
+ Status: code,
+ Data: serializer.TokenData{User: serializer.BuildUser(user), Token: token},
+ Msg: e.GetMsg(code),
+ }
+}
+
+// 用户修改信息
+func (service *UserService) Update(ctx context.Context, uId uint) serializer.Response {
+ var user *model.User
+ var err error
+ code := e.Success
+ //寻找用户
+ userDao := dao.NewUserDao(ctx)
+ user, err = userDao.GetUserById(uId)
+
+ //检查用户状态
+ if user.Status == "passive" {
+ code = e.ErrorNotActive
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ Error: "用户没有激活,没有权限",
+ }
+ }
+
+ //修改昵称nickname
+ if service.NickName != "" {
+ user.NickName = service.NickName
+ }
+ err = userDao.UpdateUserById(uId, user)
+ if err != nil {
+ util.LoggerObj.Error(err)
+ code = e.Error
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ }
+ }
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ Data: serializer.BuildUser(user),
+ }
+}
+
+// 头像更新
+func (service *UserService) Post(ctx context.Context, uId uint, file multipart.File, fileSize int64) serializer.Response {
+ code := e.Success
+ var user *model.User
+ var err error
+ userDao := dao.NewUserDao(ctx)
+ user, err = userDao.GetUserById(uId)
+
+ if user.Status == "passive" {
+ code = e.ErrorNotActive
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ Error: "用户没有激活,没有权限",
+ }
+ }
+
+ if err != nil {
+ code = e.Error
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ Error: err.Error(),
+ }
+ }
+ //保存图片到本地
+ path, err := UploadAvatarLocalStatic(file, uId, user.UserName)
+ if err != nil {
+ code = e.ErrorUploadFail
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ Error: err.Error(),
+ }
+ }
+ user.Avatar = path
+ err = userDao.UpdateUserById(uId, user)
+ if err != nil {
+ util.LoggerObj.Error(err)
+ code = e.Error
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ Error: err.Error(),
+ }
+ }
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ Data: serializer.BuildUser(user),
+ }
+}
+
+// 发送验证邮件
+func (service *SendEmailService) Send(ctx context.Context, uId uint) serializer.Response {
+ code := e.Success
+ var address string
+ var notice *model.Notice // 绑定邮箱,修改密码 模板通知
+
+ userDao := dao.NewUserDao(ctx)
+ user, err := userDao.GetUserById(uId)
+ //检查用户状态
+ if user.Status == "passive" {
+ code = e.ErrorNotActive
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ Error: "用户没有激活,没有权限",
+ }
+ }
+
+ token, err := util.GenerateEmailToken(uId, service.OperationType, service.Email, service.Password)
+ if err != nil {
+ util.LoggerObj.Error(err)
+ code = e.ErrorToken
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ Error: err.Error(),
+ }
+ }
+ noticeDao := dao.NewNoticeDao(ctx)
+ notice, err = noticeDao.GetNoticeById(service.OperationType)
+ if err != nil {
+ util.LoggerObj.Error(err)
+ code = e.Error
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ Error: err.Error(),
+ }
+ }
+ address = conf.ValidEmail + token //发送者
+ mailStr := notice.Text
+ mailText := strings.Replace(mailStr, "+", address, -1)
+ fmt.Println(mailText)
+ m := mail.NewMessage()
+ m.SetHeader("From", conf.SmtpEmail) //管理员邮箱
+ m.SetHeader("To", service.Email) //验证者邮箱
+ m.SetHeader("Subject", "fabric_mall")
+ m.SetBody("text/html", mailText)
+ d := mail.NewDialer(conf.SmtpHost, 465, conf.SmtpEmail, conf.SmtpPass)
+ d.StartTLSPolicy = mail.MandatoryStartTLS
+ if err = d.DialAndSend(m); err != nil {
+ util.LoggerObj.Error(err)
+ code = e.ErrorSendEmail
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ Error: err.Error(),
+ }
+ }
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ }
+}
+
+// 验证邮箱
+func (service *ValidEmailService) Valid(ctx context.Context, token string) serializer.Response {
+ var userId uint
+ var email string
+ var password string
+ var operationType uint
+ code := e.Success
+ //验证token
+ if token == "" {
+ code = e.InvalidParams
+
+ } else {
+ claims, err := util.ParseEmailToken(token)
+ if err != nil {
+ util.LoggerObj.Error(err)
+ code = e.ErrorToken
+
+ } else if time.Now().Unix() > claims.ExpiresAt {
+ code = e.ErrorCheckTokenTimeOut
+
+ } else {
+ userId = claims.UserID
+ email = claims.Email
+ password = claims.Password
+ operationType = claims.OperationType
+ }
+ }
+ if code != e.Success {
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ }
+ }
+
+ // token解析成功,获取用户信息
+ userDao := dao.NewUserDao(ctx)
+ user, err := userDao.GetUserById(userId)
+ if err != nil {
+ util.LoggerObj.Error(err)
+ code = e.Error
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ }
+ }
+
+ if operationType == 1 { //1.绑定邮箱
+ user.Email = email
+ } else if operationType == 2 { //2.解绑邮箱
+ user.Email = ""
+ } else if operationType == 3 { //3.修改密码
+ err = user.SetPassword(password)
+ if err != nil {
+ util.LoggerObj.Error(err)
+ code = e.Error
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ }
+ }
+ }
+ err = userDao.UpdateUserById(userId, user)
+ if err != nil {
+ util.LoggerObj.Error(err)
+ code = e.Error
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ }
+ }
+ return serializer.Response{
+ Status: code,
+ Msg: e.GetMsg(code),
+ Data: serializer.BuildUser(user),
+ }
+}
diff --git a/go_fabric/test.go b/go_fabric/test.go
new file mode 100644
index 0000000..1f2794a
--- /dev/null
+++ b/go_fabric/test.go
@@ -0,0 +1,17 @@
+package main
+
+import (
+ "github.com/gin-gonic/gin"
+)
+
+func main() {
+ router := gin.Default()
+
+ router.GET("/index", func(ctx *gin.Context) {
+ ctx.String(200, "hellpo_world")
+ })
+
+ router.StaticFile("/avatar.jpg", "/gocode/go_fabric/static/imags/avatar/avatar.jpg")
+
+ router.Run(":8080")
+}