[FEAT] 補全機台與金流設定多語系,並調整帳號管理表格佈局
All checks were successful
star-cloud-deploy-demo / deploy-demo (push) Successful in 44s

This commit is contained in:
2026-03-18 13:52:54 +08:00
parent cd34724c76
commit 3f41896532
19 changed files with 990 additions and 398 deletions

View File

@@ -2,49 +2,49 @@
@section('content')
<div class="container mx-auto px-6 py-8">
<h3 class="text-gray-900 dark:text-gray-300 text-3xl font-medium">新增機台</h3>
<h3 class="text-gray-900 dark:text-gray-300 text-3xl font-medium">{{ __('Create Machine') }}</h3>
<div class="mt-8">
<form action="{{ route('admin.machines.store') }}" method="POST" class="bg-white dark:bg-gray-800 rounded-lg shadow-xl overflow-hidden p-6 space-y-6">
@csrf
<div>
<label for="name" class="block text-sm font-medium text-gray-700 dark:text-gray-400">機台名稱</label>
<label for="name" class="block text-sm font-medium text-gray-700 dark:text-gray-400">{{ __('Machine Name') }}</label>
<input type="text" name="name" id="name" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" required>
@error('name') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div>
<div>
<label for="location" class="block text-sm font-medium text-gray-700 dark:text-gray-400">位置</label>
<label for="location" class="block text-sm font-medium text-gray-700 dark:text-gray-400">{{ __('Location') }}</label>
<input type="text" name="location" id="location" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
@error('location') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div>
<div>
<label for="status" class="block text-sm font-medium text-gray-700 dark:text-gray-400">狀態</label>
<label for="status" class="block text-sm font-medium text-gray-700 dark:text-gray-400">{{ __('Status') }}</label>
<select name="status" id="status" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
<option value="offline">離線</option>
<option value="online">連線中</option>
<option value="error">異常</option>
<option value="offline">{{ __('Offline') }}</option>
<option value="online">{{ __('Connecting...') }}</option>
<option value="error">{{ __('Error') }}</option>
</select>
@error('status') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div>
<div>
<label for="temperature" class="block text-sm font-medium text-gray-700 dark:text-gray-400">溫度 (°C)</label>
<label for="temperature" class="block text-sm font-medium text-gray-700 dark:text-gray-400">{{ __('Temperature') }} (°C)</label>
<input type="number" step="0.1" name="temperature" id="temperature" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
@error('temperature') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div>
<div>
<label for="firmware_version" class="block text-sm font-medium text-gray-700 dark:text-gray-400">韌體版本</label>
<label for="firmware_version" class="block text-sm font-medium text-gray-700 dark:text-gray-400">{{ __('Firmware Version') }}</label>
<input type="text" name="firmware_version" id="firmware_version" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
@error('firmware_version') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div>
<div class="flex justify-end">
<a href="{{ route('admin.machines.index') }}" class="bg-gray-200 dark:bg-gray-600 hover:bg-gray-300 dark:hover:bg-gray-500 text-gray-800 dark:text-white font-bold py-2 px-4 rounded mr-2">取消</a>
<button type="submit" class="btn-luxury-primary">建立</button>
<a href="{{ route('admin.machines.index') }}" class="bg-gray-200 dark:bg-gray-600 hover:bg-gray-300 dark:hover:bg-gray-500 text-gray-800 dark:text-white font-bold py-2 px-4 rounded mr-2">{{ __('Cancel') }}</a>
<button type="submit" class="btn-luxury-primary">{{ __('Create') }}</button>
</div>
</form>
</div>

View File

@@ -2,7 +2,7 @@
@section('content')
<div class="container mx-auto px-6 py-8">
<h3 class="text-gray-900 dark:text-gray-300 text-3xl font-medium">編輯機台</h3>
<h3 class="text-gray-900 dark:text-gray-300 text-3xl font-medium">{{ __('Edit Machine') }}</h3>
<div class="mt-8">
<form action="{{ route('admin.machines.update', $machine) }}" method="POST" class="bg-white dark:bg-gray-800 rounded-lg shadow-xl overflow-hidden p-6 space-y-6">
@@ -10,42 +10,42 @@
@method('PUT')
<div>
<label for="name" class="block text-sm font-medium text-gray-700 dark:text-gray-400">機台名稱</label>
<label for="name" class="block text-sm font-medium text-gray-700 dark:text-gray-400">{{ __('Machine Name') }}</label>
<input type="text" name="name" id="name" value="{{ old('name', $machine->name) }}" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" required>
@error('name') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div>
<div>
<label for="location" class="block text-sm font-medium text-gray-700 dark:text-gray-400">位置</label>
<label for="location" class="block text-sm font-medium text-gray-700 dark:text-gray-400">{{ __('Location') }}</label>
<input type="text" name="location" id="location" value="{{ old('location', $machine->location) }}" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
@error('location') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div>
<div>
<label for="status" class="block text-sm font-medium text-gray-700 dark:text-gray-400">狀態</label>
<label for="status" class="block text-sm font-medium text-gray-700 dark:text-gray-400">{{ __('Status') }}</label>
<select name="status" id="status" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
<option value="offline" {{ $machine->status == 'offline' ? 'selected' : '' }}>離線</option>
<option value="online" {{ $machine->status == 'online' ? 'selected' : '' }}>連線中</option>
<option value="error" {{ $machine->status == 'error' ? 'selected' : '' }}>異常</option>
<option value="offline" {{ $machine->status == 'offline' ? 'selected' : '' }}>{{ __('Offline') }}</option>
<option value="online" {{ $machine->status == 'online' ? 'selected' : '' }}>{{ __('Connecting...') }}</option>
<option value="error" {{ $machine->status == 'error' ? 'selected' : '' }}>{{ __('Error') }}</option>
</select>
@error('status') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div>
<div>
<label for="temperature" class="block text-sm font-medium text-gray-700 dark:text-gray-400">溫度 (°C)</label>
<label for="temperature" class="block text-sm font-medium text-gray-700 dark:text-gray-400">{{ __('Temperature') }} (°C)</label>
<input type="number" step="0.1" name="temperature" id="temperature" value="{{ old('temperature', $machine->temperature) }}" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
@error('temperature') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div>
<div>
<label for="firmware_version" class="block text-sm font-medium text-gray-700 dark:text-gray-400">韌體版本</label>
<label for="firmware_version" class="block text-sm font-medium text-gray-700 dark:text-gray-400">{{ __('Firmware Version') }}</label>
<input type="text" name="firmware_version" id="firmware_version" value="{{ old('firmware_version', $machine->firmware_version) }}" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
@error('firmware_version') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div>
<div class="flex justify-end">
<a href="{{ route('admin.machines.index') }}" class="bg-gray-200 dark:bg-gray-600 hover:bg-gray-300 dark:hover:bg-gray-500 text-gray-800 dark:text-white font-bold py-2 px-4 rounded mr-2">取消</a>
<button type="submit" class="btn-luxury-primary">更新</button>
<a href="{{ route('admin.machines.index') }}" class="bg-gray-200 dark:bg-gray-600 hover:bg-gray-300 dark:hover:bg-gray-500 text-gray-800 dark:text-white font-bold py-2 px-4 rounded mr-2">{{ __('Cancel') }}</a>
<button type="submit" class="btn-luxury-primary">{{ __('Update') }}</button>
</div>
</form>
</div>

View File

@@ -2,7 +2,7 @@
@section('header')
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('機台管理') }}
{{ __('Machine Management') }}
</h2>
@endsection
@@ -12,7 +12,7 @@
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg border border-gray-200">
<div class="p-6 text-gray-900">
<div class="flex justify-between items-center mb-6">
<h3 class="text-lg font-medium">機台列表</h3>
<h3 class="text-lg font-medium">{{ __('Machine List') }}</h3>
<div class="flex items-center gap-x-4">
<form method="GET" action="{{ route('admin.machines.index') }}" class="flex items-center gap-x-2">
@if(request('status'))
@@ -25,9 +25,9 @@
</select>
</form>
<div class="flex space-x-2">
<a href="{{ route('admin.machines.index') }}" class="px-4 py-2 bg-gray-100 hover:bg-gray-200 rounded-md text-sm transition">全部</a>
<a href="{{ route('admin.machines.index', ['status' => 'online']) }}" class="px-4 py-2 bg-green-100 text-green-700 hover:bg-green-200 rounded-md text-sm transition">線上</a>
<a href="{{ route('admin.machines.index', ['status' => 'error']) }}" class="px-4 py-2 bg-red-100 text-red-700 hover:bg-red-200 rounded-md text-sm transition">異常</a>
<a href="{{ route('admin.machines.index') }}" class="px-4 py-2 bg-gray-100 hover:bg-gray-200 rounded-md text-sm transition">{{ __('All') }}</a>
<a href="{{ route('admin.machines.index', ['status' => 'online']) }}" class="px-4 py-2 bg-green-100 text-green-700 hover:bg-green-200 rounded-md text-sm transition">{{ __('Online') }}</a>
<a href="{{ route('admin.machines.index', ['status' => 'error']) }}" class="px-4 py-2 bg-red-100 text-red-700 hover:bg-red-200 rounded-md text-sm transition">{{ __('Error') }}</a>
</div>
</div>
</div>
@@ -36,12 +36,12 @@
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">名稱</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">位置</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">狀態</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">溫度</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">最後心跳</th>
<th class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">操作</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">{{ __('Name') }}</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">{{ __('Location') }}</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">{{ __('Status') }}</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">{{ __('Temperature') }}</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">{{ __('Last Heartbeat') }}</th>
<th class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">{{ __('Actions') }}</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
@@ -64,17 +64,17 @@
$class = $statusClasses[$machine->status] ?? 'bg-blue-100 text-blue-800';
@endphp
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full {{ $class }}">
{{ strtoupper($machine->status) }}
{{ __($machine->status === 'online' ? 'Online' : ($machine->status === 'error' ? 'Error' : 'Offline')) }}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{{ $machine->temperature ?? '--' }} °C
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{{ $machine->last_heartbeat_at ? $machine->last_heartbeat_at->diffForHumans() : '從未連線' }}
{{ $machine->last_heartbeat_at ? $machine->last_heartbeat_at->diffForHumans() : __('Never Connected') }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<a href="{{ route('admin.machines.show', $machine->id) }}" class="text-indigo-600 hover:text-indigo-900 bg-indigo-50 px-3 py-1 rounded-md transition border border-indigo-100">查看日誌</a>
<a href="{{ route('admin.machines.show', $machine->id) }}" class="text-indigo-600 hover:text-indigo-900 bg-indigo-50 px-3 py-1 rounded-md transition border border-indigo-100">{{ __('View Logs') }}</a>
</td>
</tr>
@endforeach

View File

@@ -3,9 +3,9 @@
@section('header')
<div class="flex justify-between items-center">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
機台詳情: {{ $machine->name }}
{{ __('Machine Details') }}: {{ $machine->name }}
</h2>
<a href="{{ route('admin.machines.index') }}" class="text-sm text-gray-600 hover:text-gray-900"> 返回列表</a>
<a href="{{ route('admin.machines.index') }}" class="text-sm text-gray-600 hover:text-gray-900"> {{ __('Back to List') }}</a>
</div>
@endsection
@@ -14,21 +14,21 @@
<div class="sm:px-6 lg:px-8 space-y-6">
<!-- 基本資訊卡片 -->
<div class="bg-white shadow sm:rounded-lg p-6 border border-gray-200">
<h3 class="text-lg font-medium text-gray-900 mb-4 border-b pb-2">基本資訊</h3>
<h3 class="text-lg font-medium text-gray-900 mb-4 border-b pb-2">{{ __('Basic Information') }}</h3>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div>
<p class="text-xs text-gray-500 uppercase">當前狀態</p>
<p class="text-xs text-gray-500 uppercase">{{ __('Status') }}</p>
<p class="text-lg font-bold {{ $machine->status === 'online' ? 'text-green-600' : ($machine->status === 'error' ? 'text-red-600' : 'text-gray-600') }}">
{{ strtoupper($machine->status) }}
{{ __($machine->status === 'online' ? 'Online' : ($machine->status === 'error' ? 'Error' : 'Offline')) }}
</p>
</div>
<div>
<p class="text-xs text-gray-500 uppercase">位置</p>
<p class="text-xs text-gray-500 uppercase">{{ __('Location') }}</p>
<p class="text-sm">{{ $machine->location }}</p>
</div>
<div>
<p class="text-xs text-gray-500 uppercase">最後心跳時間</p>
<p class="text-sm">{{ $machine->last_heartbeat_at ?? 'N/A' }}</p>
<p class="text-xs text-gray-500 uppercase">{{ __('Last Heartbeat') }}</p>
<p class="text-sm">{{ $machine->last_heartbeat_at ?? __('N/A') }}</p>
</div>
</div>
</div>
@@ -36,16 +36,16 @@
<!-- 日誌顯示區 -->
<div class="bg-gray-900 shadow sm:rounded-lg overflow-hidden border border-gray-700">
<div class="p-4 bg-gray-800 border-b border-gray-700 flex justify-between items-center">
<h3 class="text-md font-medium text-gray-200">即時操作日誌 (最後 50 )</h3>
<span class="text-xs text-gray-400">所有時間為系統時區</span>
<h3 class="text-md font-medium text-gray-200">{{ __('Real-time Operation Logs (Last 50)') }}</h3>
<span class="text-xs text-gray-400">{{ __('All Times System Timezone') }}</span>
</div>
<div class="p-0 max-h-[600px] overflow-y-auto">
<table class="min-w-full divide-y divide-gray-800 font-mono text-xs">
<thead class="bg-gray-800 sticky top-0">
<tr>
<th class="px-4 py-2 text-left text-gray-500">時間</th>
<th class="px-4 py-2 text-left text-gray-500">層級</th>
<th class="px-4 py-2 text-left text-gray-500">訊息</th>
<th class="px-4 py-2 text-left text-gray-500">{{ __('Time') }}</th>
<th class="px-4 py-2 text-left text-gray-500">{{ __('Level') }}</th>
<th class="px-4 py-2 text-left text-gray-500">{{ __('Message') }}</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-800">
@@ -75,7 +75,7 @@
</tr>
@empty
<tr>
<td colspan="3" class="px-4 py-8 text-center text-gray-500 italic">暫無相關日誌</td>
<td colspan="3" class="px-4 py-8 text-center text-gray-500 italic">{{ __('No logs found') }}</td>
</tr>
@endforelse
</tbody>