refactor: 引入tailwind css & 后端部分非公共包位置调整

This commit is contained in:
meilin.huang
2025-04-18 22:07:37 +08:00
parent 585cbbed23
commit abd2b4bac0
168 changed files with 763 additions and 793 deletions

View File

@@ -1,7 +1,7 @@
package imsg
import (
"mayfly-go/internal/common/consts"
"mayfly-go/internal/pkg/consts"
"mayfly-go/pkg/i18n"
)

View File

@@ -1,13 +1,13 @@
package api
import (
"mayfly-go/internal/common/consts"
"mayfly-go/internal/db/api/form"
"mayfly-go/internal/db/api/vo"
"mayfly-go/internal/db/application"
"mayfly-go/internal/db/application/dto"
"mayfly-go/internal/db/domain/entity"
"mayfly-go/internal/db/imsg"
"mayfly-go/internal/pkg/consts"
tagapp "mayfly-go/internal/tag/application"
tagentity "mayfly-go/internal/tag/domain/entity"

View File

@@ -2,13 +2,13 @@ package application
import (
"context"
"mayfly-go/internal/common/consts"
"mayfly-go/internal/db/application/dto"
"mayfly-go/internal/db/dbm"
"mayfly-go/internal/db/dbm/dbi"
"mayfly-go/internal/db/domain/entity"
"mayfly-go/internal/db/domain/repository"
"mayfly-go/internal/db/imsg"
"mayfly-go/internal/pkg/consts"
tagapp "mayfly-go/internal/tag/application"
tagdto "mayfly-go/internal/tag/application/dto"
tagentity "mayfly-go/internal/tag/domain/entity"

View File

@@ -2,7 +2,6 @@ package dbm
import (
"fmt"
"mayfly-go/internal/common/consts"
"mayfly-go/internal/db/dbm/dbi"
_ "mayfly-go/internal/db/dbm/dm"
_ "mayfly-go/internal/db/dbm/mssql"
@@ -11,6 +10,7 @@ import (
_ "mayfly-go/internal/db/dbm/postgres"
_ "mayfly-go/internal/db/dbm/sqlite"
"mayfly-go/internal/machine/mcm"
"mayfly-go/internal/pkg/consts"
"mayfly-go/pkg/cache"
"mayfly-go/pkg/logx"
"sync"

View File

@@ -2,8 +2,8 @@ package sqlparser
import (
"io"
"mayfly-go/internal/common/utils"
"mayfly-go/internal/db/dbm/sqlparser/sqlstmt"
"mayfly-go/internal/pkg/utils"
)
type DbDialect string

View File

@@ -1,7 +1,7 @@
package imsg
import (
"mayfly-go/internal/common/consts"
"mayfly-go/internal/pkg/consts"
"mayfly-go/pkg/i18n"
)

View File

@@ -2,7 +2,6 @@ package api
import (
"fmt"
"mayfly-go/internal/common/consts"
"mayfly-go/internal/flow/api/form"
"mayfly-go/internal/flow/api/vo"
"mayfly-go/internal/flow/application"
@@ -10,6 +9,7 @@ import (
"mayfly-go/internal/flow/domain/entity"
"mayfly-go/internal/flow/domain/repository"
"mayfly-go/internal/flow/imsg"
"mayfly-go/internal/pkg/consts"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/req"
"mayfly-go/pkg/utils/collx"

View File

@@ -9,6 +9,7 @@ import (
"mayfly-go/internal/flow/domain/repository"
"mayfly-go/internal/flow/imsg"
msgdto "mayfly-go/internal/msg/application/dto"
"mayfly-go/internal/pkg/consts"
"mayfly-go/pkg/base"
"mayfly-go/pkg/contextx"
"mayfly-go/pkg/errorx"
@@ -108,7 +109,7 @@ func (p *procinstAppImpl) CancelProc(ctx context.Context, procinstId uint64) err
if la == nil {
return errorx.NewBiz("no login")
}
if procinst.CreatorId != la.Id {
if procinst.CreatorId != consts.AdminId && procinst.CreatorId != la.Id {
return errorx.NewBizI(ctx, imsg.ErrProcinstCancelSelf)
}
procinst.Status = entity.ProcinstStatusCancelled

View File

@@ -1,7 +1,7 @@
package imsg
import (
"mayfly-go/internal/common/consts"
"mayfly-go/internal/pkg/consts"
"mayfly-go/pkg/i18n"
)

View File

@@ -2,7 +2,6 @@ package api
import (
"fmt"
"mayfly-go/internal/common/consts"
"mayfly-go/internal/event"
"mayfly-go/internal/machine/api/form"
"mayfly-go/internal/machine/api/vo"
@@ -12,6 +11,7 @@ import (
"mayfly-go/internal/machine/guac"
"mayfly-go/internal/machine/imsg"
"mayfly-go/internal/machine/mcm"
"mayfly-go/internal/pkg/consts"
tagapp "mayfly-go/internal/tag/application"
tagentity "mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/biz"

View File

@@ -1,7 +1,7 @@
package imsg
import (
"mayfly-go/internal/common/consts"
"mayfly-go/internal/pkg/consts"
"mayfly-go/pkg/i18n"
)

View File

@@ -2,7 +2,7 @@ package mcm
import (
"errors"
"mayfly-go/internal/common/consts"
"mayfly-go/internal/pkg/consts"
tagentity "mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/cache"
"mayfly-go/pkg/logx"

View File

@@ -2,13 +2,13 @@ package api
import (
"context"
"mayfly-go/internal/common/consts"
"mayfly-go/internal/event"
"mayfly-go/internal/mongo/api/form"
"mayfly-go/internal/mongo/api/vo"
"mayfly-go/internal/mongo/application"
"mayfly-go/internal/mongo/domain/entity"
"mayfly-go/internal/mongo/imsg"
"mayfly-go/internal/pkg/consts"
tagapp "mayfly-go/internal/tag/application"
tagentity "mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/biz"

View File

@@ -2,11 +2,11 @@ package application
import (
"context"
"mayfly-go/internal/common/consts"
"mayfly-go/internal/mongo/domain/entity"
"mayfly-go/internal/mongo/domain/repository"
"mayfly-go/internal/mongo/imsg"
"mayfly-go/internal/mongo/mgm"
"mayfly-go/internal/pkg/consts"
tagapp "mayfly-go/internal/tag/application"
tagdto "mayfly-go/internal/tag/application/dto"
tagentity "mayfly-go/internal/tag/domain/entity"

View File

@@ -1,7 +1,7 @@
package imsg
import (
"mayfly-go/internal/common/consts"
"mayfly-go/internal/pkg/consts"
"mayfly-go/pkg/i18n"
)

View File

@@ -1,8 +1,8 @@
package mgm
import (
"mayfly-go/internal/common/consts"
"mayfly-go/internal/machine/mcm"
"mayfly-go/internal/pkg/consts"
"mayfly-go/pkg/cache"
"mayfly-go/pkg/logx"
"sync"

View File

@@ -75,8 +75,7 @@ func (m *MsgTmpl) DelMsgTmpls(rc *req.Ctx) {
func (m *MsgTmpl) SendMsg(rc *req.Ctx) {
code := rc.PathParam("code")
form := &form.SendMsg{}
req.BindJsonAndValid(rc, form)
form := req.BindJsonAndValid(rc, new(form.SendMsg))
rc.ReqParam = form

View File

@@ -1,7 +1,7 @@
package imsg
import (
"mayfly-go/internal/common/consts"
"mayfly-go/internal/pkg/consts"
"mayfly-go/pkg/i18n"
)

View File

@@ -0,0 +1,30 @@
package config
import (
"fmt"
"mayfly-go/pkg/utils/assert"
"mayfly-go/pkg/utils/cryptox"
)
type Aes struct {
Key string `yaml:"key"`
}
// 编码并base64
func (a *Aes) EncryptBase64(data []byte) (string, error) {
return cryptox.AesEncryptBase64(data, []byte(a.Key))
}
// base64解码后再aes解码
func (a *Aes) DecryptBase64(data string) ([]byte, error) {
return cryptox.AesDecryptBase64(data, []byte(a.Key))
}
func (a *Aes) Valid() {
if a.Key == "" {
return
}
aesKeyLen := len(a.Key)
assert.IsTrue(aesKeyLen == 16 || aesKeyLen == 24 || aesKeyLen == 32,
fmt.Sprintf("config.yml之 [aes.key] 长度需为16、24、32位长度, 当前为%d位", aesKeyLen))
}

View File

@@ -0,0 +1,12 @@
package config
import "fmt"
const (
AppName = "mayfly-go"
Version = "v1.9.4"
)
func GetAppInfo() string {
return fmt.Sprintf("[%s:%s]", AppName, Version)
}

View File

@@ -0,0 +1,131 @@
package config
import (
"flag"
"fmt"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/utils/ymlx"
"os"
"path/filepath"
"strconv"
)
type ConfigItem interface {
// 验证配置
Valid()
// 如果不存在配置值,则设置默认值
Default()
}
// 配置文件映射对象
var Conf *Config
func Init() {
configFilePath := flag.String("e", "./config.yml", "配置文件路径,默认为可执行文件目录")
flag.Parse()
// 获取启动参数中,配置文件的绝对路径
path, _ := filepath.Abs(*configFilePath)
startConfigParam := &CmdConfigParam{ConfigFilePath: path}
// 读取配置文件信息
yc := &Config{}
if err := ymlx.LoadYml(startConfigParam.ConfigFilePath, yc); err != nil {
logx.Warn(fmt.Sprintf("读取配置文件[%s]失败: %s, 使用系统默认配置或环境变量配置", startConfigParam.ConfigFilePath, err.Error()))
}
// 尝试使用系统环境变量替换配置信息
yc.ReplaceOsEnv()
yc.IfBlankDefaultValue()
// 校验配置文件内容信息
yc.Valid()
Conf = yc
}
// 启动配置参数
type CmdConfigParam struct {
ConfigFilePath string // -e 配置文件路径
}
// yaml配置文件映射对象
type Config struct {
Server Server `yaml:"server"`
Jwt Jwt `yaml:"jwt"`
Aes Aes `yaml:"aes"`
Mysql Mysql `yaml:"mysql"`
Sqlite Sqlite `yaml:"sqlite"`
Redis Redis `yaml:"redis"`
Log Log `yaml:"log"`
}
func (c *Config) IfBlankDefaultValue() {
c.Log.Default()
// 优先初始化log因为后续的一些default方法中会需要用到。统一日志输出
logx.Init(logx.Config{
Level: c.Log.Level,
Type: c.Log.Type,
AddSource: c.Log.AddSource,
Filename: c.Log.File.Name,
Filepath: c.Log.File.Path,
MaxSize: c.Log.File.MaxSize,
MaxAge: c.Log.File.MaxAge,
Compress: c.Log.File.Compress,
})
c.Server.Default()
c.Jwt.Default()
c.Mysql.Default()
c.Sqlite.Default()
}
// 配置文件内容校验
func (c *Config) Valid() {
c.Jwt.Valid()
c.Aes.Valid()
}
// 替换系统环境变量,如果环境变量中存在该值,则优先使用环境变量设定的值
func (c *Config) ReplaceOsEnv() {
serverPort := os.Getenv("MAYFLY_SERVER_PORT")
if serverPort != "" {
if num, err := strconv.Atoi(serverPort); err != nil {
panic("环境变量-[MAYFLY_SERVER_PORT]-服务端口号需为数字")
} else {
c.Server.Port = num
}
}
dbHost := os.Getenv("MAYFLY_DB_HOST")
if dbHost != "" {
c.Mysql.Host = dbHost
}
dbName := os.Getenv("MAYFLY_DB_NAME")
if dbName != "" {
c.Mysql.Dbname = dbName
}
dbUser := os.Getenv("MAYFLY_DB_USER")
if dbUser != "" {
c.Mysql.Username = dbUser
}
dbPwd := os.Getenv("MAYFLY_DB_PASS")
if dbPwd != "" {
c.Mysql.Password = dbPwd
}
sqlitePath := os.Getenv("MAYFLY_SQLITE_PATH")
if sqlitePath != "" {
c.Sqlite.Path = sqlitePath
}
aesKey := os.Getenv("MAYFLY_AES_KEY")
if aesKey != "" {
c.Aes.Key = aesKey
}
jwtKey := os.Getenv("MAYFLY_JWT_KEY")
if jwtKey != "" {
c.Jwt.Key = jwtKey
}
}

View File

@@ -0,0 +1,34 @@
package config
import (
"mayfly-go/pkg/logx"
"mayfly-go/pkg/utils/assert"
"mayfly-go/pkg/utils/stringx"
)
type Jwt struct {
Key string `yaml:"key"`
ExpireTime uint64 `yaml:"expire-time"` // 过期时间,单位分钟
RefreshTokenExpireTime uint64 `yaml:"refresh-token-expire-time"` // 刷新token的过期时间单位分钟
}
func (j *Jwt) Default() {
if j.Key == "" {
// 如果配置文件中的jwt key为空则随机生成字符串
j.Key = stringx.Rand(32)
logx.Warnf("未配置jwt.key, 随机生成key为: %s", j.Key)
}
if j.ExpireTime == 0 {
j.ExpireTime = 1440
logx.Warnf("未配置jwt.expire-time, 默认值: %d", j.ExpireTime)
}
if j.RefreshTokenExpireTime == 0 {
j.RefreshTokenExpireTime = j.ExpireTime * 5
logx.Warnf("未配置jwt.refresh-token-expire-time, 默认值: %d", j.RefreshTokenExpireTime)
}
}
func (j *Jwt) Valid() {
assert.IsTrue(j.ExpireTime != 0, "config.yml之[jwt.expire-time] 不能为空")
}

View File

@@ -0,0 +1,33 @@
package config
import (
"mayfly-go/pkg/logx"
)
type Log struct {
Level string `yaml:"level"`
Type string `yaml:"type"`
AddSource bool `yaml:"add-source"`
File LogFile `yaml:"file"`
}
func (l *Log) Default() {
if l.Level == "" {
l.Level = "info"
logx.Warnf("未配置log.level, 默认值: %s", l.Level)
}
if l.Type == "" {
l.Type = "text"
}
if l.File.Name == "" {
l.File.Name = "mayfly-go.log"
}
}
type LogFile struct {
Name string `yaml:"name"`
Path string `yaml:"path"`
MaxSize int `yaml:"max-size"`
MaxAge int `yaml:"max-age"`
Compress bool `yaml:"compress"`
}

View File

@@ -0,0 +1,35 @@
package config
import "mayfly-go/pkg/logx"
type Mysql struct {
Host string `mapstructure:"path" json:"host" yaml:"host"`
Config string `mapstructure:"config" json:"config" yaml:"config"`
Dbname string `mapstructure:"db-name" json:"dbname" yaml:"db-name"`
Username string `mapstructure:"username" json:"username" yaml:"username"`
Password string `mapstructure:"password" json:"password" yaml:"password"`
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"`
LogZap string `mapstructure:"log-zap" json:"logZap" yaml:"log-zap"`
}
func (m *Mysql) Default() {
if m.Host == "" {
m.Host = "localhost:3306"
logx.Warnf("[使用sqlite可忽略]未配置mysql.host, 默认值: %s", m.Host)
}
if m.Config == "" {
m.Config = "charset=utf8&loc=Local&parseTime=true"
}
if m.MaxIdleConns == 0 {
m.MaxIdleConns = 5
}
if m.MaxOpenConns == 0 {
m.MaxOpenConns = m.MaxIdleConns
}
}
func (m *Mysql) Dsn() string {
return m.Username + ":" + m.Password + "@tcp(" + m.Host + ")/" + m.Dbname + "?" + m.Config
}

View File

@@ -0,0 +1,8 @@
package config
type Redis struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
Password string `yaml:"password"`
Db int `yaml:"db"`
}

View File

@@ -0,0 +1,49 @@
package config
import (
"fmt"
"mayfly-go/pkg/i18n"
)
type Server struct {
Lang string `yaml:"lang"`
Port int `yaml:"port"`
Model string `yaml:"model"`
ContextPath string `yaml:"context-path"` // 请求路径上下文
Cors bool `yaml:"cors"`
Tls *Tls `yaml:"tls"`
Static *[]*Static `yaml:"static"`
StaticFile *[]*StaticFile `yaml:"static-file"`
}
func (s *Server) Default() {
if s.Lang == "" {
s.Lang = i18n.Zh_CN
}
if s.Model == "" {
s.Model = "release"
}
if s.Port == 0 {
s.Port = 18888
}
}
func (s *Server) GetPort() string {
return fmt.Sprintf(":%d", s.Port)
}
type Static struct {
RelativePath string `yaml:"relative-path"`
Root string `yaml:"root"`
}
type StaticFile struct {
RelativePath string `yaml:"relative-path"`
Filepath string `yaml:"filepath"`
}
type Tls struct {
Enable bool `yaml:"enable"` // 是否启用tls
KeyFile string `yaml:"key-file"` // 私钥文件路径
CertFile string `yaml:"cert-file"` // 证书文件路径
}

View File

@@ -0,0 +1,22 @@
package config
import "mayfly-go/pkg/logx"
type Sqlite struct {
Path string `mapstructure:"path" json:"path" yaml:"path"`
MaxIdleConns int `mapstructure:"max-idle-conns" json:"maxIdleConns" yaml:"max-idle-conns"`
MaxOpenConns int `mapstructure:"max-open-conns" json:"maxOpenConns" yaml:"max-open-conns"`
}
func (m *Sqlite) Default() {
if m.Path == "" {
m.Path = "./mayfly-go.sqlite"
logx.Warnf("[使用mysql可忽略]未配置sqlite.path, 默认值: %s", m.Path)
}
if m.MaxIdleConns == 0 {
m.MaxIdleConns = 5
}
if m.MaxOpenConns == 0 {
m.MaxOpenConns = m.MaxIdleConns
}
}

View File

@@ -0,0 +1,20 @@
package starter
import (
"fmt"
"mayfly-go/internal/pkg/config"
"mayfly-go/pkg/logx"
"os"
"runtime/debug"
)
func printBanner() {
buildInfo, _ := debug.ReadBuildInfo()
logx.Print(fmt.Sprintf(`
__ _
_ __ ___ __ _ _ _ / _| |_ _ __ _ ___
| '_ ' _ \ / _' | | | | |_| | | | |_____ / _' |/ _ \
| | | | | | (_| | |_| | _| | |_| |_____| (_| | (_) | version: %s | go_version: %s | pid: %d
|_| |_| |_|\__,_|\__, |_| |_|\__, | \__, |\___/
|___/ |___/ |___/ `, config.Version, buildInfo.GoVersion, os.Getpid()))
}

View File

@@ -0,0 +1,88 @@
package starter
import (
"log"
"mayfly-go/internal/pkg/config"
"mayfly-go/pkg/global"
"mayfly-go/pkg/logx"
"time"
"github.com/glebarez/sqlite"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"gorm.io/gorm/schema"
)
func initDb() {
global.Db = initGormDb()
}
func initGormDb() *gorm.DB {
m := config.Conf.Mysql
// 存在msyql数据库名则优先使用mysql
if m.Dbname != "" {
return initMysql(m)
}
return initSqlite(config.Conf.Sqlite)
}
func initMysql(m config.Mysql) *gorm.DB {
logx.Infof("connecting to mysql [%s]", m.Host)
mysqlConfig := mysql.Config{
DSN: m.Dsn(), // DSN data source name
DefaultStringSize: 191, // string 类型字段的默认长度
DisableDatetimePrecision: true, // 禁用 datetime 精度MySQL 5.6 之前的数据库不支持
DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
DontSupportRenameColumn: true, // 用 `change` 重命名列MySQL 8 之前的数据库和 MariaDB 不支持重命名列
SkipInitializeWithVersion: false, // 根据版本自动配置
}
if db, err := gorm.Open(mysql.New(mysqlConfig), getGormConfig()); err != nil {
logx.Panicf("failed to connect to mysql! [%s]", err.Error())
return nil
} else {
sqlDB, _ := db.DB()
sqlDB.SetMaxIdleConns(m.MaxIdleConns)
sqlDB.SetMaxOpenConns(m.MaxOpenConns)
return db
}
}
func initSqlite(sc config.Sqlite) *gorm.DB {
logx.Infof("connecting to sqlite [%s]", sc.Path)
if db, err := gorm.Open(sqlite.Open(sc.Path), getGormConfig()); err != nil {
logx.Panicf("failed to connect to sqlite! [%s]", err.Error())
return nil
} else {
sqlDB, _ := db.DB()
sqlDB.SetMaxIdleConns(sc.MaxIdleConns)
sqlDB.SetMaxOpenConns(sc.MaxOpenConns)
return db
}
}
func getGormConfig() *gorm.Config {
sqlLogLevel := logger.Error
logConf := logx.GetConfig()
// 如果为配置文件中配置的系统日志级别为debug则打印gorm执行的sql信息
if logConf.IsDebug() {
sqlLogLevel = logger.Info
}
gormLogger := logger.New(
log.New(logConf.GetLogOut(), "\r\n", log.LstdFlags), // io writer日志输出的目标前缀和日志包含的内容——译者注
logger.Config{
SlowThreshold: time.Second, // 慢 SQL 阈值
LogLevel: sqlLogLevel, // 日志级别, 改为logger.Info即可显示sql语句
IgnoreRecordNotFoundError: true, // 忽略ErrRecordNotFound记录未找到错误
Colorful: false, // 禁用彩色打印
},
)
return &gorm.Config{NamingStrategy: schema.NamingStrategy{
TablePrefix: "t_",
SingularTable: true,
}, Logger: gormLogger}
}

View File

@@ -0,0 +1,36 @@
package starter
import (
"context"
"fmt"
"mayfly-go/internal/pkg/config"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/rediscli"
"github.com/redis/go-redis/v9"
)
func initRedis() {
rediscli.SetCli(connRedis())
}
func connRedis() *redis.Client {
// 设置redis客户端
redisConf := config.Conf.Redis
if redisConf.Host == "" {
// logx.Panic("未找到redis配置信息")
return nil
}
logx.Infof("连接redis [%s:%d]", redisConf.Host, redisConf.Port)
rdb := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", redisConf.Host, redisConf.Port),
Password: redisConf.Password, // no password set
DB: redisConf.Db, // use default DB
})
// 测试连接
_, e := rdb.Ping(context.TODO()).Result()
if e != nil {
logx.Panicf("连接redis失败! [%s:%d][%s]", redisConf.Host, redisConf.Port, e.Error())
}
return rdb
}

View File

@@ -0,0 +1,61 @@
package starter
import (
"context"
"mayfly-go/initialize"
"mayfly-go/internal/pkg/config"
"mayfly-go/migration"
"mayfly-go/pkg/global"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/validatorx"
"os"
"os/signal"
"syscall"
)
func RunWebServer() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() {
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
cancel()
}()
// 初始化config.yml配置文件映射信息或使用环境变量。并初始化系统日志相关配置
config.Init()
// 打印banner
printBanner()
// 初始化并赋值数据库全局变量
initDb()
// 有配置redis信息则初始化redis。多台机器部署需要使用redis存储验证码、权限、公私钥等
initRedis()
// 数据库升级操作
if err := migration.RunMigrations(global.Db); err != nil {
logx.Panicf("db migration failed: %v", err)
}
// 参数校验器初始化、如错误提示中文转译等
validatorx.Init()
// 注册自定义正则表达式校验规则
RegisterCustomPatterns()
// 初始化其他需要启动时运行的方法
initialize.InitOther()
// 运行web服务
runWebServer(ctx)
}
// 注册自定义正则表达式校验规则
func RegisterCustomPatterns() {
// 账号用户名校验
validatorx.RegisterPattern("account_username", "^[a-zA-Z0-9_]{5,20}$", "只允许输入5-20位大小写字母、数字、下划线")
validatorx.RegisterPattern("resource_code", "^[a-zA-Z0-9_\\-.:]{1,32}$", "只允许输入1-32位大小写字母、数字、_-.:")
}

View File

@@ -0,0 +1,126 @@
package starter
import (
"context"
"errors"
"io/fs"
"mayfly-go/initialize"
"mayfly-go/internal/pkg/config"
"mayfly-go/pkg/i18n"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/middleware"
"mayfly-go/pkg/req"
"mayfly-go/static"
"net/http"
"time"
sysapp "mayfly-go/internal/sys/application"
"github.com/gin-gonic/gin"
)
func runWebServer(ctx context.Context) {
// 设置gin日志输出器
logOut := logx.GetConfig().GetLogOut()
gin.DefaultErrorWriter = logOut
gin.DefaultWriter = logOut
// 权限处理器
req.UseBeforeHandlerInterceptor(req.PermissionHandler)
// 日志处理器
req.UseAfterHandlerInterceptor(req.LogHandler)
// 设置日志保存函数
req.SetSaveLogFunc(sysapp.GetSyslogApp().SaveFromReq)
// jwt配置
jwtConf := config.Conf.Jwt
req.SetJwtConf(req.JwtConf{
Key: jwtConf.Key,
ExpireTime: jwtConf.ExpireTime,
RefreshTokenExpireTime: jwtConf.RefreshTokenExpireTime,
})
// i18n配置
i18n.SetLang(config.Conf.Server.Lang)
// server配置
serverConfig := config.Conf.Server
gin.SetMode(serverConfig.Model)
var router = gin.New()
router.MaxMultipartMemory = 8 << 20
// 初始化接口路由
initialize.InitRouter(router, initialize.RouterConfig{ContextPath: serverConfig.ContextPath})
// 设置静态资源
setStatic(serverConfig.ContextPath, router)
// 是否允许跨域
if serverConfig.Cors {
router.Use(middleware.Cors())
}
srv := http.Server{
Addr: config.Conf.Server.GetPort(),
// 注册路由
Handler: router,
}
go func() {
<-ctx.Done()
logx.Info("Shutdown HTTP Server ...")
timeout, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
err := srv.Shutdown(timeout)
if err != nil {
logx.Errorf("failed to Shutdown HTTP Server: %v", err)
}
initialize.Terminate()
}()
confSrv := config.Conf.Server
logx.Infof("Listening and serving HTTP on %s", srv.Addr+confSrv.ContextPath)
var err error
if confSrv.Tls != nil && confSrv.Tls.Enable {
err = srv.ListenAndServeTLS(confSrv.Tls.CertFile, confSrv.Tls.KeyFile)
} else {
err = srv.ListenAndServe()
}
if errors.Is(err, http.ErrServerClosed) {
logx.Info("HTTP Server Shutdown")
} else if err != nil {
logx.Errorf("Failed to Start HTTP Server: %v", err)
}
}
func setStatic(contextPath string, router *gin.Engine) {
// 使用embed打包静态资源至二进制文件中
fsys, _ := fs.Sub(static.Static, "static")
fileServer := http.FileServer(http.FS(fsys))
handler := WrapStaticHandler(http.StripPrefix(contextPath, fileServer))
router.GET(contextPath+"/", handler)
router.GET(contextPath+"/favicon.ico", handler)
router.GET(contextPath+"/config.js", handler)
// 所有/assets/**开头的都是静态资源文件
router.GET(contextPath+"/assets/*file", handler)
// 设置静态资源
if staticConfs := config.Conf.Server.Static; staticConfs != nil {
for _, scs := range *staticConfs {
router.StaticFS(scs.RelativePath, http.Dir(scs.Root))
}
}
// 设置静态文件
if staticFileConfs := config.Conf.Server.StaticFile; staticFileConfs != nil {
for _, sfs := range *staticFileConfs {
router.StaticFile(sfs.RelativePath, sfs.Filepath)
}
}
}
func WrapStaticHandler(h http.Handler) gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.Header().Set("Cache-Control", `public, max-age=31536000`)
h.ServeHTTP(c.Writer, c.Request)
}
}

View File

@@ -1,7 +1,7 @@
package utils
import (
"mayfly-go/pkg/config"
"mayfly-go/internal/pkg/config"
"regexp"
)

View File

@@ -2,8 +2,8 @@ package api
import (
"context"
"mayfly-go/internal/common/consts"
"mayfly-go/internal/common/utils"
"mayfly-go/internal/pkg/consts"
"mayfly-go/internal/pkg/utils"
"mayfly-go/internal/redis/api/form"
"mayfly-go/internal/redis/api/vo"
"mayfly-go/internal/redis/application"

View File

@@ -2,10 +2,10 @@ package application
import (
"context"
"mayfly-go/internal/common/consts"
"mayfly-go/internal/common/utils"
flowapp "mayfly-go/internal/flow/application"
flowentity "mayfly-go/internal/flow/domain/entity"
"mayfly-go/internal/pkg/consts"
"mayfly-go/internal/pkg/utils"
"mayfly-go/internal/redis/application/dto"
"mayfly-go/internal/redis/domain/entity"
"mayfly-go/internal/redis/domain/repository"

View File

@@ -2,7 +2,7 @@ package application
import (
"fmt"
"mayfly-go/internal/common/utils"
"mayfly-go/internal/pkg/utils"
"strings"
"testing"
)

View File

@@ -1,7 +1,7 @@
package entity
import (
"mayfly-go/internal/common/utils"
"mayfly-go/internal/pkg/utils"
"mayfly-go/internal/redis/rdm"
tagentity "mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/logx"

View File

@@ -1,7 +1,7 @@
package imsg
import (
"mayfly-go/internal/common/consts"
"mayfly-go/internal/pkg/consts"
"mayfly-go/pkg/i18n"
)

View File

@@ -2,8 +2,8 @@ package rdm
import (
"fmt"
"mayfly-go/internal/common/consts"
"mayfly-go/internal/machine/mcm"
"mayfly-go/internal/pkg/consts"
"mayfly-go/pkg/cache"
"mayfly-go/pkg/logx"
"sync"

View File

@@ -1,7 +1,7 @@
package api
import (
"mayfly-go/internal/common/utils"
"mayfly-go/internal/pkg/utils"
"mayfly-go/internal/sys/api/form"
"mayfly-go/internal/sys/api/vo"
"mayfly-go/internal/sys/application"

View File

@@ -1,12 +1,12 @@
package api
import (
"mayfly-go/internal/pkg/config"
"mayfly-go/internal/sys/api/form"
"mayfly-go/internal/sys/application"
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/internal/sys/imsg"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/config"
"mayfly-go/pkg/req"
"mayfly-go/pkg/utils/collx"
)

View File

@@ -2,7 +2,7 @@ package application
import (
"context"
"mayfly-go/internal/common/consts"
"mayfly-go/internal/pkg/consts"
"mayfly-go/internal/sys/application/dto"
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/internal/sys/domain/repository"

View File

@@ -2,7 +2,7 @@ package entity
import (
"errors"
"mayfly-go/internal/common/utils"
"mayfly-go/internal/pkg/utils"
"mayfly-go/pkg/enumx"
"mayfly-go/pkg/model"
"time"

View File

@@ -1,7 +1,7 @@
package imsg
import (
"mayfly-go/internal/common/consts"
"mayfly-go/internal/pkg/consts"
"mayfly-go/pkg/i18n"
)

View File

@@ -3,7 +3,7 @@ package application
import (
"context"
"fmt"
"mayfly-go/internal/common/consts"
"mayfly-go/internal/pkg/consts"
"mayfly-go/internal/tag/application/dto"
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/internal/tag/domain/repository"

View File

@@ -2,7 +2,7 @@ package application
import (
"context"
"mayfly-go/internal/common/consts"
"mayfly-go/internal/pkg/consts"
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/internal/tag/domain/repository"
"mayfly-go/internal/tag/imsg"

View File

@@ -2,7 +2,7 @@ package entity
import (
"errors"
"mayfly-go/internal/common/utils"
"mayfly-go/internal/pkg/utils"
"mayfly-go/pkg/model"
)

View File

@@ -2,7 +2,7 @@ package entity
import (
"fmt"
"mayfly-go/internal/common/consts"
"mayfly-go/internal/pkg/consts"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils/collx"
"strings"

View File

@@ -1,7 +1,7 @@
package imsg
import (
"mayfly-go/internal/common/consts"
"mayfly-go/internal/pkg/consts"
"mayfly-go/pkg/i18n"
)