{# trade-pro listing / category — cms 列表设计移植(Task 10c)。 设计源 D:/project/cms/runtimes/astro-site-runtime/src/pages/[locale]/: - products/[...page].astro:PageHero + 260px 产品分类侧栏(sticky)+ SectionHead + 3 列卡片栅格(CardGrid cols-3)+ 窗口式分页 - news/[...page].astro:PageHero + 1fr/310px 双栏;列表列为横向新闻行 (290px 封面 + tag/标题/摘要/Read more),侧栏三盒 (Latest / Popular / Categories 计数) 与 cms 的结构决策: 1. kind 分支按列表内容类型:post 类(/news/、/post/ 等文章集合)用 新闻行形态;其余(product/vehicle/brand/case/service)复用产品卡片 栅格——cms 只定义了这两种列表设计,品牌/案例/服务映射到产品卡形态 (与 brand.html 相关产品、product.html 相关产品一致)。非空列表只信 首项内容类型;路由子串仅作空列表 fallback 且排除 category(否则 /categories/post-sales-service/ 这类 slug 会被误判成新闻分支)。 2. 产品分类侧栏仅产品类列表渲染(侧栏链接是产品分类语义,出现在 /brands/ 等页面会误导);文章分支的侧栏是 cms 新闻三盒。空分类 数据时侧栏整段隐藏,主列变单栏。 3. cms news 页的 Tab 行(All/Company News/...)与 products 页 hero 的 “Explore Products”锚点按钮是内容数据驱动 / 页内锚点跳转,平台无 对应数据源与目标锚点,不移植;筛选面板承担列表交互入口。 4. 平台筛选契约(test_theme_pro_v3 对所有主题 listing 断言)保留: filters() 宏输出 .pro-filter-panel 且必须保持为 .pro-filter-scope 的紧邻前兄弟(pro.js 用 previousElementSibling 定位面板);卡片与 新闻行都携带 .pro-card + data-brand/data-category(pro.js 过滤的 数据源与零结果空态都依赖它们)。 5. 分页器是 cms Pagination 的窗口式页码(首尾必现 + 当前±2,其余折叠 为省略号),上一页/下一页用 arrow-left/arrow-right SVG(Task 9 图标 契约:交互箭头一律 SVG,无裸箭头字符);页码 URL 与构建期静态分页 路由一致(第 1 页 = 栏目根,形如 /products/page/2/ 递增)。 6. 空列表:筛选、栅格、分页整段隐藏,替换为友好空态提示(cms 站点 恒有内容,平台必须处理 noindex 栏目占位页的空集)。 7. 10g 评估 cms projects 列表([...page].astro)vs 本分支:核心形态 (hero + cols-3 卡栅格 + 分页)一致,仅补案例口径 hero 文案 (tp_case_like);cms 专属的 Tab 行(数据驱动分类,无数据源,同 3 不移植)与 FEATURED CASE STUDY 双栏带(HESU 特定项目的静态词典 内容,跨站即假数据)不移植。cms 卡片链到 /news// 是老站 /progect/ 同源遗留,平台链到案例详情(正确行为)。 #} {% set tp_post_like = (listing[0].type == 'post') if listing else (kind == 'listing' and ('news' in route or 'post' in route)) %} {# 10g:case 类列表走 cms projects 列表口径(OUR PROJECTS),其余非文章类 保持产品目录口径;判定与 select_listing 的路由推断同构(首项类型优先)#} {% set tp_case_like = (listing[0].type == 'case') if listing else (kind == 'listing' and 'case' in route) %} {% set tp_eyebrow = 'NEWS & INSIGHTS' if tp_post_like else ('OUR PROJECTS' if tp_case_like else 'PRODUCT CATALOGUE') %} {% set tp_hero_img = safe_image(page.cover) %} {% set tp_lead = page.summary or ('Industry updates, project stories and exhibition news from our team.' if tp_post_like else ('Project references and delivery stories from export customers worldwide.' if tp_case_like else 'Browse the full catalogue with specifications, brands and categories.')) %} {% set pg_root = (route.split('/page/')[0]).rstrip('/') ~ '/' %} {# 分页导航宏:显式传参(pg/base/icon),不依赖模板上下文闭包 #} {% macro tp_pages(pg, base, icon) -%} {% if pg and pg.pages > 1 %} {% set cur = pg.page %}{% set last = pg.pages %}{% set win = [] %} {% for i in range(1, last + 1) %} {% if i == 1 or i == last or (i - cur)|abs <= 2 %}{% if win.append(i) %}{% endif %} {% elif win and win[-1] != '…' %}{% if win.append('…') %}{% endif %}{% endif %} {% endfor %} {% endif %} {%- endmacro %}
{% if tp_hero_img %}{% endif %}
{{ tp_eyebrow }}

{{ page.title }}

{{ tp_lead }}

{% if listing %} {% if tp_post_like %}
{{ filters() }}
{% for item in listing %} {% endfor %}
{{ tp_pages(pagination, pg_root, icon) }}
{% else %} {% set tp_kind = listing[0].type %} {% set tp_show_side = categories and tp_kind in ('product', 'vehicle') %}
{% if tp_show_side %} {% endif %}
{{ tp_eyebrow }}

{{ page.title }}

{# 导语不与 hero 重复:主列头行改条目/页数计数(cms SectionHead 的 intro 位在平台无独立文案来源,用真实数据代替装饰性复述) #}

{{ listing|length }} items{% if pagination and pagination.pages > 1 %} · {{ pagination.pages }} pages{% endif %}

{{ filters() }} {{ tp_pages(pagination, pg_root, icon) }}
{% endif %} {% else %}

Nothing published here yet

Content added to this section in the admin console appears here automatically.

{% endif %}