老虎机三项修复:①来源label已有枚举(刷新即显中文) ②普通中奖/诅咒向本人发私聊通知+三7全服广播 ③FAB按钮支持拖动+位置localStorage持久化
This commit is contained in:
@@ -146,6 +146,7 @@ class SlotMachineController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ⑤ 写游戏日志
|
// ⑤ 写游戏日志
|
||||||
|
$resultLabel = SlotMachineLog::resultLabel($resultType);
|
||||||
SlotMachineLog::create([
|
SlotMachineLog::create([
|
||||||
'user_id' => $user->id,
|
'user_id' => $user->id,
|
||||||
'reel1' => $r1,
|
'reel1' => $r1,
|
||||||
@@ -156,9 +157,23 @@ class SlotMachineController extends Controller
|
|||||||
'payout' => $payout,
|
'payout' => $payout,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// ⑥ 三个7:全服公屏广播
|
// ⑥ 广播通知
|
||||||
|
$e1 = $symbols[$r1]['emoji'];
|
||||||
|
$e2 = $symbols[$r2]['emoji'];
|
||||||
|
$e3 = $symbols[$r3]['emoji'];
|
||||||
|
|
||||||
if ($resultType === 'jackpot') {
|
if ($resultType === 'jackpot') {
|
||||||
|
// 三个7:全服公屏广播
|
||||||
$this->broadcastJackpot($user->username, $payout, $cost);
|
$this->broadcastJackpot($user->username, $payout, $cost);
|
||||||
|
} elseif (in_array($resultType, ['triple_gem', 'triple', 'pair'], true)) {
|
||||||
|
// 普通中奖:仅向本人发送聊天室系统通知
|
||||||
|
$net = $payout - $cost;
|
||||||
|
$content = "🎰 {$resultLabel}!{$e1}{$e2}{$e3} 赢得 +🪙".number_format($net).' 金币';
|
||||||
|
$this->broadcastPersonal($user->username, $content);
|
||||||
|
} elseif ($resultType === 'curse') {
|
||||||
|
// 诅咒:通知本人
|
||||||
|
$content = "☠️ 三骷髅诅咒!{$e1}{$e2}{$e3} 额外扣除 🪙".number_format($cost).' 金币!';
|
||||||
|
$this->broadcastPersonal($user->username, $content);
|
||||||
}
|
}
|
||||||
|
|
||||||
$user->refresh();
|
$user->refresh();
|
||||||
@@ -246,4 +261,28 @@ class SlotMachineController extends Controller
|
|||||||
broadcast(new MessageSent(1, $msg));
|
broadcast(new MessageSent(1, $msg));
|
||||||
SaveMessageJob::dispatch($msg);
|
SaveMessageJob::dispatch($msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向特定用户发送聊天室私人系统通知(仅该用户可见)。
|
||||||
|
*
|
||||||
|
* @param string $toUsername 接收用户名
|
||||||
|
* @param string $content 消息内容
|
||||||
|
*/
|
||||||
|
private function broadcastPersonal(string $toUsername, string $content): void
|
||||||
|
{
|
||||||
|
$msg = [
|
||||||
|
'id' => $this->chatState->nextMessageId(1),
|
||||||
|
'room_id' => 1,
|
||||||
|
'from_user' => '系统传音',
|
||||||
|
'to_user' => $toUsername,
|
||||||
|
'content' => $content,
|
||||||
|
'is_secret' => true,
|
||||||
|
'font_color' => '#f59e0b',
|
||||||
|
'action' => '',
|
||||||
|
'sent_at' => now()->toDateTimeString(),
|
||||||
|
];
|
||||||
|
|
||||||
|
broadcast(new MessageSent(1, $msg));
|
||||||
|
SaveMessageJob::dispatch($msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,16 +9,24 @@
|
|||||||
- 最近记录展示
|
- 最近记录展示
|
||||||
--}}
|
--}}
|
||||||
|
|
||||||
{{-- ─── 老虎机悬浮按钮 ─── --}}
|
{{-- ─── 老虎机悬浮按钮(可拖动) ─── --}}
|
||||||
<div id="slot-fab" x-data="slotFab()" x-show="visible" x-cloak
|
<div id="slot-fab"
|
||||||
style="position:fixed; bottom:150px; right:18px; z-index:9900;">
|
x-data="slotFab()"
|
||||||
<button x-on:click="openPanel()"
|
x-show="visible"
|
||||||
style="width:52px; height:52px; border-radius:50%; border:none; cursor:pointer;
|
x-cloak
|
||||||
|
:style="'position:fixed; right:' + posX + 'px; bottom:' + posY + 'px; z-index:9900; touch-action:none; user-select:none;'"
|
||||||
|
@pointerdown.prevent="startDrag($event)"
|
||||||
|
@pointermove.window="onDrag($event)"
|
||||||
|
@pointerup.window="endDrag($event)"
|
||||||
|
@pointercancel.window="endDrag($event)">
|
||||||
|
<button
|
||||||
|
style="width:52px; height:52px; border-radius:50%; border:none;
|
||||||
background:linear-gradient(135deg,#d97706,#f59e0b);
|
background:linear-gradient(135deg,#d97706,#f59e0b);
|
||||||
box-shadow:0 4px 20px rgba(245,158,11,.5);
|
box-shadow:0 4px 20px rgba(245,158,11,.5);
|
||||||
font-size:22px; display:flex; align-items:center; justify-content:center;
|
font-size:22px; display:flex; align-items:center; justify-content:center;
|
||||||
animation:slot-pulse 2s infinite;"
|
animation:slot-pulse 2s infinite;"
|
||||||
title="老虎机">🎰</button>
|
:style="dragging ? 'cursor:grabbing;' : 'cursor:grab;'"
|
||||||
|
title="老虎机(可拖动)">🎰</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- ─── 老虎机主面板 ─── --}}
|
{{-- ─── 老虎机主面板 ─── --}}
|
||||||
@@ -259,15 +267,51 @@
|
|||||||
* 老虎机悬浮按钮 Alpine 组件(检查游戏是否开启)
|
* 老虎机悬浮按钮 Alpine 组件(检查游戏是否开启)
|
||||||
*/
|
*/
|
||||||
function slotFab() {
|
function slotFab() {
|
||||||
|
const STORAGE_KEY = 'slot_fab_pos';
|
||||||
|
const saved = JSON.parse(localStorage.getItem(STORAGE_KEY) || 'null');
|
||||||
return {
|
return {
|
||||||
visible: false,
|
visible: false,
|
||||||
|
posX: saved?.x ?? 18,
|
||||||
|
posY: saved?.y ?? 150,
|
||||||
|
dragging: false,
|
||||||
|
_startX: 0, _startY: 0,
|
||||||
|
_origX: 0, _origY: 0,
|
||||||
|
_moved: false,
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
try {
|
try {
|
||||||
const res = await fetch('/slot/info');
|
const res = await fetch('/slot/info');
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
this.visible = data.enabled === true;
|
this.visible = data.enabled === true;
|
||||||
} catch {}
|
} catch {}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
startDrag(e) {
|
||||||
|
this.dragging = true;
|
||||||
|
this._moved = false;
|
||||||
|
this._startX = e.clientX;
|
||||||
|
this._startY = e.clientY;
|
||||||
|
this._origX = this.posX;
|
||||||
|
this._origY = this.posY;
|
||||||
|
e.currentTarget.setPointerCapture?.(e.pointerId);
|
||||||
|
},
|
||||||
|
|
||||||
|
onDrag(e) {
|
||||||
|
if (!this.dragging) return;
|
||||||
|
const dx = e.clientX - this._startX;
|
||||||
|
const dy = e.clientY - this._startY;
|
||||||
|
if (Math.abs(dx) > 3 || Math.abs(dy) > 3) this._moved = true;
|
||||||
|
this.posX = Math.max(4, Math.min(window.innerWidth - 60, this._origX - dx));
|
||||||
|
this.posY = Math.max(4, Math.min(window.innerHeight - 60, this._origY + dy));
|
||||||
|
},
|
||||||
|
|
||||||
|
endDrag(e) {
|
||||||
|
if (!this.dragging) return;
|
||||||
|
this.dragging = false;
|
||||||
|
localStorage.setItem(STORAGE_KEY, JSON.stringify({ x: this.posX, y: this.posY }));
|
||||||
|
if (!this._moved) this.openPanel();
|
||||||
|
},
|
||||||
|
|
||||||
openPanel() {
|
openPanel() {
|
||||||
const panel = document.getElementById('slot-panel');
|
const panel = document.getElementById('slot-panel');
|
||||||
if (panel) Alpine.$data(panel).open();
|
if (panel) Alpine.$data(panel).open();
|
||||||
|
|||||||
Reference in New Issue
Block a user