v0.10.25: /solution/ 归档+落地页复刻(archive 组件/分页/摘录24词)、Header 全断点对齐、page_css 导入管线、reviews/populated 宽度/_css_classes/tabs HTML/图片变体修复

This commit is contained in:
bigcode
2026-11-03 03:59:04 +08:00
parent 7559977ae1
commit 9a51994860
17 changed files with 681 additions and 146 deletions
+47 -39
View File
@@ -20,7 +20,7 @@
*/
import { useState } from "react";
import { Link } from "@tanstack/react-router";
import { Search, Menu, X, ChevronRight, Mail, User, Star } from "lucide-react";
import { Search, Menu, X, ChevronRight, Mail, MessageCircleMore, Star } from "lucide-react";
import { Button } from "~/components/ui/button";
import { Input } from "~/components/ui/input";
import {
@@ -118,60 +118,68 @@ export function Header(props: { menu: MenuNode[] }) {
const tops = items.filter((it) => it.title !== "Search");
return (
<header className="sticky top-0 z-[100] border-b border-line bg-white shadow-[0_1px_6px_rgba(16,42,76,0.06)]">
{/* topbar:口号 + 社交图标 + 登录 */}
<div className="bg-footer text-[13px] text-white">
<div className="site-container flex h-10 items-center justify-between">
<a href="/landing-pages/oem-odm/" className="text-white hover:text-[#f5b278]">
<header className="sticky top-0 z-[100] bg-white shadow-[0_1px_6px_rgba(16,42,76,0.06)]">
{/* topbar:口号 + 社交图标(原站实测 2026-11-03:高 36px、容器 1350、文字 16px/16、
图标 36×36 盒 gap 10、顺序 Linkedin/Youtube/Facebook、无登录项;<768 隐藏) */}
<div className="hidden bg-footer text-white min-[768px]:block">
<div className="mx-auto flex h-9 w-full max-w-[1350px] items-center justify-between">
<a href="/landing-pages/oem-odm/" className="text-[16px] leading-4 text-white hover:text-[#f5b278]">
{t("topbar_oem")}
</a>
<div className="flex items-center gap-3.5">
<a href="https://www.youtube.com/@dusuniot" aria-label="YouTube" target="_blank" rel="noreferrer" className="text-white hover:text-[#f5b278]">
<YoutubeGlyph />
</a>
<a href="https://www.facebook.com/dusuniot" aria-label="Facebook" target="_blank" rel="noreferrer" className="text-white hover:text-[#f5b278]">
<FacebookGlyph />
</a>
<a href="https://www.linkedin.com/company/dusun-iot" aria-label="LinkedIn" target="_blank" rel="noreferrer" className="text-white hover:text-[#f5b278]">
<div className="flex items-center gap-[10px]">
<a href="https://www.linkedin.com/company/dusun-iot" aria-label="LinkedIn" target="_blank" rel="noreferrer" className="flex h-9 w-9 items-center justify-center text-white hover:text-[#f5b278]">
<LinkedinGlyph />
</a>
<span className="h-3.5 w-px bg-white/35" aria-hidden />
<a href="/my-account/" className="inline-flex items-center gap-1 text-white hover:text-[#f5b278]">
<User size={15} aria-hidden /> {t("login")}
<a href="https://www.youtube.com/@dusuniot" aria-label="YouTube" target="_blank" rel="noreferrer" className="flex h-9 w-9 items-center justify-center text-white hover:text-[#f5b278]">
<YoutubeGlyph />
</a>
<a href="https://www.facebook.com/dusuniot" aria-label="Facebook" target="_blank" rel="noreferrer" className="flex h-9 w-9 items-center justify-center text-white hover:text-[#f5b278]">
<FacebookGlyph />
</a>
</div>
</div>
</div>
{/* 主导航(原站实测:白底条高 68px,topbar 40px,合计 108px) */}
<div className="site-container flex h-[68px] items-center gap-6">
{/* 主导航(原站实测 2026-11-03:桌面 68px 容器 40/25、logo 后 80px 起菜单、项 pad 8/6 项距 6;
平板 768-959 为汉堡导航(顶栏 36 + 导航 48,logo 缩放,右侧 CONTACT US+邮件);
手机 <768 无顶栏、导航 48、汉堡在 logo 右 96px、右侧橙色气泡+邮件) */}
<div className="flex h-12 items-center px-2.5 pr-[13px] min-[768px]:pr-[68px] min-[960px]:h-[68px] min-[960px]:pl-10 min-[960px]:pr-[25px]">
{/* 直接复用原站 header logo(Elementor site-logo 同一图片,实测渲染 171×42.75px) */}
<Link to="/" className="shrink-0">
<img src="/uploads/2022/06/Dusuniot-logo-R-400-e1669108867399.png" width={300} height={75} alt="Dusun IoT" className="h-auto w-[171px]" />
<img src="/uploads/2022/06/Dusuniot-logo-R-400-e1669108867399.png" width={300} height={75} alt="Dusun IoT" className="block h-auto w-[109px] min-[768px]:w-[103px] min-[880px]:w-[124px] min-[960px]:w-[171px]" />
</Link>
<DesktopNav tops={tops} />
{searchOpen ? (
<form action="/search" method="get" className="flex items-center overflow-hidden rounded-full border border-line bg-soft">
<Input type="search" name="q" placeholder={t("search_placeholder")} aria-label="Search" autoFocus className="w-40 rounded-none border-0 bg-transparent focus-visible:border-0" />
<button type="submit" aria-label="Submit search" className="flex cursor-pointer items-center border-0 bg-transparent px-2.5 py-1.5 text-muted-foreground">
<Search size={16} aria-hidden />
<div className="ml-[80px] hidden min-w-0 min-[960px]:flex min-[960px]:flex-1 min-[960px]:items-center">
<DesktopNav tops={tops} />
{searchOpen ? (
<form action="/search" method="get" className="ml-1.5 flex items-center overflow-hidden rounded-full border border-line bg-soft">
<Input type="search" name="q" placeholder={t("search_placeholder")} aria-label="Search" autoFocus className="w-40 rounded-none border-0 bg-transparent focus-visible:border-0" />
<button type="submit" aria-label="Submit search" className="flex cursor-pointer items-center border-0 bg-transparent px-2.5 py-1.5 text-muted-foreground">
<Search size={16} aria-hidden />
</button>
</form>
) : (
<button aria-label="Open search" onClick={() => setSearchOpen(true)} className="ml-1.5 flex h-[68px] w-10 cursor-pointer items-center justify-center border-0 bg-transparent p-0 text-ink">
<Search size={19} aria-hidden />
</button>
</form>
) : (
<button aria-label="Open search" onClick={() => setSearchOpen(true)} className="flex cursor-pointer items-center border-0 bg-transparent p-1.5 text-ink">
<Search size={19} aria-hidden />
)}
</div>
{/* 汉堡:原站为 mega-toggle 块(手机位于 logo 右 96px、平板右聚拢),图标浅灰 */}
<div className="ml-[96px] flex h-12 items-center justify-end min-[768px]:ml-auto min-[960px]:hidden">
<button aria-label="Toggle menu" onClick={() => setOpen(!open)} className="flex h-12 w-10 cursor-pointer items-center justify-center rounded-[4px] border-0 bg-transparent p-0 text-[#c9c9c9]">
{open ? <X size={32} aria-hidden /> : <Menu size={32} aria-hidden />}
</button>
)}
<Button asChild className="hidden whitespace-nowrap px-[18px] py-[9px] min-[960px]:inline-flex">
</div>
<div className="min-w-0 flex-1 min-[960px]:hidden" aria-hidden />
<a href="/contact-us/" aria-label="Contact us" className="flex h-[34px] w-[38px] items-center justify-center text-brand min-[768px]:hidden">
<MessageCircleMore size={28} aria-hidden />
</a>
<Button asChild className="hidden whitespace-nowrap px-[18px] py-[9px] min-[768px]:inline-flex">
<a href="/contact-us/">{t("contact_us")}</a>
</Button>
<a href="/contact-us/" aria-label="Email us" className="hidden items-center p-1 text-brand min-[960px]:flex">
<Mail size={19} aria-hidden />
<a href="/contact-us/" aria-label="Email us" className="flex h-10 w-[52px] items-center justify-center p-0 text-brand">
<Mail size={28} aria-hidden />
</a>
<LangSwitcher />
<button aria-label="Toggle menu" onClick={() => setOpen(!open)} className="ml-auto cursor-pointer rounded-[4px] border-0 bg-transparent p-1.5 text-ink min-[960px]:hidden">
{open ? <X size={24} aria-hidden /> : <Menu size={24} aria-hidden />}
</button>
</div>
{/* 移动端菜单 */}
{open ? (
@@ -201,7 +209,7 @@ export function Header(props: { menu: MenuNode[] }) {
*/
function DesktopNav({ tops }: { tops: MenuNode[] }) {
return (
<div className="hidden min-[960px]:flex min-[960px]:flex-1 min-[960px]:items-center gap-0.5">
<div className="hidden min-[960px]:flex min-[960px]:items-center gap-1.5">
{tops.map((node) => {
const linkHref = TOP_URL_FIX[node.title] ?? normalizeUrl(node.url) ?? undefined;
// 巨幕面板项(全宽视口)
@@ -298,7 +306,7 @@ function TopTrigger({ title, href }: { title: string; href?: string }) {
if (href) {
return (
<NavigationMenuTrigger asChild chevron={false}>
<a href={href}>
<a href={href} className="pl-2 pr-1.5">
{title}
<CaretDown />
</a>