diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go index 806139e..0f5daaa 100644 --- a/cmd/wire_gen.go +++ b/cmd/wire_gen.go @@ -8,12 +8,14 @@ package main import ( "github.com/go-kratos/kratos/v3" + business2 "kra/internal/biz/business" "kra/internal/biz/integration" payment3 "kra/internal/biz/payment" system2 "kra/internal/biz/system" task2 "kra/internal/biz/task" "kra/internal/config" "kra/internal/data" + "kra/internal/data/business" integration3 "kra/internal/data/integration" payment2 "kra/internal/data/payment" "kra/internal/data/system" @@ -33,6 +35,7 @@ import ( "kra/internal/server" "kra/internal/server/handler" "kra/internal/server/router" + business3 "kra/internal/service/business" integration2 "kra/internal/service/integration" payment4 "kra/internal/service/payment" system3 "kra/internal/service/system" @@ -78,6 +81,10 @@ func wireApp(configServer *config.Server, store *config.Store, logger *slog.Logg auditRecorderUsecase := system2.NewAuditRecorderUsecase(auditRecordRepo) auditRecorder := system3.NewAuditRecorder(auditRecorderUsecase) registry := taskRegistry() + userPreferenceRepo := business.NewUserPreferenceRepo(dataData) + userPreferenceUsecase := business2.NewUserPreferenceUsecase(userPreferenceRepo) + userPreferenceService := business3.NewUserPreferenceService(userPreferenceUsecase) + handlerBusiness := handler.NewBusiness(userPreferenceService) runtimeconfigStore := data.NewIntegrationRuntime(dataData) smsSender := sms.NewSender(runtimeconfigStore) smsUsecase := integration.NewSMSUsecase(smsSender) @@ -176,6 +183,7 @@ func wireApp(configServer *config.Server, store *config.Store, logger *slog.Logg integrationConfigService := integration2.NewIntegrationConfigService(integrationConfigUsecase) integrationConfig := handler.NewIntegrationConfig(integrationConfigService) set := &handler.Set{ + Business: handlerBusiness, SMS: handlerSMS, Authority: authority, Menu: menu, diff --git a/docs/sw6-to-kra/implementation.md b/docs/sw6-to-kra/implementation.md new file mode 100644 index 0000000..2235ed2 --- /dev/null +++ b/docs/sw6-to-kra/implementation.md @@ -0,0 +1,47 @@ +# 商务功能迁移执行记录 + +## 基线与方法 + +- 旧后端:`D:/Users/Yvan/projects/yzyz/sw`,`main`,`f9a5e3a90`。 +- 框架基线:`d31082f4a7816d4c83544b8f54e6f42a3b2132b1`。 +- 旧前端:`D:/Users/Yvan/projects/yzyz/sw/web`,`dev/dev1.0`,`ba284011c87fd3d5730e0e3dceffb14a7389730c`。 +- 新实现分支:`codex/sw-business-migration`。 + +按基线至当前版本的最终差异提取功能,以当前 Java 实现、实际调用的前端接口和 SQL 为核对依据。提交记录用于解释修复和撤销,不逐提交搬运。旧前端中未接入的 mock、废弃接口不能作为已实现业务迁移。 + +沿用现有迁移 SQL 的 `/sw/` 路由与 `view/sw/` 菜单组件路径。认证、响应信封、权限、表格及图表采用 Kra;业务字段、统计口径、状态流转、可见范围保留旧实现。登录页、系统名称和品牌资源来自旧商务。新增代码注释与提交信息使用中文。 + +用户已有的 `configs/config.yaml` 修改与迁移 SQL 保留。未经最后阶段的数据库确认,不连接、复制或修改用户的旧数据库。 + +## 依赖顺序与完成标准 + +| 阶段 | 范围 | 状态 | +| --- | --- | --- | +| 1 | 商务用户字段、层级与角色、账号资料和审核、偏好、登录及找回密码 | 进行中 | +| 2 | 平台绑定、商务/渠道可见范围、外部平台与 OA 数据源、商务列表及抽屉 | 待实现 | +| 3 | 预警规则、记录与状态机、操作日志、附件、消息、任务注册与调度 | 待实现 | +| 4 | 渠道列表及新增、渠道激活、推广游戏等业务接口与页面 | 待实现 | +| 5 | 日汇总构建、充值/注册明细、渠道/游戏/区服报表、排行、画像与仪表盘 | 待实现 | +| 6 | 静态接口核对、后端测试、前端构建和页面验证 | 随阶段推进,最终全量复核 | +| 7 | 用户确认源数据库,复制至隔离库,执行迁移,启动并逐接口核对数据 | 未开始,必须等待用户确认 | + +每项完成需覆盖 DTO → service → biz → data、路由目录、权限、菜单页面和有意义的行为测试。只有真实实现并通过验证的项才标为完成。整项目标在实库验证之前保持未完成。 + +## 已核实的业务约束 + +- 超管创建一级商务,一级创建二级,二级创建三级;三级不能创建下级。层级与祖先链由服务器生成。 +- 新增子商务最终版本默认正常,不采用残留注释中的“默认待审核”。 +- 一/二级商务列表只显示下级树,不显示自己;三级列表为空。报表使用独立渠道可见范围,不能套用 Kra 的部门过滤替代。 +- `includeSubPromote` 与 `idcardDedup` 无记录或数据库值非零时均为开启,新增账号同时初始化开启。 +- SDK 商务绑定数量仅计算已通过记录;渠道计数依照当前直属渠道算法,跨平台 ID 不能混用。 +- 用户审核状态有正常、停用、驳回、待审核四种,须保留 `business_status`,不能压成 `enable` 后丢失含义。 +- 金额查询固定不做身份证去重;人数查询遵守全局偏好。 +- SQL 已建立用户、角色、文件等 ID 映射;平台实体及业务主键保留。迁移验收应按映射比较,不能直接比较所有原始 ID。 + +## 验证记录 + +- 已落地商务用户七个扩展字段的存取及增量补列;登录和既有会话同时检查商务审核状态。 +- 已落地全局偏好 GET/PUT、当前用户隔离、缺省开启、显式关闭及幂等写入;Kra 顶栏增加统计口径入口。 +- 已生成 `source-inventory.json`:现有 SQL 的 63 个接口契约、279 个变更源文件及额外找回密码控制器。此清单是范围索引,不代表已完成实现。 +- 已执行 `make generate`、相关 Go 测试、变更前端 ESLint 和生产构建。构建存在原 `arcdash` 依赖的 BigInt 浏览器目标警告。 +- 当前没有执行本轮真实数据库迁移验证。 diff --git a/docs/sw6-to-kra/source-inventory.json b/docs/sw6-to-kra/source-inventory.json new file mode 100644 index 0000000..409c9da --- /dev/null +++ b/docs/sw6-to-kra/source-inventory.json @@ -0,0 +1,1848 @@ +{ + "baseline": "d31082f4a7816d4c83544b8f54e6f42a3b2132b1", + "backend_head": "f9a5e3a9085ad0f89588cbdc61720032a80cb66c", + "frontend_head": "ba284011c87fd3d5730e0e3dceffb14a7389730c", + "contracts": [ + { + "method": "GET", + "source_path": "/system/user/preference", + "target_path": "/sw/user/preference", + "permission": "__authenticated__", + "controller": "UserPreference" + }, + { + "method": "PUT", + "source_path": "/system/user/preference", + "target_path": "/sw/user/preference", + "permission": "__authenticated__", + "controller": "UserPreference" + }, + { + "method": "GET", + "source_path": "/system/promote/list", + "target_path": "/sw/promote/list", + "permission": "system:promote:list", + "controller": "Promote" + }, + { + "method": "GET", + "source_path": "/system/promote/portrait", + "target_path": "/sw/promote/portrait", + "permission": "system:promote:list", + "controller": "Promote" + }, + { + "method": "GET", + "source_path": "/system/promote/game-distribution", + "target_path": "/sw/promote/game-distribution", + "permission": "system:promote:list", + "controller": "Promote" + }, + { + "method": "GET", + "source_path": "/system/promote/bindOptions", + "target_path": "/sw/promote/bindOptions", + "permission": "system:promote:add", + "controller": "Promote" + }, + { + "method": "POST", + "source_path": "/system/promote", + "target_path": "/sw/promote", + "permission": "system:promote:add", + "controller": "Promote" + }, + { + "method": "GET", + "source_path": "/system/promoteActivePool/bindList", + "target_path": "/sw/promoteActivePool/bindList", + "permission": "system:promoteActivePool:list", + "controller": "PromoteActivePool" + }, + { + "method": "GET", + "source_path": "/system/promoteActivePool/bindSpendDetail", + "target_path": "/sw/promoteActivePool/bindSpendDetail", + "permission": "system:promoteActivePool:list", + "controller": "PromoteActivePool" + }, + { + "method": "GET", + "source_path": "/system/workbench/summary", + "target_path": "/sw/workbench/summary", + "permission": "system:workbench:query", + "controller": "Workbench" + }, + { + "method": "GET", + "source_path": "/system/workbench/registerTop", + "target_path": "/sw/workbench/registerTop", + "permission": "system:workbench:query", + "controller": "Workbench" + }, + { + "method": "GET", + "source_path": "/system/workbench/payRank", + "target_path": "/sw/workbench/payRank", + "permission": "system:workbench:query", + "controller": "Workbench" + }, + { + "method": "GET", + "source_path": "/system/workbench/unloginTop", + "target_path": "/sw/workbench/unloginTop", + "permission": "system:workbench:query", + "controller": "Workbench" + }, + { + "method": "GET", + "source_path": "/system/rank/channel", + "target_path": "/sw/rank/channel", + "permission": "system:rank:channel", + "controller": "Rank" + }, + { + "method": "GET", + "source_path": "/system/rank/business", + "target_path": "/sw/rank/business", + "permission": "system:rank:channel", + "controller": "Rank" + }, + { + "method": "GET", + "source_path": "/system/rank/game", + "target_path": "/sw/rank/game", + "permission": "system:rank:channel", + "controller": "Rank" + }, + { + "method": "GET", + "source_path": "/system/gameData/list", + "target_path": "/sw/gameData/list", + "permission": "system:gameData:list", + "controller": "GameData" + }, + { + "method": "GET", + "source_path": "/system/channelData/list", + "target_path": "/sw/channelData/list", + "permission": "system:channelData:list", + "controller": "ChannelData" + }, + { + "method": "GET", + "source_path": "/system/register/list", + "target_path": "/sw/register/list", + "permission": "system:register:list", + "controller": "Register" + }, + { + "method": "POST", + "source_path": "/system/register/export", + "target_path": "/sw/register/export", + "permission": "system:register:export", + "controller": "Register" + }, + { + "method": "GET", + "source_path": "/system/spend/list", + "target_path": "/sw/spend/list", + "permission": "system:spend:list", + "controller": "Spend" + }, + { + "method": "POST", + "source_path": "/system/spend/export", + "target_path": "/sw/spend/export", + "permission": "system:spend:export", + "controller": "Spend" + }, + { + "method": "GET", + "source_path": "/system/serverAnalysis/games", + "target_path": "/sw/serverAnalysis/games", + "permission": "system:serverAnalysis:list", + "controller": "ServerAnalysis" + }, + { + "method": "GET", + "source_path": "/system/serverAnalysis/servers", + "target_path": "/sw/serverAnalysis/servers", + "permission": "system:serverAnalysis:list", + "controller": "ServerAnalysis" + }, + { + "method": "GET", + "source_path": "/system/serverAnalysis/list", + "target_path": "/sw/serverAnalysis/list", + "permission": "system:serverAnalysis:list", + "controller": "ServerAnalysis" + }, + { + "method": "GET", + "source_path": "/system/alertRule/list", + "target_path": "/sw/alertRule/list", + "permission": "system:alertRule:list", + "controller": "SysAlertRule" + }, + { + "method": "GET", + "source_path": "/system/alertRule/ruleTypes", + "target_path": "/sw/alertRule/ruleTypes", + "permission": "system:alertRule:list", + "controller": "SysAlertRule" + }, + { + "method": "GET", + "source_path": "/system/alertRule/{id}", + "target_path": "/sw/alertRule/:id", + "permission": "system:alertRule:query", + "controller": "SysAlertRule" + }, + { + "method": "POST", + "source_path": "/system/alertRule/add", + "target_path": "/sw/alertRule/add", + "permission": "system:alertRule:add", + "controller": "SysAlertRule" + }, + { + "method": "PUT", + "source_path": "/system/alertRule/edit", + "target_path": "/sw/alertRule/edit", + "permission": "system:alertRule:edit", + "controller": "SysAlertRule" + }, + { + "method": "DELETE", + "source_path": "/system/alertRule/{id}", + "target_path": "/sw/alertRule/:id", + "permission": "system:alertRule:remove", + "controller": "SysAlertRule" + }, + { + "method": "PUT", + "source_path": "/system/alertRule/toggle/{id}", + "target_path": "/sw/alertRule/toggle/:id", + "permission": "system:alertRule:edit", + "controller": "SysAlertRule" + }, + { + "method": "GET", + "source_path": "/system/alertRecord/list", + "target_path": "/sw/alertRecord/list", + "permission": "system:alertRecord:list", + "controller": "SysAlertRecord" + }, + { + "method": "GET", + "source_path": "/system/alertRecord/detail/{id}", + "target_path": "/sw/alertRecord/detail/:id", + "permission": "system:alertRecord:query", + "controller": "SysAlertRecord" + }, + { + "method": "POST", + "source_path": "/system/alertRecord/startProcess", + "target_path": "/sw/alertRecord/startProcess", + "permission": "system:alertRecord:process", + "controller": "SysAlertRecord" + }, + { + "method": "POST", + "source_path": "/system/alertRecord/submitAudit", + "target_path": "/sw/alertRecord/submitAudit", + "permission": "system:alertRecord:process", + "controller": "SysAlertRecord" + }, + { + "method": "POST", + "source_path": "/system/alertRecord/approve", + "target_path": "/sw/alertRecord/approve", + "permission": "system:alertRecord:audit", + "controller": "SysAlertRecord" + }, + { + "method": "POST", + "source_path": "/system/alertRecord/reject", + "target_path": "/sw/alertRecord/reject", + "permission": "system:alertRecord:audit", + "controller": "SysAlertRecord" + }, + { + "method": "POST", + "source_path": "/system/alertRecord/reProcess", + "target_path": "/sw/alertRecord/reProcess", + "permission": "system:alertRecord:process", + "controller": "SysAlertRecord" + }, + { + "method": "POST", + "source_path": "/system/alertRecord/addNote", + "target_path": "/sw/alertRecord/addNote", + "permission": "system:alertRecord:process", + "controller": "SysAlertRecord" + }, + { + "method": "GET", + "source_path": "/system/user/list", + "target_path": "/sw/business/list", + "permission": "system:user:list", + "controller": "SysUser" + }, + { + "method": "GET", + "source_path": "/system/user/{userId}/promotes", + "target_path": "/sw/business/:userId/promotes", + "permission": "system:user:query", + "controller": "SysUser" + }, + { + "method": "GET", + "source_path": "/system/user/{userId}/portrait", + "target_path": "/sw/business/:userId/portrait", + "permission": "system:user:query", + "controller": "SysUser" + }, + { + "method": "GET", + "source_path": "/system/user/{userId}/bindPlatform", + "target_path": "/sw/business/:userId/bindPlatform", + "permission": "system:user:query", + "controller": "SysUser" + }, + { + "method": "POST", + "source_path": "/system/user/bindPlatform", + "target_path": "/sw/business/bindPlatform", + "permission": "system:user:bind", + "controller": "SysUser" + }, + { + "method": "GET", + "source_path": "/system/user/bindPlatform", + "target_path": "/sw/business/bindPlatform", + "permission": "system:user:query", + "controller": "SysUser" + }, + { + "method": "GET", + "source_path": "/system/user/bindPlatform/portrait", + "target_path": "/sw/business/bindPlatform/portrait", + "permission": "system:user:query", + "controller": "SysUser" + }, + { + "method": "DELETE", + "source_path": "/system/user/bindPlatform", + "target_path": "/sw/business/bindPlatform", + "permission": "system:user:bind", + "controller": "SysUser" + }, + { + "method": "POST", + "source_path": "/system/user/export", + "target_path": "/sw/business/export", + "permission": "system:user:export", + "controller": "SysUser" + }, + { + "method": "POST", + "source_path": "/system/user/importData", + "target_path": "/sw/business/importData", + "permission": "system:user:import", + "controller": "SysUser" + }, + { + "method": "GET", + "source_path": "/system/user/", + "target_path": "/sw/business", + "permission": "system:user:query", + "controller": "SysUser" + }, + { + "method": "GET", + "source_path": "/system/user/{userId}", + "target_path": "/sw/business/:userId", + "permission": "system:user:query", + "controller": "SysUser" + }, + { + "method": "POST", + "source_path": "/system/user", + "target_path": "/sw/business", + "permission": "system:user:add", + "controller": "SysUser" + }, + { + "method": "PUT", + "source_path": "/system/user", + "target_path": "/sw/business", + "permission": "system:user:edit", + "controller": "SysUser" + }, + { + "method": "DELETE", + "source_path": "/system/user/{userIds}", + "target_path": "/sw/business/:userIds", + "permission": "system:user:remove", + "controller": "SysUser" + }, + { + "method": "GET", + "source_path": "/system/user/optionselect", + "target_path": "/sw/business/optionselect", + "permission": "system:user:query", + "controller": "SysUser" + }, + { + "method": "PUT", + "source_path": "/system/user/resetPwd", + "target_path": "/sw/business/resetPwd", + "permission": "system:user:resetPwd", + "controller": "SysUser" + }, + { + "method": "PUT", + "source_path": "/system/user/changeStatus", + "target_path": "/sw/business/changeStatus", + "permission": "system:user:edit", + "controller": "SysUser" + }, + { + "method": "GET", + "source_path": "/system/user/unlock/{userId}", + "target_path": "/sw/business/unlock/:userId", + "permission": "system:user:edit", + "controller": "SysUser" + }, + { + "method": "GET", + "source_path": "/system/user/authRole/{userId}", + "target_path": "/sw/business/authRole/:userId", + "permission": "system:user:query", + "controller": "SysUser" + }, + { + "method": "PUT", + "source_path": "/system/user/authRole", + "target_path": "/sw/business/authRole", + "permission": "system:user:edit", + "controller": "SysUser" + }, + { + "method": "GET", + "source_path": "/system/user/deptTree", + "target_path": "/sw/business/deptTree", + "permission": "system:user:list", + "controller": "SysUser" + }, + { + "method": "GET", + "source_path": "/system/user/list/dept/{deptId}", + "target_path": "/sw/business/list/dept/:deptId", + "permission": "system:user:list", + "controller": "SysUser" + } + ], + "changed_sources": [ + { + "path": "ruoyi-admin/src/main/java/org/dromara/DromaraApplication.java", + "exists": true, + "sha256": "24915c74216d00295210808e2ad41aeab1d08da2fc6893d6505e378cd2d84f6a" + }, + { + "path": "ruoyi-admin/src/main/java/org/dromara/web/controller/ForgotPasswordController.java", + "exists": true, + "sha256": "e4e516dfd96e2c5241baf19550f7cf935a72baef10fd1dfc56e9b3581d1d7647" + }, + { + "path": "ruoyi-admin/src/main/java/org/dromara/web/domain/bo/ForgotPasswordResetBo.java", + "exists": true, + "sha256": "178e63e8b090674dcacc512fb9c7bd87065aec688e23fabd5721b092cf717d8c" + }, + { + "path": "ruoyi-admin/src/main/java/org/dromara/web/domain/bo/ForgotPasswordUsernameBo.java", + "exists": true, + "sha256": "859118ef306c049a1e5ca663a2d9e7463b5bd4d1417ff7b48060dce03343f69c" + }, + { + "path": "ruoyi-admin/src/main/java/org/dromara/web/domain/bo/ForgotPasswordVerifyBo.java", + "exists": true, + "sha256": "73aa7589b87ce857d8b9ac4ca4a18ec695cdbc13872726944a479a95ce75abe7" + }, + { + "path": "ruoyi-admin/src/main/java/org/dromara/web/domain/vo/ForgotPasswordCheckVo.java", + "exists": true, + "sha256": "21ea1b187cdda7110bf7b69e8d71d7241baec6b43810605a817126e60e2ea803" + }, + { + "path": "ruoyi-admin/src/main/java/org/dromara/web/domain/vo/ForgotPasswordSendVo.java", + "exists": true, + "sha256": "c4e84cf26fc6cc8ac08f372d5bf5651e502abdce83b4f8800dfece4867f36cee" + }, + { + "path": "ruoyi-admin/src/main/java/org/dromara/web/domain/vo/ForgotPasswordVerifyVo.java", + "exists": true, + "sha256": "0d779399a83b964e42240c36261cae99ba4756a03e413461cb97eaa78f188d47" + }, + { + "path": "ruoyi-admin/src/main/java/org/dromara/web/service/ForgotPasswordSupport.java", + "exists": true, + "sha256": "9b1dba384b4aa5bf28a374b17ad0b0f6e0c47d7dc05bc0388a570352b35c0807" + }, + { + "path": "ruoyi-admin/src/main/java/org/dromara/web/service/IForgotPasswordService.java", + "exists": true, + "sha256": "5127c9e889197ca653d98879f9ccaaa06681ae86d4c3882d4380a6cc08e37fc6" + }, + { + "path": "ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java", + "exists": true, + "sha256": "e86118365eb8a22dddae1068807fa0f1d41bd24c2a7fa72965655583c0fdf1e8" + }, + { + "path": "ruoyi-admin/src/main/java/org/dromara/web/service/impl/EmailAuthStrategy.java", + "exists": true, + "sha256": "b3a0385864d7c7a97affa7b2b4d3dfc536bd3a0aad1c6935fb4ea54b86d5c6e2" + }, + { + "path": "ruoyi-admin/src/main/java/org/dromara/web/service/impl/ForgotPasswordServiceImpl.java", + "exists": true, + "sha256": "5dcb3d807e01cb9b2c52d33c896f88777980d3d840183ba1ffc13970548ffc81" + }, + { + "path": "ruoyi-admin/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java", + "exists": true, + "sha256": "a19d74766ab6766f2087f352e6bdb59c14cda791662d152276f352af5059f1be" + }, + { + "path": "ruoyi-admin/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java", + "exists": true, + "sha256": "922341f813d354cd3837853f8df9ae26c197b89a49a0978d64abd3cb683c9e92" + }, + { + "path": "ruoyi-admin/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java", + "exists": true, + "sha256": "ac02193be3683343e9605286f3f859d4c958e95ab00636d462cb1869e2beb5a9" + }, + { + "path": "ruoyi-admin/src/main/java/org/dromara/web/service/impl/XcxAuthStrategy.java", + "exists": true, + "sha256": "0e9fa9490232299d6cf09e35c989fa3f12e6fbb7dae2cba10ee78d9903b73fb6" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/AlertRecordCreationServiceTest.java", + "exists": true, + "sha256": "52ca55903b1602dc2d3cef46a7930b6ba88cf593c2d14a94f3117faf0d42c94e" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/AlertRecordDeduplicationTest.java", + "exists": true, + "sha256": "7ea8b451313c22d8cfbd4f7b8f1f1f50b76c2759e63812ed3f61b831285325cc" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/BindPlatformPortraitScopeTest.java", + "exists": true, + "sha256": "850264319f0026548923e79e9ea715680b9c226244081c6f91ed4615bee71793" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/BusinessPortraitPeriodTest.java", + "exists": true, + "sha256": "88ce328aa0ee52e0994a8e27fdc5f3f02ddf01353d8e2e7724a0a962258b1357" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/ChannelDataPromoteNameScopeTest.java", + "exists": true, + "sha256": "35b5209aea6dec3d15e4a2301c2e2876831879efb127faf438146f0b27180c8b" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/ChannelTreeMetricsSupportTest.java", + "exists": true, + "sha256": "365967906a4e0dea74d6709a6c969d537d9fb66b65b240d75fb8a5fcf1e6f183" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/DetailChannelDisplayTest.java", + "exists": true, + "sha256": "d6ba604792f1a74d489a2b00548c95162300184ce693ac18ff2b4faf22bdd69d" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/PlatformBusinessPortraitSupportTest.java", + "exists": true, + "sha256": "d3dc92c49e255d27dfcab23c3e039f1789e5c306d84238fe247fac6414c6b6df" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/PromoteAccountRulesTest.java", + "exists": true, + "sha256": "74c753867d224e6a10c62e867998090512c15e2ac0fb2b9b14e15e5244754b8d" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/PromoteListMetricsSupportTest.java", + "exists": true, + "sha256": "372007f5cb530cc6e266249f0c6bd438e88cb049e126db45f7a7cda57864cb89" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/PromotePortraitPeriodTest.java", + "exists": true, + "sha256": "25e58332b004cff012b0789a614ff801f7467509c35354bee51c0db5f783b525" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/PromotePortraitScopeTest.java", + "exists": true, + "sha256": "7cd20febe528305c2714b42135faab9df2536c55fab39e79bcde8b8a2b17eecb" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/PromoteScopeFiltersTest.java", + "exists": true, + "sha256": "982e3402bdc0ebd0304d838dddad0afce727e651266f177545560bc59c6bc4a3" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/PromoteServiceImplTest.java", + "exists": true, + "sha256": "b5ee09b243fc45ac488fa9a249d6601a9121fdad750bf68e428058ec7ce5435e" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/ReportBuildRangeSupportTest.java", + "exists": true, + "sha256": "2904165f7425a9bad5abd24c19a46c33a25ed249904a1eac50d76c79d61259b0" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/ReportIdentityHelperTest.java", + "exists": true, + "sha256": "3aa193ce1f3911f1f6d31c2a9fca75d0936fb2f8decd984132e13a1d0a1ff1dc" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/ReportMapperPromoteScopeTest.java", + "exists": true, + "sha256": "0332712fe022a69b5c71011ba986560c302592a7b8566bd675139ebb68fc52cd" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/ReportQueryFiltersTest.java", + "exists": true, + "sha256": "742ee36b0050733f3f4c9a7056a7fbb6bd4ce1e2e9eb7eb27720815b056f33f3" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/ReportQueryScopesTest.java", + "exists": true, + "sha256": "8abaee552f43eace5b8d45f91172d03d3be8506e1091857452b751ced27eefad" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/ReportSortRowsNullSortFieldTest.java", + "exists": true, + "sha256": "8cc222a2e9fd6ea54ac5f7f9f44e83b24f0c7742d9aadf83167b1a666d08e992" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/VisiblePromoteScopeCacheKeysTest.java", + "exists": true, + "sha256": "1e7b884e62cf2841c96108585f1d253e23aced39f642268c67400b23f50841d8" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/system/VisiblePromoteScopeLoaderTest.java", + "exists": true, + "sha256": "d1cb28d7a08db2a0346154131b39d6a65b7c536dca3a041bff0382310f8695c6" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/web/ForgotPasswordServiceImplTest.java", + "exists": true, + "sha256": "2487436860b512c36d6ddbebf7ae7e28bb17c0db5ab41397d4af9f1593e23060" + }, + { + "path": "ruoyi-admin/src/test/java/org/dromara/web/ForgotPasswordSupportTest.java", + "exists": true, + "sha256": "e780985c97ee87719d4c48539f30daaa0e6833f9532941d7db7d065a4585e42e" + }, + { + "path": "ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheNames.java", + "exists": true, + "sha256": "30eb4d08f5819e577bf4da5e7964f556c3ed19e48fe9a3a7702e9a28e52c8ede" + }, + { + "path": "ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/GlobalConstants.java", + "exists": true, + "sha256": "65404a89f95d727885efc4824aa78aa85097d9d69b31fd96a9b7034e8bcd0ead" + }, + { + "path": "ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/SystemConstants.java", + "exists": true, + "sha256": "1a79e453ab57f198f7858414b1fd5e57d5c92aa1fc2d3ce07917b95340dc0d68" + }, + { + "path": "ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/UserStatus.java", + "exists": true, + "sha256": "a39f530d41cd3d88c640f886d37d28d14e2fc849198c72c2bd4a868ffa9ae823" + }, + { + "path": "ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/enums/BusinessType.java", + "exists": true, + "sha256": "fc93efabff03f7d4f1f11dce2804d6a43133b0cad06a612790938cc60f1d2911" + }, + { + "path": "ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/OssClientConfig.java", + "exists": true, + "sha256": "a6e63bdd1fd82d29e0a9726b9aa0b0e96a207c4b117d3481eba729a56e23b0e7" + }, + { + "path": "ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java", + "exists": true, + "sha256": "30c5307fe06489ac4b27d24ba4dae2ffbec2268969a752d65c84316c04bbc28f" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/constant/PlatformSourceDb.java", + "exists": true, + "sha256": "ab035c53e16b8ed9dc9373c20a19b5ae7043fd46f9fbc75ce5da7a0582d0c630" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/constant/ReportMetric.java", + "exists": true, + "sha256": "16f08defa82a0a54064c36e6c6c37857eef84d487a9c7150df428a33c7e2b50c" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/ChannelDataController.java", + "exists": true, + "sha256": "f97862893745219605954252f8dc82c2ec2ae69da9429b28f7a044a2acf009b0" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/GameDataController.java", + "exists": true, + "sha256": "004855e44ed88b4840c2dd2df4c606a0bea7f9149560dfd62b027569cce396e4" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/PromoteActivePoolController.java", + "exists": true, + "sha256": "577bb406a9b701bfd8442c7a7047d67885c3958d70392204931a152cdbe35c53" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/PromoteController.java", + "exists": true, + "sha256": "a8977e1e5f9b8962f8f7d5132f818bc6913c4bcac8ec63c9cc4ea3da5231ae9a" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/RankController.java", + "exists": true, + "sha256": "e621f595fbe3c0f12d2265ffaf98609f6ad98ce92bc5616c0603efc9143948aa" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/RegisterController.java", + "exists": true, + "sha256": "d3150eb0549d45057082c89927cfa6d4b49cc5f5a4db716f58db8d18ebca4181" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/ServerAnalysisController.java", + "exists": true, + "sha256": "e4ad877b4b7be3c060e182d88db0d5ca3e5d288e209dd8733b10d0c811a5c153" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SpendController.java", + "exists": true, + "sha256": "14707a4adeac9c2b4fe8ea87e794532a6851c5a0a2f28e679a9b2f0b0412454c" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysAlertRecordController.java", + "exists": true, + "sha256": "8c82679f89e74408f4c9b784d691cdd4452494e9c55423bffc3f6d6dc7de4fbf" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysAlertRuleController.java", + "exists": true, + "sha256": "cbd4a8a0c2638139831dbbc0e87b85bb38d7145525c7bafba22918fc4bfa7789" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java", + "exists": true, + "sha256": "e8240b10f44321e22e7b53a3bad1f638b3105a4849282ccaf977325e613cbea9" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/UserPreferenceController.java", + "exists": true, + "sha256": "e1b749146e829c1c574b7161dfd995a4e656c53ed44a755695393b50e67c0d0e" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/WorkbenchController.java", + "exists": true, + "sha256": "45306b5be2fe6f1342bd10153e2a0df9077b718021274c5dbe5e3a6d419116a9" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/PlatformTabPromote.java", + "exists": true, + "sha256": "611ffecb45910a8e9622504bd2e7869c5a525dd8839c31b7ed0aa8eb3ee3508a" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysAlertOperationLog.java", + "exists": true, + "sha256": "1a89dd672e7aca6bcfdf927baf9a22cc5c8a9ba796f8cb7720d1c6558159def7" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysAlertRecord.java", + "exists": true, + "sha256": "3450242cebeac918f7e81381976ab7c41ddcf7caac7a91cb4a7ad1a3eda8e657" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysAlertRule.java", + "exists": true, + "sha256": "ddc904bef0a5b80119032cd0faf39275b2e178c8e3144113b2a6bacdecbac4f4" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysPromoteActivePoolBind.java", + "exists": true, + "sha256": "454b78bf9312b24795aea8292b4fdee1e4a9f4a56f170bb192de24c6bbbaf46e" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java", + "exists": true, + "sha256": "ae23a706c92123cb4dbb8f8e7fa0ebacb2b18909e408d807c6854dcf82946f55" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUserBindPlatform.java", + "exists": true, + "sha256": "8a0a5b114de04a32f12a91410b8652d3456cc955ca098ea583eb72738bb81cbd" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUserPreference.java", + "exists": true, + "sha256": "247e3ed364641051fc9ce8687dfdcc3cce229be3c89524382624e84ae128925d" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/TabDatareportTopPid.java", + "exists": true, + "sha256": "11141feba23835a60053fe78ac5eef6c736e8670c52efacd3d5470cf0a2a4b74" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/TabGame.java", + "exists": true, + "sha256": "c10d72f022a49bb4c263f3f31a15b628e3e502be21a10ade5b31d3eefcdd5ebf" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/TabGameServer.java", + "exists": true, + "sha256": "21db3ffbdb6a3096f496b200ff82d40b3c9d1c6ff9f91e849e06e63597f69333" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/TabPromote.java", + "exists": true, + "sha256": "6e8744abf917de3cd57d32b8c4f79098bb23fc6e0ed985241c53ff66272e43e0" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/TabPromoteApply.java", + "exists": true, + "sha256": "b2dea3457cbd52bdd541f8d5e5342a8b78a749f50eef0618e882d7eb178f1eff" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/TabPromoteBusiness.java", + "exists": true, + "sha256": "1a53c44f0163bd7510b132b59eafdb55b6c01220a513729a4ecc051c579252bf" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/TabPromoteSettlementTime.java", + "exists": true, + "sha256": "ebc92e2b3d940ae178ab8f27ff345bc15299a1134c882c6aedbb1f054649cb3c" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/TabSpend.java", + "exists": true, + "sha256": "6ea8a08f9b6e13571571185622baae3abbdb40c586b9a6a29937aa5af1c4980c" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/TabSwReportDay.java", + "exists": true, + "sha256": "48f6fc23079ea94ce5f922e3137c920fa9dcca5f0ba2ff90328220378839ffe6" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/TabSwReportDayKey.java", + "exists": true, + "sha256": "8038fb753563e7bb97f5481c6696350d3ed4785dd9a8dc5bc888eacb904187ec" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/TabSwReportServerDay.java", + "exists": true, + "sha256": "50f4593aa31bb483393b054e9449baabac7e78bf8171f6e53ca6fb3c828f7148" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/TabSwReportServerDayKey.java", + "exists": true, + "sha256": "86752b4a3dcfbeee4a6b586cb65186ffa93cb4fed579a55652d3177384458d68" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/TabUser.java", + "exists": true, + "sha256": "bfd41b7f6756ab7e2e616694e9300f785f12928e88b9f94c5f9eec6f15f5afb4" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/TabUserDayLogin.java", + "exists": true, + "sha256": "32b37251c4e1b31eb27a5b9bed2512e8813f7b2474fe127af220cb5ebb4db338" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/TabUserPlayInfo.java", + "exists": true, + "sha256": "78b8e453926c7beb7634b746af64c39cda2a06ff0243215d7053271603cc1799" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/AlertNoteBo.java", + "exists": true, + "sha256": "b8af0f2adf444059ef5739cdaacdf8d512d7404ff5fcfd871a078bb00020b2f3" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/AlertProcessBo.java", + "exists": true, + "sha256": "948e96a3af9bda85acbe70d978fc236e1c5ed2bbe9d9bfc043b3885f016bee36" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/BindGameBusinessBo.java", + "exists": true, + "sha256": "fc710fb637ad18e4a35850a98c2cb22fdbf860ea98072cf4c5d10063e6a1a03b" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/BindPlatformPortraitQueryBo.java", + "exists": true, + "sha256": "2ce4a69f0eb91e75b1427d303360fa392a4b235f123ce59bf2137221906d9b72" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/BusierPair.java", + "exists": true, + "sha256": "c1d30dec62cb8d392091db6f1e392551b382721eab07b4e898737316ac230126" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/BusinessPortraitQueryBo.java", + "exists": true, + "sha256": "a84897fc61ac957183cb1194c39e432334a16d853804a7642cfd78115d43665e" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/ChannelDataQueryBo.java", + "exists": true, + "sha256": "fafd6e00f2130c0bec4a6e369ce1fbe46b433a0fc5786e606b90097f7dc1d39d" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/GameDataQueryBo.java", + "exists": true, + "sha256": "29401e39cbf7b046abb07ef049acfaac9d6c2b57f09e23366b09ab02b4adc316" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/PromoteActivePoolBindQueryBo.java", + "exists": true, + "sha256": "2be3f74e88799ebcd8829222883d539bf8355256cceab0c2c9f100dca23f9f54" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/PromoteAddBo.java", + "exists": true, + "sha256": "b90bde429bf5eadc4082e5553b9407ce3328260837cbb5b796b93b1982fce1fe" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/PromotePortraitQueryBo.java", + "exists": true, + "sha256": "cd5dd236f18b4761219a7ef8f43ba0c049c6f06856c40b17edcd5d31c2ce0bad" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/PromoteQueryBo.java", + "exists": true, + "sha256": "f418449cc11ee4554a1f9f595e146e1082ae328b3b8ee71af216571465b0fc26" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/RankQueryBo.java", + "exists": true, + "sha256": "384629d732ee45575c10e9d0f7fc203a0a816c1428ef1b5d194cb9cb37f12f43" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/RegisterQueryBo.java", + "exists": true, + "sha256": "cfd1fe6146448002681e649514cabd52a16340a8879e2e02b346731672701b2d" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/ReportQueryScope.java", + "exists": true, + "sha256": "0aa28037ee87c7bfae2f611d598455e88165c300d9f3f83dfa84c37050f494d7" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/ReportScopeMode.java", + "exists": true, + "sha256": "ce9965a9e1800fad9f9a0109d1466f9b791d5a7a7adfaee33d04f94183c81314" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/ServerAnalysisGameQueryBo.java", + "exists": true, + "sha256": "c633df1d773f4f121ca9cdffe3409a5a56d745a19385d37b3917de966d1bcb1d" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/ServerAnalysisQueryBo.java", + "exists": true, + "sha256": "7e1747ac38728f756cac1b05564bc4be216b86b30ace227dcc28d12a0a823e19" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/ServerAnalysisServerQueryBo.java", + "exists": true, + "sha256": "4d717b49c11a651936fd581d78c3532a2588eb3007c7bddb7cdd65105f9c28d8" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/ServerReportQueryScope.java", + "exists": true, + "sha256": "ff25be16e8fc41aae8c141085f0e00c2b3fbb681bee2c75e999e0b09cb991d33" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SpendQueryBo.java", + "exists": true, + "sha256": "20d34c0614e8ed36e1daaa0152dcaf7ea01d47e7f21d536643066fb1e4227ff6" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysAlertRecordQueryBo.java", + "exists": true, + "sha256": "61202192f9be390addabbba76db4eb7511d3665d51e1f8ccaff13a7ee59a3e97" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysAlertRuleQueryBo.java", + "exists": true, + "sha256": "e076b3adc548b8c3ef1f81a92ea1cb34f4240a8fc229b8aff81c4b72b49d7a16" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysAlertRuleSaveBo.java", + "exists": true, + "sha256": "19bdaba24b14880377cc4e7cabd538c40954cd702f2a3bf45e61e717ae996827" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBindPlatformBo.java", + "exists": true, + "sha256": "ad90dcc9a431df873631b9ebc2913ed18ff84c7df37e10ed36c8b4c8c6001a8f" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java", + "exists": true, + "sha256": "427dd2c3ba375f966d37dc2ec38c18ce2f7f7f37277f4e05513709e2c8c0b9bf" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/UnbindGameBusinessBo.java", + "exists": true, + "sha256": "3938773c2224801d2e7a86b73c2eb114f44b6a7a31aaa5474964c6d401aaa25d" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/UserPreferenceBo.java", + "exists": true, + "sha256": "c66ebdc507cc83b7efac0c75823a25845e0311649d8d3d47780f367776a00550" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/VisiblePromoteQuery.java", + "exists": true, + "sha256": "f86ddc96dfbacd93fa15ae71e8453edae98e63ba76e687f7f2ed17c32a222795" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/VisiblePromoteScope.java", + "exists": true, + "sha256": "5f2fdd086c79cd474195d6d4123224d419282713ce9a3f6448ed3a8812c342fa" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/VisiblePromoteScopeCacheEntry.java", + "exists": true, + "sha256": "9b7743248926886aca11fa5befdeba896d7d4f2e3fd9189ac216d9da6ae1072e" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/WorkbenchQueryBo.java", + "exists": true, + "sha256": "64a9b48f12fc84131fbadaaade4640c1047e2d56226698162da4969d46b6cffe" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/AlertChannelMetricVo.java", + "exists": true, + "sha256": "2348a4b3e11a6bc1e2f780e079a3b552d013aa407d96d525d45a32cc6af2dedd" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/AlertRecordDetailVo.java", + "exists": true, + "sha256": "1c75bed76e7d984084c216d2af9b4dfeed92e2d24def1fe70dd3fbcc38aea4dd" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/AlertRecordPageVo.java", + "exists": true, + "sha256": "dc4419787cff060b076aaeb7ca89516a5bcd97efa05f7dd371d71b920f46f239" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/BusinessPortraitBasicVo.java", + "exists": true, + "sha256": "9982d42fc5f40aca1fd538f72214f7974c6329e0bfb723dfe6e902ac704a5573" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/BusinessPortraitMetricsVo.java", + "exists": true, + "sha256": "379347988399a9fc1e2420d8798246c00a8d271177b57781f908dea7e45244b2" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/BusinessPortraitTrendPointVo.java", + "exists": true, + "sha256": "34cafaa9aa68dece8f37599f6243c79d10f7558c9688fcb54dbd0dc17f7e7fd2" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/BusinessPortraitVo.java", + "exists": true, + "sha256": "e6f4a11a6696bbb2580b2be654e360fb597a9edd1ae9a69cee7ec40e650f6a90" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/BusinessPromoteVo.java", + "exists": true, + "sha256": "0d941a0ec63532b83d6c5514a9e5da620ca6c607fd4490dee8f3b23a8101194f" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ChannelDataPageVo.java", + "exists": true, + "sha256": "1c0d9acb297f54f016dec93c2e9177b6e90a39b96a728c99c8974a855e737851" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ChannelDataVo.java", + "exists": true, + "sha256": "dc6ad1f4aad8cc2d115f064114fa7b9779ce7a8cb48905f36fa1d430ef04e6ec" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/GameDataPageVo.java", + "exists": true, + "sha256": "238c1ecb5078717d5cd2a1d6c5d5d281d4b62792d77a812635d6077086f31248" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/GameDataVo.java", + "exists": true, + "sha256": "0c7a5f55492d4b7e9a6d65899f769a1482aaad85f2486a400e4acf5c5fc2e56f" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/HourBucketAggVo.java", + "exists": true, + "sha256": "21657e74aec568135c0b4840d619d925a1ec60d008a8a6a4b6cdbc75a8d88e46" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/IdentityPayAggVo.java", + "exists": true, + "sha256": "a5c4188a7744de2c16d250df9c70644e8ba427631229a2f134b5c0dae56c99e6" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MetricCounts.java", + "exists": true, + "sha256": "48bfc72f4ec1a6d185d55bc509ba0e61344586024a9655e8bb5c534258e388c8" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/PlatformBusinessBindingVo.java", + "exists": true, + "sha256": "402cf41c6702af6e9d4f7828594c042ec96f7dccb54ef4254ef71fba7a2ff752" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/PromoteActivePoolBindSpendDetailVo.java", + "exists": true, + "sha256": "bdcd83f53a3288f4621f776b14abad92579e8fb4aeb7909fe42545cf3a1212cc" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/PromoteActivePoolBindVo.java", + "exists": true, + "sha256": "dd73859a9044e3bb3b04a32892ec9c45a811b6790a486ed014b343d0d699fc87" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/PromoteAddResultVo.java", + "exists": true, + "sha256": "7e83646136bb862d34ceaf776c55e2c2e9fe373d0565af5b34d95be5d8e57700" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/PromoteBindOptionVo.java", + "exists": true, + "sha256": "8167180fa79c6cf2135727f1b2bfa2eeddc9d035bccdc03ad88321e7a141dcc5" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/PromotePlayerRowVo.java", + "exists": true, + "sha256": "cf1eba2f7537c78578dd2401538a3d003dcdcb6610dc66f2dbfce076af36c089" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/PromotePortraitBasicVo.java", + "exists": true, + "sha256": "20bf0a14d456cd1b49ed24838ffd5cb3b05f59e1ac9f2800308ef635dba411d4" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/PromotePortraitGameVo.java", + "exists": true, + "sha256": "a320310c7291485ff19a52f0f1dd1b284eeafbafd0084cd8b33e92565b8c5a3e" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/PromotePortraitMetricsVo.java", + "exists": true, + "sha256": "9d3bffa4405eaaa2527584e0dfd516e4da693bbccb5bdd78ea79c64ed98dfb8e" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/PromotePortraitPayTierVo.java", + "exists": true, + "sha256": "58a95c830d663185a1f26360f2a0de1911d068e5d74c3dc4a4cc13e27f851bae" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/PromotePortraitVo.java", + "exists": true, + "sha256": "1916847880873ff673cedd53fbdf15f6548ae02731bf0ce9f0272d29faa58a65" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/PromoteVo.java", + "exists": true, + "sha256": "d8520435f2e0f71826c45d726e3be588e5089b04c5a69c7215def377715d46f7" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/RankItemVo.java", + "exists": true, + "sha256": "0b19e855d62e34ec985c7c9ace7992e4368bf8e5b9e367765f9de1a7daa5b9bf" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/RankListVo.java", + "exists": true, + "sha256": "33c8fd9fa54d57a5845207acb83e3fa9604dfd271e4c9bad45887be046ab0631" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/RegisterPageVo.java", + "exists": true, + "sha256": "aa0e113ad01aa1a76be74db449b15b98556dfc580b660ee472bba17367625765" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/RegisterVo.java", + "exists": true, + "sha256": "7e8825326516e8c7d64544c27b6f91b693bd64c0e240de55e6efc74709b04f2c" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ReportDateMetricCountVo.java", + "exists": true, + "sha256": "a171a8b46ead5df5256dc8d81bf2be1cee2ba69f606ebfd618564140446367e3" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ReportDatePayAggVo.java", + "exists": true, + "sha256": "9fb71935128667e6ace209583325deac5bbcc11b920b7b4714d0858448d9a029" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ReportMetricCountVo.java", + "exists": true, + "sha256": "d2595fe4c999633ddbf576c7426cae69085e86b42b84db8d446181c49ad7bfe7" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ReportPayAggVo.java", + "exists": true, + "sha256": "ffba4aa180fd37324d898b93c9051fe5fd24fae627421d56d03a1b52cc74c529" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ReportServerMetricCountVo.java", + "exists": true, + "sha256": "b43cf186f36f509aad60a6091e6ead5f1c7d0006abb77c94ce45eedf3a2238e2" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ReportServerPayAggVo.java", + "exists": true, + "sha256": "727f7014db7382af102d242c3a5276673214b5bf29fc05bbbf44a9e41dd84df5" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ReportSummaryMetricCountVo.java", + "exists": true, + "sha256": "4871ef4df7c1581ae8ed7bdf7a34e26582220ddffd6dbbfaaa4fcaeb8fc3ae5a" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ServerAnalysisGameOptionVo.java", + "exists": true, + "sha256": "e39c23273bbc36cbc507ae622042e99fed5cf47439dbcb94b92d09c10229518c" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ServerAnalysisPageVo.java", + "exists": true, + "sha256": "84a86c4b7aaeece2f4d8ea3aa077d8da1ecc8da2870a0e1759a8c5d95621239e" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ServerAnalysisServerOptionVo.java", + "exists": true, + "sha256": "03224103fdbbf275adb23df3d585a0ca561c361c2ba47c9f78a9f99f77b1a03f" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ServerAnalysisVo.java", + "exists": true, + "sha256": "d05b2d161f67552d77495bd75e7c19aa7b95e88f476e254938645df12d3c359b" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SpendPageVo.java", + "exists": true, + "sha256": "448edad3f32d79a0d98dd697561e75f2f30dbc533f89167676928973f619c24a" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SpendVo.java", + "exists": true, + "sha256": "9ad595303ed6d389cfa4807240365b6b27d7654c47b923cd1e1cb0f2d089625f" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysAlertOperationLogVo.java", + "exists": true, + "sha256": "3dce67f962ea5c978ae140d30170b965e866807dd9579eff80eabdee38918961" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysAlertRecordVo.java", + "exists": true, + "sha256": "46dea0d675c67d180a96009300643f0ce7dd5e457d738855741215d720c91f8d" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysAlertRuleVo.java", + "exists": true, + "sha256": "bf1ee3fc078740dec4df6c3b57da37766b424f6ee792825302542c1c613311b9" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserBindPlatformVo.java", + "exists": true, + "sha256": "03c2c35b8ada0011a7acd7fd18846ed728e8bfb20efb495bca1b7cd4d2023760" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserIdNameVo.java", + "exists": true, + "sha256": "ed14ec83ddb2ea3ede0c6501c971d175528dd64c3f50f72a3f6be261a4fbd6e3" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java", + "exists": true, + "sha256": "5220f8dbe78e898deb32e5f35cf98806f89035a856a59b667650bdf7cf5d9188" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/UserLevelInfoVo.java", + "exists": true, + "sha256": "4f895ddeaf69a1d05eba569d05f148da744e06ddcbb8919f2fe2fa6113aaba07" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/UserPayAggVo.java", + "exists": true, + "sha256": "aa3ed9c43809a30980f09105e40f0a4b1640639e36dc6dabb40529dc1804217b" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/UserPreferenceVo.java", + "exists": true, + "sha256": "c6021805686f7bd1b44599ad49c735caf491d7e5926592b086be07e1a644bebe" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/WorkbenchMetricCardVo.java", + "exists": true, + "sha256": "90d560e5c214104de5896958335e130ef010d77f8326f2df70f30c30dd946375" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/WorkbenchRankItemVo.java", + "exists": true, + "sha256": "d59a73d3c6007f5acb33b671a0be74ee22f866b5477c9cb4e397e4a355a41a13" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/WorkbenchSummaryVo.java", + "exists": true, + "sha256": "ba29598f64d945be5474e9a4e5b94712f23b56e6608ef4e9846483fdff7c1753" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/enums/AlertActionEnum.java", + "exists": true, + "sha256": "6ee7eee5209fdd922be8ea443195a19a1da38552ec12fa31d80f8959937ecdee" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/enums/AlertLogType.java", + "exists": true, + "sha256": "a037137ad596d3c27b47a819f2bad818a18dfbfd78018e3314892fad9d9074b4" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/enums/AlertStatus.java", + "exists": true, + "sha256": "145f4b685dcc0828f66af74d062ff7969898b0efc4b125401a6e9819aaf04622" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/enums/MomDirection.java", + "exists": true, + "sha256": "885904dfab18f550a1ecd94b4920e327725c8d66f3fda9e8544986293bc1373a" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/enums/MonitorMetric.java", + "exists": true, + "sha256": "b435003b219fd7b02cdc437109399dbdd7e2e8e09017f047696510bc18cbd927" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/enums/RankMetricEnum.java", + "exists": true, + "sha256": "73aa171f970a039d3a7e91ca78c18709a0dd8bcaf44bf09e046237390ff586e9" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/enums/RuleType.java", + "exists": true, + "sha256": "34d6708afc9beee427f1d4ced7dc2be7d0bb9df35d2253ef2db08cb6d0527b7c" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/job/AlertJobExecutor.java", + "exists": true, + "sha256": "c674c0566184ca67c903743d08b0303aa6e1d777a4e2ef49f6a263765c3a95c3" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/job/SwReportDayJobExecutor.java", + "exists": true, + "sha256": "fbcd04515c0a242beb459faf6e3ba37d2de26d8d74b4c4f7b503189c7cde9725" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/job/SwReportServerDayJobExecutor.java", + "exists": true, + "sha256": "e6bda283d8c3257c9c4a1a3908abfeb924a8fe597884dbe782782db65b2dae8a" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/PlatformTabPromoteMapper.java", + "exists": true, + "sha256": "69fb83f93d1027450a4aae1679b60363f1b5f05f362191e4a2521aa83eac2975" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysAlertOperationLogMapper.java", + "exists": true, + "sha256": "4cdfa9906ba92bb4fd3eaec3756be7d154b9ff17e0b08764a836fc2b99e42f62" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysAlertRecordMapper.java", + "exists": true, + "sha256": "99659f7f80c1c46c027a56bb0323ad6ba3a36a35577124978d03fd32eb0a49f4" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysAlertRuleMapper.java", + "exists": true, + "sha256": "bd0ebf36323c3e32ec3ee98ddae152062d5ce5b6a3c5c39b674882928e0d8f73" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysPromoteActivePoolBindMapper.java", + "exists": true, + "sha256": "d47cc3a3681c13a32ba5a470bcdbef3d8c77d9ecf52d505868825131fd00a2e8" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserBindPlatformMapper.java", + "exists": true, + "sha256": "5a67aa777be291ca90407a619cd710dde9a8b95f3d3feedbc7c3b74e803e4ddd" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserPreferenceMapper.java", + "exists": true, + "sha256": "787f357f80f395b6ab8fed7c095ecc648996644e3b8c6898dae9b80f063b25c3" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/TabDatareportTopPidMapper.java", + "exists": true, + "sha256": "5a80491c499b45729226f3db0976af1ff2aae7df114841772ef6a3bc30c84f6c" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/TabGameMapper.java", + "exists": true, + "sha256": "ec9610c7a8d6a7de6a4bbf19f57865260455678b88dd3a5d329911791d3c1eaf" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/TabGameServerMapper.java", + "exists": true, + "sha256": "66ce5cfcdf8cc6285bc77fb286ca9800e1e3be353814fc65c00da025b0a970c2" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/TabPromoteApplyMapper.java", + "exists": true, + "sha256": "efe03a89e929cd7e6ba09ad2e2cb9b3f35fa757f33816cfff5e8600b8f4db36b" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/TabPromoteBusinessMapper.java", + "exists": true, + "sha256": "a3a0ed3315ea3fc867ec44c4ee58e12769a8af3bf56ce2f6a589b698f682a326" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/TabPromoteMapper.java", + "exists": true, + "sha256": "86014c512da235c4c6bcc0dc2484025b02da3b222141850b258a300a99900114" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/TabPromoteSettlementTimeMapper.java", + "exists": true, + "sha256": "061346767e6a515e9c18543331636980cb81231794735612c00c0a9b031288da" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/TabSpendMapper.java", + "exists": true, + "sha256": "a03ebaf0dd0cd1eb163226c369e9ca1c9f280b86ed043c18da3ab32bc7782a2b" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/TabSwReportDayKeyMapper.java", + "exists": true, + "sha256": "8e4dfc3cf907b85750ec681a2d9775f5a583e468f0a5d9af439780daef43f736" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/TabSwReportDayMapper.java", + "exists": true, + "sha256": "0a1585edf552e085006a415cca6fe03db969ad861ca8c8c7bb997f893181aea4" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/TabSwReportServerDayKeyMapper.java", + "exists": true, + "sha256": "e8a32dec54e3fbc17d04a4cc437e2451dbc7c7b45ce31de8d31757299d6620ac" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/TabSwReportServerDayMapper.java", + "exists": true, + "sha256": "89caefcf96732fa9ddbbe38f7a354532c8d31c9f1e97404dc62f725c97852d1e" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/TabUserDayLoginMapper.java", + "exists": true, + "sha256": "5ad4cf6914d94f0a1c199e364e96b2bfb2c7d820feae9b52cd69657b4f1bbe43" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/TabUserMapper.java", + "exists": true, + "sha256": "1b96e27ca3a0a932cff007470cc8f9e6e643a6c93639e058fe42ddb7ff9fb5ab" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/TabUserPlayInfoMapper.java", + "exists": true, + "sha256": "03ae07fc169541084abc20ded43b23eb55d17335e4737060cc5d487ff482e698" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IAlertTriggerService.java", + "exists": true, + "sha256": "b1ee13a6762022f83acee5288f6b8f1e724457610bc812871f3e65b10c66ea18" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IBusinessBindScopeService.java", + "exists": true, + "sha256": "e1f38ff280e2c74ab6d78afbf27929a88b8b670dbb1aff17b8ec8b43ea7c1e68" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IBusinessPortraitService.java", + "exists": true, + "sha256": "5a230ef1f14bcbd41938fce2d3d12f2e66e60ec7b8e153e5e3ba5b7560bdaf9d" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IBusinessPromoteService.java", + "exists": true, + "sha256": "6faa1fe23302d1a64318dcda691aa0df7f2b361c3cb5f76a396092eb72fb0787" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IChannelDataService.java", + "exists": true, + "sha256": "b3f77910e9b2ae870c32920c0736243c61e17cf48e5d95c01f71595e2a02ead3" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IGameDataService.java", + "exists": true, + "sha256": "b2a840af847acd8f411e25c8d71db19ce3f36b37a37a75b45f556d3ecb481b5f" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IPlatformPromoteBusinessService.java", + "exists": true, + "sha256": "517d7c1d3860d064a575690e8bf98158d8dc830c948de0c19e4d87f4536d4384" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IPlatformPromoteWriteService.java", + "exists": true, + "sha256": "4bdbbd17536ee874f040205af0e88963868d4b75655860a6f7980ab54f3f800a" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IPromoteActivePoolBindService.java", + "exists": true, + "sha256": "2df5d3b3d102a48faa2b721d1f9ce3315a85c54e93864d7f74a80af77062e16b" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IPromotePortraitService.java", + "exists": true, + "sha256": "5677cbe0a33bc19aff7cb35b3fc405613f9f0957ab6d90eb26973d989eaba859" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IPromoteService.java", + "exists": true, + "sha256": "d4f4f5c1a9612cc8c9c4dac72f4e2e67298a138c910bc7f49b52d17bcec4153c" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IRankService.java", + "exists": true, + "sha256": "80af79f9056ee8f7fc754745aa9c8d4327b6c7c63e8834a085eb031f28c0c7f7" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IRegisterService.java", + "exists": true, + "sha256": "da5db13b026ce66bd54eac65e93edcd1b27785fcccb804f968c655ac6875f8a2" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IServerAnalysisService.java", + "exists": true, + "sha256": "204b86c2d89a717790c59ab25a53dda70544c2835c46bc11ee2e677f0784d65d" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISpendService.java", + "exists": true, + "sha256": "f140cfda53cfe0d7f0fe07d699f05f1bded6276525fe135c3adc440f89276a77" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISwReportDayBuildService.java", + "exists": true, + "sha256": "ea7d9073ab6273e594f5fefc10eace2b44177aa109cd29bb31c94d7bebb345f8" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISwReportDayQueryService.java", + "exists": true, + "sha256": "5b18090738ddc581104675739b716819ad7540ef1a342a3eea5b6b6a0786f275" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISwReportServerDayBuildService.java", + "exists": true, + "sha256": "a5adccaa33c65275d0587385b7d8dd24857f169770340b8bf1a4c17f629833ee" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISwReportServerDayQueryService.java", + "exists": true, + "sha256": "88a103695596ee02357290953bb75d78a43e244c6890d4f811ad3db55fa77473" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysAlertOperationLogService.java", + "exists": true, + "sha256": "c0a15d0c0b070695cb43960256a2069db7c645618f8b515888348f6838bc4aff" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysAlertRecordService.java", + "exists": true, + "sha256": "6a9e7bb433fb0dc9d7899c7944e896bb9bb473d82e4b9464a628be3c65947da3" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysAlertRuleService.java", + "exists": true, + "sha256": "ac079a3eddbf671585e913892dd46735cc8fc06b4392e60683aab30e59c45e3c" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysUserService.java", + "exists": true, + "sha256": "8b9ac396056b160d2e55b58295c673c40a7ddf027aea449cd6f69b52f3c882f1" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IUserPreferenceService.java", + "exists": true, + "sha256": "e320521b57ad3abde37abf76c3c90a685bb516d8d0067a98604bee9e31a74820" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IWorkbenchService.java", + "exists": true, + "sha256": "ac1a5e0e872b78371a82cb007077448aa9208834ffa77f37e30931612d5c6bd3" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/AlertRecordCreationService.java", + "exists": true, + "sha256": "8b505a0032f78fa6726a3f64c8db0660acce6102d29295c9fef345db92c6a363" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/AlertTriggerServiceImpl.java", + "exists": true, + "sha256": "1475f31b5e8a95d56787bdb0465a6ffdd141ffb2c8bbeed8302b962bf2c592b9" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/BusinessBindScopeServiceImpl.java", + "exists": true, + "sha256": "0daa60e7139bf6b0446790225cc6a08488e0d7899d145eb99e309e9b6e90e5f7" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/BusinessPortraitServiceImpl.java", + "exists": true, + "sha256": "81d19a89c501d886a0072c5a7c5126fd0dffc0662a50060b53eb5681a2d3334b" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/BusinessPromoteServiceImpl.java", + "exists": true, + "sha256": "83bfef518d39c14864203de9690b4cce254331b9ca9de74351c914cb8f9f7a37" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/ChannelDataServiceImpl.java", + "exists": true, + "sha256": "a7b58297b1a0161d8a2ab79d7be122c8f241a124686d0ac2b4de26e934249932" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/GameDataServiceImpl.java", + "exists": true, + "sha256": "f2cf2a51b5d233bc58f5c84f3b58e02546978f3b24c69dfdbc279810dec7c5cf" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/PlatformPromoteBusinessServiceImpl.java", + "exists": true, + "sha256": "06fcc8fcc8be5eb9d2bbfe7170a147784e69e7f4f2087a6f6415d1193afcc412" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/PlatformPromoteWriteServiceImpl.java", + "exists": true, + "sha256": "59bf630f5d58685df83630963da5650408b623471d27f85d903f62050a8171b5" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/PromoteActivePoolBindOaHelper.java", + "exists": true, + "sha256": "932a0c14fb7b24a9810a0ea77b91441dcc48526b523ddcf643c8d0c8cd239d69" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/PromoteActivePoolBindServiceImpl.java", + "exists": true, + "sha256": "28ce522f5575b24bc623fd8d6d7b6de6c76ff556aac6f8535dc2fd1cba30fc49" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/PromotePortraitServiceImpl.java", + "exists": true, + "sha256": "3851f69c4f01e780c69193678445b87a11261195e7266bac69306ab71599a1bd" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/PromoteServiceImpl.java", + "exists": true, + "sha256": "70f58cd78caa4bb8424d931bb97143579d52712a76024fe360299e89536ff7f0" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/RankServiceImpl.java", + "exists": true, + "sha256": "8b7a12e21c71b00bf38aa7738682f86e3d4dbc3aa4a5fb6918518a93bfbcc48e" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/RegisterServiceImpl.java", + "exists": true, + "sha256": "cd0a056bbfb6a9557781c2f84a06ed0471e7c94d0d327fc85fd03ec1e40bc6e1" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/ServerAnalysisServiceImpl.java", + "exists": true, + "sha256": "1641ea177e770cf9de7379f8fa21078d939a564f4bb7ea720b4c3433a167b6a3" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SpendServiceImpl.java", + "exists": true, + "sha256": "6d20b8f8a145998e7848ed0ec99f791f6c70dd96335a23d451999655e87e89d2" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SwReportDayBuildServiceImpl.java", + "exists": true, + "sha256": "a04680802cb0b21df0d55c7b10d77056f87f5b211076068da57672618216155a" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SwReportDayQueryServiceImpl.java", + "exists": true, + "sha256": "9b6192e630785bd350fcbe2bc32f516ae51dadfef663686b0c6261f8a1ae4007" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SwReportServerDayBuildServiceImpl.java", + "exists": true, + "sha256": "1643199acae662eabe8e174d62d1b5ea68bc7b81390f51f9e5ce745b16e56639" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SwReportServerDayQueryServiceImpl.java", + "exists": true, + "sha256": "26406a9b8e7cc931b192b56586bb93264c2b6624afc15db59451da8ef3e0dbdc" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysAlertOperationLogServiceImpl.java", + "exists": true, + "sha256": "b32680d088c5108f41e841e2bfd54ce927728afc6066fe6c879d3100e9fc8e42" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysAlertRecordServiceImpl.java", + "exists": true, + "sha256": "5d2a648f4893d823361c223bd53d7dee5fe306b95a4c7c481d0d32bf96579f04" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysAlertRuleServiceImpl.java", + "exists": true, + "sha256": "c3d5c5135704b7aa0e65d96f756c03106c7b0aef7c4fa2db0b4164746a39fe05" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserBindPlatformWriteHelper.java", + "exists": true, + "sha256": "07faffffa7d154a8ade4527173d74bf9cb6a7a3d0c9a2c54907339611a956922" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java", + "exists": true, + "sha256": "65a476561bc17b05c3dbeb60e184a650888cd33970a773dddd30208f2b939b82" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/UserPreferenceServiceImpl.java", + "exists": true, + "sha256": "9eb3f75cede56b901765e3711398ceee80554d2601e9ca5b8826f04d38e018ee" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/WorkbenchServiceImpl.java", + "exists": true, + "sha256": "4175dedb22d4d429a3b5da2d72688d1472449e62aa0e449cb83081ba707e095b" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/util/BusierAccountFilters.java", + "exists": true, + "sha256": "15115fd94698ddb1a77848e75934989c14bf004ef30329b3484507af108cda22" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/util/BusinessPortraitSupport.java", + "exists": true, + "sha256": "cdfd7728d2247b94424c66773ee5783a5b283055eab871adafda2459021e2b0c" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/util/ChannelTreeMetricsSupport.java", + "exists": true, + "sha256": "7e855488863ab077630c2a7ab31df37c08bff198726ca42e104550b95750d336" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/util/PlatformBusinessPortraitSupport.java", + "exists": true, + "sha256": "970186190c9bffab766235995839ae55e52e02515b451af44e5d9124b881c972" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/util/PromoteDisplayNames.java", + "exists": true, + "sha256": "bb4f417bd4d45970a6bc21d86d1dccd4f4c68a8ddf524129632c36e3e116a48f" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/util/PromoteListMetricsSupport.java", + "exists": true, + "sha256": "e5db85e77cf3b694bd3f10f75378d97fe472ae027315fdcb4e95daa1ab7bbc6c" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/util/PromotePortraitScopeHelper.java", + "exists": true, + "sha256": "0f3aa89615e05c194902c3c0997bcc8c96597f2f81aa6f1488ae85034a321d26" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/util/PromoteScopeFilters.java", + "exists": true, + "sha256": "4e59825b83753ed0c0c0d17f36fc4c6aa62705e37c6ad6ffaf4da33846d1fa42" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/util/ReportBuildRangeSupport.java", + "exists": true, + "sha256": "40cc21c7156d5baf07c3e8d5ca929311da75c8b8ff94d33392cef08db7306418" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/util/ReportIdentityHelper.java", + "exists": true, + "sha256": "4e74db2a682a95090e7c258d0099e8af5a8dfd3945f7db91e12601cf6786427d" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/util/ReportQueryFilters.java", + "exists": true, + "sha256": "703a2ab1ab66232daf91ef86005ed70b901b011ed09196b7269395846807b105" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/util/ReportQueryScopes.java", + "exists": true, + "sha256": "7ef13a45f1fe7f5be715ce870287bf67f773261915fa48e2b264c98002f91dcf" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/util/VisiblePromoteScopeCacheKeys.java", + "exists": true, + "sha256": "726829693a65d8743d3fd4875659b5f7dd73de35eecdbcca5cf641bdbe3ab4db" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/util/VisiblePromoteScopeLoader.java", + "exists": true, + "sha256": "9deff24523683b511aaa7cdf2e292ceb31eb0962fb840aa2373b705059e1f0d3" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/utils/PromoteAccountRules.java", + "exists": true, + "sha256": "80838e35e55909cfec7e0df5eb63bfdad181237fcb68b529fce62aa88e601131" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/utils/XiguPasswordUtils.java", + "exists": true, + "sha256": "11e4de4438426e1656c297c3b1ae9581113c9b1b5ca85fbec25634c00dfa1c28" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/TabSwReportDayKeyMapper.xml", + "exists": true, + "sha256": "d77a43aa7713860a44adff9a955e62acf2831c21b5f68b552ddd17dd1ceb4d17" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/TabSwReportDayMapper.xml", + "exists": true, + "sha256": "7ad9513aa0a91b2a5fa512048314b8e3b10e053d005cedb433e169e3d115ab1f" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/TabSwReportServerDayKeyMapper.xml", + "exists": true, + "sha256": "3843980ad081613a4d28131d501ff952b62932c5ad20cead84a72321e5668fe9" + }, + { + "path": "ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/TabSwReportServerDayMapper.xml", + "exists": true, + "sha256": "c9eb902446ea88f1194d89b364da524950c6020a2575c1b39c6b7d38d9277b50" + } + ], + "additional_controllers": [ + "ruoyi-admin/src/main/java/org/dromara/web/controller/ForgotPasswordController.java" + ] +} diff --git a/internal/biz/biz.go b/internal/biz/biz.go index 00fa73d..3ef61c4 100644 --- a/internal/biz/biz.go +++ b/internal/biz/biz.go @@ -1,6 +1,7 @@ package biz import ( + "kra/internal/biz/business" "kra/internal/biz/integration" "kra/internal/biz/payment" "kra/internal/biz/system" @@ -10,4 +11,4 @@ import ( ) // ProviderSet is biz providers. -var ProviderSet = wire.NewSet(system.ProviderSet, payment.ProviderSet, integration.ProviderSet, task.ProviderSet) +var ProviderSet = wire.NewSet(system.ProviderSet, payment.ProviderSet, integration.ProviderSet, task.ProviderSet, business.NewUserPreferenceUsecase) diff --git a/internal/biz/business/preference.go b/internal/biz/business/preference.go new file mode 100644 index 0000000..68fc0e6 --- /dev/null +++ b/internal/biz/business/preference.go @@ -0,0 +1,61 @@ +package business + +import ( + "context" + + "github.com/go-kratos/kratos/v3/errors" + "kra/internal/biz/system" +) + +var ( + ErrUnauthenticated = errors.Unauthorized("SW_UNAUTHENTICATED", "请先登录") + ErrPreferenceRequired = errors.BadRequest("SW_PREFERENCE_REQUIRED", "偏好参数不能为空") + ErrStorage = errors.InternalServer("SW_STORAGE_ERROR", "商务数据访问失败") +) + +// UserPreference 使用新用户 ID,保留旧商务两个全局开关的含义。 +type UserPreference struct { + IncludeSubPromote bool + IDCardDedup bool +} + +type UserPreferenceRepo interface { + Find(context.Context, uint) (*UserPreference, error) + Save(context.Context, uint, UserPreference) error +} + +type UserPreferenceUsecase struct{ repo UserPreferenceRepo } + +func NewUserPreferenceUsecase(repo UserPreferenceRepo) *UserPreferenceUsecase { + return &UserPreferenceUsecase{repo: repo} +} + +func (uc *UserPreferenceUsecase) Current(ctx context.Context) (*UserPreference, error) { + actor, ok := system.ActorFromContext(ctx) + if !ok || actor.UserID == 0 { + return nil, ErrUnauthenticated + } + return uc.ForUser(ctx, actor.UserID) +} + +func (uc *UserPreferenceUsecase) ForUser(ctx context.Context, id uint) (*UserPreference, error) { + if id == 0 { + return nil, ErrUnauthenticated + } + pref, err := uc.repo.Find(ctx, id) + if err != nil { + return nil, err + } + if pref == nil { + return &UserPreference{IncludeSubPromote: true, IDCardDedup: true}, nil + } + return pref, nil +} + +func (uc *UserPreferenceUsecase) UpdateCurrent(ctx context.Context, pref UserPreference) error { + actor, ok := system.ActorFromContext(ctx) + if !ok || actor.UserID == 0 { + return ErrUnauthenticated + } + return uc.repo.Save(ctx, actor.UserID, pref) +} diff --git a/internal/biz/business/preference_test.go b/internal/biz/business/preference_test.go new file mode 100644 index 0000000..74895e8 --- /dev/null +++ b/internal/biz/business/preference_test.go @@ -0,0 +1,43 @@ +package business + +import ( + "context" + "kra/internal/biz/system" + "testing" +) + +type preferenceRepoFake struct { + value *UserPreference + userID uint + calls int +} + +func (r *preferenceRepoFake) Find(_ context.Context, id uint) (*UserPreference, error) { + r.calls++ + r.userID = id + return r.value, nil +} +func (r *preferenceRepoFake) Save(_ context.Context, id uint, pref UserPreference) error { + r.calls++ + r.userID, r.value = id, &pref + return nil +} + +func TestPreferenceDefaultsAndCurrentIdentity(t *testing.T) { + r := &preferenceRepoFake{} + uc := NewUserPreferenceUsecase(r) + if _, err := uc.Current(context.Background()); err != ErrUnauthenticated || r.calls != 0 { + t.Fatalf("匿名请求访问了偏好: %v", err) + } + ctx := system.NewActorContext(context.Background(), system.Actor{UserID: 7}) + pref, err := uc.Current(ctx) + if err != nil || !pref.IncludeSubPromote || !pref.IDCardDedup { + t.Fatalf("缺省开关应均为开启: %+v %v", pref, err) + } + if err = uc.UpdateCurrent(ctx, UserPreference{}); err != nil { + t.Fatal(err) + } + if r.userID != 7 || r.value.IncludeSubPromote || r.value.IDCardDedup { + t.Fatalf("未保存当前用户的关闭值: %+v", r) + } +} diff --git a/internal/biz/system/authentication.go b/internal/biz/system/authentication.go index abbf240..224b5b2 100644 --- a/internal/biz/system/authentication.go +++ b/internal/biz/system/authentication.go @@ -122,7 +122,7 @@ func (uc *AuthenticationUsecase) Login(ctx context.Context, attempt *LoginAttemp uc.recordLogin(ctx, attempt, false, "用户名不存在或者密码错误", 0) return nil, ErrInvalidCredentials } - if user.Enable != 1 { + if user.Enable != 1 || user.BusinessStatus != 0 { _, _ = uc.security.IncrementLoginIP(ctx, attempt.IP, ipTTL) uc.recordLogin(ctx, attempt, false, "用户被禁止登录", user.ID) return nil, &UserDisabledError{UserID: user.ID} @@ -183,7 +183,7 @@ func (uc *AuthenticationUsecase) currentTokenUser(ctx context.Context, claims *A if err != nil || user == nil || user.ID != claims.ID || user.Username != claims.Username { return nil, ErrTokenDisabled } - if user.Enable != 1 { + if user.Enable != 1 || user.BusinessStatus != 0 { return nil, &UserDisabledError{UserID: user.ID} } if !userHasAuthority(user, claims.AuthorityID) { diff --git a/internal/biz/system/business_authentication_test.go b/internal/biz/system/business_authentication_test.go new file mode 100644 index 0000000..7898132 --- /dev/null +++ b/internal/biz/system/business_authentication_test.go @@ -0,0 +1,27 @@ +package system + +import ( + "context" + "errors" + "golang.org/x/crypto/bcrypt" + "testing" + "time" +) + +func TestBusinessReviewStateBlocksPasswordAndExistingSession(t *testing.T) { + hash, err := bcrypt.GenerateFromPassword([]byte("secret"), bcrypt.MinCost) + if err != nil { + t.Fatal(err) + } + for _, status := range []int{1, 2, 3} { + user := &User{ID: 7, Username: "business", Password: string(hash), Enable: 1, BusinessStatus: status} + security := NewSecurityUsecase(&authenticationSecurityRepo{}, &authenticationCache{}, &authenticationSettings{}, nil) + uc := NewAuthenticationUsecase(NewUserUsecase(&authenticationUserRepo{user: user}), security, &authenticationIssuer{}, nil) + if _, err := uc.Login(context.Background(), &LoginAttempt{Username: "business", Password: "secret", IP: "127.0.0.1"}); !errors.Is(err, ErrUserDisabled) { + t.Fatalf("审核状态 %d 的登录应被拒绝: %v", status, err) + } + if _, err := uc.currentTokenUser(context.Background(), &AuthClaims{ID: 7, Username: "business", UUID: "uuid", IssuedAt: time.Now()}); !errors.Is(err, ErrUserDisabled) { + t.Fatalf("审核状态 %d 的现有会话应被拒绝: %v", status, err) + } + } +} diff --git a/internal/biz/system/user.go b/internal/biz/system/user.go index 99ffc2b..aa1aa84 100644 --- a/internal/biz/system/user.go +++ b/internal/biz/system/user.go @@ -29,6 +29,14 @@ type User struct { OriginSetting map[string]any MustChangePassword bool PasswordUpdatedAt *time.Time + // 商务资料与系统身份共用主键;平台商务 ID 另由绑定关系持有。 + Level int + ParentID uint + IDPath string + RealName string + QQNumber string + BusinessStatus int + RejectReason string } type UserListFilter struct { Username, NickName, Phone, Email, OrderKey string diff --git a/internal/data/business/migrations.go b/internal/data/business/migrations.go new file mode 100644 index 0000000..f1df307 --- /dev/null +++ b/internal/data/business/migrations.go @@ -0,0 +1,31 @@ +package business + +import ( + "gorm.io/gorm" + "kra/pkg/database/migration" +) + +func Migrations() []migration.Step { + return []migration.Step{{ID: "202611030001_business_preference", Migrate: func(db *gorm.DB) error { + // 旧表沿用;已迁移数据库不重建或重置用户偏好。 + if err := migration.CreateMissingTables(db, &preferencePO{}); err != nil { + return err + } + if !db.Migrator().HasTable("sys_authorities") || !db.Migrator().HasTable("casbin_rule") { + return nil + } + return db.Transaction(func(tx *gorm.DB) error { + // 两个接口仅操作当前身份,旧系统对所有已登录用户开放。 + for _, method := range []string{"GET", "PUT"} { + if err := tx.Exec(`INSERT INTO casbin_rule (ptype,v0,v1,v2,v3,v4,v5) + SELECT 'p', a.authority_id, ?, ?, '', '', '' FROM sys_authorities a + WHERE a.deleted_at IS NULL AND NOT EXISTS ( + SELECT 1 FROM casbin_rule p WHERE p.ptype='p' AND p.v0=a.authority_id AND p.v1=? AND p.v2=?)`, + "/sw/user/preference", method, "/sw/user/preference", method).Error; err != nil { + return err + } + } + return nil + }) + }}} +} diff --git a/internal/data/business/preference.go b/internal/data/business/preference.go new file mode 100644 index 0000000..38866d0 --- /dev/null +++ b/internal/data/business/preference.go @@ -0,0 +1,62 @@ +package business + +import ( + "context" + "errors" + "time" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "kra/internal/biz/business" +) + +// Provider 复用 Data 持有的连接,不在仓储中创建数据库客户端。 +type Provider interface{ DB() *gorm.DB } + +type preferencePO struct { + UserID uint `gorm:"primaryKey;autoIncrement:false"` + IncludeSubPromote *int + IDCardDedup *int `gorm:"column:idcard_dedup"` + UpdateTime time.Time +} + +func (preferencePO) TableName() string { return "sys_user_preference" } + +type userPreferenceRepo struct{ data Provider } + +func NewUserPreferenceRepo(data Provider) business.UserPreferenceRepo { + return &userPreferenceRepo{data: data} +} + +func (r *userPreferenceRepo) Find(ctx context.Context, id uint) (*business.UserPreference, error) { + var po preferencePO + err := r.data.DB().WithContext(ctx).First(&po, "user_id = ?", id).Error + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + if err != nil { + return nil, business.ErrStorage + } + return &business.UserPreference{ + IncludeSubPromote: po.IncludeSubPromote == nil || *po.IncludeSubPromote != 0, + IDCardDedup: po.IDCardDedup == nil || *po.IDCardDedup != 0, + }, nil +} + +func (r *userPreferenceRepo) Save(ctx context.Context, id uint, pref business.UserPreference) error { + include, dedup := 0, 0 + if pref.IncludeSubPromote { + include = 1 + } + if pref.IDCardDedup { + dedup = 1 + } + po := preferencePO{UserID: id, IncludeSubPromote: &include, IDCardDedup: &dedup, UpdateTime: time.Now()} + if err := r.data.DB().WithContext(ctx).Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "user_id"}}, + DoUpdates: clause.AssignmentColumns([]string{"include_sub_promote", "idcard_dedup", "update_time"}), + }).Create(&po).Error; err != nil { + return business.ErrStorage + } + return nil +} diff --git a/internal/data/business/preference_test.go b/internal/data/business/preference_test.go new file mode 100644 index 0000000..42b6b0b --- /dev/null +++ b/internal/data/business/preference_test.go @@ -0,0 +1,72 @@ +package business + +import ( + "context" + "github.com/glebarez/sqlite" + "gorm.io/gorm" + "kra/internal/biz/business" + "path/filepath" + "testing" +) + +type testData struct{ db *gorm.DB } + +func (d testData) DB() *gorm.DB { return d.db } + +func openTestDB(t *testing.T) *gorm.DB { + t.Helper() + db, err := gorm.Open(sqlite.Open(filepath.Join(t.TempDir(), "business.db")), &gorm.Config{}) + if err != nil { + t.Fatal(err) + } + sqlDB, err := db.DB() + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = sqlDB.Close() }) + for _, step := range Migrations() { + if err := step.Migrate(db); err != nil { + t.Fatal(err) + } + } + return db +} + +func TestPreferencePreservesLegacyValuesAndUpserts(t *testing.T) { + db := openTestDB(t) + r := NewUserPreferenceRepo(testData{db}) + ctx := context.Background() + if pref, err := r.Find(ctx, 5); err != nil || pref != nil { + t.Fatalf("缺省记录错误: %+v %v", pref, err) + } + if err := db.Exec("INSERT INTO sys_user_preference(user_id,include_sub_promote,idcard_dedup) VALUES (5,NULL,2),(6,1,1)").Error; err != nil { + t.Fatal(err) + } + pref, err := r.Find(ctx, 5) + if err != nil || !pref.IncludeSubPromote || !pref.IDCardDedup { + t.Fatalf("旧 NULL 和非零值应为开启: %+v %v", pref, err) + } + for i := 0; i < 2; i++ { + if err := r.Save(ctx, 5, business.UserPreference{}); err != nil { + t.Fatal(err) + } + } + for _, step := range Migrations() { + if err := step.Migrate(db); err != nil { + t.Fatal(err) + } + } + pref, err = r.Find(ctx, 5) + if err != nil || pref.IncludeSubPromote || pref.IDCardDedup { + t.Fatalf("重复迁移不能重置偏好: %+v %v", pref, err) + } + other, err := r.Find(ctx, 6) + if err != nil || !other.IncludeSubPromote || !other.IDCardDedup { + t.Fatalf("影响其他用户: %+v %v", other, err) + } + var count int64 + db.Model(&preferencePO{}).Where("user_id = ?", 5).Count(&count) + if count != 1 { + t.Fatalf("重复写入产生多条记录: %d", count) + } +} diff --git a/internal/data/data.go b/internal/data/data.go index 5e081e6..aeeb797 100644 --- a/internal/data/data.go +++ b/internal/data/data.go @@ -13,6 +13,7 @@ import ( "go.mongodb.org/mongo-driver/mongo" "gorm.io/gorm" "kra/internal/config" + databusiness "kra/internal/data/business" dataintegration "kra/internal/data/integration" datapayment "kra/internal/data/payment" datasystem "kra/internal/data/system" @@ -25,6 +26,8 @@ import ( var ProviderSet = wire.NewSet( NewData, + wire.Bind(new(databusiness.Provider), new(*Data)), + databusiness.NewUserPreferenceRepo, NewIntegrationRuntime, wire.Bind(new(datasystem.Provider), new(*Data)), wire.Bind(new(datasystem.DatabaseProvider), new(*Data)), diff --git a/internal/data/migrations_test.go b/internal/data/migrations_test.go index 8dee21b..bf3ea42 100644 --- a/internal/data/migrations_test.go +++ b/internal/data/migrations_test.go @@ -34,8 +34,8 @@ func TestMigrateAllRunsModuleSchemasWithoutBootstrapSeed(t *testing.T) { if err = db.Table(migration.TableName).Count(&versions).Error; err != nil { t.Fatal(err) } - if versions != 14 { - t.Fatalf("migration versions = %d, want 14", versions) + if versions != 16 { + t.Fatalf("migration versions = %d, want 16", versions) } var communicationRows []dataintegration.ConfigPO if err = db.Where("kind IN ?", []string{"mq", "websocket"}).Order("kind, provider").Find(&communicationRows).Error; err != nil { diff --git a/internal/data/system/authority.go b/internal/data/system/authority.go index 44c1f81..c5f3f3c 100644 --- a/internal/data/system/authority.go +++ b/internal/data/system/authority.go @@ -178,7 +178,7 @@ func (r *authorityAccessRepo) CreateAuthority(ctx context.Context, value *system value.Menus = nil } } - defaults := []struct{ path, method string }{{"/menu/getMenu", "POST"}, {"/jwt/jsonInBlacklist", "POST"}, {"/base/login", "POST"}, {"/user/changePassword", "POST"}, {"/user/setUserAuthority", "POST"}, {"/user/getUserInfo", "GET"}, {"/user/setSelfInfo", "PUT"}, {"/fileUploadAndDownload/upload", "POST"}, {"/sysDictionary/findSysDictionary", "GET"}} + defaults := []struct{ path, method string }{{"/sw/user/preference", "GET"}, {"/sw/user/preference", "PUT"}, {"/menu/getMenu", "POST"}, {"/jwt/jsonInBlacklist", "POST"}, {"/base/login", "POST"}, {"/user/changePassword", "POST"}, {"/user/setUserAuthority", "POST"}, {"/user/getUserInfo", "GET"}, {"/user/setSelfInfo", "PUT"}, {"/fileUploadAndDownload/upload", "POST"}, {"/sysDictionary/findSysDictionary", "GET"}} rules := make([]casbinRulePO, 0, len(defaults)) for _, item := range defaults { if strict { diff --git a/internal/data/system/business_fields_test.go b/internal/data/system/business_fields_test.go new file mode 100644 index 0000000..0f024d3 --- /dev/null +++ b/internal/data/system/business_fields_test.go @@ -0,0 +1,31 @@ +package system + +import ( + "context" + "testing" +) + +func TestBusinessFieldsSurviveMigrationAndIdentityLoad(t *testing.T) { + db, err := openWithDriver("sqlite", "file:"+t.Name()+"?mode=memory&cache=shared") + if err != nil { + t.Fatal(err) + } + if err = migrateAll(db); err != nil { + t.Fatal(err) + } + po := userPO{Username: "business", UUID: "business-uuid", Password: "original-hash", Enable: 1, Level: 2, ParentID: 11, IDPath: "0,11", RealName: "商务姓名", QQNumber: "12345", BusinessStatus: 3, RejectReason: "审核资料"} + if err = db.Create(&po).Error; err != nil { + t.Fatal(err) + } + if err = ensureBusinessUserFields(db); err != nil { + t.Fatal(err) + } + r := NewUserRepo(&Data{gormDB: newReloadableDB(db, nil)}) + user, err := r.FindUserByUUID(context.Background(), "business-uuid") + if err != nil { + t.Fatal(err) + } + if user.Level != 2 || user.ParentID != 11 || user.IDPath != "0,11" || user.RealName != "商务姓名" || user.QQNumber != "12345" || user.BusinessStatus != 3 || user.RejectReason != "审核资料" || user.Password != "original-hash" { + t.Fatalf("迁移或身份加载丢失商务字段: %+v", user) + } +} diff --git a/internal/data/system/migrations.go b/internal/data/system/migrations.go index 40520f6..ba18591 100644 --- a/internal/data/system/migrations.go +++ b/internal/data/system/migrations.go @@ -30,9 +30,25 @@ func Migrations() []migration.Step { }, {ID: "202608210002_communication_surface", Migrate: ensureCommunicationSurface}, {ID: "202608210003_communication_test_surface", Migrate: ensureCommunicationTestSurface}, + {ID: "202611030002_business_user_fields", Migrate: ensureBusinessUserFields}, } } +func ensureBusinessUserFields(db *gorm.DB) error { + // 与已交付迁移 SQL 的字段保持一致,仅补缺列,保留导入值和密码。 + for _, field := range []string{"Level", "ParentID", "IDPath", "RealName", "QQNumber", "BusinessStatus", "RejectReason"} { + if !db.Migrator().HasColumn(&userPO{}, field) { + if err := db.Migrator().AddColumn(&userPO{}, field); err != nil { + return err + } + } + } + if !db.Migrator().HasIndex(&userPO{}, "idx_sys_users_business_parent") { + return db.Migrator().CreateIndex(&userPO{}, "idx_sys_users_business_parent") + } + return nil +} + // Kept as a migration version for existing installations; the canonical // communication surface seeder is idempotent and now owns the test endpoint. func ensureCommunicationTestSurface(db *gorm.DB) error { return ensureCommunicationSurface(db) } diff --git a/internal/data/system/models.go b/internal/data/system/models.go index 68aa2ab..1ba4365 100644 --- a/internal/data/system/models.go +++ b/internal/data/system/models.go @@ -25,6 +25,13 @@ type userPO struct { OriginSetting string `gorm:"type:text"` PasswordUpdatedAt *time.Time MustChangePassword bool + Level int `gorm:"type:tinyint unsigned;not null;default:0"` + ParentID uint `gorm:"not null;default:0;index:idx_sys_users_business_parent"` + IDPath string `gorm:"column:id_path;size:255;not null;default:0"` + RealName string `gorm:"size:30;not null;default:''"` + QQNumber string `gorm:"column:qq_number;size:20;not null;default:''"` + BusinessStatus int `gorm:"type:tinyint unsigned;not null;default:0"` + RejectReason string `gorm:"size:200;not null;default:''"` } func (userPO) TableName() string { return "sys_users" } diff --git a/internal/data/system/user.go b/internal/data/system/user.go index 921e9ae..05d1a51 100644 --- a/internal/data/system/user.go +++ b/internal/data/system/user.go @@ -93,7 +93,7 @@ func (r *userRepo) loadUser(ctx context.Context, po *userPO) (*system.User, erro for _, item := range positionPOs { positions = append(positions, *posFromPO(item)) } - return &system.User{ID: po.ID, CreatedAt: po.CreatedAt, UpdatedAt: po.UpdatedAt, UUID: po.UUID, Username: po.Username, Password: po.Password, NickName: po.NickName, HeaderImg: po.HeaderImg, AuthorityID: po.AuthorityID, Authority: toBizAuthority(authority), Authorities: authorities, DeptID: po.DeptID, Department: primary, Departments: departments, Positions: positions, Phone: po.Phone, Email: po.Email, Enable: po.Enable, OriginSetting: setting, MustChangePassword: po.MustChangePassword, PasswordUpdatedAt: po.PasswordUpdatedAt}, nil + return &system.User{ID: po.ID, CreatedAt: po.CreatedAt, UpdatedAt: po.UpdatedAt, UUID: po.UUID, Username: po.Username, Password: po.Password, NickName: po.NickName, HeaderImg: po.HeaderImg, AuthorityID: po.AuthorityID, Authority: toBizAuthority(authority), Authorities: authorities, DeptID: po.DeptID, Department: primary, Departments: departments, Positions: positions, Phone: po.Phone, Email: po.Email, Enable: po.Enable, OriginSetting: setting, MustChangePassword: po.MustChangePassword, PasswordUpdatedAt: po.PasswordUpdatedAt, Level: po.Level, ParentID: po.ParentID, IDPath: po.IDPath, RealName: po.RealName, QQNumber: po.QQNumber, BusinessStatus: po.BusinessStatus, RejectReason: po.RejectReason}, nil } func toBizAuthority(po authorityPO) system.Authority { @@ -116,7 +116,7 @@ func baseBizUser(po *userPO) (*system.User, error) { if err != nil { return nil, err } - return &system.User{ID: po.ID, CreatedAt: po.CreatedAt, UpdatedAt: po.UpdatedAt, UUID: po.UUID, Username: po.Username, Password: po.Password, NickName: po.NickName, HeaderImg: po.HeaderImg, AuthorityID: po.AuthorityID, DeptID: po.DeptID, Phone: po.Phone, Email: po.Email, Enable: po.Enable, OriginSetting: setting, MustChangePassword: po.MustChangePassword, PasswordUpdatedAt: po.PasswordUpdatedAt}, nil + return &system.User{ID: po.ID, CreatedAt: po.CreatedAt, UpdatedAt: po.UpdatedAt, UUID: po.UUID, Username: po.Username, Password: po.Password, NickName: po.NickName, HeaderImg: po.HeaderImg, AuthorityID: po.AuthorityID, DeptID: po.DeptID, Phone: po.Phone, Email: po.Email, Enable: po.Enable, OriginSetting: setting, MustChangePassword: po.MustChangePassword, PasswordUpdatedAt: po.PasswordUpdatedAt, Level: po.Level, ParentID: po.ParentID, IDPath: po.IDPath, RealName: po.RealName, QQNumber: po.QQNumber, BusinessStatus: po.BusinessStatus, RejectReason: po.RejectReason}, nil } func (r *userRepo) loadUsers(ctx context.Context, pos []userPO) ([]*system.User, error) { diff --git a/internal/modules/business/definition.go b/internal/modules/business/definition.go new file mode 100644 index 0000000..19a8caf --- /dev/null +++ b/internal/modules/business/definition.go @@ -0,0 +1,13 @@ +package business + +import ( + databusiness "kra/internal/data/business" + "kra/internal/modules/surface" + "kra/pkg/module" +) + +func Definition() module.Definition { + return module.Definition{Name: "business", Migrations: databusiness.Migrations(), Surface: module.Surface{ + APIs: surface.APIsForPrefix("/sw/", 0), + }} +} diff --git a/internal/modules/catalog.go b/internal/modules/catalog.go index 73681da..8148606 100644 --- a/internal/modules/catalog.go +++ b/internal/modules/catalog.go @@ -4,6 +4,7 @@ package modules import ( + businessmodule "kra/internal/modules/business" integrationmodule "kra/internal/modules/integration" paymentmodule "kra/internal/modules/payment" systemmodule "kra/internal/modules/system" @@ -20,5 +21,6 @@ func Catalog() module.Catalog { integrationmodule.Definition(), taskmodule.Definition(), paymentmodule.Definition(), + businessmodule.Definition(), }} } diff --git a/internal/modules/catalog_test.go b/internal/modules/catalog_test.go index fd9167f..f9c4d73 100644 --- a/internal/modules/catalog_test.go +++ b/internal/modules/catalog_test.go @@ -16,25 +16,25 @@ func TestCatalogMigrationIDsAreUnique(t *testing.T) { func TestCatalogContainsBuiltInModulesInDependencyOrder(t *testing.T) { catalog := Catalog() - if len(catalog.Definitions) != 4 { - t.Fatalf("definitions = %d, want 4", len(catalog.Definitions)) + if len(catalog.Definitions) != 5 { + t.Fatalf("definitions = %d, want 5", len(catalog.Definitions)) } - want := []string{"system", "integration", "task", "payment"} + want := []string{"system", "integration", "task", "payment", "business"} for index, name := range want { if got := catalog.Definitions[index].Name; got != name { t.Fatalf("definition[%d] = %q, want %q", index, got, name) } } - if got := catalog.MigrationSteps(); len(got) != 14 { - t.Fatalf("module migrations = %d, want 14", len(got)) + if got := catalog.MigrationSteps(); len(got) != 16 { + t.Fatalf("module migrations = %d, want 16", len(got)) } var menus, apis int for _, definition := range catalog.Definitions { menus += len(definition.Surface.Menus) apis += len(definition.Surface.APIs) } - if menus != 4 || apis != 18 { - t.Fatalf("admin surface = %d menus/%d APIs, want 4/18", menus, apis) + if menus != 4 || apis != 20 { + t.Fatalf("admin surface = %d menus/%d APIs, want 4/20", menus, apis) } if got := catalog.DefaultTimedTasks(); len(got) != 2 { t.Fatalf("default timed tasks = %d, want 2", len(got)) diff --git a/internal/routecatalog/catalog.go b/internal/routecatalog/catalog.go index cec3f31..db82a9c 100644 --- a/internal/routecatalog/catalog.go +++ b/internal/routecatalog/catalog.go @@ -41,6 +41,8 @@ type routeValue struct { // Gin router files still bind handlers; tests keep those registrations aligned // with this catalog while public, audit and API metadata live only here. var routes = map[string]routeValue{ + "GET /sw/user/preference": {group: "商务偏好", description: "获取当前用户商务偏好"}, + "PUT /sw/user/preference": {group: "商务偏好", description: "更新当前用户商务偏好", audit: true}, "DELETE /api/deleteApisByIds": {group: "api", description: "批量删除api", audit: true}, "DELETE /dataAccessLog/deleteDataAccessLogByIds": {group: "数据权限审计", description: "批量删除数据权限审计日志", audit: true}, "DELETE /department/deleteDepartment": {group: "部门", description: "删除部门", audit: true}, diff --git a/internal/server/gin_test.go b/internal/server/gin_test.go index fe35134..5277b96 100644 --- a/internal/server/gin_test.go +++ b/internal/server/gin_test.go @@ -26,6 +26,7 @@ func NewGinEngine(runtime *config.Store, access *systemservice.AccessControlServ func emptyHandlers() *handler.Set { return &handler.Set{ + Business: &handler.Business{}, Authority: &handler.Authority{}, Menu: &handler.Menu{}, API: &handler.API{}, Permission: &handler.Permission{}, Organization: &handler.Organization{}, Announcement: &handler.Announcement{}, Email: &handler.Email{}, Payment: &handler.Payment{}, Task: &handler.Task{}, @@ -97,7 +98,7 @@ func TestGinStartupLogsEveryRegisteredRoute(t *testing.T) { if got, want := strings.Count(text, `"msg":"router registered"`), len(engine.Routes()); got != want { t.Fatalf("registered route log count = %d, want %d", got, want) } - if !strings.Contains(text, `"msg":"router register success"`) || !strings.Contains(text, `"route_count":197`) { + if !strings.Contains(text, `"msg":"router register success"`) || !strings.Contains(text, `"route_count":199`) { t.Fatalf("startup route summary is missing: %s", text) } } diff --git a/internal/server/handler/business.go b/internal/server/handler/business.go new file mode 100644 index 0000000..f2e63b8 --- /dev/null +++ b/internal/server/handler/business.go @@ -0,0 +1,38 @@ +package handler + +import ( + "github.com/gin-gonic/gin" + "github.com/go-kratos/kratos/v3/errors" + "kra/internal/service/business" + "kra/internal/service/dto" +) + +type Business struct { + preference *business.UserPreferenceService +} + +func NewBusiness(preference *business.UserPreferenceService) *Business { + return &Business{preference: preference} +} + +func (h *Business) UserPreference(c *gin.Context) { + value, err := h.preference.Current(c.Request.Context()) + if err != nil { + Fail(c, errors.FromError(err).Message) + return + } + OKWithData(c, value) +} + +func (h *Business) UpdateUserPreference(c *gin.Context) { + var req dto.UserPreferenceRequest + if err := c.ShouldBindJSON(&req); err != nil { + Fail(c, "偏好参数格式错误") + return + } + if err := h.preference.UpdateCurrent(c.Request.Context(), &req); err != nil { + Fail(c, errors.FromError(err).Message) + return + } + OK(c) +} diff --git a/internal/server/handler/provider.go b/internal/server/handler/provider.go index 26cf638..ba3116c 100644 --- a/internal/server/handler/provider.go +++ b/internal/server/handler/provider.go @@ -5,6 +5,7 @@ import "github.com/google/wire" // ProviderSet wires the system HTTP handlers. Set itself is filled field by // field so adding a handler only means adding its constructor here. var ProviderSet = wire.NewSet( + NewBusiness, NewAuthority, NewMenu, NewAPI, NewPermission, NewOrganization, NewAnnouncement, NewEmail, NewPayment, NewTask, NewMedia, NewAudit, NewExport, NewVersion, NewDictionary, NewParameter, NewAPIToken, diff --git a/internal/server/handler/set.go b/internal/server/handler/set.go index 2008638..373b023 100644 --- a/internal/server/handler/set.go +++ b/internal/server/handler/set.go @@ -1,6 +1,7 @@ package handler type Set struct { + Business *Business SMS *SMS Authority *Authority Menu *Menu diff --git a/internal/server/router/business.go b/internal/server/router/business.go new file mode 100644 index 0000000..254c08f --- /dev/null +++ b/internal/server/router/business.go @@ -0,0 +1,11 @@ +package router + +import ( + "github.com/gin-gonic/gin" + "kra/internal/server/handler" +) + +func RegisterBusiness(private *gin.RouterGroup, h *handler.Business) { + private.GET("/sw/user/preference", h.UserPreference) + private.PUT("/sw/user/preference", h.UpdateUserPreference) +} diff --git a/internal/server/router/routes.go b/internal/server/router/routes.go index f9bc138..3779207 100644 --- a/internal/server/router/routes.go +++ b/internal/server/router/routes.go @@ -20,6 +20,7 @@ func (r *Routes) RegisterRoutes(public, private *gin.RouterGroup, engine *gin.En return } registrations := []func(){ + func() { RegisterBusiness(private, r.handlers.Business) }, func() { RegisterPublic(public, engine, r.handlers.Public) }, func() { RegisterUser(private, r.handlers.User) }, func() { RegisterNavigation(private, r.handlers.Navigation) }, diff --git a/internal/service/business/preference.go b/internal/service/business/preference.go new file mode 100644 index 0000000..0410f62 --- /dev/null +++ b/internal/service/business/preference.go @@ -0,0 +1,33 @@ +package business + +import ( + "context" + "kra/internal/biz/business" + "kra/internal/service/dto" +) + +type PreferenceUsecase interface { + Current(context.Context) (*business.UserPreference, error) + UpdateCurrent(context.Context, business.UserPreference) error +} + +type UserPreferenceService struct{ uc PreferenceUsecase } + +func NewUserPreferenceService(uc *business.UserPreferenceUsecase) *UserPreferenceService { + return &UserPreferenceService{uc: uc} +} + +func (s *UserPreferenceService) Current(ctx context.Context) (*dto.UserPreferenceResponse, error) { + pref, err := s.uc.Current(ctx) + if err != nil { + return nil, err + } + return &dto.UserPreferenceResponse{IncludeSubPromote: pref.IncludeSubPromote, IDCardDedup: pref.IDCardDedup}, nil +} + +func (s *UserPreferenceService) UpdateCurrent(ctx context.Context, req *dto.UserPreferenceRequest) error { + if req == nil || req.IncludeSubPromote == nil || req.IDCardDedup == nil { + return business.ErrPreferenceRequired + } + return s.uc.UpdateCurrent(ctx, business.UserPreference{IncludeSubPromote: *req.IncludeSubPromote, IDCardDedup: *req.IDCardDedup}) +} diff --git a/internal/service/business/preference_test.go b/internal/service/business/preference_test.go new file mode 100644 index 0000000..215ff5e --- /dev/null +++ b/internal/service/business/preference_test.go @@ -0,0 +1,42 @@ +package business + +import ( + "context" + "kra/internal/biz/business" + "kra/internal/service/dto" + "testing" +) + +type preferenceFake struct { + calls int + value business.UserPreference +} + +func (f *preferenceFake) Current(context.Context) (*business.UserPreference, error) { + return &f.value, nil +} +func (f *preferenceFake) UpdateCurrent(_ context.Context, p business.UserPreference) error { + f.calls++ + f.value = p + return nil +} + +func TestPreferenceRequiresBothFieldsButAcceptsFalse(t *testing.T) { + f := &preferenceFake{} + s := &UserPreferenceService{uc: f} + off := false + for _, req := range []*dto.UserPreferenceRequest{nil, {}, {IncludeSubPromote: &off}, {IDCardDedup: &off}} { + if err := s.UpdateCurrent(context.Background(), req); err != business.ErrPreferenceRequired { + t.Fatalf("缺字段应被拒绝: %v", err) + } + } + if f.calls != 0 { + t.Fatal("校验失败后不应调用用例") + } + if err := s.UpdateCurrent(context.Background(), &dto.UserPreferenceRequest{IncludeSubPromote: &off, IDCardDedup: &off}); err != nil { + t.Fatal(err) + } + if f.calls != 1 || f.value.IncludeSubPromote || f.value.IDCardDedup { + t.Fatalf("false 值未完整传递: %+v", f) + } +} diff --git a/internal/service/dto/business.go b/internal/service/dto/business.go new file mode 100644 index 0000000..e027883 --- /dev/null +++ b/internal/service/dto/business.go @@ -0,0 +1,11 @@ +package dto + +type UserPreferenceRequest struct { + IncludeSubPromote *bool `json:"includeSubPromote"` + IDCardDedup *bool `json:"idcardDedup"` +} + +type UserPreferenceResponse struct { + IncludeSubPromote bool `json:"includeSubPromote"` + IDCardDedup bool `json:"idcardDedup"` +} diff --git a/internal/service/dto/system.go b/internal/service/dto/system.go index c164429..0f17123 100644 --- a/internal/service/dto/system.go +++ b/internal/service/dto/system.go @@ -73,6 +73,13 @@ type SwitchAuthorityRequest struct { } type UserResponse struct { + Level int `json:"level"` + ParentID uint `json:"parentId"` + IDPath string `json:"idPath"` + RealName string `json:"realName"` + QQNumber string `json:"qqNumber"` + BusinessStatus int `json:"businessStatus"` + RejectReason string `json:"rejectReason"` ID uint `json:"ID"` CreatedAt time.Time `json:"CreatedAt"` UpdatedAt time.Time `json:"UpdatedAt"` diff --git a/internal/service/service.go b/internal/service/service.go index 6f1df60..04d46b0 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -1,6 +1,7 @@ package service import ( + businessservice "kra/internal/service/business" integrationservice "kra/internal/service/integration" paymentservice "kra/internal/service/payment" systemservice "kra/internal/service/system" @@ -11,6 +12,7 @@ import ( // ProviderSet aggregates all service modules for Wire. var ProviderSet = wire.NewSet( + businessservice.NewUserPreferenceService, systemservice.ProviderSet, paymentservice.ProviderSet, integrationservice.ProviderSet, diff --git a/internal/service/system/user_conversion.go b/internal/service/system/user_conversion.go index 8eef6b4..388a985 100644 --- a/internal/service/system/user_conversion.go +++ b/internal/service/system/user_conversion.go @@ -40,5 +40,5 @@ func convertUser(user *system.User) *dto.UserResponse { if user.Department != nil { department = departmentResponse(user.Department) } - return &dto.UserResponse{ID: user.ID, CreatedAt: user.CreatedAt, UpdatedAt: user.UpdatedAt, UUID: user.UUID, Username: user.Username, NickName: user.NickName, HeaderImg: user.HeaderImg, AuthorityID: user.AuthorityID, Authority: convertAuthority(user.Authority), Authorities: authorities, DeptID: user.DeptID, Department: department, Departments: departments, Positions: positions, Phone: user.Phone, Email: user.Email, Enable: user.Enable, OriginSetting: user.OriginSetting, PasswordUpdatedAt: user.PasswordUpdatedAt} + return &dto.UserResponse{ID: user.ID, CreatedAt: user.CreatedAt, UpdatedAt: user.UpdatedAt, UUID: user.UUID, Username: user.Username, NickName: user.NickName, HeaderImg: user.HeaderImg, AuthorityID: user.AuthorityID, Authority: convertAuthority(user.Authority), Authorities: authorities, DeptID: user.DeptID, Department: department, Departments: departments, Positions: positions, Phone: user.Phone, Email: user.Email, Enable: user.Enable, OriginSetting: user.OriginSetting, PasswordUpdatedAt: user.PasswordUpdatedAt, Level: user.Level, ParentID: user.ParentID, IDPath: user.IDPath, RealName: user.RealName, QQNumber: user.QQNumber, BusinessStatus: user.BusinessStatus, RejectReason: user.RejectReason} } diff --git a/scripts/sw_migration_inventory.py b/scripts/sw_migration_inventory.py new file mode 100644 index 0000000..5e98953 --- /dev/null +++ b/scripts/sw_migration_inventory.py @@ -0,0 +1,48 @@ +"""从指定旧仓库和现有迁移 SQL 生成可复核的迁移清单,不访问数据库。""" + +import argparse +import hashlib +import json +import re +import subprocess +from pathlib import Path + + +def git(repo, *args): + return subprocess.check_output(["git", "-C", str(repo), *args], text=True, encoding="utf-8").strip() + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--source", required=True, type=Path) + parser.add_argument("--baseline", default="d31082f4a7816d4c83544b8f54e6f42a3b2132b1") + args = parser.parse_args() + root = Path(__file__).resolve().parents[1] + source = args.source.resolve() + sql = (root / "docs/sw6-to-kra/sw_to_kra_migrate.sql").read_text(encoding="utf-8") + contracts = [dict(zip(("method", "source_path", "target_path", "permission", "controller"), row)) + for row in re.findall(r"\('(GET|POST|PUT|DELETE)','([^']+)','([^']+)','([^']+)','([^']+)'\)", sql)] + changes = [] + for path in git(source, "diff", "--name-only", args.baseline, "main").splitlines(): + # 只登记路径与摘要,不把旧配置中的凭据写入新仓库。 + if not (path.endswith(".java") or "/mapper/" in path and path.endswith(".xml")): + continue + file = source / path + changes.append({"path": path, "exists": file.is_file(), + "sha256": hashlib.sha256(file.read_bytes()).hexdigest() if file.is_file() else None}) + custom = [] + for file in sorted((source / "ruoyi-admin/src/main/java").rglob("*Controller.java")): + text = file.read_text(encoding="utf-8") + if file.name == "ForgotPasswordController.java": + custom.append({"path": file.relative_to(source).as_posix(), "source": text}) + result = {"baseline": args.baseline, "backend_head": git(source, "rev-parse", "main"), + "frontend_head": git(source / "web", "rev-parse", "dev/dev1.0"), + "contracts": contracts, "changed_sources": changes, + "additional_controllers": [item["path"] for item in custom]} + target = root / "docs/sw6-to-kra/source-inventory.json" + target.write_text(json.dumps(result, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") + print(f"已登记 {len(contracts)} 个 SQL 接口契约、{len(changes)} 个变更源文件。") + + +if __name__ == "__main__": + main() diff --git a/web/src/api/business.js b/web/src/api/business.js new file mode 100644 index 0000000..fabc142 --- /dev/null +++ b/web/src/api/business.js @@ -0,0 +1,4 @@ +import service from '@/utils/request' + +export const getUserPreference = () => service({ url: '/sw/user/preference', method: 'get' }) +export const updateUserPreference = (data) => service({ url: '/sw/user/preference', method: 'put', data }) diff --git a/web/src/components/businessPreference/index.vue b/web/src/components/businessPreference/index.vue new file mode 100644 index 0000000..3c3ab5b --- /dev/null +++ b/web/src/components/businessPreference/index.vue @@ -0,0 +1,61 @@ + + + diff --git a/web/src/view/layout/header/tools.vue b/web/src/view/layout/header/tools.vue index 7a84911..8feafae 100644 --- a/web/src/view/layout/header/tools.vue +++ b/web/src/view/layout/header/tools.vue @@ -1,6 +1,7 @@