WCM6 收口企业微信多手机移动渲染稳定化
这个提交包含在:
@@ -8,6 +8,7 @@ import {
|
||||
MOBILE_NAV_ITEMS,
|
||||
} from "../../features/mobile/navigation";
|
||||
import { cn } from "../../lib/utils";
|
||||
import { MobileIcon } from "./MobileIcon";
|
||||
|
||||
function resolveBadgeLabel(count: number) {
|
||||
if (count > 99) {
|
||||
@@ -53,8 +54,13 @@ export function MobileBottomNav() {
|
||||
aria-disabled="true"
|
||||
title={`${item.label}不可用`}
|
||||
>
|
||||
<span className="material-symbols-outlined text-[20px]">{item.icon}</span>
|
||||
<span className="max-w-full overflow-hidden text-ellipsis whitespace-nowrap">{item.label}</span>
|
||||
<MobileIcon name={item.icon} className="size-5" />
|
||||
<span
|
||||
className="max-w-full overflow-hidden text-ellipsis whitespace-nowrap"
|
||||
data-testid={`mobile-nav-${item.key}-label`}
|
||||
>
|
||||
{item.label}
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@@ -67,29 +73,35 @@ export function MobileBottomNav() {
|
||||
data-testid={`mobile-nav-${item.key}`}
|
||||
className={({ isActive }) =>
|
||||
cn(
|
||||
"touch-target pointer-events-auto flex h-12 min-h-0 min-w-0 select-none flex-col items-center justify-center gap-0.5 rounded-xl px-0.5 py-1 text-[11px] font-medium leading-none transition-colors",
|
||||
"touch-target pointer-events-auto relative flex h-12 min-h-0 min-w-0 select-none flex-col items-center justify-center gap-0.5 rounded-xl px-0.5 py-1 text-[11px] font-medium leading-none transition-colors",
|
||||
isActive
|
||||
? "bg-primary text-white shadow-sm"
|
||||
? "bg-primary/10 text-primary ring-1 ring-primary/15"
|
||||
: "text-zinc-500 hover:bg-zinc-50 hover:text-zinc-900",
|
||||
)
|
||||
}
|
||||
>
|
||||
{({ isActive }) => (
|
||||
<>
|
||||
<span className="relative">
|
||||
<span className="material-symbols-outlined text-[19px] leading-none">{item.icon}</span>
|
||||
{badge ? (
|
||||
<span
|
||||
className={cn(
|
||||
"absolute -right-3 -top-2 min-w-5 rounded-full px-1.5 py-0.5 text-[10px] font-semibold leading-none",
|
||||
isActive ? "bg-white text-primary" : "bg-red-500 text-white",
|
||||
)}
|
||||
>
|
||||
{badge}
|
||||
</span>
|
||||
) : null}
|
||||
<span>
|
||||
<MobileIcon name={item.icon} className="size-5" />
|
||||
</span>
|
||||
<span className="max-w-full overflow-hidden text-ellipsis whitespace-nowrap">{item.label}</span>
|
||||
<span
|
||||
className="max-w-full overflow-hidden text-ellipsis whitespace-nowrap"
|
||||
data-testid={`mobile-nav-${item.key}-label`}
|
||||
>
|
||||
{item.label}
|
||||
</span>
|
||||
{badge ? (
|
||||
<span
|
||||
data-testid={`mobile-nav-${item.key}-badge`}
|
||||
className={cn(
|
||||
"pointer-events-none absolute right-1 top-1 min-w-4 rounded-full px-1 text-[10px] font-semibold leading-4 shadow-sm",
|
||||
isActive ? "bg-red-500 text-white" : "bg-red-500 text-white",
|
||||
)}
|
||||
>
|
||||
{badge}
|
||||
</span>
|
||||
) : null}
|
||||
</>
|
||||
)}
|
||||
</NavLink>
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import type { HTMLAttributes } from "react";
|
||||
import {
|
||||
Bell,
|
||||
BriefcaseBusiness,
|
||||
CalendarCheck,
|
||||
Circle,
|
||||
ClipboardCheck,
|
||||
CloudUpload,
|
||||
FileCheck2,
|
||||
FileText,
|
||||
Home,
|
||||
IdCard,
|
||||
Network,
|
||||
PackageSearch,
|
||||
ReceiptText,
|
||||
Settings,
|
||||
UserCog,
|
||||
UserRound,
|
||||
Users,
|
||||
type LucideIcon,
|
||||
} from "lucide-react";
|
||||
import { cn } from "../../lib/utils";
|
||||
|
||||
const MOBILE_ICON_MAP: Record<string, LucideIcon> = {
|
||||
account_tree: Network,
|
||||
badge: IdCard,
|
||||
cloud_upload: CloudUpload,
|
||||
event_available: CalendarCheck,
|
||||
fact_check: ClipboardCheck,
|
||||
group: Users,
|
||||
home: Home,
|
||||
inventory_2: PackageSearch,
|
||||
manage_accounts: UserCog,
|
||||
notifications: Bell,
|
||||
person: UserRound,
|
||||
picture_as_pdf: FileText,
|
||||
receipt_long: ReceiptText,
|
||||
request_quote: FileCheck2,
|
||||
settings: Settings,
|
||||
workspaces: BriefcaseBusiness,
|
||||
};
|
||||
|
||||
type MobileIconProps = HTMLAttributes<HTMLSpanElement> & {
|
||||
iconClassName?: string;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export function MobileIcon({ className, iconClassName, name, ...props }: MobileIconProps) {
|
||||
const Icon = MOBILE_ICON_MAP[name] ?? Circle;
|
||||
|
||||
return (
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className={cn("inline-flex shrink-0 items-center justify-center leading-none", className)}
|
||||
{...props}
|
||||
>
|
||||
<Icon className={cn("size-5", iconClassName)} strokeWidth={2.1} />
|
||||
</span>
|
||||
);
|
||||
}
|
||||
在新工单中引用
屏蔽一个用户