Files
dafuweng-saiadmin6.x/server/db/run_all_init.php
2026-05-26 09:43:42 +08:00

192 lines
6.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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";