import { useState, useEffect, useId, type CSSProperties } from "react"; import { Link } from "react-router"; import type { LucideIcon } from "lucide-react"; import { Share2, Compass, Library, Globe, BookOpen, Wrench, } from "lucide-react"; import { KIOSK_EVENT, loadWelcome, type WelcomeMessages } from "../kioskStorage"; import { useI18n } from "../i18n"; /** 中 / 英 / 藏 欢迎语(与「语言切换」按钮及轮播同步) */ const WELCOME_MESSAGES = [ { htmlLang: "zh-CN", label: "中文", text: "欢迎来到稻城天文台信息查询", }, { htmlLang: "en", label: "English", text: "Welcome to the Daocheng Observatory Information Query", }, { htmlLang: "bo", label: "བོད་ཡིག", text: "འདབ་ཆུ་གནམ་གཟིགས་ལྟེ་གནས་ཀྱི་ཆ་འཕྲིན་འཚོལ་ཞིབ་ལ་ཕེབས་པར་དགའ་བསུ་ཞུ།", }, ] as const; type MenuItem = { id: string; label: string; icon: LucideIcon; to?: string; href?: string; }; /** * 六块渐变:与品牌 Logo 配色一致(天蓝 / 青柠绿 / 金橙 / 青绿 / 赭红 / 深金琥珀) * 浅→深,对角 bg-gradient-to-br */ const TILE_GRADIENTS = [ "from-[#5DDBFF] via-[#29ABE2] to-[#1680C4]", "from-[#B8E85A] via-[#8DC63F] to-[#5FA028]", "from-[#FFD078] via-[#E8A33D] to-[#C67A18]", "from-[#6EC4B0] via-[#4D9E87] to-[#2F7562]", "from-[#D47868] via-[#A64D3D] to-[#6E3428]", "from-[#F0B84A] via-[#D97E1A] to-[#9A5A10]", ] as const; function ArcMenuTile({ item, index, total, }: { item: MenuItem; index: number; total: number; }) { const Icon = item.icon; const clipUid = useId().replace(/:/g, ""); const gradient = TILE_GRADIENTS[index] ?? TILE_GRADIENTS[TILE_GRADIENTS.length - 1]; const isOuterLeft = index === 0; const isOuterRight = index === total - 1; const isInnerLeftTrap = index === 1; const isInnerRightTrap = index === total - 2; const isOuterEdge = isOuterLeft || isOuterRight; const isInnerTrap = isInnerLeftTrap || isInnerRightTrap; /** 中间两块矩形(第 3、4 入口):去掉底部深色叠层,避免倒影里出现黑色遮罩感 */ const isCenterPair = index === 2 || index === 3; const trapReflectClass = isOuterEdge ? "tile-reflect--trap-outer" : isInnerTrap ? "tile-reflect--trap-inner" : ""; const clipLeftId = `tile-arc-l-${clipUid}`; const clipRightId = `tile-arc-r-${clipUid}`; const clipInnerLId = `tile-arc-il-${clipUid}`; const clipInnerRId = `tile-arc-ir-${clipUid}`; /** * 中间块高 Hc = 宽×4/3。内梯(2、5)短边 0.868·Hi = Hc,长边 0.932·Hi。 * 外梯(1、6)短边 0.82·Ho 与内梯长边对齐 → Ho = Hc×0.932/(0.868×0.82)。 * 第 3、4 块:矩形 aspect 3/4。 */ const faceShellClass = isOuterEdge ? "relative h-[calc(min(40vw,9.5rem)*4/3*0.932/0.868/0.82)] w-[min(38vw,9rem)] overflow-hidden shadow-[0_8px_22px_rgba(0,0,0,0.42)] ring-1 ring-white/30 sm:h-[calc(min(36vw,10rem)*4/3*0.932/0.868/0.82)] sm:w-[9.5rem] md:h-[calc(10.25rem*4/3*0.932/0.868/0.82)] md:w-[9.85rem]" : isInnerTrap ? "relative h-[calc(min(40vw,9.5rem)*4/3/0.868)] w-[min(40vw,9.5rem)] overflow-hidden shadow-[0_8px_22px_rgba(0,0,0,0.42)] ring-1 ring-white/30 sm:h-[calc(min(36vw,10rem)*4/3/0.868)] sm:w-[min(36vw,10rem)] md:h-[calc(10.25rem*4/3/0.868)] md:w-[10.25rem]" : "relative aspect-[3/4] w-[min(40vw,9.5rem)] overflow-hidden rounded-none shadow-[0_8px_22px_rgba(0,0,0,0.42)] ring-1 ring-white/30 sm:w-[min(36vw,10rem)] md:w-[10.25rem]"; const faceClipStyle: CSSProperties | undefined = isOuterLeft ? { clipPath: `url(#${clipLeftId})` } : isOuterRight ? { clipPath: `url(#${clipRightId})` } : isInnerLeftTrap ? { clipPath: `url(#${clipInnerLId})` } : isInnerRightTrap ? { clipPath: `url(#${clipInnerRId})` } : undefined; const face = ( <> {isOuterLeft ? ( ) : null} {isOuterRight ? ( ) : null} {isInnerLeftTrap ? ( ) : null} {isInnerRightTrap ? ( ) : null}