fix(socket): 玩家断开连接时增加保存锁,避免重复保存

在玩家断开连接时,使用 sync.Once 确保只保存一次玩家数据,
防止因并发或多次触发导致的数据异常。

feat(fight): 增加战斗资格判断与邀请取消功能

- 新增 Player.CanFight() 方法用于统一判断是否可以参与战斗
- 在多个战斗相关接口中加入 CanFight 检查
- 添加“取消战斗邀请”指令及处理逻辑(cmd: 2402)
- 修复部分错误码不准确的问题,提升提示一致性

refactor(login): 优化登录流程并增强健壮性

- 提前校验 session 合法性
- 增强获取玩家信息后的空指针检查
- 调整挖矿数据重置方式为 defer 执行
- 优化日志输出内容,便于调试追踪

docs(model): 更新部门、菜单等模型字段命名规范

将 orderNum 字段改为 ordernum,保持数据库列名风格一致,
同时更新了 base_sys_role 中 userId 为 userid。

perf(rate-limit): 提高登录接口的限流 Burst 容量

调整限流器配置,将请求 burst 容量从 2 提升至 5,
以应对短时间高频访问场景,改善用户体验。

chore(build): 忽略新增编译产物和临时文件

在 .gitignore 中添加 logic/logic2、login/login 等新生成文件路径,
避免误提交二进制文件到版本控制。
This commit is contained in:
2025-10-31 00:53:22 +08:00
parent 94e28e2601
commit cccf26788e
28 changed files with 237 additions and 191 deletions

View File

@@ -9,7 +9,7 @@ type BaseSysDepartment struct {
*cool.Model
Name string `gorm:"column:name;type:varchar(255);not null" json:"name"` // 部门名称
ParentID uint `gorm:"column:parentId;type:bigint" json:"parentId"` // 上级部门ID
OrderNum int32 `gorm:"column:orderNum;type:int;not null" json:"orderNum"` // 排序
ordernum int32 `gorm:"column:ordernum;type:int;not null" json:"ordernum"` // 排序
}
// TableName BaseSysDepartment's table name

View File

@@ -13,7 +13,7 @@ type BaseSysMenu struct {
Perms *string `gorm:"column:perms;type:text" json:"perms"` // 权限标识
Type int32 `gorm:"column:type;not null" json:"type"` // 类型 0目录 1菜单 2按钮
Icon *string `gorm:"column:icon;type:varchar(255)" json:"icon"` // 图标
OrderNum int32 `gorm:"column:orderNum;type:int;not null;default:0" json:"orderNum"` // 排序
ordernum int32 `gorm:"column:ordernum;type:int;not null;default:0" json:"ordernum"` // 排序
ViewPath *string `gorm:"column:viewPath;type:varchar(255)" json:"viewPath"` // 视图地址
KeepAlive bool `gorm:"column:keepAlive;not null;default:1" json:"keepAlive"` // 路由缓存
IsShow bool `gorm:"column:isShow;not null;default:1" json:"isShow"` // 是否显示

View File

@@ -7,7 +7,7 @@ const TableNameBaseSysRole = "base_sys_role"
// BaseSysRole mapped from table <base_sys_role>
type BaseSysRole struct {
*cool.Model
UserID string `gorm:"column:userId;type:varchar(255);not null" json:"userId"` // 用户ID
UserID string `gorm:"column:userid;type:varchar(255);not null" json:"userid"` // 用户ID
Name string `gorm:"column:name;type:varchar(255);not null;index:IDX_469d49a5998170e9550cf113da,priority:1" json:"name"` // 名称
Label *string `gorm:"column:label;type:varchar(50);index:IDX_f3f24fbbccf00192b076e549a7,priority:1" json:"label"` // 角色标签
Remark *string `gorm:"column:remark;type:varchar(255)" json:"remark"` // 备注

View File

@@ -6,7 +6,7 @@
"deleted_at": null,
"name": "SUN",
"parentId": null,
"orderNum": 0
"ordernum": 0
},
{
"id": 11,
@@ -15,7 +15,7 @@
"deleted_at": null,
"name": "开发",
"parentId": 1,
"orderNum": 0
"ordernum": 0
},
{
"id": 12,
@@ -24,7 +24,7 @@
"deleted_at": null,
"name": "测试",
"parentId": 1,
"orderNum": 0
"ordernum": 0
},
{
"id": 13,
@@ -33,6 +33,6 @@
"deleted_at": null,
"name": "游客",
"parentId": 1,
"orderNum": 0
"ordernum": 0
}
]

View File

@@ -10,7 +10,7 @@
"perms": null,
"type": 0,
"icon": "icon-workbench",
"orderNum": 1,
"ordernum": 1,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -26,7 +26,7 @@
"perms": null,
"type": 0,
"icon": "icon-system",
"orderNum": 2,
"ordernum": 2,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -42,7 +42,7 @@
"perms": null,
"type": 1,
"icon": "icon-menu",
"orderNum": 2,
"ordernum": 2,
"viewPath": "cool/modules/base/views/menu.vue",
"keepAlive": true,
"isShow": true
@@ -58,7 +58,7 @@
"perms": "base:sys:menu:add",
"type": 2,
"icon": null,
"orderNum": 1,
"ordernum": 1,
"viewPath": null,
"keepAlive": false,
"isShow": true
@@ -74,7 +74,7 @@
"perms": "base:sys:menu:delete",
"type": 2,
"icon": null,
"orderNum": 2,
"ordernum": 2,
"viewPath": null,
"keepAlive": false,
"isShow": true
@@ -90,7 +90,7 @@
"perms": "base:sys:menu:update",
"type": 2,
"icon": null,
"orderNum": 3,
"ordernum": 3,
"viewPath": null,
"keepAlive": false,
"isShow": true
@@ -106,7 +106,7 @@
"perms": "base:sys:menu:page,base:sys:menu:list,base:sys:menu:info",
"type": 2,
"icon": null,
"orderNum": 4,
"ordernum": 4,
"viewPath": null,
"keepAlive": false,
"isShow": true
@@ -122,7 +122,7 @@
"perms": null,
"type": 1,
"icon": "icon-common",
"orderNum": 3,
"ordernum": 3,
"viewPath": "cool/modules/base/views/role.vue",
"keepAlive": true,
"isShow": true
@@ -138,7 +138,7 @@
"perms": "base:sys:role:add",
"type": 2,
"icon": null,
"orderNum": 1,
"ordernum": 1,
"viewPath": null,
"keepAlive": false,
"isShow": true
@@ -154,7 +154,7 @@
"perms": "base:sys:role:delete",
"type": 2,
"icon": null,
"orderNum": 2,
"ordernum": 2,
"viewPath": null,
"keepAlive": false,
"isShow": true
@@ -170,7 +170,7 @@
"perms": "base:sys:role:update",
"type": 2,
"icon": null,
"orderNum": 3,
"ordernum": 3,
"viewPath": null,
"keepAlive": false,
"isShow": true
@@ -186,7 +186,7 @@
"perms": "base:sys:role:page,base:sys:role:list,base:sys:role:info",
"type": 2,
"icon": null,
"orderNum": 4,
"ordernum": 4,
"viewPath": null,
"keepAlive": false,
"isShow": true
@@ -202,7 +202,7 @@
"perms": null,
"type": 0,
"icon": "icon-auth",
"orderNum": 1,
"ordernum": 1,
"viewPath": null,
"keepAlive": false,
"isShow": true
@@ -218,7 +218,7 @@
"perms": null,
"type": 1,
"icon": "icon-log",
"orderNum": 1,
"ordernum": 1,
"viewPath": "cool/modules/base/views/log.vue",
"keepAlive": true,
"isShow": true
@@ -234,7 +234,7 @@
"perms": "base:sys:log:page,base:sys:log:clear,base:sys:log:getKeep,base:sys:log:setKeep",
"type": 2,
"icon": null,
"orderNum": 1,
"ordernum": 1,
"viewPath": null,
"keepAlive": false,
"isShow": true
@@ -250,7 +250,7 @@
"perms": null,
"type": 1,
"icon": "icon-favor",
"orderNum": 1,
"ordernum": 1,
"viewPath": "cool/modules/demo/views/crud.vue",
"keepAlive": true,
"isShow": true
@@ -266,7 +266,7 @@
"perms": null,
"type": 0,
"icon": "icon-common",
"orderNum": 2,
"ordernum": 2,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -282,7 +282,7 @@
"perms": null,
"type": 1,
"icon": "icon-log",
"orderNum": 0,
"ordernum": 0,
"viewPath": "https://cool-js.com",
"keepAlive": true,
"isShow": true
@@ -298,7 +298,7 @@
"perms": null,
"type": 1,
"icon": "icon-favor",
"orderNum": 2,
"ordernum": 2,
"viewPath": "cool/modules/demo/views/editor-quill.vue",
"keepAlive": true,
"isShow": true
@@ -314,7 +314,7 @@
"perms": "base:sys:department:list",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -330,7 +330,7 @@
"perms": "base:sys:department:add",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -346,7 +346,7 @@
"perms": "base:sys:department:update",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -362,7 +362,7 @@
"perms": "base:sys:department:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -378,7 +378,7 @@
"perms": "base:sys:department:order",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -394,7 +394,7 @@
"perms": "base:sys:user:move",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -410,7 +410,7 @@
"perms": null,
"type": 0,
"icon": "icon-common",
"orderNum": 4,
"ordernum": 4,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -426,7 +426,7 @@
"perms": null,
"type": 1,
"icon": "icon-menu",
"orderNum": 0,
"ordernum": 0,
"viewPath": "cool/modules/base/views/param.vue",
"keepAlive": true,
"isShow": true
@@ -442,7 +442,7 @@
"perms": "base:sys:param:add",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -458,7 +458,7 @@
"perms": "base:sys:param:info,base:sys:param:update",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -474,7 +474,7 @@
"perms": "base:sys:param:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -490,7 +490,7 @@
"perms": "base:sys:param:page,base:sys:param:list,base:sys:param:info",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -506,7 +506,7 @@
"perms": null,
"type": 0,
"icon": "icon-radioboxfill",
"orderNum": 99,
"ordernum": 99,
"viewPath": null,
"keepAlive": true,
"isShow": false
@@ -522,7 +522,7 @@
"perms": null,
"type": 1,
"icon": "icon-favor",
"orderNum": 3,
"ordernum": 3,
"viewPath": "cool/modules/demo/views/upload.vue",
"keepAlive": true,
"isShow": true
@@ -538,7 +538,7 @@
"perms": "base:app:im:message:read,base:app:im:message:page,base:app:im:session:page,base:app:im:session:list,base:app:im:session:unreadCount,base:app:im:session:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -554,7 +554,7 @@
"perms": null,
"type": 1,
"icon": "icon-favor",
"orderNum": 0,
"ordernum": 0,
"viewPath": "cool/modules/demo/views/demo.vue",
"keepAlive": true,
"isShow": true
@@ -570,7 +570,7 @@
"perms": null,
"type": 1,
"icon": "icon-user",
"orderNum": 0,
"ordernum": 0,
"viewPath": "cool/modules/base/views/user.vue",
"keepAlive": true,
"isShow": true
@@ -586,7 +586,7 @@
"perms": "base:sys:user:add",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -602,7 +602,7 @@
"perms": "base:sys:user:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -618,7 +618,7 @@
"perms": "base:sys:user:delete,base:sys:user:update",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -634,7 +634,7 @@
"perms": "base:sys:user:page,base:sys:user:list,base:sys:user:info",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -650,7 +650,7 @@
"perms": null,
"type": 0,
"icon": "icon-rank",
"orderNum": 6,
"ordernum": 6,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -666,7 +666,7 @@
"perms": null,
"type": 0,
"icon": "icon-activity",
"orderNum": 5,
"ordernum": 5,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -682,7 +682,7 @@
"perms": null,
"type": 1,
"icon": "icon-menu",
"orderNum": 0,
"ordernum": 0,
"viewPath": "cool/modules/task/views/task.vue",
"keepAlive": true,
"isShow": true
@@ -698,7 +698,7 @@
"perms": "task:info:page,task:info:list,task:info:info,task:info:add,task:info:delete,task:info:update,task:info:stop,task:info:start,task:info:once,task:info:log",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -714,7 +714,7 @@
"perms": null,
"type": 0,
"icon": "icon-log",
"orderNum": 3,
"ordernum": 3,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -730,7 +730,7 @@
"perms": null,
"type": 1,
"icon": "icon-menu",
"orderNum": 1,
"ordernum": 1,
"viewPath": "modules/dict/views/list.vue",
"keepAlive": true,
"isShow": true
@@ -746,7 +746,7 @@
"perms": "dict:info:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -762,7 +762,7 @@
"perms": "dict:info:update,dict:info:info",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -778,7 +778,7 @@
"perms": "dict:info:data",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -794,7 +794,7 @@
"perms": "dict:info:info",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -810,7 +810,7 @@
"perms": "dict:info:list",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -826,7 +826,7 @@
"perms": "dict:info:page",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -842,7 +842,7 @@
"perms": "dict:info:add",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -858,7 +858,7 @@
"perms": "dict:type:list,dict:type:update,dict:type:delete,dict:type:add",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -874,7 +874,7 @@
"perms": null,
"type": 1,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": "modules/demo/views/seer/petbag.vue",
"keepAlive": true,
"isShow": true
@@ -890,7 +890,7 @@
"perms": null,
"type": 1,
"icon": "icon-discover",
"orderNum": 0,
"ordernum": 0,
"viewPath": "modules/demo/views/pinyin.vue",
"keepAlive": true,
"isShow": true
@@ -906,7 +906,7 @@
"perms": null,
"type": 1,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": "modules/demo/views/unzip.vue",
"keepAlive": true,
"isShow": true
@@ -922,7 +922,7 @@
"perms": null,
"type": 1,
"icon": "icon-hot",
"orderNum": 0,
"ordernum": 0,
"viewPath": "modules/demo/views/seer/game.vue",
"keepAlive": true,
"isShow": true
@@ -938,7 +938,7 @@
"perms": null,
"type": 0,
"icon": "icon-task",
"orderNum": 4,
"ordernum": 4,
"viewPath": null,
"keepAlive": true,
"isShow": false
@@ -954,7 +954,7 @@
"perms": "space:info:page,space:info:list,space:info:info,space:info:add,space:info:delete,space:info:update,space:type:page,space:type:list,space:type:info,space:type:add,space:type:delete,space:type:update,dict:type:list,dict:type:page,dict:type:info,dict:type:update,dict:type:delete,dict:type:add,dict:info:list,dict:info:page,dict:info:info,dict:info:update,dict:info:delete,dict:info:add,dict:info:data,base:sys:user:getSession",
"type": 2,
"icon": null,
"orderNum": 1,
"ordernum": 1,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -970,7 +970,7 @@
"perms": "monster:refresh:add",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -986,7 +986,7 @@
"perms": "monster:refresh:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -1002,7 +1002,7 @@
"perms": "monster:refresh:info",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -1018,7 +1018,7 @@
"perms": "monster:refresh:list",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -1034,7 +1034,7 @@
"perms": "monster:refresh:page",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -1050,7 +1050,7 @@
"perms": "monster:refresh:update,monster:refresh:info",
"type": 2,
"icon": null,
"orderNum": 0,
"ordernum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true
@@ -1066,7 +1066,7 @@
"perms": null,
"type": 1,
"icon": "icon-emoji",
"orderNum": 0,
"ordernum": 0,
"viewPath": "modules/demo/views/monster_refresh.vue",
"keepAlive": true,
"isShow": true
@@ -1082,7 +1082,7 @@
"perms": null,
"type": 1,
"icon": "icon-auth",
"orderNum": 0,
"ordernum": 0,
"viewPath": "modules/crud/views/refresh.vue",
"keepAlive": false,
"isShow": true

View File

@@ -53,7 +53,7 @@ func (s *BaseSysDepartmentService) Order(ctx g.Ctx) (err error) {
type item struct {
Id uint32 `json:"id"`
ParentId *uint32 `json:"parentId,omitempty"`
OrderNum int32 `json:"orderNum"`
ordernum int32 `json:"ordernum"`
}
var data *item

View File

@@ -48,10 +48,10 @@ func (s *BaseSysMenuService) GetMenus(roleIds []string, isAdmin bool) (result gd
m := cool.DBM(s.Model).As("a").Fields("a.*")
var err error
if isAdmin {
result, err = m.Group("a.id").Order("a.orderNum", "asc").All()
result, err = m.Group("a.id").Order(`a.ordernum`, "asc").All()
fmt.Println(err)
} else {
result, _ = m.InnerJoin("base_sys_role_menu b", `a.id=b."menuId"`).Where(`b."roleId" IN (?)`, roleIds).Group("a.id").Order("a.orderNum asc").All()
result, _ = m.InnerJoin("base_sys_role_menu b", `a.id=b."menuId"`).Where(`b."roleId" IN (?)`, roleIds).Group("a.id").Order("a.ordernum asc").All()
}
return

View File

@@ -160,12 +160,12 @@ func NewBaseSysRoleService() *BaseSysRoleService {
)
return [][]interface{}{
{"label != ?", g.Slice{"admin"}, true},
{"(userId=? or id in (?))", g.Slice{userId, admin.RoleIds}, !roleIds.Contains(1)},
{"(userid=? or id in (?))", g.Slice{gconv.String(userId), admin.RoleIds}, !roleIds.Contains(1)},
}
},
},
InsertParam: func(ctx context.Context) map[string]interface{} {
return g.Map{"userId": cool.GetAdmin(ctx).UserId}
return g.Map{`"userid"`: cool.GetAdmin(ctx).UserId}
},
UniqueKey: map[string]string{
"name": "角色名称不能重复",

View File

@@ -287,6 +287,7 @@ func NewBaseSysUserService() *BaseSysUserService {
Where: func(ctx context.Context) []g.Array {
r := g.RequestFromCtx(ctx).GetMap()
return []g.Array{
{"id != ?", g.Slice{"10001"}, true}, //排除管理员
{`("departmentId" IN (?))`, gconv.SliceStr(r["departmentIds"])},
}
},