From bcd274c750ebc3aebb18d30ef87531d38da8d39a Mon Sep 17 00:00:00 2001 From: denghui <1016848185@qq.com> Date: Tue, 3 Jun 2025 13:33:35 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20web=20=E5=90=8E=E5=8F=B0?= =?UTF-8?q?=E8=8F=9C=E5=8D=95=E3=80=81=E6=96=B0=E5=A2=9E=E8=A7=92=E8=89=B2?= =?UTF-8?q?=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/controller/wx/wx_v1_we_chat_login.go | 87 +++++++++++------ internal/dao/internal/menus.go | 97 +++++++++++++++++++ internal/dao/internal/role_menus.go | 83 ++++++++++++++++ internal/dao/internal/roles.go | 87 +++++++++++++++++ internal/dao/menus.go | 27 ++++++ internal/dao/role_menus.go | 27 ++++++ internal/dao/roles.go | 27 ++++++ internal/model/do/menus.go | 28 ++++++ internal/model/do/role_menus.go | 21 ++++ internal/model/do/roles.go | 23 +++++ internal/model/entity/menus.go | 26 +++++ internal/model/entity/role_menus.go | 19 ++++ internal/model/entity/roles.go | 21 ++++ 13 files changed, 544 insertions(+), 29 deletions(-) create mode 100644 internal/dao/internal/menus.go create mode 100644 internal/dao/internal/role_menus.go create mode 100644 internal/dao/internal/roles.go create mode 100644 internal/dao/menus.go create mode 100644 internal/dao/role_menus.go create mode 100644 internal/dao/roles.go create mode 100644 internal/model/do/menus.go create mode 100644 internal/model/do/role_menus.go create mode 100644 internal/model/do/roles.go create mode 100644 internal/model/entity/menus.go create mode 100644 internal/model/entity/role_menus.go create mode 100644 internal/model/entity/roles.go diff --git a/internal/controller/wx/wx_v1_we_chat_login.go b/internal/controller/wx/wx_v1_we_chat_login.go index 304e43c..1b0ba0b 100644 --- a/internal/controller/wx/wx_v1_we_chat_login.go +++ b/internal/controller/wx/wx_v1_we_chat_login.go @@ -4,56 +4,85 @@ import ( "context" "encoding/json" "fmt" - "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/glog" + "io" + "os" + v1 "server/api/wx/v1" + "server/internal/model" "server/utility/ecode" "server/utility/wechat" + "time" - "os" - "server/api/auth/v1" + "github.com/gogf/gf/v2/frame/g" ) func (c *ControllerV1) WeChatLogin(ctx context.Context, req *v1.WeChatLoginReq) (res *v1.WeChatLoginRes, err error) { - // 1、根据 uuid 构建redis 存入数据接口 - cache := struct { - Token string `json:"token"` - OpenID string `json:"openid"` - }{ - Token: "", - OpenID: "", + glog.Infof(ctx, "收到微信登录请求,SceneId: %s", req.SceneId) + loginLimitKey := fmt.Sprintf("wx:login:limit:%s", req.SceneId) + + // 检查登录限制 + va, err := g.Redis().Get(ctx, loginLimitKey) + if err != nil { + glog.Errorf(ctx, "Redis 获取登录限制失败: %v", err) + return nil, ecode.Fail.Sub("获取登录限制失败") } - marshal, err := json.Marshal(cache) - if err != nil { - glog.Errorf(ctx, "反序列化数据出现异常") - return nil, ecode.Fail.Sub("反序列化数据出现异常") + if !va.IsEmpty() { + glog.Warningf(ctx, "SceneId %s 登录请求过于频繁", req.SceneId) + return nil, ecode.InvalidOperation.Sub("请勿重复请求登录二维码") } - // 2、存入 redis - _, err = g.Redis().Do(ctx, "SETEX", fmt.Sprintf("login_status:%s", req.UUID), 300, marshal) - if err != nil { - glog.Errorf(ctx, "写入 Redis 异常:%v", err) - return nil, ecode.Fail.Sub("写入 Redis 登录状态失败") + if err = g.Redis().SetEX(ctx, loginLimitKey, 1, 60); err != nil { + glog.Errorf(ctx, "Redis 设置登录限制失败: %v", err) + return nil, ecode.Fail.Sub("登录频率限制设置失败") } - // 3、开始获取图片 - weChatClient := wechat.GetWeChatClient() - ticket, err := weChatClient.GetTicket(req.UUID) + client := wechat.GetWeChatClient() + ticket, err := client.GetTicket(fmt.Sprintf("%s", req.SceneId)) if err != nil { - return nil, ecode.Fail.Sub("微信登录获取 ticket 错误") + glog.Errorf(ctx, "获取微信 ticket 失败: %v", err) + return nil, err } - imagePath, err := weChatClient.GetQrCode(ticket, req.UUID+".jpg") + + qrCode, err := client.GetQrCode(ticket) if err != nil { - return nil, ecode.Fail.Sub("微信登录获取二维码错误") + glog.Errorf(ctx, "生成二维码失败: %v", err) + return nil, err } - imageData, err := os.ReadFile(imagePath) + + file, err := os.Open(qrCode) if err != nil { - return nil, ecode.Fail.Sub("读取二维码图片失败") + glog.Errorf(ctx, "二维码文件打开失败: %v", err) + return nil, ecode.Fail.Sub("二维码文件打开失败") } - defer os.Remove(imagePath) + defer func() { + file.Close() + os.Remove(qrCode) + }() + + imgBytes, err := io.ReadAll(file) + if err != nil { + glog.Errorf(ctx, "读取二维码失败: %v", err) + return nil, ecode.Fail.Sub("二维码读取失败") + } + resp := g.RequestFromCtx(ctx).Response resp.Header().Set("Content-Type", "image/jpeg") - resp.Write(imageData) + resp.Write(imgBytes) + loginCache := model.LoginCache{ + Status: 0, + CreatedAt: time.Now(), + } + + data, err := json.Marshal(loginCache) + if err == nil { + _ = g.Redis().SetEX(ctx, fmt.Sprintf("wx:login:cache:%s", req.SceneId), data, 60) + glog.Infof(ctx, "SceneId %s 登录缓存已写入 Redis", req.SceneId) + } else { + glog.Warningf(ctx, "SceneId %s登录缓存序列化失败: %v", req.SceneId, err) + } + + glog.Infof(ctx, "SceneId %s 登录二维码已返回", req.SceneId) return nil, nil } diff --git a/internal/dao/internal/menus.go b/internal/dao/internal/menus.go new file mode 100644 index 0000000..1636080 --- /dev/null +++ b/internal/dao/internal/menus.go @@ -0,0 +1,97 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// MenusDao is the data access object for the table menus. +type MenusDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of the current DAO. + columns MenusColumns // columns contains all the column names of Table for convenient usage. +} + +// MenusColumns defines and stores column names for the table menus. +type MenusColumns struct { + Id string // 菜单ID + ParentId string // 父级菜单ID + Name string // 菜单名称 + Path string // 前端路由路径 + Component string // 前端组件路径 + Type string // 类型:1=目录(父级菜单),2=菜单(功能页面) + Icon string // 图标 + Sort string // 排序 + Hidden string // 是否隐藏:0=显示,1=隐藏 + Status string // 状态:1=启用,2=禁用 + CreatedAt string // 创建时间 + UpdatedAt string // 更新时间 + DeletedAt string // 软删除时间戳 +} + +// menusColumns holds the columns for the table menus. +var menusColumns = MenusColumns{ + Id: "id", + ParentId: "parent_id", + Name: "name", + Path: "path", + Component: "component", + Type: "type", + Icon: "icon", + Sort: "sort", + Hidden: "hidden", + Status: "status", + CreatedAt: "created_at", + UpdatedAt: "updated_at", + DeletedAt: "deleted_at", +} + +// NewMenusDao creates and returns a new DAO object for table data access. +func NewMenusDao() *MenusDao { + return &MenusDao{ + group: "default", + table: "menus", + columns: menusColumns, + } +} + +// DB retrieves and returns the underlying raw database management object of the current DAO. +func (dao *MenusDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of the current DAO. +func (dao *MenusDao) Table() string { + return dao.table +} + +// Columns returns all column names of the current DAO. +func (dao *MenusDao) Columns() MenusColumns { + return dao.columns +} + +// Group returns the database configuration group name of the current DAO. +func (dao *MenusDao) Group() string { + return dao.group +} + +// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation. +func (dao *MenusDao) Ctx(ctx context.Context) *gdb.Model { + return dao.DB().Model(dao.table).Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rolls back the transaction and returns the error if function f returns a non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note: Do not commit or roll back the transaction in function f, +// as it is automatically handled by this function. +func (dao *MenusDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/internal/dao/internal/role_menus.go b/internal/dao/internal/role_menus.go new file mode 100644 index 0000000..4747f79 --- /dev/null +++ b/internal/dao/internal/role_menus.go @@ -0,0 +1,83 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// RoleMenusDao is the data access object for the table role_menus. +type RoleMenusDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of the current DAO. + columns RoleMenusColumns // columns contains all the column names of Table for convenient usage. +} + +// RoleMenusColumns defines and stores column names for the table role_menus. +type RoleMenusColumns struct { + Id string // ID + RoleId string // 角色ID + MenuId string // 菜单ID + CreatedAt string // 创建时间 + UpdatedAt string // 更新时间 + DeletedAt string // 软删除时间戳 +} + +// roleMenusColumns holds the columns for the table role_menus. +var roleMenusColumns = RoleMenusColumns{ + Id: "id", + RoleId: "role_id", + MenuId: "menu_id", + CreatedAt: "created_at", + UpdatedAt: "updated_at", + DeletedAt: "deleted_at", +} + +// NewRoleMenusDao creates and returns a new DAO object for table data access. +func NewRoleMenusDao() *RoleMenusDao { + return &RoleMenusDao{ + group: "default", + table: "role_menus", + columns: roleMenusColumns, + } +} + +// DB retrieves and returns the underlying raw database management object of the current DAO. +func (dao *RoleMenusDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of the current DAO. +func (dao *RoleMenusDao) Table() string { + return dao.table +} + +// Columns returns all column names of the current DAO. +func (dao *RoleMenusDao) Columns() RoleMenusColumns { + return dao.columns +} + +// Group returns the database configuration group name of the current DAO. +func (dao *RoleMenusDao) Group() string { + return dao.group +} + +// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation. +func (dao *RoleMenusDao) Ctx(ctx context.Context) *gdb.Model { + return dao.DB().Model(dao.table).Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rolls back the transaction and returns the error if function f returns a non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note: Do not commit or roll back the transaction in function f, +// as it is automatically handled by this function. +func (dao *RoleMenusDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/internal/dao/internal/roles.go b/internal/dao/internal/roles.go new file mode 100644 index 0000000..f23a75d --- /dev/null +++ b/internal/dao/internal/roles.go @@ -0,0 +1,87 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// RolesDao is the data access object for the table roles. +type RolesDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of the current DAO. + columns RolesColumns // columns contains all the column names of Table for convenient usage. +} + +// RolesColumns defines and stores column names for the table roles. +type RolesColumns struct { + Id string // 角色ID + Name string // 角色名称 + Code string // 角色编码 + Description string // 角色描述 + Status string // 状态:1=启用,2=禁用 + CreatedAt string // 创建时间 + UpdatedAt string // 更新时间 + DeletedAt string // 软删除时间戳 +} + +// rolesColumns holds the columns for the table roles. +var rolesColumns = RolesColumns{ + Id: "id", + Name: "name", + Code: "code", + Description: "description", + Status: "status", + CreatedAt: "created_at", + UpdatedAt: "updated_at", + DeletedAt: "deleted_at", +} + +// NewRolesDao creates and returns a new DAO object for table data access. +func NewRolesDao() *RolesDao { + return &RolesDao{ + group: "default", + table: "roles", + columns: rolesColumns, + } +} + +// DB retrieves and returns the underlying raw database management object of the current DAO. +func (dao *RolesDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of the current DAO. +func (dao *RolesDao) Table() string { + return dao.table +} + +// Columns returns all column names of the current DAO. +func (dao *RolesDao) Columns() RolesColumns { + return dao.columns +} + +// Group returns the database configuration group name of the current DAO. +func (dao *RolesDao) Group() string { + return dao.group +} + +// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation. +func (dao *RolesDao) Ctx(ctx context.Context) *gdb.Model { + return dao.DB().Model(dao.table).Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rolls back the transaction and returns the error if function f returns a non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note: Do not commit or roll back the transaction in function f, +// as it is automatically handled by this function. +func (dao *RolesDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/internal/dao/menus.go b/internal/dao/menus.go new file mode 100644 index 0000000..ffc6e1d --- /dev/null +++ b/internal/dao/menus.go @@ -0,0 +1,27 @@ +// ================================================================================= +// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed. +// ================================================================================= + +package dao + +import ( + "server/internal/dao/internal" +) + +// internalMenusDao is an internal type for wrapping the internal DAO implementation. +type internalMenusDao = *internal.MenusDao + +// menusDao is the data access object for the table menus. +// You can define custom methods on it to extend its functionality as needed. +type menusDao struct { + internalMenusDao +} + +var ( + // Menus is a globally accessible object for table menus operations. + Menus = menusDao{ + internal.NewMenusDao(), + } +) + +// Add your custom methods and functionality below. diff --git a/internal/dao/role_menus.go b/internal/dao/role_menus.go new file mode 100644 index 0000000..ad3e6fc --- /dev/null +++ b/internal/dao/role_menus.go @@ -0,0 +1,27 @@ +// ================================================================================= +// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed. +// ================================================================================= + +package dao + +import ( + "server/internal/dao/internal" +) + +// internalRoleMenusDao is an internal type for wrapping the internal DAO implementation. +type internalRoleMenusDao = *internal.RoleMenusDao + +// roleMenusDao is the data access object for the table role_menus. +// You can define custom methods on it to extend its functionality as needed. +type roleMenusDao struct { + internalRoleMenusDao +} + +var ( + // RoleMenus is a globally accessible object for table role_menus operations. + RoleMenus = roleMenusDao{ + internal.NewRoleMenusDao(), + } +) + +// Add your custom methods and functionality below. diff --git a/internal/dao/roles.go b/internal/dao/roles.go new file mode 100644 index 0000000..d3735de --- /dev/null +++ b/internal/dao/roles.go @@ -0,0 +1,27 @@ +// ================================================================================= +// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed. +// ================================================================================= + +package dao + +import ( + "server/internal/dao/internal" +) + +// internalRolesDao is an internal type for wrapping the internal DAO implementation. +type internalRolesDao = *internal.RolesDao + +// rolesDao is the data access object for the table roles. +// You can define custom methods on it to extend its functionality as needed. +type rolesDao struct { + internalRolesDao +} + +var ( + // Roles is a globally accessible object for table roles operations. + Roles = rolesDao{ + internal.NewRolesDao(), + } +) + +// Add your custom methods and functionality below. diff --git a/internal/model/do/menus.go b/internal/model/do/menus.go new file mode 100644 index 0000000..b852d95 --- /dev/null +++ b/internal/model/do/menus.go @@ -0,0 +1,28 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// Menus is the golang structure of table menus for DAO operations like Where/Data. +type Menus struct { + g.Meta `orm:"table:menus, do:true"` + Id interface{} // 菜单ID + ParentId interface{} // 父级菜单ID + Name interface{} // 菜单名称 + Path interface{} // 前端路由路径 + Component interface{} // 前端组件路径 + Type interface{} // 类型:1=目录(父级菜单),2=菜单(功能页面) + Icon interface{} // 图标 + Sort interface{} // 排序 + Hidden interface{} // 是否隐藏:0=显示,1=隐藏 + Status interface{} // 状态:1=启用,2=禁用 + CreatedAt *gtime.Time // 创建时间 + UpdatedAt *gtime.Time // 更新时间 + DeletedAt *gtime.Time // 软删除时间戳 +} diff --git a/internal/model/do/role_menus.go b/internal/model/do/role_menus.go new file mode 100644 index 0000000..a9b2d66 --- /dev/null +++ b/internal/model/do/role_menus.go @@ -0,0 +1,21 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// RoleMenus is the golang structure of table role_menus for DAO operations like Where/Data. +type RoleMenus struct { + g.Meta `orm:"table:role_menus, do:true"` + Id interface{} // ID + RoleId interface{} // 角色ID + MenuId interface{} // 菜单ID + CreatedAt *gtime.Time // 创建时间 + UpdatedAt *gtime.Time // 更新时间 + DeletedAt *gtime.Time // 软删除时间戳 +} diff --git a/internal/model/do/roles.go b/internal/model/do/roles.go new file mode 100644 index 0000000..42e24bd --- /dev/null +++ b/internal/model/do/roles.go @@ -0,0 +1,23 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// Roles is the golang structure of table roles for DAO operations like Where/Data. +type Roles struct { + g.Meta `orm:"table:roles, do:true"` + Id interface{} // 角色ID + Name interface{} // 角色名称 + Code interface{} // 角色编码 + Description interface{} // 角色描述 + Status interface{} // 状态:1=启用,2=禁用 + CreatedAt *gtime.Time // 创建时间 + UpdatedAt *gtime.Time // 更新时间 + DeletedAt *gtime.Time // 软删除时间戳 +} diff --git a/internal/model/entity/menus.go b/internal/model/entity/menus.go new file mode 100644 index 0000000..b82dcfb --- /dev/null +++ b/internal/model/entity/menus.go @@ -0,0 +1,26 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// Menus is the golang structure for table menus. +type Menus struct { + Id int64 `json:"id" orm:"id" description:"菜单ID"` // 菜单ID + ParentId int64 `json:"parentId" orm:"parent_id" description:"父级菜单ID"` // 父级菜单ID + Name string `json:"name" orm:"name" description:"菜单名称"` // 菜单名称 + Path string `json:"path" orm:"path" description:"前端路由路径"` // 前端路由路径 + Component string `json:"component" orm:"component" description:"前端组件路径"` // 前端组件路径 + Type int `json:"type" orm:"type" description:"类型:1=目录(父级菜单),2=菜单(功能页面)"` // 类型:1=目录(父级菜单),2=菜单(功能页面) + Icon string `json:"icon" orm:"icon" description:"图标"` // 图标 + Sort int `json:"sort" orm:"sort" description:"排序"` // 排序 + Hidden int `json:"hidden" orm:"hidden" description:"是否隐藏:0=显示,1=隐藏"` // 是否隐藏:0=显示,1=隐藏 + Status int `json:"status" orm:"status" description:"状态:1=启用,2=禁用"` // 状态:1=启用,2=禁用 + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 + DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳 +} diff --git a/internal/model/entity/role_menus.go b/internal/model/entity/role_menus.go new file mode 100644 index 0000000..e085667 --- /dev/null +++ b/internal/model/entity/role_menus.go @@ -0,0 +1,19 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// RoleMenus is the golang structure for table role_menus. +type RoleMenus struct { + Id int64 `json:"id" orm:"id" description:"ID"` // ID + RoleId int64 `json:"roleId" orm:"role_id" description:"角色ID"` // 角色ID + MenuId int64 `json:"menuId" orm:"menu_id" description:"菜单ID"` // 菜单ID + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 + DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳 +} diff --git a/internal/model/entity/roles.go b/internal/model/entity/roles.go new file mode 100644 index 0000000..68d1166 --- /dev/null +++ b/internal/model/entity/roles.go @@ -0,0 +1,21 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// Roles is the golang structure for table roles. +type Roles struct { + Id int64 `json:"id" orm:"id" description:"角色ID"` // 角色ID + Name string `json:"name" orm:"name" description:"角色名称"` // 角色名称 + Code string `json:"code" orm:"code" description:"角色编码"` // 角色编码 + Description string `json:"description" orm:"description" description:"角色描述"` // 角色描述 + Status int `json:"status" orm:"status" description:"状态:1=启用,2=禁用"` // 状态:1=启用,2=禁用 + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 + DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳 +}