feat: 新增租戶品牌客製化系統(Logo、主色系)、修正 hardcoded 顏色為 CSS 變數
All checks were successful
Koori-ERP-Deploy-System / deploy-demo (push) Successful in 47s
Koori-ERP-Deploy-System / deploy-production (push) Has been skipped

This commit is contained in:
2026-01-16 14:36:24 +08:00
parent a2c99e3a36
commit 55272d5d43
36 changed files with 568 additions and 70 deletions

View File

@@ -20,7 +20,7 @@ import {
} from "lucide-react";
import { toast, Toaster } from "sonner";
import { useState, useEffect, useMemo } from "react";
import { Link, usePage } from "@inertiajs/react";
import { Link, usePage, Head } from "@inertiajs/react";
import { cn } from "@/lib/utils";
import BreadcrumbNav, { BreadcrumbItemType } from "@/Components/shared/BreadcrumbNav";
import {
@@ -33,6 +33,7 @@ import {
} from "@/Components/ui/dropdown-menu";
import { usePermission } from "@/hooks/usePermission";
import ApplicationLogo from "@/Components/ApplicationLogo";
import { generateLightestColor, generateLightColor, generateDarkColor, generateActiveColor } from "@/utils/colorUtils";
interface MenuItem {
id: string;
@@ -328,6 +329,18 @@ export default function AuthenticatedLayout({
return (
<div className="flex min-h-screen bg-slate-50">
<Head>
<link rel="icon" type="image/png" href="/favicon.png" />
<style>{`
:root {
--primary-main: ${(props as any).branding?.primary_color || '#01ab83'};
--primary-dark: ${generateDarkColor((props as any).branding?.primary_color || '#01ab83')};
--primary-light: ${generateLightColor((props as any).branding?.primary_color || '#01ab83')};
--primary-lightest: ${generateLightestColor((props as any).branding?.primary_color || '#01ab83')};
--button-main-active: ${generateActiveColor((props as any).branding?.primary_color || '#01ab83')};
}
`}</style>
</Head>
{/* Mobile Header -> Global Header */}
<header className="fixed top-0 left-0 right-0 h-16 bg-white border-b border-slate-200 z-[60] flex items-center justify-between px-4 transition-all duration-300">
<div className="flex items-center gap-2">
@@ -395,7 +408,7 @@ export default function AuthenticatedLayout({
{!isCollapsed && (
<Link href="/" className="flex items-center gap-2 group">
<ApplicationLogo className="w-8 h-8 rounded-lg object-contain group-hover:scale-110 transition-transform" />
<span className="font-extrabold text-[#01ab83] text-lg tracking-tight"> ERP</span>
<span className="font-extrabold text-primary-main text-lg tracking-tight"> ERP</span>
</Link>
)}
{isCollapsed && (
@@ -444,7 +457,7 @@ export default function AuthenticatedLayout({
<div className="h-16 flex items-center justify-between px-6 border-b border-slate-100">
<Link href="/" className="flex items-center gap-2">
<ApplicationLogo className="w-8 h-8 rounded-lg object-contain" />
<span className="font-extrabold text-[#01ab83] text-lg"> ERP</span>
<span className="font-extrabold text-primary-main text-lg"> ERP</span>
</Link>
<button onClick={() => setIsMobileOpen(false)} className="p-2 text-slate-400">
<X className="h-5 w-5" />