Files
star-erp/app/Http/Controllers/Landlord/TenantController.php
sky121113 d4cef2cd84
All checks were successful
Koori-ERP-Deploy-System / deploy-demo (push) Has been skipped
Koori-ERP-Deploy-System / deploy-production (push) Successful in 51s
fix(tenancy): force seeders in production and set default branding
2026-01-28 13:45:28 +08:00

240 lines
7.2 KiB
PHP

<?php
namespace App\Http\Controllers\Landlord;
use App\Http\Controllers\Controller;
use App\Modules\Core\Models\Tenant;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Inertia\Inertia;
class TenantController extends Controller
{
/**
* 顯示租戶列表
*/
public function index()
{
$tenants = Tenant::with('domains')->get()->map(function ($tenant) {
return [
'id' => $tenant->id,
'name' => $tenant->name ?? $tenant->id,
'email' => $tenant->email ?? null,
'is_active' => $tenant->is_active ?? true,
'created_at' => $tenant->created_at->format('Y-m-d H:i'),
'domains' => $tenant->domains->pluck('domain')->toArray(),
];
});
return Inertia::render('Landlord/Tenant/Index', [
'tenants' => $tenants,
]);
}
/**
* 顯示新增租戶表單
*/
public function create()
{
return Inertia::render('Landlord/Tenant/Create');
}
/**
* 儲存新租戶
*/
public function store(Request $request)
{
$validated = $request->validate([
'id' => ['required', 'string', 'max:50', 'alpha_dash', Rule::unique('tenants', 'id')],
'name' => ['required', 'string', 'max:100'],
'email' => ['nullable', 'email', 'max:100'],
'domain' => ['nullable', 'string', 'max:100'],
]);
$tenant = Tenant::create([
'id' => $validated['id'],
'name' => $validated['name'],
'email' => $validated['email'] ?? null,
'is_active' => true,
'branding' => [
'logo_path' => 'defaults/logo.png', // 預設 Logo 路徑
'login_background_path' => 'defaults/login_bg.jpg', // 預設登入背景
'primary_color' => '#4F46E5', // 預設主色系 (Indigo-600)
],
]);
// 綁定網域(如果沒有輸入,使用預設網域)
$defaultDomain = env('TENANT_DEFAULT_DOMAIN', 'star-erp.test');
$domain = !empty($validated['domain'])
? $validated['domain']
: $validated['id'] . '.' . $defaultDomain;
$tenant->domains()->create(['domain' => $domain]);
return redirect()->route('landlord.tenants.index')
->with('success', "租戶 {$validated['name']} 建立成功!");
}
/**
* 顯示單一租戶詳情
*/
public function show(string $id)
{
$tenant = Tenant::with('domains')->findOrFail($id);
return Inertia::render('Landlord/Tenant/Show', [
'tenant' => [
'id' => $tenant->id,
'name' => $tenant->name ?? $tenant->id,
'email' => $tenant->email ?? null,
'is_active' => $tenant->is_active ?? true,
'created_at' => $tenant->created_at->format('Y-m-d H:i'),
'updated_at' => $tenant->updated_at->format('Y-m-d H:i'),
'domains' => $tenant->domains->map(fn($d) => [
'id' => $d->id,
'domain' => $d->domain,
])->toArray(),
],
]);
}
/**
* 顯示租戶樣式管理頁面
*/
public function showBranding(Tenant $tenant)
{
$logoUrl = null;
if (isset($tenant->branding['logo_path'])) {
$logoUrl = \Storage::url($tenant->branding['logo_path']);
}
return Inertia::render('Landlord/Tenant/Branding', [
'tenant' => [
'id' => $tenant->id,
'name' => $tenant->name ?? $tenant->id,
'branding' => $tenant->branding ?? [],
],
'logo_url' => $logoUrl,
]);
}
/**
* 顯示編輯租戶表單
*/
public function edit(string $id)
{
$tenant = Tenant::findOrFail($id);
return Inertia::render('Landlord/Tenant/Edit', [
'tenant' => [
'id' => $tenant->id,
'name' => $tenant->name ?? $tenant->id,
'email' => $tenant->email ?? null,
'is_active' => $tenant->is_active ?? true,
],
]);
}
/**
* 更新租戶
*/
public function update(Request $request, string $id)
{
$tenant = Tenant::findOrFail($id);
$validated = $request->validate([
'name' => ['required', 'string', 'max:100'],
'email' => ['nullable', 'email', 'max:100'],
'is_active' => ['boolean'],
]);
$tenant->update($validated);
return redirect()->route('landlord.tenants.index')
->with('success', "租戶 {$validated['name']} 更新成功!");
}
/**
* 刪除租戶
*/
public function destroy(string $id)
{
$tenant = Tenant::findOrFail($id);
$name = $tenant->name ?? $id;
$tenant->delete();
return redirect()->route('landlord.tenants.index')
->with('success', "租戶 {$name} 已刪除!");
}
/**
* 新增域名到租戶
*/
public function addDomain(Request $request, string $id)
{
$tenant = Tenant::findOrFail($id);
$validated = $request->validate([
'domain' => ['required', 'string', 'max:100', Rule::unique('domains', 'domain')],
]);
$tenant->domains()->create(['domain' => $validated['domain']]);
return back()->with('success', "域名 {$validated['domain']} 已綁定!");
}
/**
* 移除租戶的域名
*/
public function removeDomain(string $id, int $domainId)
{
$tenant = Tenant::findOrFail($id);
$domain = $tenant->domains()->findOrFail($domainId);
$domainName = $domain->domain;
$domain->delete();
return back()->with('success', "域名 {$domainName} 已移除!");
}
/**
* 更新租戶品牌樣式設定
*/
public function updateBranding(Request $request, Tenant $tenant)
{
$validated = $request->validate([
'logo' => 'nullable|image|max:2048',
'primary_color' => 'required|regex:/^#[0-9A-Fa-f]{6}$/',
'text_color' => 'nullable|regex:/^#[0-9A-Fa-f]{6}$/',
]);
$branding = $tenant->branding ?? [];
// 處理 Logo 上傳
if ($request->hasFile('logo')) {
// 刪除舊 Logo
if (isset($branding['logo_path'])) {
\Storage::disk('public')->delete($branding['logo_path']);
}
// 儲存新 Logo
$path = $request->file('logo')->store('tenant-logos', 'public');
$branding['logo_path'] = $path;
}
// 更新主色系
$branding['primary_color'] = $validated['primary_color'];
// 如果有傳入字體顏色則更新,否則保留原值(或預設值)
if (isset($validated['text_color'])) {
$branding['text_color'] = $validated['text_color'];
} elseif (!isset($branding['text_color'])) {
$branding['text_color'] = '#1a1a1a';
}
$tenant->update(['branding' => $branding]);
return redirect()->back()->with('success', '樣式設定已更新');
}
}