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