@@ -0,0 +1,405 @@
// 按「方法名 → 注解」显式白名单写入 @Log(不做 URL 猜配,避免错位)
//
// node bin/checks/set-known-audit-logs.js 干跑
// node bin/checks/set-known-audit-logs.js --apply 落盘
//
// 按钮文案全部取自页面源码原文(每条的来源写在本表注释里,格式:views/xxx.vue:行号):
// 工具条按钮(生成招商账号/一键上架/发放CDK)优先于弹窗里的通用【确 定】——
// 运营的心智是"我点了那颗有名字的按钮",【确 定】记进日志等于没信息。
const fs = require ( 'fs' ) ;
const path = require ( 'path' ) ;
const ROOT = path . resolve ( _ _dirname , '..' , '..' ) ;
const apply = process . argv . includes ( '--apply' ) ;
const A = 'skins-service/service-admin/src/main/java/com/ruoyi/admin/controller/' ;
const W = 'skins-service/game-wheel-service/src/main/java/com/ruoyi/game/wheel/controller/' ;
const O = 'skins-service/game-olympus-service/src/main/java/com/ruoyi/game/olympus/controller/' ;
const TARGETS = [
// ---- 用户列表(ttuser/index.vue:工具条 113/121/129,行内 86/96,下拉 212/218/224) ----
[ A + 'TtUserController.java' , 'generateAccount' , { menu : '用户列表' , action : '生成招商账号' , type : 'INSERT' } ] ,
[ A + 'TtUserController.java' , 'generateRobot' , { menu : '用户列表' , action : '生成机器人' , type : 'INSERT' } ] ,
[ A + 'TtUserController.java' , 'generateBlankAccount' , { menu : '用户列表' , action : '生成白号' , type : 'INSERT' } ] ,
[ A + 'TtUserController.java' , 'generateCardMerchant' , { menu : '用户列表' , action : '生成卡商账号' , type : 'INSERT' } ] ,
[ A + 'TtUserController.java' , 'edit' , { menu : '用户列表' , action : '修改' , type : 'UPDATE' , entity : 'TtUser' , mapper : 'TtUserMapper' } ] ,
[ A + 'TtUserController.java' , 'editInvitationCode' , { menu : '用户列表' , action : '修改邀请码' , type : 'UPDATE' , entity : 'TtUser' , mapper : 'TtUserMapper' } ] ,
[ A + 'TtUserController.java' , 'remove' , { menu : '用户列表' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TtUserController.java' , 'removeUserPackSackData' , { menu : '背包列表' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TtUserController.java' , 'resetUserBalance' , { menu : '用户列表' , action : '重置余额积分' , type : 'CLEAN' , entity : 'TtUser' , mapper : 'TtUserMapper' , idField : 'userId' } ] ,
[ A + 'TtUserController.java' , 'forceDelete' , { menu : '用户列表' , action : '真删除' , type : 'FORCE' } ] ,
// ---- 亏损返水(ttredPacket/lossRebate.vue: 31 保存上限 / 112 发放CDK) ----
[ A + 'LossRebateController.java' , 'grant' , { menu : '亏损返水' , action : '发放CDK' , type : 'GRANT' , entity : 'TtLossRebate' , mapper : 'TtLossRebateMapper' , idField : 'id' } ] ,
[ A + 'LossRebateController.java' , 'saveConfig' , { menu : '亏损返水' , action : '保存上限' , type : 'UPDATE' } ] ,
// ---- 卡商充值(ttCardMerchantRecharge/index.vue: 126 确认充值 / 160 确认修改)----
[ A + 'TtCardMerchantController.java' , 'cardMerchantRecharge' , { menu : '卡商充值' , action : '确认充值' , type : 'GRANT' , entity : 'TtUser' , mapper : 'TtUserMapper' , idField : 'userId' } ] ,
[ A + 'TtCardMerchantController.java' , 'cardMerchantUpdateBalance' , { menu : '卡商充值' , action : '确认修改' , type : 'UPDATE' , entity : 'TtUser' , mapper : 'TtUserMapper' , idField : 'userId' } ] ,
// ---- 生成空白卡密(blankCardKey/index.vue: 5 生成空白卡密 开弹窗)----
[ A + 'AdminBlankCardKeyController.java' , 'generate' , { menu : '生成空白卡密' , action : '生成空白卡密' , type : 'INSERT' } ] ,
// ---- 疯狂转盘 游戏配置(game/wheel/config/index.vue: 8 重置奖池 / 44 调整奖池 / 241 保存)----
[ W + 'AdminWheelController.java' , 'resetPool' , { menu : '游戏配置' , action : '重置奖池' , type : 'CLEAN' } ] ,
[ W + 'AdminWheelController.java' , 'adjustPool' , { menu : '游戏配置' , action : '调整奖池' , type : 'GRANT' } ] ,
[ W + 'AdminWheelController.java' , 'updateGameConfig' , { menu : '游戏配置' , action : '保存' , type : 'UPDATE' } ] ,
// ---- 疯狂转盘 奖励矩阵(game/wheel/prize/index.vue: 79 保存 / 89 全部保存 → saveMatrix) ----
[ W + 'AdminWheelController.java' , 'matrixSave' , { menu : '奖励矩阵' , action : '保存' , type : 'UPDATE' } ] ,
// ---- 商城列表(ttShopping/index.vue: 75 一键下架 / 82 一键上架)----
[ A + 'ShoppingController.java' , 'putAwayAll' , { menu : '商城列表' , action : '一键上架' , type : 'UPDATE' } ] ,
[ A + 'ShoppingController.java' , 'soldOutAll' , { menu : '商城列表' , action : '一键下架' , type : 'UPDATE' } ] ,
// ---- Roll房列表(ttRoll/index.vue: 222 新 增 / 223 修 改 / 120 删除)----
[ A + 'TtRollController.java' , 'add' , { menu : 'Roll房列表' , action : '新增' , type : 'INSERT' , entity : 'TtRoll' , mapper : 'TtRollMapper' } ] ,
[ A + 'TtRollController.java' , 'edit' , { menu : 'Roll房列表' , action : '修改' , type : 'UPDATE' , entity : 'TtRoll' , mapper : 'TtRollMapper' } ] ,
[ A + 'TtRollController.java' , 'remove' , { menu : 'Roll房列表' , action : '删除' , type : 'DELETE' } ] ,
// ---- 抽奖活动(turnoverLottery/list.vue: 43 新增抽奖活动 / 86 修改 / 92 删除)----
[ A + 'TurnoverLotteryAdminController.java' , 'create' , { menu : '抽奖活动' , action : '新增抽奖活动' , type : 'INSERT' } ] ,
[ A + 'TurnoverLotteryAdminController.java' , 'update' , { menu : '抽奖活动' , action : '修改' , type : 'UPDATE' } ] ,
[ A + 'TurnoverLotteryAdminController.java' , 'delete' , { menu : '抽奖活动' , action : '删除' , type : 'DELETE' } ] ,
// ---- 奥林匹斯 奖池水位(game/olympus/rewardPool/index.vue: 101/106 批量注水|抽水、111 重置调整、172/175 行内图标→弹窗 213 确定注水|抽水)----
[ O + 'OlympusAdminController.java' , 'rewardPoolAdjust' , { menu : '奖池水位' , action : '注水/抽水' , type : 'GRANT' } ] ,
[ O + 'OlympusAdminController.java' , 'rewardPoolAdjustBatch' , { menu : '奖池水位' , action : '批量注水/抽水' , type : 'GRANT' } ] ,
[ O + 'OlympusAdminController.java' , 'rewardPoolAdjustReset' , { menu : '奖池水位' , action : '重置调整' , type : 'CLEAN' } ] ,
// ---- 宝箱列表(ttBox/index.vue: 48 新增 / 59 修改 / 70 删除 / 282 重置宝箱)----
[ A + 'TtBoxController.java' , 'add' , { menu : '宝箱列表' , action : '新增' , type : 'INSERT' , entity : 'TtBox' , mapper : 'TtBoxMapper' } ] ,
[ A + 'TtBoxController.java' , 'edit' , { menu : '宝箱列表' , action : '修改' , type : 'UPDATE' } ] ,
[ A + 'TtBoxController.java' , 'remove' , { menu : '宝箱列表' , action : '删除' , type : 'DELETE' } ] ,
// 注意:resetBox 是 @GetMapping,但它改数据(GET 不在常规扫描范围内,这里显式补上)
[ A + 'TtBoxController.java' , 'resetBox' , { menu : '宝箱列表' , action : '重置宝箱' , type : 'CLEAN' , entity : 'TtBox' , mapper : 'TtBoxMapper' , idField : 'boxId' } ] ,
// ---- Roll 奖品/房间(awarddetali.vue: 22 指定获奖者 / 23 取消奖品;rollUser.vue: 10 加入机器人 / 18 加入用户)----
[ A + 'TtRollController.java' , 'namedWinner' , { menu : '装备列表' , action : '指定获奖者' , type : 'INSERT' } ] ,
[ A + 'TtRollController.java' , 'cancelNamedWinner' , { menu : '装备列表' , action : '取消奖品' , type : 'DELETE' } ] ,
[ A + 'TtRollController.java' , 'addRobot' , { menu : '房间用户' , action : '加入机器人' , type : 'INSERT' } ] ,
[ A + 'TtRollController.java' , 'addUser' , { menu : '房间用户' , action : '加入用户' , type : 'INSERT' } ] ,
// ---- 奥林匹斯 箱子配置(game/olympus/box/index.vue: 53 编辑 / 180 保存 / 15+141 一键重算分布 / 179 保存为模板 / 214 应用选中模板 / 207 删除模板)----
[ O + 'OlympusAdminController.java' , 'boxSave' , { menu : '箱子配置' , action : '编辑' , type : 'UPDATE' } ] ,
[ O + 'OlympusAdminController.java' , 'boxOrnamentsSave' , { menu : '箱子配置' , action : '保存' , type : 'UPDATE' } ] ,
[ O + 'OlympusAdminController.java' , 'recalcBatch' , { menu : '箱子配置' , action : '一键重算分布' , type : 'CLEAN' } ] ,
[ O + 'OlympusAdminController.java' , 'templateSave' , { menu : '箱子配置' , action : '保存为模板' , type : 'INSERT' } ] ,
[ O + 'OlympusAdminController.java' , 'templateApply' , { menu : '箱子配置' , action : '应用选中模板' , type : 'UPDATE' } ] ,
[ O + 'OlympusAdminController.java' , 'templateDelete' , { menu : '箱子配置' , action : '删除' , type : 'DELETE' } ] ,
// ---- 奥林匹斯 奖品管理(game/olympus/prize/index.vue: 44 编辑 → 87 确定 → prizeSave) ----
[ O + 'OlympusAdminController.java' , 'prizeSave' , { menu : '奖品管理' , action : '编辑' , type : 'UPDATE' } ] ,
// ---- 消费排行榜奖励(rechargeRankingReward.vue: 5 生成消费奖励 / 23 修改 / 8 重置→handleReset:165) ----
[ A + 'TtRechargeRankingRewardController.java' , 'generatePromotionLevel' , { menu : '消费排行榜奖励' , action : '生成消费奖励' , type : 'UPDATE' } ] ,
[ A + 'TtRechargeRankingRewardController.java' , 'edit' , { menu : '消费排行榜奖励' , action : '修改' , type : 'UPDATE' } ] ,
[ A + 'TtRechargeRankingRewardController.java' , 'truncateRankingReward' , { menu : '消费排行榜奖励' , action : '重置' , type : 'CLEAN' } ] ,
// ---- 对战排行榜奖励(fightRankingReward.vue: 5 生成排名奖励 / 23 修改 / 8 重置→handleReset:167) ----
[ A + 'TtFightRankingRewardController.java' , 'generatePromotionLevel' , { menu : '对战排行榜奖励' , action : '生成排名奖励' , type : 'UPDATE' } ] ,
[ A + 'TtFightRankingRewardController.java' , 'edit' , { menu : '对战排行榜奖励' , action : '修改' , type : 'UPDATE' } ] ,
[ A + 'TtFightRankingRewardController.java' , 'truncateRankingReward' , { menu : '对战排行榜奖励' , action : '重置' , type : 'CLEAN' } ] ,
// ---- 饰品列表(ttOrnaments/index.vue: 58 新增饰品 / 123 编辑 / 125=77 删除 / 117 发放饰品)----
[ A + 'TtOrnamentsController.java' , 'add' , { menu : '饰品列表' , action : '新增饰品' , type : 'INSERT' , entity : 'TtOrnament' , mapper : 'TtOrnamentMapper' } ] ,
[ A + 'TtOrnamentsController.java' , 'edit' , { menu : '饰品列表' , action : '编辑' , type : 'UPDATE' , entity : 'TtOrnament' , mapper : 'TtOrnamentMapper' } ] ,
[ A + 'TtOrnamentsController.java' , 'delete' , { menu : '饰品列表' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TtOrnamentsController.java' , 'grantOrnaments' , { menu : '饰品列表' , action : '发放饰品' , type : 'GRANT' } ] ,
// ================= 以下为"存量旧 JSON 格式"转人话(按钮文案已逐页核实:都是标准 新增/修改/删除)=================
// ---- 福利列表 / 福利开箱记录(ttWelfare/index.vue、welfareBoxRecords.vue) ----
[ A + 'TtWelfareController.java' , 'add' , { menu : '福利列表' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtWelfareController.java' , 'edit' , { menu : '福利列表' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtWelfareController.java' , 'remove' , { menu : '福利列表' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TtWelfareController.java' , 'removeBoxRecords' , { menu : '福利开箱记录' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TtWelfareController.java' , 'clearBoxRecords' , { menu : '福利开箱记录' , action : '清空全部记录' , type : 'CLEAN' } ] ,
// ---- 每月充值福利(monthlyRecharges.vue) ----
[ A + 'TtWelfareMonthlyRechargesController.java' , 'add' , { menu : '每月充值福利' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtWelfareMonthlyRechargesController.java' , 'edit' , { menu : '每月充值福利' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtWelfareMonthlyRechargesController.java' , 'remove' , { menu : '每月充值福利' , action : '删除' , type : 'DELETE' } ] ,
// ---- 首充赠送(ttBonus/firstRecharge.vue) ----
[ A + 'TtFirstRechargeController.java' , 'add' , { menu : '首充赠送' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtFirstRechargeController.java' , 'edit' , { menu : '首充赠送' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtFirstRechargeController.java' , 'remove' , { menu : '首充赠送' , action : '删除' , type : 'DELETE' } ] ,
// ---- CDK管理(ttRedPack/index.vue) ----
[ A + 'TtRedPackController.java' , 'add' , { menu : 'CDK管理' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtRedPackController.java' , 'edit' , { menu : 'CDK管理' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtRedPackController.java' , 'remove' , { menu : 'CDK管理' , action : '删除' , type : 'DELETE' } ] ,
// ---- 汰换记录(ttReplacementRecord/index.vue) ----
[ A + 'TtReplacementRecordController.java' , 'add' , { menu : '汰换记录' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtReplacementRecordController.java' , 'edit' , { menu : '汰换记录' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtReplacementRecordController.java' , 'remove' , { menu : '汰换记录' , action : '删除' , type : 'DELETE' } ] ,
// ---- 机器人对战分组(ttFight/robotFightGroup.vue) ----
[ A + 'TtRobotFightGroupController.java' , 'add' , { menu : '机器人对战分组' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtRobotFightGroupController.java' , 'edit' , { menu : '机器人对战分组' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtRobotFightGroupController.java' , 'remove' , { menu : '机器人对战分组' , action : '删除' , type : 'DELETE' } ] ,
// ---- 机器人对战分组宝箱(ttFight/robotFightGroupBox.vue) ----
[ A + 'TtRobotFightGroupBoxController.java' , 'add' , { menu : '机器人对战分组宝箱' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtRobotFightGroupBoxController.java' , 'edit' , { menu : '机器人对战分组宝箱' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtRobotFightGroupBoxController.java' , 'remove' , { menu : '机器人对战分组宝箱' , action : '删除' , type : 'DELETE' } ] ,
// ---- 机器人对战配置(ttFight/robotFightConfig.vue,两个 controller 共用一页)----
[ A + 'TtRobotFightJoinConfigController.java' , 'add' , { menu : '机器人对战配置' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtRobotFightJoinConfigController.java' , 'edit' , { menu : '机器人对战配置' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtRobotFightJoinConfigController.java' , 'remove' , { menu : '机器人对战配置' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TtRobotFightPriceConfigController.java' , 'add' , { menu : '机器人对战配置' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtRobotFightPriceConfigController.java' , 'edit' , { menu : '机器人对战配置' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtRobotFightPriceConfigController.java' , 'remove' , { menu : '机器人对战配置' , action : '删除' , type : 'DELETE' } ] ,
// ---- 转赠申请(delivery/transferApply.vue:同意 / 驳回 / 确定同意)----
[ A + 'TtTransferApplyController.java' , 'approve' , { menu : '转赠申请' , action : '同意' , type : 'GRANT' } ] ,
[ A + 'TtTransferApplyController.java' , 'reject' , { menu : '转赠申请' , action : '驳回' , type : 'GRANT' } ] ,
[ A + 'TtTransferApplyController.java' , 'approveBatch' , { menu : '转赠申请' , action : '确定同意' , type : 'GRANT' } ] ,
[ A + 'TtTransferApplyController.java' , 'rejectBatch' , { menu : '转赠申请' , action : '驳回' , type : 'GRANT' } ] ,
// ---- 任务列表(ttTaskCenter/index.vue) ----
[ A + 'TtTaskCenterController.java' , 'add' , { menu : '任务列表' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtTaskCenterController.java' , 'edit' , { menu : '任务列表' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtTaskCenterController.java' , 'remove' , { menu : '任务列表' , action : '删除' , type : 'DELETE' } ] ,
// ---- 开箱机会(ttOrnaments/boxOpenChance.vue;库里无同名菜单,用页面功能名)----
[ A + 'TtBoxOpenChanceController.java' , 'add' , { menu : '开箱机会' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtBoxOpenChanceController.java' , 'edit' , { menu : '开箱机会' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtBoxOpenChanceController.java' , 'remove' , { menu : '开箱机会' , action : '删除' , type : 'DELETE' } ] ,
// ================= 其余有按钮证据的页面(标签来自 evidence.js:直接调用方的按钮文案,CRUD 页按工具条 新增/修改/删除)=================
// ---- 公告(ttSetting/announcement.vue) ----
[ A + 'TtAnnouncementController.java' , 'addAnnouncement' , { menu : '公告' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtAnnouncementController.java' , 'editAnnouncement' , { menu : '公告' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtAnnouncementController.java' , 'removeAnnouncementByAnnouncementId' , { menu : '公告' , action : '删除' , type : 'DELETE' } ] ,
// ---- Banner设置 / 彩金 / 文章 / 文章类型 / 宝箱分类(ttSetting/banner.vue, ttBonus/index.vue, contentList, contentType, ttBox/boxType) ----
[ A + 'TtBannerController.java' , 'add' , { menu : 'Banner设置' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtBannerController.java' , 'edit' , { menu : 'Banner设置' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtBannerController.java' , 'remove' , { menu : 'Banner设置' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TtBonusController.java' , 'add' , { menu : '彩金' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtBonusController.java' , 'edit' , { menu : '彩金' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtBonusController.java' , 'remove' , { menu : '彩金' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TtContentController.java' , 'add' , { menu : '文章' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtContentController.java' , 'edit' , { menu : '文章' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtContentController.java' , 'remove' , { menu : '文章' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TtContentTypeController.java' , 'add' , { menu : '文章类型' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtContentTypeController.java' , 'edit' , { menu : '文章类型' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtContentTypeController.java' , 'remove' , { menu : '文章类型' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TtBoxTypeController.java' , 'add' , { menu : '宝箱分类' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtBoxTypeController.java' , 'edit' , { menu : '宝箱分类' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtBoxTypeController.java' , 'remove' , { menu : '宝箱分类' , action : '删除' , type : 'DELETE' } ] ,
// ---- 宝箱饰品(挂在宝箱列表下;批量填货按钮见 ttBox/index.vue:283) ----
[ A + 'TtBoxOrnamentsController.java' , 'add' , { menu : '宝箱列表' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtBoxOrnamentsController.java' , 'edit' , { menu : '宝箱列表' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtBoxOrnamentsController.java' , 'remove' , { menu : '宝箱列表' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TtBoxOrnamentsController.java' , 'batchAdd' , { menu : '宝箱列表' , action : '批量填货' , type : 'INSERT' } ] ,
// ---- 等级类(ttOrnamentsLevel/index.vue, ttSetting/promotionLevel.vue, ttSetting/vips.vue) ----
[ A + 'TtOrnamentsLevelController.java' , 'edit' , { menu : '饰品等级' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtOrnamentsLevelController.java' , 'generateOrnamentsLevel' , { menu : '饰品等级' , action : '新增' , type : 'INSERT' } ] ,
[ A + 'TtPromotionLevelController.java' , 'edit' , { menu : '推广等级设置' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtPromotionLevelController.java' , 'generatePromotionLevel' , { menu : '推广等级设置' , action : '生成推广列表' , type : 'INSERT' } ] ,
[ A + 'TtPromotionLevelController.java' , 'truncateVipLevel' , { menu : '推广等级设置' , action : '重置' , type : 'CLEAN' } ] ,
[ A + 'TtVipLevelController.java' , 'edit' , { menu : 'VIP等级设置' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtVipLevelController.java' , 'generateVipLevel' , { menu : 'VIP等级设置' , action : '生成VIP等级' , type : 'INSERT' } ] ,
[ A + 'TtVipLevelController.java' , 'truncateVipLevel' , { menu : 'VIP等级设置' , action : '重置' , type : 'CLEAN' } ] ,
// ---- 充值/卡密(ttRechargeList/index.vue, ttRechargeRecord? , ttGenerateCard/index.vue:135) ----
[ A + 'TtRechargeListController.java' , 'add' , { menu : '货币列表' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtRechargeListController.java' , 'edit' , { menu : '货币列表' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtRechargeListController.java' , 'remove' , { menu : '货币列表' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TtRechargeConfigController.java' , 'add' , { menu : '网站货币管理' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtRechargeConfigController.java' , 'edit' , { menu : '网站货币管理' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtRechargeConfigController.java' , 'remove' , { menu : '网站货币管理' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TtRechargeCardController.java' , 'generateCard' , { menu : '卡密' , action : '生成卡密' , type : 'INSERT' } ] ,
[ A + 'TtRechargeCardController.java' , 'generateBlankCard' , { menu : '卡密' , action : '生成空白卡密' , type : 'INSERT' } ] ,
// ---- CDK口令 / Roll奖池 / 限时Roll / 官方周期Roll配置 / 奖项配置 ----
[ A + 'TtRedPacketController.java' , 'add' , { menu : 'CDK口令' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtRedPacketController.java' , 'edit' , { menu : 'CDK口令' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtRedPacketController.java' , 'remove' , { menu : 'CDK口令' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TtRollJackpotController.java' , 'add' , { menu : '奖池列表' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtRollJackpotController.java' , 'edit' , { menu : '奖池列表' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtRollJackpotController.java' , 'remove' , { menu : '奖池列表' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TtRollJackpotOrnamentsController.java' , 'add' , { menu : '奖池列表' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtRollJackpotOrnamentsController.java' , 'edit' , { menu : '奖池列表' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtRollJackpotOrnamentsController.java' , 'remove' , { menu : '奖池列表' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TtTimeRollController.java' , 'add' , { menu : '时间roll房' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtTimeRollController.java' , 'edit' , { menu : '时间roll房' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtTimeRollController.java' , 'remove' , { menu : '时间roll房' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TtOfficialRollConfigController.java' , 'add' , { menu : '官方周期Roll配置' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtOfficialRollConfigController.java' , 'edit' , { menu : '官方周期Roll配置' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtOfficialRollConfigController.java' , 'remove' , { menu : '官方周期Roll配置' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TurnoverLotteryPrizeController.java' , 'add' , { menu : '奖项配置' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TurnoverLotteryPrizeController.java' , 'edit' , { menu : '奖项配置' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TurnoverLotteryPrizeController.java' , 'remove' , { menu : '奖项配置' , action : '删除' , type : 'DELETE' } ] ,
// ---- 升级饰品 / 失败奖励(ttUpgrade/index.vue, upgradeFall.vue) ----
[ A + 'TtUpgradeOrnamentsController.java' , 'batchAdd' , { menu : '饰品列表' , action : '新增' , type : 'INSERT' } ] ,
[ A + 'TtUpgradeOrnamentsController.java' , 'edit' , { menu : '饰品列表' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtUpgradeOrnamentsController.java' , 'remove' , { menu : '饰品列表' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TtUpgradeFailOrnamentsController.java' , 'batchAdd' , { menu : '失败奖励' , action : '新增' , type : 'INSERT' } ] ,
[ A + 'TtUpgradeFailOrnamentsController.java' , 'edit' , { menu : '失败奖励' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtUpgradeFailOrnamentsController.java' , 'remove' , { menu : '失败奖励' , action : '删除' , type : 'DELETE' } ] ,
// ---- 头像设置 / 网站道具 / 发货记录 / 商城上下架 / 站点参数 ----
[ A + 'TtUserAvatarController.java' , 'add' , { menu : '头像设置' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'TtUserAvatarController.java' , 'edit' , { menu : '头像设置' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'TtUserAvatarController.java' , 'remove' , { menu : '头像设置' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'WebsitePropertyController.java' , 'add' , { menu : '网站道具' , action : '新增' , type : 'INSERT' , auto : true } ] ,
[ A + 'WebsitePropertyController.java' , 'edit' , { menu : '网站道具' , action : '修改' , type : 'UPDATE' , auto : true } ] ,
[ A + 'WebsitePropertyController.java' , 'remove' , { menu : '网站道具' , action : '删除' , type : 'DELETE' } ] ,
[ A + 'TtDeliveryRecordController.java' , 'deliveryApprove' , { menu : '发货记录' , action : '确认发货' , type : 'GRANT' } ] ,
[ A + 'ShoppingController.java' , 'batchPutAwayOrSoldOut' , { menu : '商城列表' , action : '上架/下架' , type : 'UPDATE' } ] ,
[ A + 'WebsiteSetupController.java' , 'updateParameterSetting' , { menu : '网站设置' , action : '保存' , type : 'UPDATE' } ] ,
// ---- 疯狂转盘 奖励矩阵删除 ----
[ W + 'AdminWheelController.java' , 'matrixDelete' , { menu : '奖励矩阵' , action : '删除' , type : 'DELETE' } ] ,
] ;
const IMPORTS = {
TtUser : 'com.ruoyi.domain.entity.sys.TtUser' ,
TtUserMapper : 'com.ruoyi.admin.mapper.TtUserMapper' ,
TtLossRebate : 'com.ruoyi.domain.entity.TtLossRebate' ,
TtLossRebateMapper : 'com.ruoyi.admin.mapper.TtLossRebateMapper' ,
TtRoll : 'com.ruoyi.domain.entity.roll.TtRoll' ,
TtRollMapper : 'com.ruoyi.admin.mapper.TtRollMapper' ,
TtBox : 'com.ruoyi.domain.other.TtBox' ,
TtBoxMapper : 'com.ruoyi.admin.mapper.TtBoxMapper' ,
TtOrnament : 'com.ruoyi.domain.entity.TtOrnament' ,
TtOrnamentMapper : 'com.ruoyi.admin.mapper.TtOrnamentMapper' ,
} ;
const isBlockMember = ( l ) =>
/ ^ \ s * ( \ / \ / | \ * | \ / \ * | @ ) / . test ( l ) || ( /^\s*[\w.]+\s*=/ . test ( l ) && /[,)]\s*$/ . test ( l ) ) ;
// ---- 自动解析实体/Mapper: attrs.auto = true 时,按方法入参里的实体类型去认 ----
function collectFiles ( dir , out , suffix ) {
if ( ! fs . existsSync ( dir ) ) return out ;
for ( const e of fs . readdirSync ( dir , { withFileTypes : true } ) ) {
const p = path . join ( dir , e . name ) ;
if ( e . isDirectory ( ) ) collectFiles ( p , out , suffix ) ;
else if ( e . isFile ( ) && e . name . endsWith ( suffix ) ) out . push ( p ) ;
}
return out ;
}
const ENTITY = new Map ( ) ; // simpleName -> fqn( skins-model 全部类;真正用的时候还要求有 Mapper)
for ( const f of collectFiles ( path . join ( ROOT , 'skins-model' ) , [ ] , '.java' ) ) {
const src = fs . readFileSync ( f , 'utf8' ) ;
const cls = ( src . match ( /public\s+class\s+(\w+)/ ) || [ , null ] ) [ 1 ] ;
const pkg = ( src . match ( /^package\s+([\w.]+);/m ) || [ , '' ] ) [ 1 ] ;
if ( cls && ! ENTITY . has ( cls ) ) ENTITY . set ( cls , ` ${ pkg } . ${ cls } ` ) ;
}
const MAPPER = new Map ( ) ; // entitySimple -> {simple, fqn}( BaseMapper 与普通 MyBatis 接口都要认)
for ( const f of collectFiles ( path . join ( ROOT , 'skins-service' ) , [ ] , 'Mapper.java' ) ) {
const simple = path . basename ( f , '.java' ) ;
const entityName = simple . endsWith ( 'Mapper' ) ? simple . slice ( 0 , - 6 ) : null ;
if ( ! entityName || ! ENTITY . has ( entityName ) || MAPPER . has ( entityName ) ) continue ;
const pkg = ( fs . readFileSync ( f , 'utf8' ) . match ( /^package\s+([\w.]+);/m ) || [ , '' ] ) [ 1 ] ;
MAPPER . set ( entityName , { simple , fqn : ` ${ pkg } . ${ simple } ` } ) ;
}
/** 取方法参数里的类型名(优先 @RequestBody 那个) */
function methodTypes ( lines , sig ) {
let text = '' ;
for ( let i = sig ; i < Math . min ( sig + 10 , lines . length ) ; i ++ ) {
text += lines [ i ] + ' ' ;
if ( /\)\s*\{/ . test ( lines [ i ] ) || /\)\s*$/ . test ( lines [ i ] ) ) break ;
}
const inner = ( text . match ( /\(([\s\S]*?)\)/ ) || [ , '' ] ) [ 1 ] ;
const types = [ ] ;
const rb = inner . match ( /@RequestBody\s+(?:@\w+(?:\([^)]*\))?\s+)*(\w+)/ ) ;
if ( rb ) types . push ( rb [ 1 ] ) ;
for ( const m of inner . matchAll ( /(?:^|,)\s*(?:final\s+)?([A-Z]\w+)\s+\w+/g ) ) if ( ! types . includes ( m [ 1 ] ) ) types . push ( m [ 1 ] ) ;
return types ;
}
function render ( a , indent ) {
const parts = [ ` title = " ${ a . menu } " ` , ` action = " ${ a . action } " ` , ` businessType = BusinessType. ${ a . type } ` ] ;
if ( a . entity ) parts . push ( ` entityClass = ${ a . entity } .class ` ) ;
if ( a . mapper ) parts . push ( ` mapperClass = ${ a . mapper } .class ` ) ;
if ( a . idField ) parts . push ( ` idField = " ${ a . idField } " ` ) ;
const one = ` ${ indent } @Log( ${ parts . join ( ', ' ) } ) ` ;
if ( one . length <= 130 ) return [ one ] ;
return [ ` ${ indent } @Log( ${ parts . slice ( 0 , 3 ) . join ( ', ' ) } , ` , ` ${ indent } ${ parts . slice ( 3 ) . join ( ', ' ) } ) ` ] ;
}
function insertImports ( lines , entries ) {
for ( const e of entries ) {
// 集合里既有全限定名(com.ruoyi...),也有短名(TtUser),分开处理
const fqn = e . includes ( '.' ) ? e : IMPORTS [ e ] ;
if ( ! fqn ) continue ;
const simple = fqn . split ( '.' ) . pop ( ) ;
if ( lines . some ( ( l ) => new RegExp ( ` ^import \\ s+[ \\ w.]* \\ b ${ simple } ; ` ) . test ( l . trim ( ) ) ) ) continue ;
let at = lines . findIndex ( ( l ) => / ^ import com \ . ruoyi \ . / . test ( l ) ) ;
if ( at < 0 ) at = lines . findIndex ( ( l ) => / ^ import / . test ( l ) ) ;
if ( at >= 0 ) lines . splice ( at , 0 , ` import ${ fqn } ; ` ) ;
}
}
const byFile = new Map ( ) ;
for ( const [ file , method , attrs ] of TARGETS ) {
if ( ! byFile . has ( file ) ) byFile . set ( file , [ ] ) ;
byFile . get ( file ) . push ( { method , attrs } ) ;
}
if ( process . argv . includes ( '--debug' ) ) {
console . log ( ` 实体索引 ${ ENTITY . size } , Mapper 索引 ${ MAPPER . size } ` ) ;
for ( const t of [ 'TtWelfare' , 'TtRedPack' , 'TtTaskCenter' , 'TtBox' ] ) {
console . log ( ` ${ t } : entity= ${ ENTITY . get ( t ) || '无' } mapper= ${ MAPPER . has ( t ) ? MAPPER . get ( t ) . fqn : '无' } ` ) ;
}
}
let done = 0 , skipped = 0 ;
for ( const [ rel , list ] of byFile ) {
const abs = path . join ( ROOT , rel ) ;
const lines = fs . readFileSync ( abs , 'utf8' ) . split ( /\r?\n/ ) ;
const edits = [ ] ;
const imports = new Set ( [ 'com.ruoyi.common.annotation.Log' , 'com.ruoyi.common.enums.BusinessType' ] ) ;
for ( const { method , attrs } of list ) {
// 找方法签名
let sig = - 1 ;
for ( let i = 0 ; i < lines . length ; i ++ ) {
if ( new RegExp ( ` ^ \\ s*(?:public|protected|private) \\ s+[ \\ w<> \\ [ \\ ], \\ . \\ ? ]+ \\ s+ ${ method } \\ s* \\ ( ` ) . test ( lines [ i ] ) ) { sig = i ; break ; }
}
if ( sig < 0 ) { console . log ( ` [跳过] 找不到方法 ${ path . basename ( rel ) } . ${ method } ` ) ; skipped ++ ; continue ; }
// 注解块顶部
let top = sig ;
for ( let j = sig - 1 ; j >= 0 ; j -- ) {
if ( lines [ j ] . trim ( ) === '' || ! isBlockMember ( lines [ j ] ) ) break ;
top = j ;
}
// 已有 @Log 就整块删掉(支持多行)
let start = - 1 , end = - 1 ;
for ( let j = top ; j < sig ; j ++ ) {
if ( /^\s*@Log\(/ . test ( lines [ j ] ) ) {
start = j ;
let depth = 0 ;
outer :
for ( let k = j ; k < sig ; k ++ ) {
for ( const ch of lines [ k ] ) {
if ( ch === '(' ) depth ++ ;
else if ( ch === ')' ) { depth -- ; if ( depth === 0 ) { end = k ; break outer ; } }
}
}
break ;
}
}
const indent = ( lines [ top ] . match ( /^\s*/ ) || [ ' ' ] ) [ 0 ] ;
// 自动认实体:入参里第一个"有 @TableName 且有对应 Mapper"的类型
if ( attrs . auto && ! attrs . entity )
{
for ( const t of methodTypes ( lines , sig ) )
{
if ( ENTITY . has ( t ) && MAPPER . has ( t ) ) { attrs . entity = t ; attrs . mapper = MAPPER . get ( t ) . simple ; break ; }
}
}
edits . push ( { start , end , top , newLines : render ( attrs , indent ) , method , attrs } ) ;
if ( attrs . entity && ENTITY . has ( attrs . entity ) ) imports . add ( ENTITY . get ( attrs . entity ) ) ;
if ( attrs . entity && MAPPER . has ( attrs . entity ) ) imports . add ( MAPPER . get ( attrs . entity ) . fqn ) ;
if ( attrs . mapper && IMPORTS [ attrs . mapper ] ) imports . add ( IMPORTS [ attrs . mapper ] ) ;
}
for ( const ed of edits . sort ( ( a , b ) => b . top - a . top ) ) {
if ( ed . start >= 0 ) lines . splice ( ed . start , ed . end - ed . start + 1 , ... ed . newLines ) ;
else lines . splice ( ed . top , 0 , ... ed . newLines ) ;
console . log ( ` ${ path . basename ( rel ) } . ${ ed . method } → ${ ed . attrs . menu } / ${ ed . attrs . action } ` +
` ${ ed . attrs . entity ? ' diff=' + ed . attrs . entity : '' } ${ ed . attrs . idField ? ' idField=' + ed . attrs . idField : '' } ` ) ;
done ++ ;
}
insertImports ( lines , imports ) ;
if ( apply ) fs . writeFileSync ( abs , lines . join ( '\r\n' ) , 'utf8' ) ;
}
console . log ( ` \n ${ apply ? 'APPLIED' : 'DRY-RUN' } : 写入 ${ done } 个方法,跳过 ${ skipped } ` ) ;