DB数据库文件
This commit is contained in:
84
server/db/audit_channel_config.php
Normal file
84
server/db/audit_channel_config.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/**
|
||||
* 审计各渠道游戏配置是否已从默认模板实例化
|
||||
* 用法:php server/db/audit_channel_config.php [--fix]
|
||||
*/
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
require_once __DIR__ . '/../support/bootstrap.php';
|
||||
|
||||
use app\dice\helper\AdminScopeHelper;
|
||||
use app\dice\service\DiceChannelConfigService;
|
||||
use plugin\saiadmin\app\model\system\SystemDept;
|
||||
use support\think\Db;
|
||||
|
||||
$fix = in_array('--fix', $argv ?? [], true);
|
||||
$templateId = AdminScopeHelper::DEFAULT_TEMPLATE_DEPT;
|
||||
$tables = [
|
||||
'dice_config',
|
||||
'dice_ante_config',
|
||||
'dice_lottery_pool_config',
|
||||
'dice_reward_config',
|
||||
'dice_game',
|
||||
'dice_reward',
|
||||
];
|
||||
|
||||
$templateCounts = [];
|
||||
foreach ($tables as $table) {
|
||||
$templateCounts[$table] = (int) Db::table($table)
|
||||
->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";
|
||||
16
server/db/check_reward_config.php
Normal file
16
server/db/check_reward_config.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
define('BASE_PATH', dirname(__DIR__));
|
||||
require BASE_PATH . '/vendor/autoload.php';
|
||||
\Dotenv\Dotenv::createUnsafeMutable(BASE_PATH)->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";
|
||||
}
|
||||
11
server/db/count_config_tables.php
Normal file
11
server/db/count_config_tables.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
define('BASE_PATH', dirname(__DIR__));
|
||||
require BASE_PATH . '/vendor/autoload.php';
|
||||
\Dotenv\Dotenv::createUnsafeMutable(BASE_PATH)->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";
|
||||
}
|
||||
61
server/db/debug_reward_api_user123.php
Normal file
61
server/db/debug_reward_api_user123.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
define('BASE_PATH', dirname(__DIR__));
|
||||
require BASE_PATH . '/vendor/autoload.php';
|
||||
\Dotenv\Dotenv::createUnsafeMutable(BASE_PATH)->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";
|
||||
}
|
||||
46
server/db/debug_reward_index_user123.php
Normal file
46
server/db/debug_reward_index_user123.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
define('BASE_PATH', dirname(__DIR__));
|
||||
require BASE_PATH . '/vendor/autoload.php';
|
||||
\Dotenv\Dotenv::createUnsafeMutable(BASE_PATH)->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";
|
||||
39
server/db/debug_reward_query_detail.php
Normal file
39
server/db/debug_reward_query_detail.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
define('BASE_PATH', dirname(__DIR__));
|
||||
require BASE_PATH . '/vendor/autoload.php';
|
||||
\Dotenv\Dotenv::createUnsafeMutable(BASE_PATH)->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);
|
||||
}
|
||||
36
server/db/debug_user123_reward.php
Normal file
36
server/db/debug_user123_reward.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
define('BASE_PATH', dirname(__DIR__));
|
||||
require BASE_PATH . '/vendor/autoload.php';
|
||||
\Dotenv\Dotenv::createUnsafeMutable(BASE_PATH)->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";
|
||||
26
server/db/dept_flatten_channels.sql
Normal file
26
server/db/dept_flatten_channels.sql
Normal file
@@ -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';
|
||||
10
server/db/dice_player_dept_username_unique.sql
Normal file
10
server/db/dice_player_dept_username_unique.sql
Normal file
@@ -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`);
|
||||
2
server/db/dice_player_username_index.sql
Normal file
2
server/db/dice_player_username_index.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
-- 已废弃:请使用 dice_player_dept_username_unique.sql(同一渠道 dept_id + username 唯一)
|
||||
-- 历史脚本保留说明,勿再单独执行本文件
|
||||
92
server/db/dice_tables_add_dept_id.sql
Normal file
92
server/db/dice_tables_add_dept_id.sql
Normal file
@@ -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;
|
||||
93
server/db/inspect_player_destroy.php
Normal file
93
server/db/inspect_player_destroy.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/**
|
||||
* 排查 dice_player 删除报错:
|
||||
* - 表结构
|
||||
* - 外键引用情况
|
||||
* - 实际 destroy 流程(不真的删,仅 dry-run 抓异常)
|
||||
*
|
||||
* 用法:php server/db/inspect_player_destroy.php [<id1>,<id2>,...]
|
||||
*/
|
||||
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";
|
||||
35
server/db/remove_safeguard_ops_role_menus.sql
Normal file
35
server/db/remove_safeguard_ops_role_menus.sql
Normal file
@@ -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'
|
||||
);
|
||||
14
server/db/remove_system_post.sql
Normal file
14
server/db/remove_system_post.sql
Normal file
@@ -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`;
|
||||
191
server/db/run_all_init.php
Normal file
191
server/db/run_all_init.php
Normal file
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
/**
|
||||
* 一键执行渠道与游戏配置初始化(需已备份数据库)
|
||||
* 用法:在 server 目录执行 php db/run_all_init.php
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
define('BASE_PATH', dirname(__DIR__));
|
||||
|
||||
require_once BASE_PATH . '/vendor/autoload.php';
|
||||
|
||||
if (class_exists(\Dotenv\Dotenv::class) && is_file(BASE_PATH . '/.env')) {
|
||||
if (method_exists(\Dotenv\Dotenv::class, 'createUnsafeMutable')) {
|
||||
\Dotenv\Dotenv::createUnsafeMutable(BASE_PATH)->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";
|
||||
16
server/db/run_backfill_dept_id.php
Normal file
16
server/db/run_backfill_dept_id.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
define('BASE_PATH', dirname(__DIR__));
|
||||
require_once BASE_PATH . '/vendor/autoload.php';
|
||||
\Dotenv\Dotenv::createUnsafeMutable(BASE_PATH)->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";
|
||||
46
server/db/run_channel_config_init.php
Normal file
46
server/db/run_channel_config_init.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/**
|
||||
* 渠道配置初始化:默认模板 + 为已有渠道补齐配置 + 业务数据 dept_id 回填
|
||||
* 用法:在 server 目录执行 php db/run_channel_config_init.php
|
||||
*/
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$bootstrap = __DIR__ . '/../support/bootstrap.php';
|
||||
if (is_file($bootstrap)) {
|
||||
require_once $bootstrap;
|
||||
}
|
||||
|
||||
use app\dice\service\DiceChannelConfigService;
|
||||
use support\think\Db;
|
||||
|
||||
$service = new DiceChannelConfigService();
|
||||
|
||||
echo "1. 将 dept_id=0 的配置归为默认模板(dept_id 置空)...\n";
|
||||
echo " 若需将全部现有配置作为模板,请确认后手动执行 UPDATE ... SET dept_id=NULL\n";
|
||||
foreach (
|
||||
[
|
||||
'dice_config',
|
||||
'dice_ante_config',
|
||||
'dice_lottery_pool_config',
|
||||
'dice_reward_config',
|
||||
'dice_reward',
|
||||
'dice_game',
|
||||
] as $table
|
||||
) {
|
||||
try {
|
||||
Db::table($table)->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";
|
||||
55
server/db/run_dept_flatten_channels.php
Normal file
55
server/db/run_dept_flatten_channels.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* 渠道扁平化迁移脚本(多级子渠道用户归并到顶级渠道后删除子渠道)
|
||||
* 用法:在 server 目录下执行 php db/run_dept_flatten_channels.php
|
||||
*/
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use plugin\saiadmin\app\model\system\SystemDept;
|
||||
use plugin\saiadmin\app\model\system\SystemUser;
|
||||
use support\think\Db;
|
||||
|
||||
$bootstrap = __DIR__ . '/../support/bootstrap.php';
|
||||
if (is_file($bootstrap)) {
|
||||
require_once $bootstrap;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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";
|
||||
});
|
||||
53
server/db/run_dice_player_dept_username_unique.php
Normal file
53
server/db/run_dice_player_dept_username_unique.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* 为 dice_player 增加 (dept_id, username) 唯一索引
|
||||
* 用法:在 server 目录执行 php db/run_dice_player_dept_username_unique.php
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
define('BASE_PATH', dirname(__DIR__));
|
||||
|
||||
require_once BASE_PATH . '/vendor/autoload.php';
|
||||
|
||||
if (class_exists(\Dotenv\Dotenv::class) && is_file(BASE_PATH . '/.env')) {
|
||||
if (method_exists(\Dotenv\Dotenv::class, 'createUnsafeMutable')) {
|
||||
\Dotenv\Dotenv::createUnsafeMutable(BASE_PATH)->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";
|
||||
33
server/db/run_fill_missing_channel_config.php
Normal file
33
server/db/run_fill_missing_channel_config.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* 为已有渠道补齐缺失的默认配置(不删除已有数据)
|
||||
* 用法:php db/run_fill_missing_channel_config.php
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
define('BASE_PATH', dirname(__DIR__));
|
||||
require_once BASE_PATH . '/vendor/autoload.php';
|
||||
|
||||
if (class_exists(\Dotenv\Dotenv::class) && is_file(BASE_PATH . '/.env')) {
|
||||
\Dotenv\Dotenv::createUnsafeMutable(BASE_PATH)->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";
|
||||
100
server/db/run_remove_safeguard_ops_role_menus.php
Normal file
100
server/db/run_remove_safeguard_ops_role_menus.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
/**
|
||||
* 从所有角色中移除以下运维菜单及其按钮权限:
|
||||
* /safeguard/dict
|
||||
* /safeguard/attachment
|
||||
* /safeguard/database
|
||||
* /safeguard/server
|
||||
* /safeguard/cache
|
||||
* /safeguard/email-log
|
||||
*
|
||||
* 用法(在 server 目录): php db/run_remove_safeguard_ops_role_menus.php
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
require_once __DIR__ . '/../support/bootstrap.php';
|
||||
|
||||
use plugin\saiadmin\app\cache\UserMenuCache;
|
||||
use support\think\Db;
|
||||
|
||||
$targetRoutes = [
|
||||
'/safeguard/dict',
|
||||
'/safeguard/attachment',
|
||||
'/safeguard/database',
|
||||
'/safeguard/server',
|
||||
'/safeguard/cache',
|
||||
'/safeguard/email-log',
|
||||
];
|
||||
|
||||
/**
|
||||
* @param int[] $parentIds
|
||||
* @return int[]
|
||||
*/
|
||||
function collectChildMenuIds(array $parentIds): array
|
||||
{
|
||||
if ($parentIds === []) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$childIds = Db::name('sa_system_menu')
|
||||
->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";
|
||||
74
server/db/run_sa_system_role_dept_id.php
Normal file
74
server/db/run_sa_system_role_dept_id.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/**
|
||||
* 执行 sa_system_role 渠道隔离迁移,并为已有渠道复制默认角色、映射用户角色
|
||||
*
|
||||
* 用法(在 server 目录): php db/run_sa_system_role_dept_id.php
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
require_once __DIR__ . '/../support/bootstrap.php';
|
||||
|
||||
use plugin\saiadmin\app\service\SystemRoleChannelService;
|
||||
use support\think\Db;
|
||||
|
||||
function tableHasColumn(string $table, string $column): bool
|
||||
{
|
||||
try {
|
||||
$fields = Db::getFields($table);
|
||||
return isset($fields[$column]);
|
||||
} catch (\Throwable $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function indexExists(string $table, string $indexName): bool
|
||||
{
|
||||
$rows = Db::query("SHOW INDEX FROM `{$table}` WHERE Key_name = ?", [$indexName]);
|
||||
return !empty($rows);
|
||||
}
|
||||
|
||||
echo "=== sa_system_role dept_id migration ===\n";
|
||||
|
||||
if (!tableHasColumn('sa_system_role', 'dept_id')) {
|
||||
Db::execute(
|
||||
"ALTER TABLE `sa_system_role`
|
||||
ADD COLUMN `dept_id` bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT '所属渠道ID,0=默认模板' AFTER `id`"
|
||||
);
|
||||
echo "OK: ADD COLUMN dept_id\n";
|
||||
} else {
|
||||
echo "SKIP: dept_id column exists\n";
|
||||
}
|
||||
|
||||
if (!indexExists('sa_system_role', 'idx_dept_id')) {
|
||||
Db::execute('ALTER TABLE `sa_system_role` ADD INDEX `idx_dept_id` (`dept_id`)');
|
||||
echo "OK: ADD INDEX idx_dept_id\n";
|
||||
} else {
|
||||
echo "SKIP: idx_dept_id exists\n";
|
||||
}
|
||||
|
||||
Db::execute('UPDATE `sa_system_role` SET `dept_id` = 0 WHERE `id` > 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";
|
||||
58
server/db/run_sync_channel_config.php
Normal file
58
server/db/run_sync_channel_config.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* 仅执行渠道配置同步(步骤 4-6),适用于已完成表结构迁移后
|
||||
* 用法:php db/run_sync_channel_config.php
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
define('BASE_PATH', dirname(__DIR__));
|
||||
require_once BASE_PATH . '/vendor/autoload.php';
|
||||
|
||||
if (class_exists(\Dotenv\Dotenv::class) && is_file(BASE_PATH . '/.env')) {
|
||||
\Dotenv\Dotenv::createUnsafeMutable(BASE_PATH)->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";
|
||||
85
server/db/run_system_log_dept_id.php
Normal file
85
server/db/run_system_log_dept_id.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/**
|
||||
* 为登录日志、操作日志补充 dept_id 字段并回填历史数据。
|
||||
*
|
||||
* 用法(在 server 目录): php db/run_system_log_dept_id.php
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
require_once __DIR__ . '/../support/bootstrap.php';
|
||||
|
||||
use support\think\Db;
|
||||
|
||||
function systemLogTableHasColumn(string $table, string $column): bool
|
||||
{
|
||||
try {
|
||||
$fields = Db::getFields($table);
|
||||
return isset($fields[$column]);
|
||||
} catch (\Throwable $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function systemLogIndexExists(string $table, string $indexName): bool
|
||||
{
|
||||
$rows = Db::query("SHOW INDEX FROM `{$table}` WHERE Key_name = ?", [$indexName]);
|
||||
return !empty($rows);
|
||||
}
|
||||
|
||||
function addLogDeptColumn(string $table, string $afterColumn): void
|
||||
{
|
||||
if (!systemLogTableHasColumn($table, 'dept_id')) {
|
||||
Db::execute(
|
||||
"ALTER TABLE `{$table}`
|
||||
ADD COLUMN `dept_id` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '所属渠道ID' AFTER `{$afterColumn}`"
|
||||
);
|
||||
echo "OK: {$table} ADD COLUMN dept_id\n";
|
||||
} else {
|
||||
echo "SKIP: {$table} dept_id column exists\n";
|
||||
}
|
||||
|
||||
if (!systemLogIndexExists($table, 'idx_dept_id')) {
|
||||
Db::execute("ALTER TABLE `{$table}` ADD INDEX `idx_dept_id` (`dept_id`)");
|
||||
echo "OK: {$table} ADD INDEX idx_dept_id\n";
|
||||
} else {
|
||||
echo "SKIP: {$table} idx_dept_id exists\n";
|
||||
}
|
||||
}
|
||||
|
||||
echo "=== system log dept_id migration ===\n";
|
||||
|
||||
addLogDeptColumn('sa_system_login_log', 'login_time');
|
||||
addLogDeptColumn('sa_system_oper_log', 'request_data');
|
||||
|
||||
$loginByCreator = Db::execute(
|
||||
"UPDATE `sa_system_login_log` l
|
||||
INNER JOIN `sa_system_user` u ON u.id = l.created_by
|
||||
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 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";
|
||||
10
server/db/sa_system_role_add_dept_id.sql
Normal file
10
server/db/sa_system_role_add_dept_id.sql
Normal file
@@ -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`);
|
||||
21
server/db/sync_channel_default_roles.php
Normal file
21
server/db/sync_channel_default_roles.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* 为各渠道补齐三个默认代理角色,并清理多余角色(无用户绑定的)
|
||||
* 用法: php db/sync_channel_default_roles.php
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
require_once __DIR__ . '/../support/bootstrap.php';
|
||||
|
||||
use plugin\saiadmin\app\service\SystemRoleChannelService;
|
||||
|
||||
$service = new SystemRoleChannelService();
|
||||
echo 'Default role codes: ' . implode(', ', $service->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";
|
||||
20
server/db/test_reward_config_list.php
Normal file
20
server/db/test_reward_config_list.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
define('BASE_PATH', dirname(__DIR__));
|
||||
require BASE_PATH . '/vendor/autoload.php';
|
||||
\Dotenv\Dotenv::createUnsafeMutable(BASE_PATH)->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";
|
||||
18
server/db/test_reward_config_scope.php
Normal file
18
server/db/test_reward_config_scope.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
define('BASE_PATH', dirname(__DIR__));
|
||||
require BASE_PATH . '/vendor/autoload.php';
|
||||
\Dotenv\Dotenv::createUnsafeMutable(BASE_PATH)->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";
|
||||
}
|
||||
45
server/db/verify_channel_init.php
Normal file
45
server/db/verify_channel_init.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
define('BASE_PATH', dirname(__DIR__));
|
||||
require_once BASE_PATH . '/vendor/autoload.php';
|
||||
\Dotenv\Dotenv::createUnsafeMutable(BASE_PATH)->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";
|
||||
}
|
||||
26
server/db/verify_reward_index_all.php
Normal file
26
server/db/verify_reward_index_all.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
define('BASE_PATH', dirname(__DIR__));
|
||||
require BASE_PATH . '/vendor/autoload.php';
|
||||
\Dotenv\Dotenv::createUnsafeMutable(BASE_PATH)->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;
|
||||
Reference in New Issue
Block a user