Compare commits

..

7 Commits

Author SHA1 Message Date
black1552 60f0d8053d fix(database): 优化SQLite数据库初始化逻辑
- 在创建数据库文件前先检查文件是否存在
- 避免重复创建已存在的数据库文件
- 更新项目配置文件中的文件修改时间戳
2026-02-05 10:30:56 +08:00
black1552 258112d38e feat(valid): 更新验证功能支持多种绑定方式
- 修改 ValidToStruct 函数使用 c.Bind 替代 c.BindJSON
- 新增 ValidToMap 函数支持将参数验证后转换为 map 类型
- 更新 ValidToStructAndMap 函数使用 c.Bind 进行参数绑定
- 添加相应的错误处理和类型转换逻辑
- 更新项目缓存配置文件中的文件扫描路径信息
2026-02-04 16:19:36 +08:00
black1552 8927551779 refactor(valid): 重构验证函数命名和返回值
- 将 ValidAndStruct 函数重命名为 ValidToStruct
- 将 ValidAndMap 函数重命名为 ValidToStructAndMap
- 修改 ValidToStructAndMap 函数返回结构体和映射两个值
- 更新 .idea/GOHCache.xml 中的文件修改时间戳
2026-02-04 15:05:09 +08:00
black1552 0ad7304eca feat(valid): 添加参数验证并返回map功能
- 新增ValidAndMap函数用于验证参数并返回map类型
- 修改ValidAndStruct函数优化对象绑定逻辑
- 添加gconv包导入支持map转换功能
- 更新IDE缓存配置添加新的验证类型映射
2026-02-04 14:59:26 +08:00
black1552 a1a2785c71 refactor(valid): 重构验证模块使用Goframe验证器
- 移除原有的validator和国际化翻译相关代码
- 使用Goframe的g.Validator进行参数验证
- 简化ValidAndStruct函数实现
- 更新依赖包从validator切换到gogf
- 删除不再使用的ValidateError工具函数
- 移除init函数中的翻译器初始化逻辑
2026-02-04 14:18:10 +08:00
black1552 8743f40739 refactor(valid): 使用Gin内置验证器替代手动创建实例
移除ApiResponse结构体并改用Gin绑定的validator实例,确保验证器与翻译器的一致性
2026-02-03 17:21:58 +08:00
black1552 d549cf929b refactor(valid): 重构验证器初始化和错误处理逻辑
- 调整全局变量声明顺序并移除未使用的 uni 变量
- 添加 ApiResponse 结构体定义
- 重命名 GetFirstValidateError 函数为 ValidateError
- 优化 init 函数中的中文本地化初始化流程
- 更新字段名映射函数的注释说明
- 改进错误处理逻辑和代码注释
2026-02-03 17:09:46 +08:00
4 changed files with 501 additions and 65 deletions

461
.idea/GOHCache.xml Normal file
View File

@ -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>

View File

@ -68,10 +68,12 @@ func mysqlInit() {
}
func sqliteInit() {
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()))
}

View File

@ -1 +0,0 @@
package valid

View File

@ -1,70 +1,44 @@
package valid
import (
"errors"
"reflect"
"strings"
"github.com/go-playground/locales/zh"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
zh_translations "github.com/go-playground/validator/v10/translations/zh"
"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"
)
var (
uni *ut.UniversalTranslator // 全局翻译器实例
validate *validator.Validate // 全局验证器实例
trans ut.Translator // 全局中文翻译器
foun bool
)
func init() {
// 1. 初始化中文本地化实例
zhLocale := zh.New()
// 2. 初始化通用翻译器,加载中文本地化
uni = ut.New(zhLocale, zhLocale)
// 3. 获取中文翻译器实例
var err error
trans, foun = uni.GetTranslator("zh")
if !foun {
panic("获取中文翻译器失败")
// 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
}
// 4. 获取 Gin 内置的 validator 验证器实例
validate = validator.New()
// 5. 注册 validator 中文翻译(替换默认英文错误提示)
err = zh_translations.RegisterDefaultTranslations(validate, trans)
if err != nil {
panic("注册中文翻译失败:" + err.Error())
// 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)
}
// 6. 核心优化:注册字段名映射函数,用结构体的 json 标签作为返回的字段名
// 例如:结构体字段 Username -> json 标签 username -> 错误提示中显示 username更友好
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
// 提取 json 标签(忽略 ,omitempty 等附加选项)
jsonTag := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
// 若 json 标签为 "-"(表示忽略该字段),返回空字符串
if jsonTag == "-" {
return ""
// 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)
}
return jsonTag
})
if err := g.Validator().Data(obj).Run(c); err != nil {
panic(gerror.Current(err).Error())
}
func GetFirstValidateError(err error) string {
// 1. 断言错误类型是否为 validator 验证错误
var validateErrors validator.ValidationErrors
ok := errors.As(err, &validateErrors)
if !ok {
// 非参数验证错误(如绑定格式错误),直接返回错误信息
return "参数格式错误:" + err.Error()
}
// 2. 仅返回第一条验证错误(核心:取切片索引 0 的元素)
firstErr := validateErrors[0]
// 3. 翻译第一条错误为中文,返回给前端
return firstErr.Translate(trans)
return obj, gconv.Map(obj)
}