feat: 神秘箱子系统完整实现 + 婚姻状态弹窗 + 工具栏优化

## 新功能
- 神秘箱子系统(MysteryBox)完整实现:
  - 新增 MysteryBox / MysteryBoxClaim 模型及迁移文件
  - DropMysteryBoxJob / ExpireMysteryBoxJob 队列作业
  - MysteryBoxController(/mystery-box/status + /mystery-box/claim)
  - 支持三种类型:普通箱(500~2000金)/ 稀有箱(5000~20000金)/ 黑化箱(陷阱扣200~1000金)
  - 调度器自动投放 + 管理员手动投放
  - CurrencySource 新增 MYSTERY_BOX / MYSTERY_BOX_TRAP 枚举

- 婚姻状态弹窗(工具栏「婚姻」按钮):
  - 工具栏「呼叫」改为「婚姻」,点击打开婚姻状态弹窗
  - 动态渲染三种状态:单身 / 求婚中 / 已婚
  - 被求婚方可直接「答应 / 婉拒」;已婚可申请离婚(含二次确认)

## 优化修复
- frame.blade.php:Alpine.js CDN 补加 defer,修复所有组件初始化报错
- scripts.blade.php:神秘箱子暗号主动拦截(不依赖轮询),领取成功后弹 chatDialog 展示结果,更新金币余额
- MysteryBoxController:claim() 时 change() 补传 room_id 记录来源房间
- 后台游戏管理页(game-configs):投放箱子按钮颜色修复;弹窗替换为 window.adminDialog
- admin/layouts:新增全局 adminDialog 弹窗组件(替代原生 alert/confirm)
- baccarat-panel:FAB 拖动重构为 Alpine.js baccaratFab() 组件,与 slotFab 一致
- GAMES_TODO.md:神秘箱子移入已完成区,补全修复记录
This commit is contained in:
2026-03-03 19:29:43 +08:00
parent 40fcce2db3
commit 602dcd7cf1
21 changed files with 1799 additions and 139 deletions

View File

@@ -0,0 +1,59 @@
<?php
/**
* 文件功能:神秘箱子主表迁移
*
* 记录每次系统/管理员投放的神秘箱信息,包含类型、暗号、奖惩范围及领取状态。
*
* @author ChatRoom Laravel
* @version 1.0.0
*/
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* 创建神秘箱子表。
*/
public function up(): void
{
Schema::create('mystery_boxes', function (Blueprint $table) {
$table->id();
// 箱子类型normal=普通(500~2000) / rare=稀有(5000~20000) / trap=黑化(陷阱,倒扣)
$table->enum('box_type', ['normal', 'rare', 'trap'])->default('normal')->comment('箱子类型');
// 领取暗号管理员设置或自动生成4~8位随机字串
$table->string('passcode', 20)->comment('领取暗号');
// 奖励金额范围trap 类型此字段为负值上下界)
$table->integer('reward_min')->default(500)->comment('最低奖励金币');
$table->integer('reward_max')->default(2000)->comment('最高奖励金币');
// 状态open=可领取 / claimed=已被领取 / expired=已过期
$table->enum('status', ['open', 'claimed', 'expired'])->default('open')->comment('箱子状态');
// 领取截止时间(投放后 N 秒内有效)
$table->timestamp('expires_at')->nullable()->comment('过期时间');
// 由哪个管理员用户投放null=系统自动投放)
$table->unsignedBigInteger('dropped_by')->nullable()->comment('投放者用户IDnull=系统自动');
$table->timestamps();
$table->index('status');
$table->index('expires_at');
});
}
/**
* 回滚:删除神秘箱子表。
*/
public function down(): void
{
Schema::dropIfExists('mystery_boxes');
}
};

View File

@@ -0,0 +1,51 @@
<?php
/**
* 文件功能:神秘箱子领取记录表迁移
*
* 记录每个箱子被哪位用户在何时用什么暗号领取,以及实际奖励金额。
*
* @author ChatRoom Laravel
* @version 1.0.0
*/
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* 创建神秘箱子领取记录表。
*/
public function up(): void
{
Schema::create('mystery_box_claims', function (Blueprint $table) {
$table->id();
// 关联箱子
$table->unsignedBigInteger('mystery_box_id')->comment('关联神秘箱子ID');
$table->foreign('mystery_box_id')->references('id')->on('mystery_boxes')->cascadeOnDelete();
// 领取用户
$table->unsignedBigInteger('user_id')->comment('领取用户ID');
$table->foreign('user_id')->references('id')->on('users')->cascadeOnDelete();
// 实际奖励(正数=获得,负数=被扣)
$table->integer('reward_amount')->comment('实际奖励金额(负数表示扣除)');
$table->timestamps();
$table->index('mystery_box_id');
$table->index('user_id');
});
}
/**
* 回滚:删除领取记录表。
*/
public function down(): void
{
Schema::dropIfExists('mystery_box_claims');
}
};

View File

@@ -70,14 +70,16 @@ class GameConfigSeeder extends Seeder
'description' => '管理员随时投放或系统定时自动投放神秘箱,最快发送暗号的用户开箱获得奖励。',
'enabled' => false,
'params' => [
'auto_drop_enabled' => false, // 是否自动定时投放
'auto_interval_hours' => 2, // 自动投放间隔(小时)
'auto_drop_enabled' => false, // 是否自动定时投放
'auto_interval_hours' => 2, // 自动投放间隔(小时)
'claim_window_seconds' => 60, // 领取窗口(秒)
'min_reward' => 500, // 普通箱最低奖励
'max_reward' => 2000, // 普通箱最高奖励
'rare_min_reward' => 5000, // 稀有箱最低奖励
'rare_max_reward' => 20000, // 稀有箱最高奖励
'trap_chance_percent' => 10, // 黑化箱触发概率(%
'normal_reward_min' => 500, // 普通箱最低奖励
'normal_reward_max' => 2000, // 普通箱最高奖励
'rare_reward_min' => 5000, // 稀有箱最低奖励
'rare_reward_max' => 20000, // 稀有箱最高奖励
'trap_penalty_min' => 200, // 黑化箱最低惩罚
'trap_penalty_max' => 1000, // 黑化箱最高惩罚
'trap_chance_percent' => 10, // 黑化箱触发概率(%
],
],