Compare commits
22 Commits
v1.0.0.000
...
main
| Author | SHA1 | Date |
|---|---|---|
|
|
60f0d8053d | |
|
|
258112d38e | |
|
|
8927551779 | |
|
|
0ad7304eca | |
|
|
a1a2785c71 | |
|
|
8743f40739 | |
|
|
d549cf929b | |
|
|
6c72a05b64 | |
|
|
27e26b1d72 | |
|
|
edff2f198a | |
|
|
53aa8367dc | |
|
|
3bfca3805a | |
|
|
60dcd37901 | |
|
|
b704eee2bc | |
|
|
0067b7385e | |
|
|
bb7b3eacc7 | |
|
|
dd8d406c33 | |
|
|
04736c3ba9 | |
|
|
931b539b61 | |
|
|
8dde22e47c | |
|
|
a4ca7a754f | |
|
|
14af10fdce |
|
|
@ -0,0 +1,461 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GoORMHelperCache">
|
||||
<option name="schemaMapping">
|
||||
<map>
|
||||
<entry key="Api">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/response/code.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="BaseConfig">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/config/structs.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="Client">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/mqtt/client/mqtt.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="Config">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/ws/websocket.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="Connection">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/ws/websocket.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="ConnectionPool">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/tcp/tcp.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="Curd">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/curd/curd.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="DataBaseConfig">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/config/structs.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="JWTClaims">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/utils/jwt.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="JwtConfig">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/config/structs.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="Manager">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/ws/websocket.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="Msg">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/ws/websocket.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="NewsOne">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/../gin_test/api/new.go" />
|
||||
<option value="file://$PROJECT_DIR$/../gin_test/req/new.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="NewsSave">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/../gin_test/api/new.go" />
|
||||
<option value="file://$PROJECT_DIR$/../gin_test/req/new.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="Paginate">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/curd/curd.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="ServerConfig">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/config/structs.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="TCPServer">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/tcp/tcp.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="TcpConnection">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/tcp/tcpConfig.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="TcpMessage">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/tcp/tcpConfig.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="TcpPoolConfig">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/tcp/tcpConfig.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="response">
|
||||
<value>
|
||||
<set>
|
||||
<option value="file://$PROJECT_DIR$/response/code.go" />
|
||||
</set>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
<option name="scannedPathMapping">
|
||||
<map>
|
||||
<entry key="file://$PROJECT_DIR$/config/fun.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770100625919" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/config/index.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770011355476" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/config/structs.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770022381063" />
|
||||
<option name="schema">
|
||||
<list>
|
||||
<option value="BaseConfig" />
|
||||
<option value="ServerConfig" />
|
||||
<option value="DataBaseConfig" />
|
||||
<option value="JwtConfig" />
|
||||
</list>
|
||||
</option>
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/curd/curd.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770102564408" />
|
||||
<option name="schema">
|
||||
<list>
|
||||
<option value="Paginate" />
|
||||
<option value="Curd" />
|
||||
</list>
|
||||
</option>
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/database/database.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770258641711" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/database/index.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770025447924" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/database/migrate.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770101088203" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/log/index.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770011347706" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/log/log.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770011076335" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/main.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770025551953" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/middleware/middleware.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770108038945" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/mqtt/client/mqtt.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770025698340" />
|
||||
<option name="schema">
|
||||
<list>
|
||||
<option value="Client" />
|
||||
</list>
|
||||
</option>
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/response/code.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770014431840" />
|
||||
<option name="schema">
|
||||
<list>
|
||||
<option value="response" />
|
||||
<option value="Api" />
|
||||
</list>
|
||||
</option>
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/server/server.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770026239951" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/tcp/example.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770025697304" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/tcp/tcp.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770025697304" />
|
||||
<option name="schema">
|
||||
<list>
|
||||
<option value="TCPServer" />
|
||||
<option value="ConnectionPool" />
|
||||
</list>
|
||||
</option>
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/tcp/tcpConfig.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770025697304" />
|
||||
<option name="schema">
|
||||
<list>
|
||||
<option value="TcpPoolConfig" />
|
||||
<option value="TcpConnection" />
|
||||
<option value="TcpMessage" />
|
||||
</list>
|
||||
</option>
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/utils/file.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1769850381300" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/utils/jwt.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770090940817" />
|
||||
<option name="schema">
|
||||
<list>
|
||||
<option value="JWTClaims" />
|
||||
</list>
|
||||
</option>
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/utils/ptr.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770016124510" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/valid/valid.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770197737203" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/ws/example.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770025697531" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/ws/websocket.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770018907536" />
|
||||
<option name="schema">
|
||||
<list>
|
||||
<option value="Config" />
|
||||
<option value="Connection" />
|
||||
<option value="Manager" />
|
||||
<option value="Msg" />
|
||||
</list>
|
||||
</option>
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/../gin_test/api/home.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770190095707" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/../gin_test/api/new.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770191206242" />
|
||||
<option name="schema">
|
||||
<list>
|
||||
<option value="NewsOne" />
|
||||
<option value="NewsSave" />
|
||||
</list>
|
||||
</option>
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/../gin_test/controller/home/houeRouter.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770191001042" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/../gin_test/controller/home/index.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770255253603" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/../gin_test/controller/home/router.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770190557848" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/../gin_test/req/new.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770186504009" />
|
||||
<option name="schema">
|
||||
<list>
|
||||
<option value="NewsOne" />
|
||||
<option value="NewsSave" />
|
||||
</list>
|
||||
</option>
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file://$PROJECT_DIR$/../gin_test/router/router.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1770191024510" />
|
||||
</ScannedPath>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
<option name="tableStructMapping">
|
||||
<map>
|
||||
<entry key="api" value="Api" />
|
||||
<entry key="base_config" value="BaseConfig" />
|
||||
<entry key="client" value="Client" />
|
||||
<entry key="config" value="Config" />
|
||||
<entry key="connection" value="Connection" />
|
||||
<entry key="connection_pool" value="ConnectionPool" />
|
||||
<entry key="curd" value="Curd" />
|
||||
<entry key="data_base_config" value="DataBaseConfig" />
|
||||
<entry key="jwt_claims" value="JWTClaims" />
|
||||
<entry key="jwt_config" value="JwtConfig" />
|
||||
<entry key="manager" value="Manager" />
|
||||
<entry key="msg" value="Msg" />
|
||||
<entry key="news_one" value="NewsOne" />
|
||||
<entry key="news_save" value="NewsSave" />
|
||||
<entry key="paginate" value="Paginate" />
|
||||
<entry key="response" value="response" />
|
||||
<entry key="server_config" value="ServerConfig" />
|
||||
<entry key="tcp_connection" value="TcpConnection" />
|
||||
<entry key="tcp_message" value="TcpMessage" />
|
||||
<entry key="tcp_pool_config" value="TcpPoolConfig" />
|
||||
<entry key="tcp_server" value="TCPServer" />
|
||||
</map>
|
||||
</option>
|
||||
<option name="lastTimeChecked" value="1770185677345" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -57,8 +57,8 @@ func init() {
|
|||
func SetDefault() {
|
||||
viper.Set("SERVER.addr", "127.0.0.1:8080")
|
||||
viper.Set("SERVER.mode", "release")
|
||||
viper.Set("DATABASE.type", "mysql")
|
||||
viper.Set("DATABASE.dns", "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local")
|
||||
viper.Set("DATABASE.type", "sqlite")
|
||||
viper.Set("DATABASE.dns", gfile.Join(gfile.Pwd(), "db", "database.db"))
|
||||
viper.Set("JWT.secret", "SET-YOUR-SECRET")
|
||||
viper.Set("JWT.expire", 86400)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,614 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/schema"
|
||||
)
|
||||
|
||||
// 定义上下文别名,保持原代码风格
|
||||
type ctx = context.Context
|
||||
|
||||
// IDao -------------------------- 核心接口定义 --------------------------
|
||||
// IDao GORM 版本的Dao接口,提供GORM DB实例和表相关信息
|
||||
type IDao interface {
|
||||
DB() *gorm.DB // 返回GORM的DB实例
|
||||
Table() string // 返回表名
|
||||
PrimaryKey() string // 返回主键字段名(如:id)
|
||||
Ctx(ctx context.Context) *gorm.DB // 绑定上下文的DB实例
|
||||
Transaction(ctx context.Context, f func(ctx context.Context, tx *gorm.DB) error) error // 事务方法
|
||||
}
|
||||
|
||||
// Paginate -------------------------- 分页结构体定义 --------------------------
|
||||
// Paginate 分页参数结构体(补全原代码中缺失的定义,保持功能完整)
|
||||
type Paginate struct {
|
||||
Page int // 页码(从1开始)
|
||||
Limit int // 每页条数
|
||||
}
|
||||
|
||||
// -------------------------- 全局常量 --------------------------
|
||||
// 分页相关字段,用于清理请求参数
|
||||
var pageInfo = []string{
|
||||
"page",
|
||||
"size",
|
||||
"num",
|
||||
"limit",
|
||||
"pagesize",
|
||||
"pageSize",
|
||||
"page_size",
|
||||
"pageNum",
|
||||
"pagenum",
|
||||
"page_num",
|
||||
}
|
||||
|
||||
// Curd -------------------------- 泛型CURD核心结构体 --------------------------
|
||||
// Curd GORM 版本的泛型CURD封装,R为对应的模型结构体
|
||||
type Curd[R any] struct {
|
||||
Dao IDao
|
||||
}
|
||||
|
||||
// -------------------------- 工具方法:字段名转换(保持原代码的命名风格转换) --------------------------
|
||||
// caseConvert 字段名风格转换(下划线 <-> 小驼峰)
|
||||
func caseConvert(key string, toSnake bool) string {
|
||||
if toSnake {
|
||||
// 驼峰转下划线(参考GORM的命名策略)
|
||||
return schema.NamingStrategy{}.ColumnName("", key)
|
||||
}
|
||||
// 下划线转小驼峰
|
||||
var result strings.Builder
|
||||
upperNext := false
|
||||
for i, c := range key {
|
||||
if c == '_' && i < len(key)-1 {
|
||||
upperNext = true
|
||||
continue
|
||||
}
|
||||
if upperNext {
|
||||
result.WriteRune(rune(strings.ToUpper(string(c))[0]))
|
||||
upperNext = false
|
||||
} else {
|
||||
result.WriteRune(c)
|
||||
}
|
||||
}
|
||||
return result.String()
|
||||
}
|
||||
|
||||
// BuildWhere -------------------------- 原BuildWhere对应实现:构建查询条件map --------------------------
|
||||
func (c Curd[R]) BuildWhere(req any, changeWhere any, subWhere any, removeFields []string, isSnake ...bool) map[string]any {
|
||||
// 默认使用小写下划线方式
|
||||
toSnake := true
|
||||
if len(isSnake) > 0 && !isSnake[0] {
|
||||
toSnake = false
|
||||
}
|
||||
|
||||
// 1. 转换req为map并清理无效数据
|
||||
reqMap := convToMap(req)
|
||||
cleanedReq := make(map[string]any)
|
||||
|
||||
for k, v := range reqMap {
|
||||
// 清理空值
|
||||
if isEmpty(v) {
|
||||
continue
|
||||
}
|
||||
// 清理分页字段
|
||||
if strInArray(pageInfo, k) {
|
||||
continue
|
||||
}
|
||||
// 清理指定移除字段
|
||||
if len(removeFields) > 0 && strInArray(removeFields, k) {
|
||||
continue
|
||||
}
|
||||
// 转换字段名风格并存入
|
||||
cleanedReq[caseConvert(k, toSnake)] = v
|
||||
}
|
||||
|
||||
// 2. 处理changeWhere(修改查询操作符,如:eq -> gt)
|
||||
if changeWhere != nil {
|
||||
changeMap := convToMap(changeWhere)
|
||||
for k, v := range changeMap {
|
||||
// 跳过不存在于cleanedReq的字段
|
||||
if _, exists := cleanedReq[k]; !exists {
|
||||
continue
|
||||
}
|
||||
// 跳过指定移除的字段
|
||||
if len(removeFields) > 0 && strInArray(removeFields, k) {
|
||||
continue
|
||||
}
|
||||
|
||||
vMap := convToMap(v)
|
||||
value, hasValue := vMap["value"]
|
||||
op, hasOp := vMap["op"]
|
||||
|
||||
if hasValue {
|
||||
// 存在操作符则重构字段名(GORM支持 "字段名 >" 这种格式作为where key)
|
||||
if hasOp && op != "" {
|
||||
newKey := fmt.Sprintf("%s %s", k, op)
|
||||
delete(cleanedReq, k)
|
||||
cleanedReq[newKey] = value
|
||||
} else {
|
||||
cleanedReq[k] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 字段名风格最终转换(确保一致性)
|
||||
resultMap := make(map[string]any)
|
||||
for k, v := range cleanedReq {
|
||||
// 拆分字段名和操作符
|
||||
parts := strings.SplitN(k, " ", 2)
|
||||
fieldName := parts[0]
|
||||
opStr := ""
|
||||
if len(parts) == 2 {
|
||||
opStr = parts[1]
|
||||
}
|
||||
|
||||
// 转换字段名风格
|
||||
convertedField := caseConvert(fieldName, toSnake)
|
||||
|
||||
// 重构带操作符的key
|
||||
if opStr != "" {
|
||||
resultMap[fmt.Sprintf("%s %s", convertedField, opStr)] = v
|
||||
} else {
|
||||
resultMap[convertedField] = v
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 合并subWhere附加条件
|
||||
if subWhere != nil {
|
||||
subMap := convToMap(subWhere)
|
||||
for k, v := range subMap {
|
||||
resultMap[caseConvert(k, toSnake)] = v
|
||||
}
|
||||
}
|
||||
|
||||
return resultMap
|
||||
}
|
||||
|
||||
// BuildMap -------------------------- 原BuildMap对应实现:构建变更条件map --------------------------
|
||||
func (c Curd[R]) BuildMap(op string, value any, field ...string) map[string]any {
|
||||
res := map[string]any{
|
||||
"op": op,
|
||||
"field": "",
|
||||
"value": value,
|
||||
}
|
||||
if len(field) > 0 {
|
||||
res["field"] = field[0]
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ClearField -------------------------- 原ClearField对应实现:清理请求参数并返回有效map --------------------------
|
||||
func (c Curd[R]) ClearField(req any, delField []string, subField ...map[string]any) map[string]any {
|
||||
reqMap := convToMap(req)
|
||||
resultMap := make(map[string]any)
|
||||
|
||||
// 过滤无效数据和指定删除字段
|
||||
for k, v := range reqMap {
|
||||
if isEmpty(v) {
|
||||
continue
|
||||
}
|
||||
if strInArray(pageInfo, k) {
|
||||
continue
|
||||
}
|
||||
if len(delField) > 0 && strInArray(delField, k) {
|
||||
continue
|
||||
}
|
||||
resultMap[k] = v
|
||||
}
|
||||
|
||||
// 合并附加字段
|
||||
if len(subField) > 0 && subField[0] != nil {
|
||||
for k, v := range subField[0] {
|
||||
resultMap[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return resultMap
|
||||
}
|
||||
|
||||
// ClearFieldPage -------------------------- 原ClearFieldPage对应实现:清理参数+分页查询 --------------------------
|
||||
func (c Curd[R]) ClearFieldPage(ctx ctx, req any, delField []string, where any, page *Paginate, order any, with bool) (items []*R, total int64, err error) {
|
||||
// 1. 清理请求参数
|
||||
filterMap := c.ClearField(req, delField)
|
||||
|
||||
// 2. 初始化GORM查询
|
||||
db := c.Dao.Ctx(ctx)
|
||||
if with {
|
||||
db = db.Preload("*") // GORM 关联查询全部,对应GF的WithAll()
|
||||
}
|
||||
|
||||
// 3. 构建查询条件
|
||||
db = db.Model(new(R)).Where(filterMap)
|
||||
if where != nil {
|
||||
db = db.Where(where)
|
||||
}
|
||||
|
||||
// 4. 排序
|
||||
if order != nil {
|
||||
db = db.Order(order)
|
||||
}
|
||||
|
||||
// 5. 统计总数
|
||||
if err = db.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// 6. 分页查询
|
||||
if page != nil && page.Limit > 0 {
|
||||
offset := (page.Page - 1) * page.Limit
|
||||
db = db.Offset(offset).Limit(page.Limit)
|
||||
}
|
||||
|
||||
// 7. 执行查询
|
||||
err = db.Find(&items).Error
|
||||
return
|
||||
}
|
||||
|
||||
// ClearFieldList -------------------------- 原ClearFieldList对应实现:清理参数+列表查询(不分页) --------------------------
|
||||
func (c Curd[R]) ClearFieldList(ctx ctx, req any, delField []string, where any, order any, with bool) (items []*R, err error) {
|
||||
filterMap := c.ClearField(req, delField)
|
||||
db := c.Dao.Ctx(ctx).Model(new(R))
|
||||
|
||||
if with {
|
||||
db = db.Preload("*")
|
||||
}
|
||||
if where != nil {
|
||||
db = db.Where(where)
|
||||
}
|
||||
if order != nil {
|
||||
db = db.Order(order)
|
||||
}
|
||||
|
||||
err = db.Where(filterMap).Find(&items).Error
|
||||
return
|
||||
}
|
||||
|
||||
// ClearFieldOne -------------------------- 原ClearFieldOne对应实现:清理参数+单条查询 --------------------------
|
||||
func (c Curd[R]) ClearFieldOne(ctx ctx, req any, delField []string, where any, order any, with bool) (item *R, err error) {
|
||||
item = new(R)
|
||||
filterMap := c.ClearField(req, delField)
|
||||
db := c.Dao.Ctx(ctx).Model(item)
|
||||
|
||||
if with {
|
||||
db = db.Preload("*")
|
||||
}
|
||||
if where != nil {
|
||||
db = db.Where(where)
|
||||
}
|
||||
if order != nil {
|
||||
db = db.Order(order)
|
||||
}
|
||||
|
||||
err = db.Where(filterMap).First(item).Error
|
||||
// 处理记录不存在的情况(GORM会返回ErrRecordNotFound)
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
panic("未找到数据")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Value -------------------------- 原Value对应实现:查询单个字段值 --------------------------
|
||||
func (c Curd[R]) Value(ctx ctx, where any, field any) (interface{}, error) {
|
||||
var result interface{}
|
||||
db := c.Dao.Ctx(ctx).Model(new(R)).Where(where)
|
||||
|
||||
// 处理字段参数
|
||||
if field != nil {
|
||||
fieldStr, ok := field.(string)
|
||||
if !ok || fieldStr == "" {
|
||||
fieldStr = "*"
|
||||
}
|
||||
db = db.Select(fieldStr)
|
||||
} else {
|
||||
db = db.Select("*")
|
||||
}
|
||||
|
||||
// 执行查询(取第一条记录的指定字段)
|
||||
err := db.First(&result).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
panic("未找到数据")
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
// DeletePri -------------------------- 原DeletePri对应实现:按主键删除 --------------------------
|
||||
func (c Curd[R]) DeletePri(ctx ctx, primaryKey any) error {
|
||||
db := c.Dao.Ctx(ctx).Model(new(R))
|
||||
// 按主键字段构建查询
|
||||
pk := c.Dao.PrimaryKey()
|
||||
if pk == "" {
|
||||
panic("主键字段未配置")
|
||||
}
|
||||
return db.Where(fmt.Sprintf("%s = ?", pk), primaryKey).Delete(new(R)).Error
|
||||
}
|
||||
|
||||
// DeleteWhere -------------------------- 原DeleteWhere对应实现:按条件删除 --------------------------
|
||||
func (c Curd[R]) DeleteWhere(ctx ctx, where any) error {
|
||||
return c.Dao.Ctx(ctx).Model(new(R)).Where(where).Delete(new(R)).Error
|
||||
}
|
||||
|
||||
// Sum -------------------------- 原Sum对应实现:字段求和 --------------------------
|
||||
func (c Curd[R]) Sum(ctx ctx, where any, field string) float64 {
|
||||
var sum float64
|
||||
if field == "" {
|
||||
panic("求和字段不能为空")
|
||||
}
|
||||
|
||||
err := c.Dao.Ctx(ctx).Model(new(R)).Where(where).Select(fmt.Sprintf("SUM(%s) as sum", field)).Scan(&sum).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
panic("未找到数据")
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
// ArrayField -------------------------- 原ArrayField对应实现:查询指定字段数组 --------------------------
|
||||
func (c Curd[R]) ArrayField(ctx ctx, where any, field any) []interface{} {
|
||||
var result []interface{}
|
||||
db := c.Dao.Ctx(ctx).Model(new(R)).Where(where)
|
||||
|
||||
// 处理字段参数
|
||||
if field != nil {
|
||||
fieldStr, ok := field.(string)
|
||||
if !ok || fieldStr == "" {
|
||||
fieldStr = "*"
|
||||
}
|
||||
db = db.Select(fieldStr)
|
||||
} else {
|
||||
db = db.Select("*")
|
||||
}
|
||||
|
||||
// 执行查询
|
||||
err := db.Find(&result).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
panic("未找到数据")
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// FindPri -------------------------- 原FindPri对应实现:按主键查询单条记录 --------------------------
|
||||
func (c Curd[R]) FindPri(ctx ctx, primaryKey any, with bool) (model *R) {
|
||||
model = new(R)
|
||||
db := c.Dao.Ctx(ctx).Model(model)
|
||||
pk := c.Dao.PrimaryKey()
|
||||
|
||||
if pk == "" {
|
||||
panic("主键字段未配置")
|
||||
}
|
||||
if with {
|
||||
db = db.Preload("*")
|
||||
}
|
||||
|
||||
// 按主键查询
|
||||
err := db.Where(fmt.Sprintf("%s = ?", pk), primaryKey).First(model).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
panic("未找到数据")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// -------------------------- 原First对应实现:按条件查询第一条记录 --------------------------
|
||||
func (c Curd[R]) First(ctx ctx, where any, order any, with bool) (model *R) {
|
||||
model = new(R)
|
||||
db := c.Dao.Ctx(ctx).Model(model)
|
||||
|
||||
if with {
|
||||
db = db.Preload("*")
|
||||
}
|
||||
if where != nil {
|
||||
db = db.Where(where)
|
||||
}
|
||||
if order != nil {
|
||||
db = db.Order(order)
|
||||
}
|
||||
|
||||
err := db.First(model).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
panic("未找到数据")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// -------------------------- 原Exists对应实现:判断记录是否存在 --------------------------
|
||||
func (c Curd[R]) Exists(ctx ctx, where any) (exists bool) {
|
||||
var count int64
|
||||
err := c.Dao.Ctx(ctx).Model(new(R)).Where(where).Count(&count).Error
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Exists查询错误: %v", err))
|
||||
}
|
||||
return count > 0
|
||||
}
|
||||
|
||||
// -------------------------- 原All对应实现:查询所有符合条件的记录 --------------------------
|
||||
func (c Curd[R]) All(ctx ctx, where any, order any, with bool) (items []*R) {
|
||||
db := c.Dao.Ctx(ctx).Model(new(R))
|
||||
|
||||
if with {
|
||||
db = db.Preload("*")
|
||||
}
|
||||
if where != nil {
|
||||
db = db.Where(where)
|
||||
}
|
||||
if order != nil {
|
||||
db = db.Order(order)
|
||||
}
|
||||
|
||||
err := db.Find(&items).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
panic(fmt.Sprintf("All查询错误: %v", err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// -------------------------- 原Count对应实现:统计记录总数 --------------------------
|
||||
func (c Curd[R]) Count(ctx ctx, where any) (count int64) {
|
||||
err := c.Dao.Ctx(ctx).Model(new(R)).Where(where).Count(&count).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
panic(fmt.Sprintf("Count查询错误: %v", err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// -------------------------- 原Save对应实现:新增/更新记录(对应GORM的Save) --------------------------
|
||||
func (c Curd[R]) Save(ctx ctx, data any) {
|
||||
err := c.Dao.Ctx(ctx).Model(new(R)).Create(data).Error
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Save保存错误: %v", err))
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------- 原Update对应实现:按条件更新记录 --------------------------
|
||||
func (c Curd[R]) Update(ctx ctx, where any, data any) (count int64) {
|
||||
result := c.Dao.Ctx(ctx).Model(new(R)).Where(where).Updates(data)
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
panic(fmt.Sprintf("Update更新错误: %v", result.Error.Error()))
|
||||
}
|
||||
return result.RowsAffected
|
||||
}
|
||||
|
||||
// -------------------------- 原UpdatePri对应实现:按主键更新记录 --------------------------
|
||||
func (c Curd[R]) UpdatePri(ctx ctx, primaryKey any, data any) (count int64) {
|
||||
db := c.Dao.Ctx(ctx).Model(new(R))
|
||||
pk := c.Dao.PrimaryKey()
|
||||
|
||||
if pk == "" {
|
||||
panic("主键字段未配置")
|
||||
}
|
||||
|
||||
result := db.Where(fmt.Sprintf("%s = ?", pk), primaryKey).Updates(data)
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
panic(fmt.Sprintf("UpdatePri更新错误: %v", result.Error.Error()))
|
||||
}
|
||||
return result.RowsAffected
|
||||
}
|
||||
|
||||
// -------------------------- 原Paginate对应实现:分页查询 --------------------------
|
||||
func (c Curd[R]) Paginate(ctx context.Context, where any, p Paginate, with bool, order any) (items []*R, total int64) {
|
||||
db := c.Dao.Ctx(ctx).Model(new(R))
|
||||
|
||||
// 1. 构建查询条件
|
||||
if where != nil {
|
||||
db = db.Where(where)
|
||||
}
|
||||
|
||||
// 2. 统计总数
|
||||
if err := db.Count(&total).Error; err != nil {
|
||||
panic(fmt.Sprintf("Paginate查询错误: %v", err))
|
||||
}
|
||||
|
||||
// 3. 关联查询
|
||||
if with {
|
||||
db = db.Preload("*")
|
||||
}
|
||||
|
||||
// 4. 排序
|
||||
if order != nil {
|
||||
db = db.Order(order)
|
||||
}
|
||||
|
||||
// 5. 分页(offset = (页码-1)*每页条数)
|
||||
if p.Limit > 0 {
|
||||
offset := (p.Page - 1) * p.Limit
|
||||
db = db.Offset(offset).Limit(p.Limit)
|
||||
}
|
||||
|
||||
// 6. 执行查询
|
||||
err := db.Find(&items).Error
|
||||
if err != nil || errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
panic(fmt.Sprintf("Paginate查询错误: %v", err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// -------------------------- 内部辅助工具函数 --------------------------
|
||||
// convToMap 将任意类型转换为map[string]any(简化版,适配常见场景)
|
||||
func convToMap(v any) map[string]any {
|
||||
if v == nil {
|
||||
return make(map[string]any)
|
||||
}
|
||||
|
||||
val := reflect.ValueOf(v)
|
||||
// 处理指针类型
|
||||
if val.Kind() == reflect.Ptr {
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
// 只处理结构体和map类型
|
||||
if val.Kind() != reflect.Struct && val.Kind() != reflect.Map {
|
||||
return make(map[string]any)
|
||||
}
|
||||
|
||||
result := make(map[string]any)
|
||||
|
||||
if val.Kind() == reflect.Map {
|
||||
// 处理map类型
|
||||
for _, key := range val.MapKeys() {
|
||||
keyStr, ok := key.Interface().(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
result[keyStr] = val.MapIndex(key).Interface()
|
||||
}
|
||||
} else {
|
||||
// 处理结构体类型
|
||||
typ := val.Type()
|
||||
for i := 0; i < val.NumField(); i++ {
|
||||
field := typ.Field(i)
|
||||
fieldVal := val.Field(i)
|
||||
|
||||
// 获取json标签作为key(优先),否则用字段名
|
||||
jsonTag := field.Tag.Get("json")
|
||||
if jsonTag == "" || jsonTag == "-" {
|
||||
jsonTag = field.Name
|
||||
} else {
|
||||
// 分割json标签(忽略omitempty等选项)
|
||||
jsonTag = strings.Split(jsonTag, ",")[0]
|
||||
}
|
||||
|
||||
result[jsonTag] = fieldVal.Interface()
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// isEmpty 判断值是否为空
|
||||
func isEmpty(v any) bool {
|
||||
if v == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
val := reflect.ValueOf(v)
|
||||
switch val.Kind() {
|
||||
case reflect.String:
|
||||
return val.String() == ""
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return val.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return val.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return val.Float() == 0
|
||||
case reflect.Bool:
|
||||
return !val.Bool()
|
||||
case reflect.Slice, reflect.Array, reflect.Map, reflect.Chan:
|
||||
return val.Len() == 0
|
||||
case reflect.Ptr, reflect.Interface:
|
||||
return val.IsNil()
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// strInArray 判断字符串是否在数组中
|
||||
func strInArray(arr []string, str string) bool {
|
||||
for _, v := range arr {
|
||||
if strings.EqualFold(v, str) { // 忽略大小写比较
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
@ -2,13 +2,16 @@ package database
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/config"
|
||||
"git.magicany.cc/black1552/gin-base/log"
|
||||
"github.com/glebarez/sqlite"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/schema"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -16,7 +19,7 @@ var (
|
|||
Db *gorm.DB
|
||||
err error
|
||||
sqlDb *sql.DB
|
||||
dns = config.GetConfigValue("database.dns", "")
|
||||
dns = config.GetConfigValue("database.dns", gfile.Join(gfile.Pwd(), "db", "database.db"))
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
@ -24,7 +27,7 @@ func init() {
|
|||
log.Error("gormDns未配置", "请检查配置文件")
|
||||
return
|
||||
}
|
||||
switch config.GetConfigValue("database.type", "mysql").String() {
|
||||
switch config.GetConfigValue("database.type", "sqlite").String() {
|
||||
case "mysql":
|
||||
log.Info("使用mysql数据库")
|
||||
mysqlInit()
|
||||
|
|
@ -32,7 +35,13 @@ func init() {
|
|||
log.Info("使用sqlite数据库")
|
||||
sqliteInit()
|
||||
}
|
||||
Db, err = gorm.Open(Type, &gorm.Config{})
|
||||
Db, err = gorm.Open(Type, &gorm.Config{
|
||||
SkipDefaultTransaction: true,
|
||||
// 命名策略:保持与模型一致,避免字段/表名转换问题
|
||||
NamingStrategy: schema.NamingStrategy{
|
||||
SingularTable: true, // 表名禁用复数形式(例如 User 对应 user 表,而非 users)
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("数据库连接失败: ", err)
|
||||
return
|
||||
|
|
@ -50,7 +59,7 @@ func init() {
|
|||
|
||||
func mysqlInit() {
|
||||
Type = mysql.New(mysql.Config{
|
||||
DSN: config.GetConfigValue("database.dns", "").String(),
|
||||
DSN: dns.String(),
|
||||
DefaultStringSize: 255, // string 类型字段的默认长度
|
||||
DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
|
||||
DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
|
||||
|
|
@ -59,5 +68,12 @@ func mysqlInit() {
|
|||
}
|
||||
|
||||
func sqliteInit() {
|
||||
Type = sqlite.Open(config.GetConfigValue("database.dns", "").String())
|
||||
if !gfile.Exists(dns.String()) {
|
||||
_, err = gfile.Create(dns.String())
|
||||
if err != nil {
|
||||
log.Error("创建数据库文件失败: ", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
Type = sqlite.Open(fmt.Sprintf("%s?cache=shared&mode=rwc&_busy_timeout=10000&_fk=1&_journal=WAL&_sync=FULL", dns.String()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ func SetAutoMigrate(models ...interface{}) {
|
|||
log.Error("数据库连接失败")
|
||||
return
|
||||
}
|
||||
Db = Db.Set("gorm:table_options", "ENGINE=InnoDB")
|
||||
err := Db.AutoMigrate(models...)
|
||||
if err != nil {
|
||||
log.Error("数据库迁移失败", err)
|
||||
|
|
|
|||
29
go.mod
29
go.mod
|
|
@ -6,12 +6,16 @@ require (
|
|||
github.com/eclipse/paho.mqtt.golang v1.5.1
|
||||
github.com/fsnotify/fsnotify v1.9.0
|
||||
github.com/gin-gonic/gin v1.7.7
|
||||
github.com/glebarez/sqlite v1.11.0
|
||||
github.com/go-playground/locales v0.13.0
|
||||
github.com/go-playground/universal-translator v0.17.0
|
||||
github.com/go-playground/validator/v10 v10.4.2
|
||||
github.com/gogf/gf/v2 v2.10.0
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/spf13/viper v1.21.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
gorm.io/driver/mysql v1.6.0
|
||||
gorm.io/driver/sqlite v1.6.0
|
||||
gorm.io/gorm v1.31.1
|
||||
)
|
||||
|
||||
|
|
@ -19,34 +23,33 @@ require (
|
|||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/emirpasic/gods/v2 v2.0.0-alpha // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/glebarez/go-sqlite v1.21.2 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-playground/locales v0.13.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.17.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.4.1 // indirect
|
||||
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||
github.com/golang/protobuf v1.3.3 // indirect
|
||||
github.com/golang/protobuf v1.3.5 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/grokify/html-strip-tags-go v0.1.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/json-iterator/go v1.1.9 // indirect
|
||||
github.com/leodido/go-urn v1.2.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/magiconair/properties v1.8.10 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/olekukonko/errors v1.1.0 // indirect
|
||||
github.com/olekukonko/ll v0.0.9 // indirect
|
||||
github.com/olekukonko/tablewriter v1.1.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.11.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
|
||||
|
|
@ -54,7 +57,7 @@ require (
|
|||
github.com/spf13/cast v1.10.0 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/ugorji/go/codec v1.1.7 // indirect
|
||||
github.com/ugorji/go/codec v1.1.14 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/otel v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
||||
|
|
@ -68,4 +71,8 @@ require (
|
|||
golang.org/x/text v0.33.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.8 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
modernc.org/libc v1.22.6 // indirect
|
||||
modernc.org/mathutil v1.5.0 // indirect
|
||||
modernc.org/memory v1.5.0 // indirect
|
||||
modernc.org/sqlite v1.23.1 // indirect
|
||||
)
|
||||
|
|
|
|||
53
go.sum
53
go.sum
|
|
@ -7,6 +7,8 @@ github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/eclipse/paho.mqtt.golang v1.5.1 h1:/VSOv3oDLlpqR2Epjn1Q7b2bSTplJIeV2ISgCl2W7nE=
|
||||
github.com/eclipse/paho.mqtt.golang v1.5.1/go.mod h1:1/yJCneuyOoCOzKSsOTUc0AJfpsItBGWvYpBLimhArU=
|
||||
github.com/emirpasic/gods/v2 v2.0.0-alpha h1:dwFlh8pBg1VMOXWGipNMRt8v96dKAIvBehtCt6OtunU=
|
||||
|
|
@ -21,6 +23,10 @@ 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.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
|
||||
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
|
||||
github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo=
|
||||
github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
|
||||
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
|
||||
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
|
|
@ -32,19 +38,25 @@ github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8c
|
|||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
|
||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||
github.com/go-playground/validator/v10 v10.4.2 h1:RqFe5MzGf2UOFhxQYnjHabHOT6CLbYWkeXOfcXB7fsM=
|
||||
github.com/go-playground/validator/v10 v10.4.2/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/gogf/gf/v2 v2.10.0 h1:rzDROlyqGMe/eM6dCalSR8dZOuMIdLhmxKSH1DGhbFs=
|
||||
github.com/gogf/gf/v2 v2.10.0/go.mod h1:Svl1N+E8G/QshU2DUbh/3J/AJauqCgUnxHurXWR4Qx0=
|
||||
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
|
|
@ -55,14 +67,16 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
|
|||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
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/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
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/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
|
||||
github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
|
|
@ -73,12 +87,12 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
|
|||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||
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 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
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/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM=
|
||||
github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
|
||||
github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI=
|
||||
|
|
@ -89,6 +103,9 @@ github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0
|
|||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
|
|
@ -106,15 +123,22 @@ github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3A
|
|||
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
|
||||
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
|
||||
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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
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.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
||||
github.com/ugorji/go v1.1.14/go.mod h1:8lpbXS0IfYpSwsLmwWThGZ7Qm2dNUIb0/kcsxHbwNpM=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/ugorji/go/codec v1.1.14 h1:3kmVO19VOoEBcborYacgFopagfu1s1+73nR7uRuN0lM=
|
||||
github.com/ugorji/go/codec v1.1.14/go.mod h1:CburFl4ZXbHpzvp1gzm2I8tpnFk9XPHOJwIheJViqKk=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
|
||||
|
|
@ -160,11 +184,18 @@ gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYs
|
|||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
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.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg=
|
||||
gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo=
|
||||
gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=
|
||||
gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8=
|
||||
gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg=
|
||||
gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
|
||||
modernc.org/libc v1.22.6 h1:cbXU8R+A6aOjRuhsFh3nbDWXO/Hs4ClJRXYB11KmPDo=
|
||||
modernc.org/libc v1.22.6/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
|
||||
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
||||
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
|
||||
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
||||
modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM=
|
||||
modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
|
||||
|
|
|
|||
|
|
@ -12,8 +12,17 @@ func ErrorHandler() gin.HandlerFunc {
|
|||
return func(c *gin.Context) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
log.Error("发生panic", "path", c.Request.URL.Path, "method", c.Request.Method, err)
|
||||
response.Error(c).SetCode(http.StatusInternalServerError).SetMsg("服务器内部错误").End()
|
||||
res := response.Error(c).SetCode(http.StatusInternalServerError)
|
||||
switch e := err.(type) {
|
||||
case string:
|
||||
res = res.SetMsg(e)
|
||||
case error:
|
||||
res = res.SetMsg(e.Error())
|
||||
default:
|
||||
res = res.SetMsg("服务器内部异常,请稍后重试")
|
||||
}
|
||||
res.End()
|
||||
log.Error("发生panic=》", "path:", c.Request.URL.Path, ",method:", c.Request.Method, ",", err)
|
||||
c.Abort()
|
||||
}
|
||||
}()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrTokenInvalid = errors.New("token无效")
|
||||
ErrTokenExpired = errors.New("token已过期")
|
||||
)
|
||||
|
||||
// JWTClaims JWT声明
|
||||
type JWTClaims struct {
|
||||
UserID int `json:"user_id"`
|
||||
Username string `json:"username"`
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
// GenerateToken 生成JWT Token
|
||||
func GenerateToken(userID int, username, secret string, expiresInHours int) (string, error) {
|
||||
claims := JWTClaims{
|
||||
UserID: userID,
|
||||
Username: username,
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(expiresInHours) * time.Hour)),
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
NotBefore: jwt.NewNumericDate(time.Now()),
|
||||
},
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
return token.SignedString([]byte(secret))
|
||||
}
|
||||
|
||||
// ParseToken 解析JWT Token
|
||||
func ParseToken(tokenString, secret string) (*JWTClaims, error) {
|
||||
token, err := jwt.ParseWithClaims(tokenString, &JWTClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, errors.New("签名方法无效")
|
||||
}
|
||||
return []byte(secret), nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if claims, ok := token.Claims.(*JWTClaims); ok && token.Valid {
|
||||
return claims, nil
|
||||
}
|
||||
|
||||
return nil, ErrTokenInvalid
|
||||
}
|
||||
|
||||
// ValidateToken 验证Token是否有效
|
||||
func ValidateToken(tokenString, secret string) error {
|
||||
claims, err := ParseToken(tokenString, secret)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if claims.ExpiresAt != nil && claims.ExpiresAt.Time.Before(time.Now()) {
|
||||
return ErrTokenExpired
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package valid
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
// ValidToStruct 验证参数并返回结构体
|
||||
func ValidToStruct[T any](c *gin.Context) (object *T) {
|
||||
obj := new(T)
|
||||
if err := c.Bind(obj); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := g.Validator().Data(obj).Run(c); err != nil {
|
||||
panic(gerror.Current(err).Error())
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
// ValidToMap 验证参数并返回结构体
|
||||
func ValidToMap[T any](c *gin.Context) (object map[string]any) {
|
||||
obj := new(T)
|
||||
if err := c.Bind(obj); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := g.Validator().Data(obj).Run(c); err != nil {
|
||||
panic(gerror.Current(err).Error())
|
||||
}
|
||||
return gconv.Map(obj)
|
||||
}
|
||||
|
||||
// ValidToStructAndMap 验证参数并返回map
|
||||
func ValidToStructAndMap[T any](c *gin.Context) (stru *T, object map[string]any) {
|
||||
obj := new(T)
|
||||
if err := c.Bind(obj); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := g.Validator().Data(obj).Run(c); err != nil {
|
||||
panic(gerror.Current(err).Error())
|
||||
}
|
||||
return obj, gconv.Map(obj)
|
||||
}
|
||||
Loading…
Reference in New Issue