新增赠送金币功能:任意用户可从自己余额赠送金币给他人,成功后聊天室系统传音广播;职务奖励金币移入管理区,删除管理区私信按钮
This commit is contained in:
@@ -1135,4 +1135,73 @@ class ChatController extends Controller
|
||||
|
||||
return $isLeveledUp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户间赠送金币(任何登录用户均可调用)
|
||||
*
|
||||
* 从自己的余额中扣除指定金额,转入对方账户,
|
||||
* 并在房间内通过「系统传音」广播一条赠送提示。
|
||||
*/
|
||||
public function giftGold(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'to_user' => 'required|string',
|
||||
'room_id' => 'required|integer',
|
||||
'amount' => 'required|integer|min:1|max:999999',
|
||||
]);
|
||||
|
||||
$sender = Auth::user();
|
||||
$toName = $request->input('to_user');
|
||||
$roomId = $request->integer('room_id');
|
||||
$amount = $request->integer('amount');
|
||||
|
||||
// 不能给自己转账
|
||||
if ($toName === $sender->username) {
|
||||
return response()->json(['status' => 'error', 'message' => '不能给自己赠送哦~']);
|
||||
}
|
||||
|
||||
// 查目标用户
|
||||
$receiver = User::where('username', $toName)->first();
|
||||
if (! $receiver) {
|
||||
return response()->json(['status' => 'error', 'message' => '用户不存在']);
|
||||
}
|
||||
|
||||
// 余额校验
|
||||
if (($sender->jjb ?? 0) < $amount) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => '金币不足!您当前余额 '.($sender->jjb ?? 0)." 金币,无法赠送 {$amount} 金币。",
|
||||
]);
|
||||
}
|
||||
|
||||
// 执行转账(直接操作字段,与 sendFlower 保持一致风格)
|
||||
$sender->decrement('jjb', $amount);
|
||||
$receiver->increment('jjb', $amount);
|
||||
|
||||
// 广播「系统传音」条目至全房间
|
||||
$sysMsg = [
|
||||
'id' => $this->chatState->nextMessageId($roomId),
|
||||
'room_id' => $roomId,
|
||||
'from_user' => '系统传音',
|
||||
'to_user' => '大家',
|
||||
'content' => "💝 【{$sender->username}】 向 【{$toName}】 赠送了 {$amount} 金币!",
|
||||
'is_secret' => false,
|
||||
'font_color' => '#b45309',
|
||||
'action' => '',
|
||||
'sent_at' => now()->toDateTimeString(),
|
||||
];
|
||||
|
||||
$this->chatState->pushMessage($roomId, $sysMsg);
|
||||
broadcast(new MessageSent($roomId, $sysMsg));
|
||||
SaveMessageJob::dispatch($sysMsg);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => "赠送成功!已向 {$toName} 赠送 {$amount} 金币。",
|
||||
'data' => [
|
||||
'my_jjb' => $sender->fresh()->jjb,
|
||||
'target_jjb' => $receiver->fresh()->jjb,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,8 @@
|
||||
rewardUrl: "{{ route('command.reward') }}",
|
||||
rewardQuotaUrl: "{{ route('command.reward_quota') }}",
|
||||
userJjb: {{ (int) $user->jjb }}, // 当前用户金币(求婚前金额预检查用)
|
||||
myGold: {{ (int) $user->jjb }}, // 赠金币面板显示余额用(赠送成功后前端更新)
|
||||
|
||||
// ─── 婚姻系统 ──────────────────────────────
|
||||
minWeddingCost: {{ (int) \App\Models\WeddingTier::where('is_active', true)->orderBy('amount')->value('amount') ?? 0 }},
|
||||
marriage: {
|
||||
|
||||
@@ -96,7 +96,8 @@
|
||||
];
|
||||
@endphp
|
||||
@foreach ($welcomeMessages as $msg)
|
||||
<div class="welcome-menu-item" onclick="sendWelcomeTpl({{ json_encode($msg) }})">{{ $msg }}</div>
|
||||
<div class="welcome-menu-item" onclick="sendWelcomeTpl({{ json_encode($msg) }})">
|
||||
{{ $msg }}</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@@ -145,8 +146,8 @@
|
||||
|
||||
{{-- 第二行:输入框 + 发送 --}}
|
||||
<div class="input-row">
|
||||
<input type="text" id="content" name="content" class="say-input" placeholder="在这里输入聊天内容,按 Enter 发送..."
|
||||
autocomplete="off">
|
||||
<input type="text" id="content" name="content" class="say-input"
|
||||
placeholder="在这里输入聊天内容,按 Enter 发送..." autocomplete="off">
|
||||
<button type="submit" id="send-btn" class="send-btn">发送</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -759,7 +759,7 @@
|
||||
</div>
|
||||
|
||||
{{-- 操作按钮区:加好友 + 送礼物 + 送金币(有职务且有奖励权限时显示) --}}
|
||||
<div x-data="{ showGiftPanel: false, showRewardPanel: false }" x-show="userInfo.username !== window.chatContext.username">
|
||||
<div x-data="{ showGiftPanel: false, showGiftGoldPanel: false, giftGoldAmount: '', giftGoldSending: false }" x-show="userInfo.username !== window.chatContext.username">
|
||||
|
||||
<div class="modal-actions" style="margin-bottom: 0; display: flex; gap: 6px;">
|
||||
{{-- 加好友 / 删好友 --}}
|
||||
@@ -774,16 +774,16 @@
|
||||
|
||||
{{-- 送礼物按钮 --}}
|
||||
<button class="btn-whisper" style="flex:1;"
|
||||
x-on:click="showGiftPanel = !showGiftPanel; showRewardPanel = false;">
|
||||
x-on:click="showGiftPanel = !showGiftPanel; showGiftGoldPanel = false;">
|
||||
🎁 送礼物
|
||||
</button>
|
||||
|
||||
{{-- 送金币按钮:有在职职务且 max_reward 不为 0(0=禁止,-1=不限,正数=有上限) --}}
|
||||
<button x-show="window.chatContext?.myMaxReward !== 0"
|
||||
{{-- 赠送金币按钮:所有人均可使用,自己金币转给对方 --}}
|
||||
<button
|
||||
style="flex:1; padding: 7px 10px; border-radius: 5px; font-size: 12px; font-weight: bold; cursor: pointer;
|
||||
background: linear-gradient(135deg,#f59e0b,#d97706); color:#fff; border:none;"
|
||||
x-on:click="openRewardModal(userInfo.username)">
|
||||
💰 送金币
|
||||
x-on:click="showGiftGoldPanel = !showGiftGoldPanel; showGiftPanel = false;">
|
||||
💰 赠金币
|
||||
</button>
|
||||
|
||||
{{-- 求婚按钮:对方未婚 + 双方均已设置性别 + 异性 --}}
|
||||
@@ -831,6 +831,55 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{{-- 内联赠送金币面板 --}}
|
||||
<div x-show="showGiftGoldPanel" x-transition
|
||||
style="display: none; padding: 12px 16px; background: #fffbeb; border-top: 1px solid #fde68a;">
|
||||
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:8px;">
|
||||
<span style="font-size:13px; color:#92400e; font-weight:bold;">💰 赠送金币给 <span x-text="userInfo.username"></span></span>
|
||||
<button x-on:click="showGiftGoldPanel = false"
|
||||
style="background:none; border:none; color:#92400e; cursor:pointer; font-size:18px; line-height:1; opacity:.6;">×</button>
|
||||
</div>
|
||||
<div style="font-size:11px; color:#b45309; margin-bottom:8px;">您当前余额:<b x-text="window.chatContext.myGold ?? '—'"></b> 金币</div>
|
||||
<div style="display:flex; gap:8px; align-items:center;">
|
||||
<input type="number" x-model.number="giftGoldAmount" min="1" max="999999"
|
||||
placeholder="输入金额"
|
||||
style="flex:1; height:36px; padding:0 10px; border:1px solid #fbbf24; border-radius:6px; font-size:13px; color:#334155;">
|
||||
<button
|
||||
x-on:click="
|
||||
if (!giftGoldAmount || giftGoldAmount <= 0) return;
|
||||
giftGoldSending = true;
|
||||
fetch('/gift/gold', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name=csrf-token]').content,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
to_user: userInfo.username,
|
||||
room_id: window.chatContext.roomId,
|
||||
amount: giftGoldAmount
|
||||
})
|
||||
}).then(r => r.json()).then(d => {
|
||||
if (d.status === 'success') {
|
||||
window.chatContext.myGold = d.data?.my_jjb ?? window.chatContext.myGold;
|
||||
showGiftGoldPanel = false;
|
||||
giftGoldAmount = '';
|
||||
$alert(d.message, '赠送成功 💝', '#d97706');
|
||||
} else {
|
||||
$alert(d.message, '赠送失败', '#cc4444');
|
||||
}
|
||||
}).catch(() => $alert('网络异常', '错误', '#cc4444'))
|
||||
.finally(() => { giftGoldSending = false; });
|
||||
"
|
||||
:disabled="giftGoldSending"
|
||||
style="height:36px; padding:0 16px; background:linear-gradient(135deg,#f59e0b,#d97706); color:#fff;
|
||||
border:none; border-radius:6px; font-size:13px; font-weight:bold; cursor:pointer; white-space:nowrap;"
|
||||
:style="giftGoldSending ? 'opacity:.6; cursor:not-allowed;' : ''"
|
||||
x-text="giftGoldSending ? '赠送中…' : '💝 确认赠送'"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 内联礼物面板 --}}
|
||||
<div x-show="showGiftPanel" x-transition
|
||||
style="display: none;
|
||||
@@ -934,6 +983,12 @@
|
||||
style="flex:1; padding: 5px; border-radius: 4px; font-size: 11px; background: #f3e8ff; border: 1px solid #a855f7; cursor: pointer;"
|
||||
x-on:click="loadWhispers()">🔍 私信</button>
|
||||
@endif
|
||||
{{-- 职务奖励金币(凭空产生),仅有在职职务且 max_reward != 0 的人可见 --}}
|
||||
@if (Auth::user()->activePosition || $myLevel >= $superLevel)
|
||||
<button x-show="window.chatContext?.myMaxReward !== 0"
|
||||
style="flex:1; padding: 5px; border-radius: 4px; font-size: 11px; background: #fef3c7; border: 1px solid #f59e0b; cursor: pointer;"
|
||||
x-on:click="openRewardModal(userInfo.username)">💰 奖励金币</button>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@@ -270,6 +270,7 @@ Route::middleware(['chat.auth'])->group(function () {
|
||||
|
||||
// ---- 送花/礼物互动 ----
|
||||
Route::post('/gift/flower', [ChatController::class, 'sendFlower'])->name('gift.flower');
|
||||
Route::post('/gift/gold', [ChatController::class, 'giftGold'])->name('gift.gold');
|
||||
|
||||
// ---- 管理员命令(聊天室内实时操作)----
|
||||
Route::post('/command/warn', [AdminCommandController::class, 'warn'])->name('command.warn');
|
||||
|
||||
Reference in New Issue
Block a user