功能:站长礼包系统(金币/经验双类型)+ 后台用户编辑权限收紧(仅 id=1 超管)
新增功能:
- 礼包系统:superlevel 站长可发 888 数量 10 份礼包,支持金币/经验双类型
- 发包前三按钮选择(金币礼包 / 经验礼包 / 取消),使用 chatBanner 弹窗
- 聊天室系统公告含「立即抢包」按钮,金币红色/经验紫色配色区分
- WebSocket 实时推送红包弹窗卡片至所有在线用户
- Redis LPOP 原子分发 + 数据库 unique 约束防重领,并发安全
- 弹窗打开自动拉取服务端最新状态(剩余数量/已领/过期实时刷新)
- 新增 GET /red-packet/{id}/status 状态查询接口
- 新增 CurrencySource::RED_PACKET_RECV / RED_PACKET_RECV_EXP 枚举
安全加固:
- 后台用户编辑/强杀按钮仅 id=1 超管可见(前端隐藏 + 后端 403 双重拦截)
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 文件功能:创建聊天室礼包(红包)相关数据表
|
||||
*
|
||||
* red_packet_envelopes:红包主表(superlevel 用户发出的 888 金币红包)
|
||||
* red_packet_claims:红包领取记录(先到先得,每人只能领一次)
|
||||
*
|
||||
* @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('red_packet_envelopes', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('sender_id')->comment('发包用户 ID');
|
||||
$table->string('sender_username', 20)->comment('发包用户名(快照)');
|
||||
$table->unsignedInteger('room_id')->comment('发出所在房间 ID');
|
||||
$table->unsignedInteger('total_amount')->comment('红包总金额(金币)');
|
||||
$table->unsignedInteger('total_count')->comment('红包总份数');
|
||||
$table->unsignedInteger('claimed_count')->default(0)->comment('已被领取份数');
|
||||
$table->unsignedInteger('claimed_amount')->default(0)->comment('已被领取总金额');
|
||||
$table->string('status', 10)->default('active')->comment('状态:active / completed / expired');
|
||||
$table->timestamp('expires_at')->comment('过期时间(超时未领完则关闭)');
|
||||
$table->timestamps();
|
||||
|
||||
$table->index(['room_id', 'status']);
|
||||
$table->index('sender_id');
|
||||
});
|
||||
|
||||
// 领取记录表
|
||||
Schema::create('red_packet_claims', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('envelope_id')->comment('关联红包 ID');
|
||||
$table->unsignedBigInteger('user_id')->comment('领取用户 ID');
|
||||
$table->string('username', 20)->comment('领取用户名(快照)');
|
||||
$table->unsignedInteger('amount')->comment('本次领取金额');
|
||||
$table->timestamp('claimed_at')->useCurrent()->comment('领取时间');
|
||||
|
||||
// 每人每个红包只能领一次
|
||||
$table->unique(['envelope_id', 'user_id']);
|
||||
$table->index('envelope_id');
|
||||
$table->foreign('envelope_id')->references('id')->on('red_packet_envelopes')->cascadeOnDelete();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 回滚:删除红包相关表。
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('red_packet_claims');
|
||||
Schema::dropIfExists('red_packet_envelopes');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 文件功能:为礼包红包主表新增货币类型字段
|
||||
*
|
||||
* type 字段区分本次红包发放的是金币(gold)还是经验(exp)。
|
||||
* 默认 gold,兼容已有记录。
|
||||
*
|
||||
* @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
|
||||
{
|
||||
/**
|
||||
* 新增 type 字段到 red_packet_envelopes 表。
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('red_packet_envelopes', function (Blueprint $table) {
|
||||
// 货币类型:gold = 金币,exp = 经验值
|
||||
$table->string('type', 10)->default('gold')->after('room_id')->comment('货币类型:gold / exp');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 回滚:删除 type 字段。
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('red_packet_envelopes', function (Blueprint $table) {
|
||||
$table->dropColumn('type');
|
||||
});
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user