202508281054

加入心情留言與貼圖
加入音控介面
修正 Button 載圖會太大的問題
This commit is contained in:
allen.yan 2025-08-28 11:57:13 +08:00
parent f070df7d03
commit d13b00cb1f
12 changed files with 246 additions and 5 deletions

View File

@ -0,0 +1,44 @@
<?php
namespace App\Livewire\Modals;
use Livewire\Component;
class StickerModal extends Component
{
protected $listeners = [
'openModal','closeModal'
];
public bool $showModal = false;
public $selectedSticker = null;
public $stickers = [];
public function mount()
{
$this->stickers = collect(glob(storage_path('app/public/superstar-pic/*.png')))
//->map(fn($path) => 'superstar-pic/' . basename($path))
->map(fn($path) => basename($path))
->toArray();
}
public function openModal()
{
$this->showModal = true;
}
public function closeModal()
{
$this->showModal = false;
}
public function select($sticker)
{
$this->dispatch('stickerSelected', $sticker);
$this->selectedSticker =$sticker;
$this->showModal = false;
}
public function render()
{
return view('livewire.modals.sticker-modal');
}
}

View File

@ -11,7 +11,7 @@ class Home extends Component
public function mount()
{
// 先從 URL 取得 room_code再存進 session
session()->forget('room_code');
//session()->forget('room_code');
$this->roomCode = request()->query('room_code', session('room_code', null));
if ($this->roomCode) {
session(['room_code' => $this->roomCode]);

View File

@ -0,0 +1,38 @@
<?php
namespace App\Livewire\Pages;
use Livewire\Component;
class LoveMessage extends Component
{
protected $listeners = ['stickerSelected' => 'handleSticker'];
public $message = '';
public $selectedSticker=null;
public function handleSticker($sticker)
{
$this->selectedSticker = $sticker;
}
public function submitMessage()
{
// 實際存留言時,可同時存貼圖
$data = [
'message' => $this->message,
'sticker' => $this->selectedSticker,
'user' => auth()->user()?->name ?? '訪客',
];
// 存到資料庫或送到 API
// ...
session()->flash('success', '留言已送出!');
// 重置
$this->message = '';
$this->selectedSticker = null;
}
public function render()
{
return view('livewire.pages.love-message');
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace App\Livewire\Pages;
use Livewire\Component;
class SoundControl extends Component
{
public $buttons = [
['img'=>'音控-01.jpg', 'action'=>'pause'],
['img'=>'音控-02.jpg', 'action'=>'volume_up'],
['img'=>'音控-04.jpg', 'action'=>'mic_up'],
['img'=>'音控-06.jpg', 'action'=>'mute'],
['img'=>'音控-03.jpg', 'action'=>'volume_down'],
['img'=>'音控-05.jpg', 'action'=>'mic_down'],
['img'=>'音控-07.jpg', 'action'=>'original_song'],
['img'=>'音控-08.jpg', 'action'=>'service'],
['img'=>'音控-09.jpg', 'action'=>'replay'],
['img'=>'音控-11.jpg', 'action'=>'male_key'],
['img'=>'音控-12.jpg', 'action'=>'female_key'],
['img'=>'音控-10.jpg', 'action'=>'cut'],
['img'=>'音控-15.jpg', 'action'=>'lower_key'],
['img'=>'音控-14.jpg', 'action'=>'standard_key'],
['img'=>'音控-13.jpg', 'action'=>'raise_key'],
];
public function sendVolumeControl(string $action)
{
// 這裡可以加你的 API 或邏輯
// 範例:發送到後台控制音量
info("Sound control action: ".$action);
$this->dispatchBrowserEvent('notify', [
'message' => "已執行操作: {$action}"
]);
}
public function render()
{
return view('livewire.pages.sound-control');
}
}

View File

@ -3,12 +3,17 @@
'href' => null,
])
@php
// 使用 Tailwind aspect-auto 保持圖片原始比例
$classes = 'relative w-full rounded-lg overflow-hidden shadow-md hover:scale-105 transition-transform cursor-pointer';
@endphp
@if($href)
<a href="{{ $href }}" {{ $attributes->merge(['class' => 'relative w-full h-48 rounded-lg overflow-hidden shadow-md hover:scale-105 transition-transform cursor-pointer']) }}>
<img src="{{ $image }}" alt="" class="w-full h-full object-cover">
<a href="{{ $href }}" {{ $attributes->merge(['class' => $classes]) }}>
<img src="{{ $image }}" alt="" class="w-full h-auto object-contain">
</a>
@else
<div {{ $attributes->merge(['class' => 'relative w-full h-48 rounded-lg overflow-hidden shadow-md hover:scale-105 transition-transform cursor-pointer']) }}>
<img src="{{ $image }}" alt="" class="w-full h-full object-cover">
<div {{ $attributes->merge(['class' => $classes]) }}>
<img src="{{ $image }}" alt="" class="w-full h-auto object-contain">
</div>
@endif

View File

@ -0,0 +1,27 @@
<x-modal id="sticker-modal" wire:model.defer="showModal" persistent>
<x-card class="border border-gray-200">
<x-slot name="action">
<button class="cursor-pointer p-1 rounded-full focus:outline-none focus:outline-hidden focus:ring-2 focus:ring-secondary-200 text-secondary-300"
wire:click="closeModal"
tabindex="-1"
>
<x-dynamic-component :component="WireUi::component('icon')" name="x-mark" class="w-5 h-5" />
</button>
</x-slot>
<x-slot name="title">
選擇貼圖
</x-slot>
<div class="flex flex-wrap gap-2 max-h-64 overflow-y-auto">
@foreach($stickers as $sticker)
<img
src="{{ asset('superstar-pic/'.$sticker) }}"
wire:click="select('{{ $sticker }}')"
class="w-16 h-16 object-contain bg-white border-2 rounded cursor-pointer
{{ $selectedSticker === $sticker ? 'border-pink-500' : 'border-transparent' }}"
>
@endforeach
</div>
</x-card>
</x-modal>

View File

@ -0,0 +1,50 @@
<div class="max-w-lg mx-auto py-12 px-4 sm:px-6 lg:px-8">
<div class="bg-white shadow rounded-lg p-6 space-y-4">
<h2 class="text-2xl font-semibold text-center">真情告白</h2>
<div class="space-y-2">
<input
type="text"
maxlength="64"
placeholder="請輸入您的留言"
wire:model.lazy="message"
class="w-full border rounded-lg p-3 focus:ring-2 focus:ring-pink-400 focus:outline-none"
/>
<div class="text-gray-500 text-sm text-right">
字串長度:{{ strlen($message) }} 個單位
</div>
</div>
<x-button
wire:click="submitMessage"
pink
label="確認送出"
class="w-full mt-4 text-xl font-semibold py-2 px-4 rounded-lg transition"
/>
{{-- 打開貼圖 Modal --}}
<x-card
class="mt-2 w-full cursor-pointer hover:bg-gray-50 transition"
wire:click="$dispatchTo('modals.sticker-modal','openModal')"
>
<div class="flex flex-col items-center text-gray-400">
<span class="text-gray-600 mb-2">已選貼圖:</span>
@if($selectedSticker)
<img src="{{ asset('superstar-pic/'.$selectedSticker) }}" class="w-16 h-16 object-contain bg-white border-2 rounded cursor-pointer ">
@else
<span class="w-16 h-16 flex items-center justify-center text-gray-400 text-sm text-center">選擇貼圖</span>
@endif
<span class="text-sm">點擊此處選擇</span>
</div>
</x-card>
</div>
<div class="mt-6 bg-yellow-50 border-l-4 border-yellow-400 p-4 text-sm text-yellow-700 rounded-lg space-y-1">
<ul class="list-disc pl-5 space-y-1">
<li>注意:不要使用特殊符號,可能無法正常顯示!</li>
<li>播歌畫面可顯示的字串長度為64會員名稱 + 訊息內容)!</li>
<li>如果非要給這愛加個期限,我希望是一萬年…真情告白,等您留言!(每則留言輪播三次)</li>
</ul>
</div>
<livewire:modals.sticker-modal />
</div>

View File

@ -0,0 +1,10 @@
<div class="py-12 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid grid-cols-3 gap-6">
@foreach($buttons as $btn)
<x-button.flat-card
image="{{ asset('手機點歌/'.$btn['img']) }}"
wire:click="sendVolumeControl('{{ $btn['action'] }}')"
/>
@endforeach
</div>
</div>

View File

@ -0,0 +1,10 @@
<x-app-layout>
<x-slot name="header">
<div class="header">超級巨星 自助式KTV</div>
<div class="banner">
<img src="{{ asset('手機點歌/BANNER-12.png') }}" alt="超級巨星 Banner">
</div>
</x-slot>
<livewire:pages.love-message />
</x-app-layout>

View File

@ -0,0 +1,10 @@
<x-app-layout>
<x-slot name="header">
<div class="header">超級巨星 自助式KTV</div>
<div class="banner">
<img src="{{ asset('手機點歌/BANNER-09.png') }}" alt="超級巨星 Banner">
</div>
</x-slot>
<livewire:pages.sound-control />
</x-app-layout>

View File

@ -7,6 +7,8 @@ Route::view('/welcome', 'welcome')->name('welcome');
Route::view('/new-songs', 'new-songs')->name('new-songs');
Route::view('/top-ranking', 'top-ranking')->name('top-ranking');
Route::view('/search-song', 'search-song')->name('search-song');
Route::view('/sound-control', 'sound-control')->name('sound-control');
Route::view('/love-message', 'love-message')->name('love-message');
Route::view('dashboard', 'dashboard')
->middleware(['auth', 'verified'])

View File

@ -1,2 +1,5 @@
npm install && npm run build
https://ktvremote.test/?room_code=abc123
php artisan storage:link