202508211813
加入與中控資料同步 移除 這首歌與下首歌的 API
This commit is contained in:
parent
1bb201bacb
commit
4c8ac6ddab
@ -4,8 +4,10 @@ namespace App\Http\Controllers\Api;
|
|||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Requests\OrderSongRequest;
|
use App\Http\Requests\OrderSongRequest;
|
||||||
|
use App\Http\Requests\SyncOrderSongRequest;
|
||||||
use App\Http\Requests\RoomSongRequest;
|
use App\Http\Requests\RoomSongRequest;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use App\Services\MachineStatusForwarder;
|
||||||
use App\Models\Room;
|
use App\Models\Room;
|
||||||
use App\Models\Song;
|
use App\Models\Song;
|
||||||
use App\Models\OrderedSong;
|
use App\Models\OrderedSong;
|
||||||
@ -56,6 +58,10 @@ class RoomSongController extends Controller
|
|||||||
// 取得對應的 RoomSession(透過 api_token)
|
// 取得對應的 RoomSession(透過 api_token)
|
||||||
$roomSession = $this->getRoomSession($request->api_token) ;
|
$roomSession = $this->getRoomSession($request->api_token) ;
|
||||||
|
|
||||||
|
// 找這個 session 的最大 order_number,下一首加 1
|
||||||
|
$lastOrder = OrderedSong::where('room_session_id', $roomSession->id)->max('order_number');
|
||||||
|
$orderNumber = $lastOrder ? $lastOrder + 1 : 1;
|
||||||
|
|
||||||
// 取得歌曲名稱
|
// 取得歌曲名稱
|
||||||
$song = Song::findOrFail($request->song_id);
|
$song = Song::findOrFail($request->song_id);
|
||||||
|
|
||||||
@ -63,6 +69,7 @@ class RoomSongController extends Controller
|
|||||||
$orderedSong = OrderedSong::create([
|
$orderedSong = OrderedSong::create([
|
||||||
'room_session_id' => $roomSession->id,
|
'room_session_id' => $roomSession->id,
|
||||||
'from_by' => $request->from_by,
|
'from_by' => $request->from_by,
|
||||||
|
'order_number' => $orderNumber,
|
||||||
'status' => $request->status,
|
'status' => $request->status,
|
||||||
'song_id' => $request->song_id,
|
'song_id' => $request->song_id,
|
||||||
'song_name' => $song->name,
|
'song_name' => $song->name,
|
||||||
@ -78,7 +85,7 @@ class RoomSongController extends Controller
|
|||||||
if ($countInSession === 1) { // 第一次點才加
|
if ($countInSession === 1) { // 第一次點才加
|
||||||
$song->increment('song_counts');
|
$song->increment('song_counts');
|
||||||
}
|
}
|
||||||
|
$this->sys($roomSession,$orderedSong);
|
||||||
return ApiResponse::success([
|
return ApiResponse::success([
|
||||||
'ordered_song' => $orderedSong,
|
'ordered_song' => $orderedSong,
|
||||||
'next_song_name' => $this->nextSongName($roomSession),
|
'next_song_name' => $this->nextSongName($roomSession),
|
||||||
@ -156,125 +163,6 @@ class RoomSongController extends Controller
|
|||||||
'not_played' => $not_played,
|
'not_played' => $not_played,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @OA\Post(
|
|
||||||
* path="/api/room/current-song",
|
|
||||||
* summary="取得目前播放中的歌曲",
|
|
||||||
* description="回傳當前房間正在播放的歌曲資訊 (包含部分 song 欄位)",
|
|
||||||
* tags={"Room Control Song"},
|
|
||||||
* security={{"Authorization":{}}},
|
|
||||||
* @OA\RequestBody(
|
|
||||||
* required=true,
|
|
||||||
* @OA\JsonContent(ref="#/components/schemas/RoomSongRequest")
|
|
||||||
* ),
|
|
||||||
* @OA\Response(
|
|
||||||
* response=200,
|
|
||||||
* description="成功回傳目前播放的歌曲",
|
|
||||||
* @OA\JsonContent(
|
|
||||||
* type="object",
|
|
||||||
* @OA\Property(
|
|
||||||
* property="success",
|
|
||||||
* type="boolean",
|
|
||||||
* example=true
|
|
||||||
* ),
|
|
||||||
* @OA\Property(
|
|
||||||
* property="data",
|
|
||||||
* type="object",
|
|
||||||
* @OA\Property(
|
|
||||||
* property="current",
|
|
||||||
* ref="#/components/schemas/OrderedSongWithPartialSong"
|
|
||||||
* )
|
|
||||||
* )
|
|
||||||
* )
|
|
||||||
* )
|
|
||||||
* )
|
|
||||||
*/
|
|
||||||
public function currentSong(RoomSongRequest $request)
|
|
||||||
{
|
|
||||||
$roomSession = $this->getRoomSession($request->api_token) ;
|
|
||||||
$current = OrderedSong::where('room_session_id', $roomSession->id)
|
|
||||||
->where('status', 'Playing')
|
|
||||||
->withPartialSong()
|
|
||||||
->first();
|
|
||||||
return ApiResponse::success([
|
|
||||||
'current' => $current ,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @OA\Post(
|
|
||||||
* path="/api/room/next-song",
|
|
||||||
* summary="播放下一首歌曲",
|
|
||||||
* description="將目前播放的歌標記為結束,並將下一首設為播放中,回傳下首與下下首資訊。",
|
|
||||||
* tags={"Room Control Song"},
|
|
||||||
* security={{"Authorization":{}}},
|
|
||||||
* @OA\RequestBody(
|
|
||||||
* required=true,
|
|
||||||
* @OA\JsonContent(ref="#/components/schemas/RoomSongRequest")
|
|
||||||
* ),
|
|
||||||
* @OA\Response(
|
|
||||||
* response=200,
|
|
||||||
* description="成功回傳歌曲資訊",
|
|
||||||
* @OA\JsonContent(
|
|
||||||
* type="object",
|
|
||||||
* @OA\Property(
|
|
||||||
* property="current",
|
|
||||||
* type="object",
|
|
||||||
* nullable=true,
|
|
||||||
* ref="#/components/schemas/OrderedSongWithPartialSong"
|
|
||||||
* ),
|
|
||||||
* @OA\Property(
|
|
||||||
* property="next",
|
|
||||||
* type="object",
|
|
||||||
* nullable=true,
|
|
||||||
* ref="#/components/schemas/OrderedSongWithPartialSong"
|
|
||||||
* )
|
|
||||||
* )
|
|
||||||
* ),
|
|
||||||
* @OA\Response(
|
|
||||||
* response=401,
|
|
||||||
* description="未授權或 Token 錯誤"
|
|
||||||
* ),
|
|
||||||
* @OA\Response(
|
|
||||||
* response=404,
|
|
||||||
* description="找不到房間或歌曲"
|
|
||||||
* )
|
|
||||||
* )
|
|
||||||
*/
|
|
||||||
public function nextSong(RoomSongRequest $request)
|
|
||||||
{
|
|
||||||
$roomSession = $this->getRoomSession($request->api_token) ;
|
|
||||||
// 找目前正在播
|
|
||||||
$current = OrderedSong::where('room_session_id', $roomSession->id)
|
|
||||||
->where('status', 'Playing')
|
|
||||||
->first();
|
|
||||||
if ($current) {
|
|
||||||
// 把當前設為 finished,並記錄結束時間
|
|
||||||
$current->update([
|
|
||||||
'status' => 'Played',
|
|
||||||
'finished_at' => now(),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
// 撈出候播清單(下首 + 下下首)
|
|
||||||
$queue = OrderedSong::where('room_session_id', $roomSession->id)
|
|
||||||
->whereIn('status', ['InsertPlayback', 'NotPlayed'])
|
|
||||||
->withPartialSong()
|
|
||||||
->orderByRaw("FIELD(status, 'InsertPlayback', 'NotPlayed')") // InsertPlayback > NotPlayed
|
|
||||||
->orderByRaw("CASE WHEN status = 'InsertPlayback' THEN ordered_at END DESC") // InsertPlayback 後插播的先播
|
|
||||||
->orderByRaw("CASE WHEN status = 'NotPlayed' THEN ordered_at END ASC") // NotPlayed 先點的先播
|
|
||||||
->limit(2)
|
|
||||||
->get();
|
|
||||||
$current =$queue->get(0);
|
|
||||||
if ($current) {
|
|
||||||
$current->update([
|
|
||||||
'status' => 'Playing',
|
|
||||||
'started_at' => now(),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
return ApiResponse::success([
|
|
||||||
'current' => $current,// 下首
|
|
||||||
'next' => $queue->get(1) ?? null,// 下下首
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function nextSongName(RoomSession $roomSession)
|
private function nextSongName(RoomSession $roomSession)
|
||||||
{
|
{
|
||||||
@ -298,4 +186,60 @@ class RoomSongController extends Controller
|
|||||||
->whereIn('status', ['active', 'maintain'])
|
->whereIn('status', ['active', 'maintain'])
|
||||||
->firstOrFail();
|
->firstOrFail();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function sys($roomSession,$orderedSong)
|
||||||
|
{
|
||||||
|
$validated = [
|
||||||
|
'api_token' => $roomSession->api_token,
|
||||||
|
'order_number' => $orderedSong->order_number,
|
||||||
|
'from_by' => $orderedSong->from_by,
|
||||||
|
'song_id' => $orderedSong->song_id,
|
||||||
|
'song_name' => $orderedSong->song_name,
|
||||||
|
'artist_name' => $orderedSong->artist_name,
|
||||||
|
'status' => $orderedSong->status,
|
||||||
|
'ordered_at' => $orderedSong->ordered_at,
|
||||||
|
'started_at' => $orderedSong->started_at,
|
||||||
|
'finished_at' => $orderedSong->finished_at,
|
||||||
|
];
|
||||||
|
$response = (new MachineStatusForwarder(
|
||||||
|
$roomSession->room->branch->external_ip,
|
||||||
|
"/api/room/sync-order-song",
|
||||||
|
$validated
|
||||||
|
))->forward();
|
||||||
|
}
|
||||||
|
public function syncOrderSong(SyncOrderSongRequest $request)
|
||||||
|
{
|
||||||
|
$roomSession = $this->getRoomSession($request->api_token) ;
|
||||||
|
|
||||||
|
// 建立或更新 OrderedSong
|
||||||
|
$orderedSong = OrderedSong::updateOrCreate(
|
||||||
|
[
|
||||||
|
'room_session_id' => $roomSession->id,
|
||||||
|
'order_number' => $request->order_number,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'from_by' => $request->from_by,
|
||||||
|
'song_id' => $request->song_id,
|
||||||
|
'song_name' => $request->song_name,
|
||||||
|
'artist_name' => $request->artist_name,
|
||||||
|
'status' => $request->status,
|
||||||
|
'ordered_at' => $request->ordered_at,
|
||||||
|
'started_at' => $request->started_at,
|
||||||
|
'finished_at' => $request->finished_at,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// 檢查這首歌在此 session 是否第一次點
|
||||||
|
if ($orderedSong->wasRecentlyCreated) {
|
||||||
|
$countInSession = OrderedSong::where('room_session_id', $roomSession->id)
|
||||||
|
->where('song_id', $request->song_id)->count();
|
||||||
|
if ($countInSession === 1) { // 第一次點才加
|
||||||
|
$song->increment('song_counts');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ApiResponse::success([
|
||||||
|
'ordered_song' => $orderedSong
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
@ -4,6 +4,7 @@ namespace App\Http\Controllers;
|
|||||||
|
|
||||||
use App\Http\Requests\SendRoomSwitchCommandRequest;
|
use App\Http\Requests\SendRoomSwitchCommandRequest;
|
||||||
use App\Http\Requests\ReceiveSwitchRequest;
|
use App\Http\Requests\ReceiveSwitchRequest;
|
||||||
|
use App\Http\Requests\SessionRequest;
|
||||||
use App\Services\TcpSocketClient;
|
use App\Services\TcpSocketClient;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
@ -22,6 +23,81 @@ use Illuminate\Support\Facades\Log;
|
|||||||
*/
|
*/
|
||||||
class RoomControlController extends Controller
|
class RoomControlController extends Controller
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @OA\Post(
|
||||||
|
* path="/api/room/session",
|
||||||
|
* summary="取得包廂狀態",
|
||||||
|
* description="依據 hostname 與 branch_name 取得或建立房間,並回傳房間資料與最新 session",
|
||||||
|
* tags={"Room Control"},
|
||||||
|
* security={{"Authorization":{}}},
|
||||||
|
* @OA\RequestBody(
|
||||||
|
* required=true,
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/SessionRequest")
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=200,
|
||||||
|
* description="成功取得房間狀態",
|
||||||
|
* @OA\JsonContent(
|
||||||
|
* type="object",
|
||||||
|
* @OA\Property(
|
||||||
|
* property="room",
|
||||||
|
* type="object",
|
||||||
|
* ref="#/components/schemas/Room"
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=422,
|
||||||
|
* description="驗證失敗",
|
||||||
|
* @OA\JsonContent(
|
||||||
|
* type="object",
|
||||||
|
* @OA\Property(property="message", type="string", example="The given data was invalid."),
|
||||||
|
* @OA\Property(property="errors", type="object")
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public function session(SessionRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$validated = $request->validated();
|
||||||
|
$roomType = null;
|
||||||
|
$roomName = null;
|
||||||
|
$floor = null;
|
||||||
|
// 從 room_name(例如 PC101, SVR01)中擷取 type 與 name
|
||||||
|
if (preg_match('/^([A-Za-z]+)(\d+)$/', $validated['hostname'], $matches)) {
|
||||||
|
$roomType = strtolower($matches[1]); // 'PC' → 'pc'
|
||||||
|
$roomName = $matches[2]; // '101'
|
||||||
|
if($roomType =='svr'){
|
||||||
|
$floor = '0';
|
||||||
|
} else{
|
||||||
|
$floor = (int) substr($roomName, 0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$branch=Branch::where('name',$validated['branch_name'])->first();
|
||||||
|
$room = Room::firstOrNew([
|
||||||
|
'branch_id' => $branch->id,
|
||||||
|
'floor' => $floor,
|
||||||
|
'name' => $roomName,
|
||||||
|
'type' => $roomType,
|
||||||
|
]);
|
||||||
|
$room->internal_ip = $validated['ip'];
|
||||||
|
$room->port = 1000;
|
||||||
|
$room->is_online=1;
|
||||||
|
$room->touch(); // 更新 updated_at
|
||||||
|
$room->save();
|
||||||
|
$room->load('latestSession');
|
||||||
|
if ($room->latestSession) {
|
||||||
|
$room->latestSession->api_token = !empty($validated['token'])
|
||||||
|
? $validated['token']
|
||||||
|
: bin2hex(random_bytes(32));
|
||||||
|
$room->latestSession->save();
|
||||||
|
$validated['token']=$room->latestSession->api_token;
|
||||||
|
}
|
||||||
|
return ApiResponse::success([
|
||||||
|
'room' => $room->latestSession,
|
||||||
|
]);
|
||||||
|
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @OA\Post(
|
* @OA\Post(
|
||||||
* path="/api/room/sendSwitch",
|
* path="/api/room/sendSwitch",
|
||||||
|
32
app/Http/Requests/SessionRequest.php
Normal file
32
app/Http/Requests/SessionRequest.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @OA\Schema(
|
||||||
|
* schema="SessionRequest",
|
||||||
|
* required={"branch_name","hostname", "ip"},
|
||||||
|
* @OA\Property(property="branch_name", type="string", example="測試"),
|
||||||
|
* @OA\Property(property="hostname", type="string", example="PC101"),
|
||||||
|
* @OA\Property(property="ip", type="string", example="192.168.XX.XX"),
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
class SessionRequest extends ApiRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'branch_name' =>'required|string|exists:branches,name',
|
||||||
|
'hostname' => 'required|string',
|
||||||
|
'ip' => 'required|string',
|
||||||
|
'token' => 'nullable|string',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
25
app/Http/Requests/SyncOrderSongRequest.php
Normal file
25
app/Http/Requests/SyncOrderSongRequest.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
|
|
||||||
|
class SyncOrderSongRequest extends ApiRequest
|
||||||
|
{
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'api_token' => 'required|exists:room_sessions,api_token',
|
||||||
|
'from_by' => 'nullable',
|
||||||
|
'order_number' => 'required|integer',
|
||||||
|
'song_id' => 'required|exists:songs,id',
|
||||||
|
'song_name' => 'nullable',
|
||||||
|
'artist_name' => 'nullable',
|
||||||
|
'status' => 'required|in:NotPlayed,Playing,Played,NoFile,Skipped,InsertPlayback',
|
||||||
|
'ordered_at' => 'required',
|
||||||
|
'started_at' => 'nullable',
|
||||||
|
'finished_at' => 'nullable',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -12,6 +12,7 @@ use Illuminate\Database\Eloquent\Model;
|
|||||||
* @OA\Property(property="id", type="integer", example=123),
|
* @OA\Property(property="id", type="integer", example=123),
|
||||||
* @OA\Property(property="room_session_id", type="integer", example=1),
|
* @OA\Property(property="room_session_id", type="integer", example=1),
|
||||||
* @OA\Property(property="from_by", type="string", example="remote"),
|
* @OA\Property(property="from_by", type="string", example="remote"),
|
||||||
|
* @OA\Property(property="order_number", type="integer", example=1),
|
||||||
* @OA\Property(property="song_id", type="integer", example=5),
|
* @OA\Property(property="song_id", type="integer", example=5),
|
||||||
* @OA\Property(property="song_name", type="string", example="歌名"),
|
* @OA\Property(property="song_name", type="string", example="歌名"),
|
||||||
* @OA\Property(property="artist_name", type="string", example="歌手名稱"),
|
* @OA\Property(property="artist_name", type="string", example="歌手名稱"),
|
||||||
@ -49,6 +50,7 @@ class OrderedSong extends Model
|
|||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'room_session_id',
|
'room_session_id',
|
||||||
'from_by',
|
'from_by',
|
||||||
|
'order_number',
|
||||||
'song_id',
|
'song_id',
|
||||||
'song_name',
|
'song_name',
|
||||||
'artist_name',
|
'artist_name',
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use App\Traits\LogsModelActivity;
|
use App\Traits\LogsModelActivity;
|
||||||
@ -89,11 +91,27 @@ class Room extends Model
|
|||||||
return $this->type->labelPowergridFilter().$this->name;
|
return $this->type->labelPowergridFilter().$this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function statusLogs() {
|
public function statusLogs() : HasMany
|
||||||
|
{
|
||||||
return $this->hasMany(RoomStatusLog::class);
|
return $this->hasMany(RoomStatusLog::class);
|
||||||
}
|
}
|
||||||
public function sessions()
|
public function sessions() : HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(RoomSession::class);
|
return $this->hasMany(RoomSession::class);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 最新的一筆 session
|
||||||
|
*/
|
||||||
|
public function latestSession() : HasOne
|
||||||
|
{
|
||||||
|
return $this->hasOne(RoomSession::class)->latestOfMany();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 方便取得最新狀態
|
||||||
|
*/
|
||||||
|
public function getLatestStatusAttribute() : string
|
||||||
|
{
|
||||||
|
return $this->latestSession?->status ?? 'error';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,6 @@ class RoomObserver
|
|||||||
'mode' => $mode,
|
'mode' => $mode,
|
||||||
'status' => $room->status->value,
|
'status' => $room->status->value,
|
||||||
'started_at' => $now,
|
'started_at' => $now,
|
||||||
'api_token' => bin2hex(random_bytes(32)),
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
46
app/Services/MachineStatusForwarder.php
Normal file
46
app/Services/MachineStatusForwarder.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Http\Client\Response;
|
||||||
|
use App\Services\ApiClient;
|
||||||
|
|
||||||
|
class MachineStatusForwarder
|
||||||
|
{
|
||||||
|
protected string $externalUrl;
|
||||||
|
protected string $endpoint;
|
||||||
|
protected array $validated;
|
||||||
|
protected ?User $user = null;
|
||||||
|
|
||||||
|
public function __construct(string $externalUrl, string $endpoint, array $validated)
|
||||||
|
{
|
||||||
|
$this->externalUrl = $externalUrl;
|
||||||
|
$this->endpoint = $endpoint;
|
||||||
|
$this->validated = $validated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function forward(): ?Response
|
||||||
|
{
|
||||||
|
$response = null;
|
||||||
|
|
||||||
|
$this->user = User::find(2); // 或用 dependency injection 把 User 帶進來
|
||||||
|
|
||||||
|
if ($this->user && $this->user->api_plain_token) {
|
||||||
|
$client = new ApiClient($this->externalUrl, $this->user->api_plain_token);
|
||||||
|
$response = $client->post($this->endpoint, $this->validated);
|
||||||
|
|
||||||
|
Log::info('✅ Machine status forwarded', [
|
||||||
|
'endpoint' => $this->endpoint,
|
||||||
|
'request' => $this->validated,
|
||||||
|
'status' => $response->status(),
|
||||||
|
'body' => $response->json(),
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
Log::warning("🔒 User with ID 2 not found or missing token");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@ return new class extends Migration
|
|||||||
$table->id();
|
$table->id();
|
||||||
$table->foreignId('room_session_id')->constrained('room_sessions')->cascadeOnDelete();
|
$table->foreignId('room_session_id')->constrained('room_sessions')->cascadeOnDelete();
|
||||||
$table->string('from_by')->nullable();
|
$table->string('from_by')->nullable();
|
||||||
|
$table->integer('order_number')->default(0);
|
||||||
|
|
||||||
// 歌曲資訊
|
// 歌曲資訊
|
||||||
$table->foreignId('song_id')->constrained()->cascadeOnDelete();
|
$table->foreignId('song_id')->constrained()->cascadeOnDelete();
|
||||||
@ -30,7 +31,7 @@ return new class extends Migration
|
|||||||
$table->timestamp('started_at')->nullable(); // 開始播放時間
|
$table->timestamp('started_at')->nullable(); // 開始播放時間
|
||||||
$table->timestamp('finished_at')->nullable(); // 播放結束時間
|
$table->timestamp('finished_at')->nullable(); // 播放結束時間
|
||||||
|
|
||||||
|
$table->unique(['room_session_id', 'order_number']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,11 @@ Route::post('/room/receiveRegister', [RoomControlController::class, 'receiveRegi
|
|||||||
Route::middleware('auth:sanctum')->group(function () {
|
Route::middleware('auth:sanctum')->group(function () {
|
||||||
Route::get ('/profile', [AuthController::class, 'profile']);
|
Route::get ('/profile', [AuthController::class, 'profile']);
|
||||||
Route::get ('/branches',[BranchControlController::class, 'Branches']);
|
Route::get ('/branches',[BranchControlController::class, 'Branches']);
|
||||||
|
|
||||||
Route::post('/room/sendSwitch', [RoomControlController::class, 'sendSwitch']);
|
Route::post('/room/sendSwitch', [RoomControlController::class, 'sendSwitch']);
|
||||||
Route::post('/room/receiveSwitch', [RoomControlController::class, 'receiveSwitch']);
|
Route::post('/room/receiveSwitch', [RoomControlController::class, 'receiveSwitch']);
|
||||||
Route::post('/room/heartbeat', [RoomControlController::class, 'StatusReport']);
|
Route::post('/room/session',[RoomControlController::class, 'session']);
|
||||||
Route::post('/room/order-song', [RoomSongController::class, 'orderSong']);
|
Route::post('/room/order-song', [RoomSongController::class, 'orderSong']);
|
||||||
Route::get ('/room/ordered-songs', [RoomSongController::class, 'listOrderedSongs']);
|
Route::get ('/room/ordered-songs', [RoomSongController::class, 'listOrderedSongs']);
|
||||||
Route::post ('/room/current-song', [RoomSongController::class, 'currentSong']);
|
Route::post ('/room/sync-order-song', [RoomSongController::class, 'syncOrderSong']);
|
||||||
Route::post ('/room/next-song', [RoomSongController::class, 'nextSong']);
|
|
||||||
});
|
});
|
Loading…
x
Reference in New Issue
Block a user