功能:站长礼包系统(金币/经验双类型)+ 后台用户编辑权限收紧(仅 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:
80
app/Models/RedPacketEnvelope.php
Normal file
80
app/Models/RedPacketEnvelope.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 文件功能:聊天室礼包(红包)主表 Model
|
||||
*
|
||||
* 由 superlevel 管理员在聊天室内发出,每次固定 888 金币分 10 个名额。
|
||||
* 先到先得,领完或超时后自动关闭。
|
||||
*
|
||||
* @author ChatRoom Laravel
|
||||
* @version 1.0.0
|
||||
*/
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class RedPacketEnvelope extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'sender_id',
|
||||
'sender_username',
|
||||
'room_id',
|
||||
'type',
|
||||
'total_amount',
|
||||
'total_count',
|
||||
'claimed_count',
|
||||
'claimed_amount',
|
||||
'status',
|
||||
'expires_at',
|
||||
];
|
||||
|
||||
/**
|
||||
* 类型转换。
|
||||
*/
|
||||
public function casts(): array
|
||||
{
|
||||
return [
|
||||
'expires_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 关联领取记录。
|
||||
*
|
||||
* @return HasMany<RedPacketClaim>
|
||||
*/
|
||||
public function claims(): HasMany
|
||||
{
|
||||
return $this->hasMany(RedPacketClaim::class, 'envelope_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断红包当前是否可以被领取。
|
||||
*
|
||||
* 条件:状态为 active + 未过期 + 未领满。
|
||||
*/
|
||||
public function isClaimable(): bool
|
||||
{
|
||||
return $this->status === 'active'
|
||||
&& $this->expires_at->isFuture()
|
||||
&& $this->claimed_count < $this->total_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 剩余可领份数。
|
||||
*/
|
||||
public function remainingCount(): int
|
||||
{
|
||||
return max(0, $this->total_count - $this->claimed_count);
|
||||
}
|
||||
|
||||
/**
|
||||
* 剩余金额。
|
||||
*/
|
||||
public function remainingAmount(): int
|
||||
{
|
||||
return max(0, $this->total_amount - $this->claimed_amount);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user