diff --git a/server/db/audit_channel_config.php b/server/db/audit_channel_config.php new file mode 100644 index 0000000..d95fe3d --- /dev/null +++ b/server/db/audit_channel_config.php @@ -0,0 +1,84 @@ +where(function ($q) use ($templateId) { + $q->where('dept_id', $templateId)->whereOr('dept_id', null); + }) + ->count(); +} + +$depts = SystemDept::where('id', '>', 0)->column('id'); +echo "========== 渠道配置实例化审计 ==========\n"; +echo "默认模板 dept_id={$templateId} 行数:\n"; +foreach ($templateCounts as $table => $cnt) { + echo " {$table}: {$cnt}\n"; +} +echo "\n"; + +$missing = []; +foreach ($depts as $deptId) { + $deptId = (int) $deptId; + if ($deptId <= 0) { + continue; + } + $issues = []; + foreach ($tables as $table) { + $expected = $templateCounts[$table]; + if ($expected <= 0) { + continue; + } + $actual = (int) Db::table($table)->where('dept_id', $deptId)->count(); + if ($actual < $expected) { + $issues[] = "{$table}: {$actual}/{$expected}"; + } + } + if ($issues !== []) { + $missing[$deptId] = $issues; + echo "渠道 {$deptId} 不完整 → " . implode(', ', $issues) . "\n"; + } else { + echo "渠道 {$deptId} OK\n"; + } +} + +if ($missing === []) { + echo "\n全部渠道配置已实例化。\n"; + exit(0); +} + +if (!$fix) { + echo "\n存在缺失。执行 php server/db/audit_channel_config.php --fix 可自动补齐。\n"; + exit(1); +} + +echo "\n开始补齐...\n"; +$service = new DiceChannelConfigService(); +$summary = $service->syncAllChannelsFromDefault(); +foreach ($summary as $deptId => $info) { + $copied = implode(',', $info['copied_tables'] ?? []); + echo "渠道 {$deptId}: 新增表 [{$copied}] 补齐行 " . ($info['merged_rows'] ?? 0) . "\n"; +} +echo "补齐完成,请重新运行审计确认。\n"; diff --git a/server/db/check_reward_config.php b/server/db/check_reward_config.php new file mode 100644 index 0000000..513a8c8 --- /dev/null +++ b/server/db/check_reward_config.php @@ -0,0 +1,16 @@ +load(); +\Webman\Config::load(BASE_PATH . '/config', ['route', 'plugin']); +\Webman\ThinkOrm\ThinkOrm::start(null); +use support\think\Db; +$depts = Db::table('sa_system_dept')->column('id'); +array_unshift($depts, 0); +foreach ($depts as $d) { + $c = Db::table('dice_reward_config')->where('dept_id', $d)->count(); + $r = Db::table('dice_reward')->where('dept_id', $d)->count(); + $nonBig = Db::table('dice_reward_config')->where('dept_id', $d)->where('tier', '<>', 'BIGWIN')->count(); + echo "dept {$d}: reward_config={$c}, non_bigwin={$nonBig}, reward={$r}\n"; +} diff --git a/server/db/count_config_tables.php b/server/db/count_config_tables.php new file mode 100644 index 0000000..a42013a --- /dev/null +++ b/server/db/count_config_tables.php @@ -0,0 +1,11 @@ +load(); +\Webman\ThinkOrm\ThinkOrm::start(null); +use support\think\Db; + +foreach (['dice_config', 'dice_ante_config', 'dice_game', 'dice_lottery_pool_config'] as $table) { + echo "{$table} dept1123: " . Db::table($table)->where('dept_id', 1123)->count() . "\n"; +} diff --git a/server/db/debug_reward_api_user123.php b/server/db/debug_reward_api_user123.php new file mode 100644 index 0000000..8288de9 --- /dev/null +++ b/server/db/debug_reward_api_user123.php @@ -0,0 +1,61 @@ +load(); +\Webman\Config::load(BASE_PATH . '/config', ['route', 'plugin']); +\Webman\ThinkOrm\ThinkOrm::start(null); + +use app\dice\helper\AdminScopeHelper; +use app\dice\logic\reward_config\DiceRewardConfigLogic; +use plugin\saiadmin\app\cache\UserInfoCache; +use support\think\Db; + +$adminInfo = UserInfoCache::getUserInfo(123); +$logic = new DiceRewardConfigLogic(); +$query = $logic->search([]); +AdminScopeHelper::applyConfigScope($query, $adminInfo, 0); +$_GET['limit'] = 200; +$_REQUEST['limit'] = 200; +$result = $logic->getList($query); +echo "limit=200 data count: " . count($result['data'] ?? []) . " total=" . ($result['total'] ?? 0) . "\n"; +$bw = 0; +foreach ($result['data'] ?? [] as $row) { + if (($row['tier'] ?? '') === 'BIGWIN') { + $bw++; + echo "BIGWIN id={$row['id']} grid={$row['grid_number']}\n"; + } +} + +$query3 = $logic->search([]); +AdminScopeHelper::applyConfigScope($query3, $adminInfo, 0); +unset($_GET['limit'], $_REQUEST['limit']); +$result3 = $logic->getList($query3); +echo "default limit data count: " . count($result3['data'] ?? []) . "\n"; +$bw3 = 0; +foreach ($result3['data'] ?? [] as $row) { + if (($row['tier'] ?? '') === 'BIGWIN') { + $bw3++; + } +} +echo "default limit BIGWIN: {$bw3}\n"; + +$_GET['saiType'] = 'all'; +$_REQUEST['saiType'] = 'all'; +$resultAll = $logic->getList($query); +echo "saiType=all count: " . (is_array($resultAll) ? count($resultAll) : 0) . "\n"; +if (is_array($resultAll)) { + $bwAll = 0; + foreach ($resultAll as $row) { + if (($row['tier'] ?? '') === 'BIGWIN') { + $bwAll++; + } + } + echo "saiType=all BIGWIN: {$bwAll}\n"; +} + +echo "\nAll rows by id for dept 1123:\n"; +$allRows = \support\think\Db::table('dice_reward_config')->where('dept_id', 1123)->order('id', 'asc')->select(); +foreach ($allRows as $r) { + echo "id={$r['id']} tier={$r['tier']} grid={$r['grid_number']}\n"; +} diff --git a/server/db/debug_reward_index_user123.php b/server/db/debug_reward_index_user123.php new file mode 100644 index 0000000..d07e710 --- /dev/null +++ b/server/db/debug_reward_index_user123.php @@ -0,0 +1,46 @@ +load(); +\Webman\Config::load(BASE_PATH . '/config', ['route', 'plugin']); +\Webman\ThinkOrm\ThinkOrm::start(null); + +use app\dice\helper\AdminScopeHelper; +use app\dice\logic\reward_config\DiceRewardConfigLogic; +use plugin\saiadmin\app\cache\UserInfoCache; + +$adminInfo = UserInfoCache::getUserInfo(123); +$logic = new DiceRewardConfigLogic(); + +// paginated default +$query = $logic->search([]); +AdminScopeHelper::applyConfigScope($query, $adminInfo, 0); +$page = $logic->getList($query); +echo "default paginate count=" . count($page['data'] ?? []) . " total=" . ($page['total'] ?? 0) . "\n"; + +// saiType all +$_GET['saiType'] = 'all'; +$_REQUEST['saiType'] = 'all'; +$query2 = $logic->search([]); +AdminScopeHelper::applyConfigScope($query2, $adminInfo, 0); +$all = $logic->getList($query2); +echo "saiType=all is_array=" . (is_array($all) ? 'yes' : 'no') . " count=" . (is_array($all) ? count($all) : 0) . "\n"; + +$nonBigwin = 0; +if (is_array($all)) { + foreach ($all as $row) { + if (($row['tier'] ?? '') !== 'BIGWIN') { + $nonBigwin++; + } + } +} +echo "non-BIGWIN rows for index tab: {$nonBigwin}\n"; + +// simulate dept_id=1123 explicit +unset($_GET['saiType'], $_REQUEST['saiType']); +$_GET['saiType'] = 'all'; +$query3 = $logic->search([]); +AdminScopeHelper::applyConfigScope($query3, $adminInfo, 1123); +$all3 = $logic->getList($query3); +echo "dept_id=1123 saiType=all count=" . (is_array($all3) ? count($all3) : 0) . "\n"; diff --git a/server/db/debug_reward_query_detail.php b/server/db/debug_reward_query_detail.php new file mode 100644 index 0000000..372ce2a --- /dev/null +++ b/server/db/debug_reward_query_detail.php @@ -0,0 +1,39 @@ +load(); +\Webman\Config::load(BASE_PATH . '/config', ['route', 'plugin']); +\Webman\ThinkOrm\ThinkOrm::start(null); + +use app\dice\helper\AdminScopeHelper; +use app\dice\logic\reward_config\DiceRewardConfigLogic; +use app\dice\model\reward_config\DiceRewardConfig; +use plugin\saiadmin\app\cache\UserInfoCache; +use support\think\Db; + +$adminInfo = UserInfoCache::getUserInfo(123); + +echo "Raw DB count dept 1123: " . Db::table('dice_reward_config')->where('dept_id', 1123)->whereNull('delete_time')->count() . "\n"; + +$logic = new DiceRewardConfigLogic(); +$query = $logic->search([]); +AdminScopeHelper::applyConfigScope($query, $adminInfo, 1123); +$sql = $query->fetchSql(true)->select(); +echo "SQL: {$sql}\n"; +$rows = $query->fetchSql(false)->select()->toArray(); +echo "Model select count: " . count($rows) . "\n"; + +$model = new DiceRewardConfig(); +$q2 = $model->where('dept_id', 1123)->order('id', 'asc'); +$rows2 = $q2->select()->toArray(); +echo "Direct model dept 1123: " . count($rows2) . "\n"; + +$tierCounts = Db::table('dice_reward_config')->where('dept_id', 1123)->group('tier')->column('count(*)', 'tier'); +echo "Tier counts: " . json_encode($tierCounts, JSON_UNESCAPED_UNICODE) . "\n"; + +$idCounts = Db::query('SELECT id, COUNT(*) as c FROM dice_reward_config WHERE dept_id=1123 GROUP BY id HAVING c>1'); +echo "Duplicate business ids in dept 1123: " . count($idCounts) . "\n"; +if ($idCounts) { + print_r($idCounts); +} diff --git a/server/db/debug_user123_reward.php b/server/db/debug_user123_reward.php new file mode 100644 index 0000000..a39cd6d --- /dev/null +++ b/server/db/debug_user123_reward.php @@ -0,0 +1,36 @@ +load(); +\Webman\Config::load(BASE_PATH . '/config', ['route', 'plugin']); +\Webman\ThinkOrm\ThinkOrm::start(null); + +use app\dice\helper\AdminScopeHelper; +use plugin\saiadmin\app\cache\UserInfoCache; +use plugin\saiadmin\app\logic\system\SystemUserLogic; +use support\think\Db; + +$uid = 123; +$user = Db::table('sa_system_user')->where('id', $uid)->find(); +echo "DB user: " . json_encode($user, JSON_UNESCAPED_UNICODE) . "\n"; + +$logic = new SystemUserLogic(); +$info = $logic->getUser($uid); +echo "getUser deptList: " . json_encode($info['deptList'] ?? null, JSON_UNESCAPED_UNICODE) . "\n"; +echo "getUser dept_id: " . ($info['dept_id'] ?? 'null') . "\n"; + +$cached = UserInfoCache::getUserInfo($uid); +echo "cache deptList: " . json_encode($cached['deptList'] ?? null, JSON_UNESCAPED_UNICODE) . "\n"; +echo "getDeptId: " . var_export(AdminScopeHelper::getDeptId($cached), true) . "\n"; +echo "resolveConfigDeptId(null): " . AdminScopeHelper::resolveConfigDeptId($cached, null) . "\n"; +echo "resolveConfigDeptId(0): " . AdminScopeHelper::resolveConfigDeptId($cached, 0) . "\n"; + +$deptId = 1123; +$all = Db::table('dice_reward_config')->where('dept_id', $deptId)->count(); +$bigwin = Db::table('dice_reward_config')->where('dept_id', $deptId)->where('tier', 'BIGWIN')->count(); +$reward = Db::table('dice_reward')->where('dept_id', $deptId)->count(); +echo "dept {$deptId}: reward_config={$all}, BIGWIN={$bigwin}, dice_reward={$reward}\n"; + +$sample = Db::table('dice_reward_config')->where('dept_id', $deptId)->limit(3)->select(); +echo "sample reward_config: " . json_encode($sample, JSON_UNESCAPED_UNICODE) . "\n"; diff --git a/server/db/dept_flatten_channels.sql b/server/db/dept_flatten_channels.sql new file mode 100644 index 0000000..397c3ee --- /dev/null +++ b/server/db/dept_flatten_channels.sql @@ -0,0 +1,26 @@ +-- 渠道扁平化:将子渠道用户归并到顶级渠道,删除子渠道,更新表注释 +-- 执行前请备份数据库 + +-- 1. 表及字段注释改为「渠道」 +ALTER TABLE `sa_system_dept` COMMENT = '渠道表'; +ALTER TABLE `sa_system_dept` + MODIFY COLUMN `parent_id` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '父级ID(扁平渠道固定为0)', + MODIFY COLUMN `name` varchar(64) NOT NULL COMMENT '渠道名称', + MODIFY COLUMN `code` varchar(64) NULL DEFAULT NULL COMMENT '渠道编码', + MODIFY COLUMN `leader_id` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '渠道负责人ID'; + +-- 2. 菜单名称(按实际 id 调整,id=5 为渠道管理菜单) +UPDATE `sa_system_menu` SET `name` = '渠道管理' WHERE `id` = 5 OR `name` LIKE '%渠道(部门)%' OR `name` = '部门管理'; + +-- 3. 将子渠道下的用户 dept_id 提升到顶级渠道(需配合 run_dept_flatten_channels.php 处理多级) +-- 以下为单级子渠道快速迁移(parent_id != 0 的直接挂到父级) +UPDATE `sa_system_user` u +INNER JOIN `sa_system_dept` d ON u.dept_id = d.id AND d.parent_id > 0 +INNER JOIN `sa_system_dept` p ON d.parent_id = p.id +SET u.dept_id = p.id; + +-- 4. 删除所有子渠道(parent_id > 0) +DELETE FROM `sa_system_dept` WHERE `parent_id` > 0; + +-- 5. 剩余渠道统一为顶级 +UPDATE `sa_system_dept` SET `parent_id` = 0, `level` = '0'; diff --git a/server/db/dice_player_dept_username_unique.sql b/server/db/dice_player_dept_username_unique.sql new file mode 100644 index 0000000..5c75a15 --- /dev/null +++ b/server/db/dice_player_dept_username_unique.sql @@ -0,0 +1,10 @@ +-- dice_player:同一渠道内用户名唯一(dept_id + username)— 数据库根本约束 +-- 执行前请备份;若存在重复数据需先清理后再执行 +-- 推荐:php db/run_dice_player_dept_username_unique.php + +-- 移除仅按 username 的普通索引(若不存在可忽略报错) +-- ALTER TABLE `dice_player` DROP INDEX `idx_dice_player_username`; + +-- 同一渠道下用户名唯一(UNIQUE 为数据库层最终约束) +ALTER TABLE `dice_player` + ADD UNIQUE INDEX `uk_dice_player_dept_username` (`dept_id`, `username`); diff --git a/server/db/dice_player_username_index.sql b/server/db/dice_player_username_index.sql new file mode 100644 index 0000000..979ce31 --- /dev/null +++ b/server/db/dice_player_username_index.sql @@ -0,0 +1,2 @@ +-- 已废弃:请使用 dice_player_dept_username_unique.sql(同一渠道 dept_id + username 唯一) +-- 历史脚本保留说明,勿再单独执行本文件 diff --git a/server/db/dice_tables_add_dept_id.sql b/server/db/dice_tables_add_dept_id.sql new file mode 100644 index 0000000..4fdb945 --- /dev/null +++ b/server/db/dice_tables_add_dept_id.sql @@ -0,0 +1,92 @@ +-- 大富翁游戏相关表增加 dept_id,关联 sa_system_dept(渠道表) + +ALTER TABLE `dice_ante_config` + ADD COLUMN `dept_id` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '所属渠道ID' AFTER `id`, + ADD INDEX `idx_dept_id` (`dept_id`); + +ALTER TABLE `dice_config` + ADD COLUMN `dept_id` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '所属渠道ID' AFTER `id`, + ADD INDEX `idx_dept_id` (`dept_id`); + +ALTER TABLE `dice_game` + ADD COLUMN `dept_id` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '所属渠道ID' AFTER `id`, + ADD INDEX `idx_dept_id` (`dept_id`); + +ALTER TABLE `dice_lottery_config` + ADD COLUMN `dept_id` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '所属渠道ID' AFTER `id`, + ADD INDEX `idx_dept_id` (`dept_id`); + +ALTER TABLE `dice_lottery_poll_record` + ADD COLUMN `dept_id` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '所属渠道ID' AFTER `id`, + ADD INDEX `idx_dept_id` (`dept_id`); + +ALTER TABLE `dice_lottery_pool_config` + ADD COLUMN `dept_id` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '所属渠道ID' AFTER `id`, + ADD INDEX `idx_dept_id` (`dept_id`); + +ALTER TABLE `dice_play_record` + ADD COLUMN `dept_id` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '所属渠道ID' AFTER `id`, + ADD INDEX `idx_dept_id` (`dept_id`); + +ALTER TABLE `dice_play_record_test` + ADD COLUMN `dept_id` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '所属渠道ID' AFTER `id`, + ADD INDEX `idx_dept_id` (`dept_id`); + +ALTER TABLE `dice_player` + ADD COLUMN `dept_id` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '所属渠道ID' AFTER `id`, + ADD INDEX `idx_dept_id` (`dept_id`); + +-- 同一渠道内用户名唯一(根本约束,新库初始化时执行;已有库请用 dice_player_dept_username_unique.sql) +ALTER TABLE `dice_player` + ADD UNIQUE INDEX `uk_dice_player_dept_username` (`dept_id`, `username`); + +ALTER TABLE `dice_player_ticket_record` + ADD COLUMN `dept_id` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '所属渠道ID' AFTER `id`, + ADD INDEX `idx_dept_id` (`dept_id`); + +ALTER TABLE `dice_player_wallet_record` + ADD COLUMN `dept_id` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '所属渠道ID' AFTER `id`, + ADD INDEX `idx_dept_id` (`dept_id`); + +ALTER TABLE `dice_reward` + ADD COLUMN `dept_id` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '所属渠道ID' AFTER `id`, + ADD INDEX `idx_dept_id` (`dept_id`); + +ALTER TABLE `dice_reward_config` + ADD COLUMN `dept_id` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '所属渠道ID' AFTER `id`, + ADD INDEX `idx_dept_id` (`dept_id`); + +ALTER TABLE `dice_reward_config_record` + ADD COLUMN `dept_id` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '所属渠道ID' AFTER `id`, + ADD INDEX `idx_dept_id` (`dept_id`); + +-- 从管理员归属回填玩家 dept_id +UPDATE `dice_player` p +INNER JOIN `sa_system_user` u ON p.admin_id = u.id +SET p.dept_id = u.dept_id +WHERE p.dept_id IS NULL AND u.dept_id IS NOT NULL AND u.dept_id > 0; + +UPDATE `dice_play_record` r +INNER JOIN `dice_player` p ON r.player_id = p.id +SET r.dept_id = p.dept_id +WHERE r.dept_id IS NULL AND p.dept_id IS NOT NULL; + +UPDATE `dice_play_record_test` r +INNER JOIN `dice_player` p ON r.player_id = p.id +SET r.dept_id = p.dept_id +WHERE r.dept_id IS NULL AND p.dept_id IS NOT NULL; + +UPDATE `dice_player_ticket_record` r +INNER JOIN `dice_player` p ON r.player_id = p.id +SET r.dept_id = p.dept_id +WHERE r.dept_id IS NULL AND p.dept_id IS NOT NULL; + +UPDATE `dice_player_wallet_record` r +INNER JOIN `dice_player` p ON r.player_id = p.id +SET r.dept_id = p.dept_id +WHERE r.dept_id IS NULL AND p.dept_id IS NOT NULL; + +UPDATE `dice_reward_config_record` r +INNER JOIN `sa_system_user` u ON r.admin_id = u.id +SET r.dept_id = u.dept_id +WHERE r.dept_id IS NULL AND u.dept_id IS NOT NULL AND u.dept_id > 0; diff --git a/server/db/inspect_player_destroy.php b/server/db/inspect_player_destroy.php new file mode 100644 index 0000000..e12644f --- /dev/null +++ b/server/db/inspect_player_destroy.php @@ -0,0 +1,93 @@ +,,...] + */ +require_once __DIR__ . '/../vendor/autoload.php'; +require_once __DIR__ . '/../support/bootstrap.php'; + +use support\think\Db; + +$config = config('database'); +$default = $config['default']; +$conn = $config['connections'][$default]; +$dbName = $conn['database'] ?? ''; +echo "[DB] {$default} -> {$dbName}\n\n"; + +echo "--- dice_player columns ---\n"; +$cols = Db::query("SHOW FULL COLUMNS FROM `dice_player`"); +foreach ($cols as $c) { + echo str_pad((string)$c['Field'], 26) . ' | ' . str_pad((string)$c['Type'], 24) . ' | NULL=' . $c['Null'] . ' | Key=' . $c['Key'] . "\n"; +} +echo "\n"; + +echo "--- referenced by foreign keys (other tables -> dice_player) ---\n"; +$fks = Db::query("SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME + FROM information_schema.KEY_COLUMN_USAGE + WHERE TABLE_SCHEMA = ? AND REFERENCED_TABLE_NAME = 'dice_player'", [$dbName]); +if (empty($fks)) { + echo " (none)\n"; +} else { + foreach ($fks as $f) { + echo " {$f['TABLE_NAME']}.{$f['COLUMN_NAME']} -> {$f['REFERENCED_TABLE_NAME']}.{$f['REFERENCED_COLUMN_NAME']} [{$f['CONSTRAINT_NAME']}]\n"; + } +} +echo "\n"; + +echo "--- top 3 dice_player rows ---\n"; +$rows = Db::table('dice_player')->limit(3)->select()->toArray(); +foreach ($rows as $r) { + echo "id={$r['id']} dept_id={$r['dept_id']} username={$r['username']} delete_time=" . ($r['delete_time'] ?? 'null') . "\n"; +} +echo "\n"; + +$idsArg = $argv[1] ?? ''; +if ($idsArg === '') { + echo "(no ids passed, skip dry-run delete)\n"; + return; +} +$ids = array_filter(array_map('intval', explode(',', $idsArg))); +if (empty($ids)) { + echo "(invalid ids)\n"; + return; +} + +echo "--- dry-run destroy ids: " . implode(',', $ids) . " ---\n"; +$beforeAll = Db::query('SELECT id, delete_time FROM dice_player WHERE id IN (' . implode(',', array_fill(0, count($ids), '?')) . ')', $ids); +echo "before (raw): " . count($beforeAll) . " rows\n"; + +$placeholders = implode(',', array_fill(0, count($ids), '?')); + +// Case A: static destroy +try { + Db::startTrans(); + $result = \app\dice\model\player\DicePlayer::destroy($ids, true); + $afterAny = Db::query("SELECT COUNT(*) AS c FROM dice_player WHERE id IN ({$placeholders})", $ids); + echo "[static destroy] returned: " . var_export($result, true) . ", remaining raw rows: " . ($afterAny[0]['c'] ?? 'n/a') . "\n"; + Db::rollback(); +} catch (\Throwable $e) { + Db::rollback(); + echo "EXCEPTION (static destroy): " . get_class($e) . ": " . $e->getMessage() . "\n"; +} + +// Case B: instance ->delete() +try { + Db::startTrans(); + $instance = \app\dice\model\player\DicePlayer::find($ids[0]); + if ($instance) { + $r = $instance->delete(); + $afterAny = Db::query("SELECT COUNT(*) AS c FROM dice_player WHERE id = ?", [$ids[0]]); + echo "[instance delete] returned: " . var_export($r, true) . ", remaining raw rows for id={$ids[0]}: " . ($afterAny[0]['c'] ?? 'n/a') . "\n"; + } else { + echo "[instance delete] no instance found for id={$ids[0]}\n"; + } + Db::rollback(); +} catch (\Throwable $e) { + Db::rollback(); + echo "EXCEPTION (instance delete): " . get_class($e) . ": " . $e->getMessage() . "\n"; +} +echo "(both rolled back, no actual delete)\n"; diff --git a/server/db/remove_safeguard_ops_role_menus.sql b/server/db/remove_safeguard_ops_role_menus.sql new file mode 100644 index 0000000..ea44827 --- /dev/null +++ b/server/db/remove_safeguard_ops_role_menus.sql @@ -0,0 +1,35 @@ +-- 从所有角色中移除以下运维菜单及其按钮权限 +-- /safeguard/dict +-- /safeguard/attachment +-- /safeguard/database +-- /safeguard/server +-- /safeguard/cache +-- /safeguard/email-log +-- +-- 推荐执行:php db/run_remove_safeguard_ops_role_menus.php +-- 该脚本会按 route 动态匹配菜单及其子权限,并清理菜单缓存 + +-- 主菜单 +DELETE rm FROM `sa_system_role_menu` rm +INNER JOIN `sa_system_menu` m ON rm.menu_id = m.id +WHERE m.component IN ( + '/safeguard/dict', + '/safeguard/attachment', + '/safeguard/database', + '/safeguard/server', + '/safeguard/cache', + '/safeguard/email-log' +); + +-- 子按钮权限 +DELETE rm FROM `sa_system_role_menu` rm +INNER JOIN `sa_system_menu` child ON rm.menu_id = child.id +INNER JOIN `sa_system_menu` parent ON child.parent_id = parent.id +WHERE parent.component IN ( + '/safeguard/dict', + '/safeguard/attachment', + '/safeguard/database', + '/safeguard/server', + '/safeguard/cache', + '/safeguard/email-log' +); diff --git a/server/db/remove_system_post.sql b/server/db/remove_system_post.sql new file mode 100644 index 0000000..4966fca --- /dev/null +++ b/server/db/remove_system_post.sql @@ -0,0 +1,14 @@ +-- 移除岗位(Post)相关数据表与菜单 +-- 执行前请备份数据库 + +-- 删除岗位子菜单权限(id: 41-47) +DELETE FROM `sa_system_role_menu` WHERE `menu_id` IN (41, 42, 43, 44, 45, 46, 47); +DELETE FROM `sa_system_menu` WHERE `id` IN (41, 42, 43, 44, 45, 46, 47); + +-- 删除岗位管理主菜单(id: 7) +DELETE FROM `sa_system_role_menu` WHERE `menu_id` = 7; +DELETE FROM `sa_system_menu` WHERE `id` = 7; + +-- 删除用户岗位关联表与岗位信息表 +DROP TABLE IF EXISTS `sa_system_user_post`; +DROP TABLE IF EXISTS `sa_system_post`; diff --git a/server/db/run_all_init.php b/server/db/run_all_init.php new file mode 100644 index 0000000..c107f3a --- /dev/null +++ b/server/db/run_all_init.php @@ -0,0 +1,191 @@ +load(); + } else { + \Dotenv\Dotenv::createMutable(BASE_PATH)->load(); + } +} + +// 加载配置(排除 route.php,避免 CLI 报错) +\Webman\Config::load(BASE_PATH . '/config', ['route', 'plugin']); +\Webman\ThinkOrm\ThinkOrm::start(null); + +use app\dice\service\DiceChannelConfigService; +use plugin\saiadmin\app\model\system\SystemDept; +use plugin\saiadmin\app\model\system\SystemUser; +use support\think\Db; + +function cliPdo(): PDO +{ + $host = getenv('DB_HOST') ?: '127.0.0.1'; + $port = getenv('DB_PORT') ?: '3306'; + $db = getenv('DB_NAME') ?: ''; + $user = getenv('DB_USER') ?: ''; + $pass = getenv('DB_PASSWORD') ?: ''; + $dsn = "mysql:host={$host};port={$port};dbname={$db};charset=utf8mb4"; + return new PDO($dsn, $user, $pass, [ + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + ]); +} + +function runSqlFile(PDO $pdo, string $path, string $label, bool $alterOnly = false): void +{ + echo "\n=== {$label} ===\n"; + if (!is_file($path)) { + echo "跳过:文件不存在\n"; + return; + } + $sql = file_get_contents($path); + $sql = preg_replace('/--.*$/m', '', $sql); + $parts = array_filter(array_map('trim', explode(';', $sql))); + $ok = 0; + $skip = 0; + foreach ($parts as $statement) { + if ($statement === '') { + continue; + } + if ($alterOnly && stripos($statement, 'ALTER TABLE') !== 0) { + continue; + } + try { + $pdo->exec($statement); + $ok++; + } catch (PDOException $e) { + $msg = $e->getMessage(); + $isAlter = stripos($statement, 'ALTER TABLE') === 0; + if ($isAlter && (stripos($msg, 'Duplicate column') !== false + || stripos($msg, 'Duplicate key name') !== false)) { + $skip++; + } elseif (!$isAlter) { + echo " [警告] " . substr($msg, 0, 120) . "\n"; + $skip++; + } else { + echo " [错误] {$msg}\n"; + throw $e; + } + } + } + echo "完成:成功 {$ok} 条" . ($skip > 0 ? ",跳过 {$skip} 条(字段已存在)" : '') . "\n"; +} + +function getRootDeptId(int $deptId): ?int +{ + $currentId = $deptId; + $visited = []; + while ($currentId > 0 && !isset($visited[$currentId])) { + $visited[$currentId] = true; + $dept = SystemDept::find($currentId); + if (!$dept) { + return null; + } + $parentId = (int) ($dept->parent_id ?? 0); + if ($parentId === 0) { + return $currentId; + } + $currentId = $parentId; + } + return $currentId > 0 ? $currentId : null; +} + +echo "========== 大富翁渠道/配置初始化 ==========\n"; +echo '数据库: ' . (getenv('DB_NAME') ?: '') . '@' . (getenv('DB_HOST') ?: '') . "\n"; + +$pdo = cliPdo(); + +runSqlFile($pdo, __DIR__ . '/dice_tables_add_dept_id.sql', '1. dice 表增加 dept_id', true); +runSqlFile($pdo, __DIR__ . '/dept_flatten_channels.sql', '2. 渠道扁平化 SQL'); + +echo "\n=== 3. 渠道扁平化 PHP(多级用户归并 + 删除子渠道) ===\n"; +Db::transaction(function () { + $users = SystemUser::where('dept_id', '>', 0)->select(); + $moved = 0; + foreach ($users as $user) { + $deptId = (int) $user->dept_id; + $rootId = getRootDeptId($deptId); + if ($rootId !== null && $rootId !== $deptId) { + SystemUser::where('id', $user->id)->update(['dept_id' => $rootId]); + echo " 用户 {$user->id}: dept {$deptId} -> {$rootId}\n"; + $moved++; + } + } + $childIds = SystemDept::where('parent_id', '>', 0)->column('id'); + if (!empty($childIds)) { + SystemDept::destroy($childIds); + echo ' 已删除子渠道: ' . implode(',', $childIds) . "\n"; + } else { + echo " 无子渠道需删除\n"; + } + SystemDept::where('id', '>', 0)->update(['parent_id' => 0, 'level' => '0']); + echo " 用户归并 {$moved} 人,渠道扁平化完成\n"; +}); + +$service = new DiceChannelConfigService(); + +echo "\n=== 3.5 配置表复合键与默认模板 dept_id=0 ===\n"; +$service->ensureConfigCompositeKeys(); +echo " dice_config / dice_reward_config: ok\n"; + +echo "\n=== 3.6 彩金池配置按渠道唯一(dept_id + name) ===\n"; +try { + $indexes = Db::query("SHOW INDEX FROM `dice_lottery_pool_config` WHERE Key_name = 'dice_lottery_poll_config_unique'"); + if (!empty($indexes)) { + Db::execute('ALTER TABLE `dice_lottery_pool_config` DROP INDEX `dice_lottery_poll_config_unique`'); + echo " 已移除 name 全局唯一索引\n"; + } + $uk = Db::query("SHOW INDEX FROM `dice_lottery_pool_config` WHERE Key_name = 'uk_dept_name'"); + if (empty($uk)) { + Db::execute('ALTER TABLE `dice_lottery_pool_config` ADD UNIQUE KEY `uk_dept_name` (`dept_id`, `name`)'); + echo " 已添加 uk_dept_name(dept_id, name)\n"; + } else { + echo " uk_dept_name 已存在\n"; + } +} catch (\Throwable $e) { + echo " 跳过: {$e->getMessage()}\n"; +} + +echo "\n=== 4. 将现有配置设为默认模板(dept_id=0) ===\n"; +$tables = [ + 'dice_config', + 'dice_ante_config', + 'dice_lottery_pool_config', + 'dice_reward_config', + 'dice_reward', + 'dice_game', +]; +foreach ($tables as $table) { + try { + Db::table($table)->update(['dept_id' => 0]); + echo " {$table}: ok\n"; + } catch (\Throwable $e) { + echo " {$table}: 跳过 ({$e->getMessage()})\n"; + } +} + +echo "\n=== 5. 为所有渠道从默认模板复制配置 ===\n"; +$summary = $service->syncAllChannelsFromDefault(); +foreach ($summary as $deptId => $info) { + $copied = implode(',', $info['copied'] ?? []) ?: '无'; + $skipped = implode(',', $info['skipped'] ?? []) ?: '无'; + echo " 渠道 {$deptId}: 复制 [{$copied}],跳过 [{$skipped}]\n"; +} + +echo "\n=== 6. 修复无效渠道并回填 dept_id ===\n"; +echo " 无效渠道归并: "; +print_r($service->repairOrphanDeptReferences()); +echo " 回填: "; +print_r($service->backfillDataDeptId()); + +$deptCount = SystemDept::count(); +echo "\n当前顶级渠道数: {$deptCount}\n"; +echo "========== 全部初始化完成 ==========\n"; diff --git a/server/db/run_backfill_dept_id.php b/server/db/run_backfill_dept_id.php new file mode 100644 index 0000000..0d7a034 --- /dev/null +++ b/server/db/run_backfill_dept_id.php @@ -0,0 +1,16 @@ +load(); +\Webman\Config::load(BASE_PATH . '/config', ['route', 'plugin']); +\Webman\ThinkOrm\ThinkOrm::start(null); + +use app\dice\service\DiceChannelConfigService; + +$service = new DiceChannelConfigService(); +echo "修复无效渠道引用...\n"; +print_r($service->repairOrphanDeptReferences()); +echo "\n回填 dept_id...\n"; +print_r($service->backfillDataDeptId()); +echo "完成。\n"; diff --git a/server/db/run_channel_config_init.php b/server/db/run_channel_config_init.php new file mode 100644 index 0000000..cbd4312 --- /dev/null +++ b/server/db/run_channel_config_init.php @@ -0,0 +1,46 @@ +where('dept_id', 0)->update(['dept_id' => null]); + echo " {$table}: ok\n"; + } catch (\Throwable $e) { + echo " {$table}: 跳过 ({$e->getMessage()})\n"; + } +} + +echo "2. 为所有渠道补齐默认配置...\n"; +$summary = $service->syncAllChannelsFromDefault(); +print_r($summary); + +echo "3. 回填玩家及记录 dept_id...\n"; +$stats = $service->backfillDataDeptId(); +print_r($stats); + +echo "完成。\n"; diff --git a/server/db/run_dept_flatten_channels.php b/server/db/run_dept_flatten_channels.php new file mode 100644 index 0000000..0f5bb86 --- /dev/null +++ b/server/db/run_dept_flatten_channels.php @@ -0,0 +1,55 @@ + 0 && !isset($visited[$currentId])) { + $visited[$currentId] = true; + $dept = SystemDept::find($currentId); + if (!$dept) { + return null; + } + $parentId = (int) ($dept->parent_id ?? 0); + if ($parentId === 0) { + return $currentId; + } + $currentId = $parentId; + } + return $currentId > 0 ? $currentId : null; +} + +Db::transaction(function () { + $users = SystemUser::where('dept_id', '>', 0)->select(); + foreach ($users as $user) { + $deptId = (int) $user->dept_id; + $rootId = getRootDeptId($deptId); + if ($rootId !== null && $rootId !== $deptId) { + SystemUser::where('id', $user->id)->update(['dept_id' => $rootId]); + echo "用户 {$user->id} dept_id {$deptId} -> {$rootId}\n"; + } + } + + $childIds = SystemDept::where('parent_id', '>', 0)->column('id'); + if (!empty($childIds)) { + SystemDept::destroy($childIds); + echo '已删除子渠道: ' . implode(',', $childIds) . "\n"; + } + + SystemDept::where('id', '>', 0)->update(['parent_id' => 0, 'level' => '0']); + echo "渠道扁平化完成\n"; +}); diff --git a/server/db/run_dice_player_dept_username_unique.php b/server/db/run_dice_player_dept_username_unique.php new file mode 100644 index 0000000..847f406 --- /dev/null +++ b/server/db/run_dice_player_dept_username_unique.php @@ -0,0 +1,53 @@ +load(); + } else { + \Dotenv\Dotenv::createMutable(BASE_PATH)->load(); + } +} + +\Webman\Config::load(BASE_PATH . '/config', ['route', 'plugin']); +\Webman\ThinkOrm\ThinkOrm::start(null); + +use support\think\Db; + +echo "检查 (dept_id, username) 重复...\n"; +$dupes = Db::query( + 'SELECT dept_id, username, COUNT(*) AS c FROM dice_player + WHERE username IS NOT NULL AND username <> \'\' + GROUP BY dept_id, username HAVING c > 1 LIMIT 20' +); +if (!empty($dupes)) { + echo "存在重复记录,请先处理后再执行:\n"; + print_r($dupes); + exit(1); +} + +$indexes = Db::query("SHOW INDEX FROM `dice_player` WHERE Key_name = 'idx_dice_player_username'"); +if (!empty($indexes)) { + Db::execute('ALTER TABLE `dice_player` DROP INDEX `idx_dice_player_username`'); + echo "已删除 idx_dice_player_username\n"; +} + +$uk = Db::query("SHOW INDEX FROM `dice_player` WHERE Key_name = 'uk_dice_player_dept_username'"); +if (empty($uk)) { + Db::execute( + 'ALTER TABLE `dice_player` ADD UNIQUE INDEX `uk_dice_player_dept_username` (`dept_id`, `username`)' + ); + echo "已创建 uk_dice_player_dept_username\n"; +} else { + echo "uk_dice_player_dept_username 已存在,跳过\n"; +} + +echo "完成\n"; diff --git a/server/db/run_fill_missing_channel_config.php b/server/db/run_fill_missing_channel_config.php new file mode 100644 index 0000000..d3dab5e --- /dev/null +++ b/server/db/run_fill_missing_channel_config.php @@ -0,0 +1,33 @@ +load(); +} +\Webman\Config::load(BASE_PATH . '/config', ['route', 'plugin']); +\Webman\ThinkOrm\ThinkOrm::start(null); + +use app\dice\service\DiceChannelConfigService; +use plugin\saiadmin\app\model\system\SystemDept; + +echo "========== 补齐渠道缺失配置 ==========\n"; + +$service = new DiceChannelConfigService(); +$service->ensureConfigCompositeKeys(); + +$summary = $service->syncAllChannelsFromDefault(); +foreach ($summary as $deptId => $info) { + $copied = implode(',', $info['copied'] ?? []) ?: '无'; + $merged = empty($info['merged']) ? '无' : json_encode($info['merged'], JSON_UNESCAPED_UNICODE); + $skipped = implode(',', $info['skipped'] ?? []) ?: '无'; + echo "渠道 {$deptId}: 新增表 [{$copied}] 补齐行 {$merged} 跳过 [{$skipped}]\n"; +} + +echo "\n渠道数: " . SystemDept::count() . "\n完成。\n"; diff --git a/server/db/run_remove_safeguard_ops_role_menus.php b/server/db/run_remove_safeguard_ops_role_menus.php new file mode 100644 index 0000000..30617a4 --- /dev/null +++ b/server/db/run_remove_safeguard_ops_role_menus.php @@ -0,0 +1,100 @@ +whereIn('parent_id', $parentIds) + ->column('id'); + + if ($childIds === []) { + return []; + } + + $childIds = array_map('intval', $childIds); + $deeper = collectChildMenuIds($childIds); + + return array_values(array_unique(array_merge($childIds, $deeper))); +} + +echo "=== remove safeguard ops menus from all roles ===\n"; + +$rootMenuIds = Db::name('sa_system_menu') + ->whereIn('component', $targetRoutes) + ->column('id'); + +$rootMenuIds = array_map('intval', $rootMenuIds ?: []); +$childMenuIds = collectChildMenuIds($rootMenuIds); +$menuIds = array_values(array_unique(array_merge($rootMenuIds, $childMenuIds))); + +if ($menuIds === []) { + echo "WARN: no menu matched target routes\n"; + exit(0); +} + +$menuRows = Db::name('sa_system_menu') + ->whereIn('id', $menuIds) + ->field('id, parent_id, name, component, slug, type') + ->order('id', 'asc') + ->select() + ->toArray(); + +echo "Matched menus (" . count($menuRows) . "):\n"; +foreach ($menuRows as $row) { + echo sprintf( + " - id=%d parent=%d type=%s component=%s slug=%s name=%s\n", + (int) ($row['id'] ?? 0), + (int) ($row['parent_id'] ?? 0), + (string) ($row['type'] ?? ''), + (string) ($row['component'] ?? ''), + (string) ($row['slug'] ?? ''), + (string) ($row['name'] ?? '') + ); +} + +$deleted = Db::name('sa_system_role_menu')->whereIn('menu_id', $menuIds)->delete(); +echo "Deleted role-menu rows: {$deleted}\n"; + +$roleCount = Db::name('sa_system_role_menu') + ->whereIn('menu_id', $menuIds) + ->count(); +echo "Remaining role-menu rows for these menus: {$roleCount}\n"; + +UserMenuCache::clearMenuCache(); +echo "Cleared menu cache\n"; + +echo "Done.\n"; diff --git a/server/db/run_sa_system_role_dept_id.php b/server/db/run_sa_system_role_dept_id.php new file mode 100644 index 0000000..ebd3428 --- /dev/null +++ b/server/db/run_sa_system_role_dept_id.php @@ -0,0 +1,74 @@ + 1'); +echo "OK: UPDATE template dept_id\n"; + +if (indexExists('sa_system_role', 'uk_slug')) { + Db::execute('ALTER TABLE `sa_system_role` DROP INDEX `uk_slug`'); + echo "OK: DROP INDEX uk_slug\n"; +} else { + echo "SKIP: uk_slug not found\n"; +} + +if (!indexExists('sa_system_role', 'uk_dept_code')) { + Db::execute('ALTER TABLE `sa_system_role` ADD UNIQUE KEY `uk_dept_code` (`dept_id`, `code`)'); + echo "OK: ADD UNIQUE uk_dept_code\n"; +} else { + echo "SKIP: uk_dept_code exists\n"; +} + +$service = new SystemRoleChannelService(); +$sync = $service->syncAllChannelsFromDefault(); +echo "Synced roles for channels: " . json_encode($sync, JSON_UNESCAPED_UNICODE) . "\n"; + +$mapped = $service->remapUserRolesToChannelRoles(); +echo "Remapped user roles: {$mapped}\n"; + +echo "Done.\n"; diff --git a/server/db/run_sync_channel_config.php b/server/db/run_sync_channel_config.php new file mode 100644 index 0000000..00872f2 --- /dev/null +++ b/server/db/run_sync_channel_config.php @@ -0,0 +1,58 @@ +load(); +} +\Webman\Config::load(BASE_PATH . '/config', ['route', 'plugin']); +\Webman\ThinkOrm\ThinkOrm::start(null); + +use app\dice\service\DiceChannelConfigService; +use plugin\saiadmin\app\model\system\SystemDept; +use support\think\Db; + +echo "========== 渠道配置同步 ==========\n"; + +$service = new DiceChannelConfigService(); +echo "调整配置表主键与默认模板 dept_id=0...\n"; +$service->ensureConfigCompositeKeys(); + +$tables = ['dice_config', 'dice_ante_config', 'dice_lottery_pool_config', 'dice_reward_config', 'dice_reward', 'dice_game']; + +echo "\n清理各渠道不完整配置后重新复制...\n"; +$deptIds = SystemDept::column('id'); +foreach ($deptIds as $deptId) { + $deptId = (int) $deptId; + if ($deptId <= 0) { + continue; + } + foreach ($tables as $table) { + try { + Db::table($table)->where('dept_id', $deptId)->delete(); + } catch (\Throwable $e) { + } + } +} + +echo "设为默认模板 (dept_id=0)...\n"; +foreach ($tables as $table) { + Db::table($table)->whereNull('dept_id')->update(['dept_id' => 0]); +} + +echo "从默认模板复制到各渠道...\n"; +$summary = $service->syncAllChannelsFromDefault(); +foreach ($summary as $deptId => $info) { + echo "渠道 {$deptId}: 复制 [" . (implode(',', $info['copied'] ?? []) ?: '无') . "] 跳过 [" . (implode(',', $info['skipped'] ?? []) ?: '无') . "]\n"; +} + +echo "\n回填 dept_id...\n"; +print_r($service->backfillDataDeptId()); + +echo "\n渠道数: " . SystemDept::count() . "\n完成。\n"; diff --git a/server/db/run_system_log_dept_id.php b/server/db/run_system_log_dept_id.php new file mode 100644 index 0000000..04ca456 --- /dev/null +++ b/server/db/run_system_log_dept_id.php @@ -0,0 +1,85 @@ + 0" +); +echo "OK: login log backfilled by created_by: {$loginByCreator}\n"; + +$loginByUsername = Db::execute( + "UPDATE `sa_system_login_log` l + INNER JOIN `sa_system_user` u ON u.username = l.username + SET l.dept_id = u.dept_id + WHERE (l.dept_id IS NULL OR l.dept_id = 0) + AND u.dept_id IS NOT NULL + AND u.dept_id > 0" +); +echo "OK: login log backfilled by username: {$loginByUsername}\n"; + +$operByUsername = Db::execute( + "UPDATE `sa_system_oper_log` o + INNER JOIN `sa_system_user` u ON u.username = o.username + SET o.dept_id = u.dept_id + WHERE (o.dept_id IS NULL OR o.dept_id = 0) + AND u.dept_id IS NOT NULL + AND u.dept_id > 0" +); +echo "OK: oper log backfilled by username: {$operByUsername}\n"; + +echo "Done.\n"; diff --git a/server/db/sa_system_role_add_dept_id.sql b/server/db/sa_system_role_add_dept_id.sql new file mode 100644 index 0000000..c6df43a --- /dev/null +++ b/server/db/sa_system_role_add_dept_id.sql @@ -0,0 +1,10 @@ +-- 角色表按渠道隔离:dept_id=0 为默认模板角色,各渠道拥有独立角色副本 + +ALTER TABLE `sa_system_role` + ADD COLUMN `dept_id` bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT '所属渠道ID,0=默认模板' AFTER `id`, + ADD INDEX `idx_dept_id` (`dept_id`); + +UPDATE `sa_system_role` SET `dept_id` = 0 WHERE `dept_id` IS NULL OR `id` > 1; + +ALTER TABLE `sa_system_role` DROP INDEX `uk_slug`; +ALTER TABLE `sa_system_role` ADD UNIQUE KEY `uk_dept_code` (`dept_id`, `code`); diff --git a/server/db/sync_channel_default_roles.php b/server/db/sync_channel_default_roles.php new file mode 100644 index 0000000..9b73946 --- /dev/null +++ b/server/db/sync_channel_default_roles.php @@ -0,0 +1,21 @@ +getDefaultChannelRoleCodes()) . "\n"; + +$sync = $service->syncAllChannelsFromDefault(); +echo json_encode($sync, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n"; + +$mapped = $service->remapUserRolesToChannelRoles(); +echo "Remapped user roles: {$mapped}\n"; +echo "Done.\n"; diff --git a/server/db/test_reward_config_list.php b/server/db/test_reward_config_list.php new file mode 100644 index 0000000..5a4ed87 --- /dev/null +++ b/server/db/test_reward_config_list.php @@ -0,0 +1,20 @@ +load(); +\Webman\Config::load(BASE_PATH . '/config', ['route', 'plugin']); +\Webman\ThinkOrm\ThinkOrm::start(null); + +use app\dice\helper\AdminScopeHelper; +use app\dice\model\reward_config\DiceRewardConfig; +use app\dice\logic\reward_config\DiceRewardConfigLogic; + +$deptId = 1123; +$query = (new DiceRewardConfig())->order('id', 'asc'); +AdminScopeHelper::applyConfigScope($query, null, $deptId); +$logic = new DiceRewardConfigLogic(); +$result = $logic->getList($query); +echo 'keys: ' . implode(',', array_keys($result)) . "\n"; +$data = $result['data'] ?? $result['records'] ?? []; +echo 'count: ' . (is_array($data) ? count($data) : 0) . "\n"; diff --git a/server/db/test_reward_config_scope.php b/server/db/test_reward_config_scope.php new file mode 100644 index 0000000..e641e1c --- /dev/null +++ b/server/db/test_reward_config_scope.php @@ -0,0 +1,18 @@ +load(); +\Webman\Config::load(BASE_PATH . '/config', ['route', 'plugin']); +\Webman\ThinkOrm\ThinkOrm::start(null); + +use app\dice\helper\AdminScopeHelper; +use app\dice\model\reward_config\DiceRewardConfig; + +foreach ([0, 1123] as $deptId) { + $q1 = DiceRewardConfig::where('dept_id', $deptId); + echo "direct dept {$deptId}: " . $q1->count() . "\n"; + $q2 = (new DiceRewardConfig())->order('id', 'asc'); + AdminScopeHelper::applyConfigScope($q2, ['id' => 1], $deptId); + echo "super admin scoped dept {$deptId}: " . $q2->count() . "\n"; +} diff --git a/server/db/verify_channel_init.php b/server/db/verify_channel_init.php new file mode 100644 index 0000000..fcc06f3 --- /dev/null +++ b/server/db/verify_channel_init.php @@ -0,0 +1,45 @@ +load(); +\Webman\Config::load(BASE_PATH . '/config', ['route', 'plugin']); +\Webman\ThinkOrm\ThinkOrm::start(null); + +use plugin\saiadmin\app\model\system\SystemDept; +use support\think\Db; + +$deptIds = SystemDept::column('id'); +echo "渠道数: " . count($deptIds) . " [" . implode(',', $deptIds) . "]\n\n"; + +$tables = [ + 'dice_config', + 'dice_ante_config', + 'dice_lottery_pool_config', + 'dice_reward_config', + 'dice_reward', + 'dice_game', +]; + +echo "=== 配置按 dept_id 统计 ===\n"; +foreach ($tables as $table) { + $rows = Db::query("SELECT dept_id, COUNT(*) AS cnt FROM `{$table}` GROUP BY dept_id ORDER BY dept_id"); + echo "{$table}:\n"; + foreach ($rows as $r) { + $dept = $r['dept_id'] === null ? 'NULL' : (string) $r['dept_id']; + echo " dept_id={$dept}: {$r['cnt']}\n"; + } +} + +echo "\n=== 业务数据未回填 dept_id ===\n"; +$biz = ['dice_player', 'dice_play_record', 'dice_play_record_test']; +foreach ($biz as $table) { + if (!Db::getFields($table)) { + continue; + } + $nullCnt = Db::table($table)->where(function ($q) { + $q->whereNull('dept_id')->whereOr('dept_id', 0); + })->count(); + $total = Db::table($table)->count(); + echo "{$table}: 未回填 {$nullCnt} / 总计 {$total}\n"; +} diff --git a/server/db/verify_reward_index_all.php b/server/db/verify_reward_index_all.php new file mode 100644 index 0000000..98f9b31 --- /dev/null +++ b/server/db/verify_reward_index_all.php @@ -0,0 +1,26 @@ +load(); +\Webman\Config::load(BASE_PATH . '/config', ['route', 'plugin']); +\Webman\ThinkOrm\ThinkOrm::start(null); + +use app\dice\helper\AdminScopeHelper; +use app\dice\logic\reward_config\DiceRewardConfigLogic; +use plugin\saiadmin\app\cache\UserInfoCache; + +$adminInfo = UserInfoCache::getUserInfo(123); +$logic = new DiceRewardConfigLogic(); +$query = $logic->search([]); +AdminScopeHelper::applyConfigScope($query, $adminInfo, 1123); +$data = $query->order('id', 'asc')->select()->toArray(); +echo 'controller-style all rows: ' . count($data) . PHP_EOL; +$nonBig = 0; +foreach ($data as $row) { + if (($row['tier'] ?? '') !== 'BIGWIN') { + $nonBig++; + } +} +echo 'index tab rows (non-BIGWIN): ' . $nonBig . PHP_EOL; +echo 'bigwin tab rows: ' . (count($data) - $nonBig) . PHP_EOL;