2026-10-23 16:59:52 +08:00
{# trade-pro case detail — cms 案例详情设计移植(Task 10g)。
区块序列对照 D:/project/cms/runtimes/astro-site-runtime/src/pages/[locale]/projects/[slug].astro
(像素基准 dist/hesupipe/en/projects/< slug > /):
PageHero(面包屑 Home › Cases › 标题 + 封面底图 + 眉题/h1/导语)→
detail-grid 双栏(1.2fr 文案列:Project Overview 眉题 + h2 + ● location/
industry 行 + 富文本正文;0.8fr sticky 侧列:主图 + 3 列相册缩略图 +
Results 成果卡)→ Recommended Products( soft 底产品卡)→ Other Projects
(相关案例卡,排除自身)。
与 cms 的结构决策:
1. cms 文案列是 customerBackground / challenge / solution 三个结构化字段
(空时回退 HESU 词典段落);平台案例只有单一富文本 body——概览块后
正文一整块渲染(10d sf-tp-article-body 排版层双挂),Challenge/
Solution 分段由正文自身的 h2/h3 标题承担;不移植词典兜底段落
(那是 HESU 站点文案,跨站即假数据)。
2. 侧列数据映射:相册 = make_context 的 gallery( cover + fields.gallery
去重,与 10b 产品画廊同源);主图 gallery[0],缩略图全量含首图
(cms 同款,>1 张才渲染缩略图行);无图回退 sf-tp-photo-plain 占位。
Results 成果卡 = fields.results 开放字段(分号/换行分隔要点;cms 的
resultsPoints 词典兜底不移植),空则整段隐藏——绝不编造成果;
✓ 圆徽用 Task 9 check SVG 图标,非文本字符。
3. ● location 行 = blueprints 为 case 定义的字段 location + industry
( cms 的 item.text 单行对应物);均空时行隐藏,概览块(眉题 + h2)
保留 cms 结构位。
4. Recommended Products = 产品/车型前 4( cms fetchProducts 前 4 同构),
空则整段隐藏;Other Projects = groups['case'] 排除自身前 4,动作位
回 /cases/( cms 回 /projects/,平台栏目根)。
5. 页尾 Cta 横幅由 pro.html 的 .pro-end-cta 承担(10b/10d 同决策);
cms 的 CreativeWork JSON-LD 不移植(pro.html 的 og:type=article 已覆盖
分享语义)。 #}
{% set tp_case_others = groups['case']|rejectattr('route','equalto',page.route)|list %}
{% set tp_case_products = (groups['product'] + groups['vehicle'])[:4] %}
{% set tp_results = ((fields.get('results') or '')|string|replace('\r\n','\n')|replace('\r','\n')|replace(';','\n')|trim).split('\n')|map('trim')|reject('equalto','')|list %}
< section class = "sf-tp-page-hero sf-tp-case-hero" >
{% if safe_image(page.cover) %}< img class = "sf-tp-page-hero-bg" src = "{{ safe_image(page.cover) }}" alt = "" width = "1600" height = "900" fetchpriority = "high" decoding = "async" > {% endif %}
< div class = "sf-tp-page-hero-overlay" aria-hidden = "true" ></ div >
< div class = "wrap" >
< nav class = "sf-tp-breadcrumb" aria-label = "Breadcrumb" data-reveal >
< a href = "/" > Home</ a >< a href = "/cases/" > Cases</ a >< span class = "sf-tp-breadcrumb-current" > {{ page.title }}</ span >
</ nav >
< div class = "sf-tp-page-hero-copy" data-reveal style = "--reveal-i: 1" >
< span class = "eyebrow" > OUR PROJECTS</ span >
< h1 > {{ page.title }}</ h1 >
{% if page.summary %}< p class = "sf-tp-page-hero-lead" > {{ page.summary }}</ p > {% endif %}
</ div >
</ div >
</ section >
< section class = "section sf-tp-case-detail" >
< div class = "wrap sf-tp-case-grid" >
< div class = "sf-tp-case-copy" data-reveal >
< div class = "sf-tp-case-overview" >
< span class = "eyebrow" > PROJECT OVERVIEW</ span >
< h2 > {{ page.title }}</ h2 >
{% if fields.get('location') %}< p class = "sf-tp-case-location" >< span aria-hidden = "true" > ●</ span > {{ fields.get('location') }}</ p > {% endif %}
{% if fields.get('industry') %}< p class = "sf-tp-case-location" >< span aria-hidden = "true" > ●</ span > {{ fields.get('industry') }}</ p > {% endif %}
</ div >
< div class = "sf-tp-case-body sf-tp-article-body" > {{ body_copy(content, page) }}</ div >
</ div >
< div class = "sf-tp-case-side" >
< div class = "sf-tp-photo" data-reveal style = "--reveal-i: 1" >
{% if gallery %}< img src = "{{ gallery[0] }}" alt = "{{ page.title }}" width = "800" height = "600" loading = "lazy" decoding = "async" >
{% else %}< div class = "sf-tp-photo-plain" aria-hidden = "true" >< span > CASE STUDY</ span ></ div > {% endif %}
</ div >
{% if gallery|length > 1 %}
< div class = "sf-tp-case-gallery" data-reveal style = "--reveal-i: 2" aria-label = "Project photo gallery" >
{% for shot in gallery %}< img src = "{{ shot }}" alt = "{{ page.title }} photo {{ loop.index }}" width = "200" height = "140" loading = "lazy" decoding = "async" > {% endfor %}
</ div >
{% endif %}
{% if tp_results %}
< div class = "sf-tp-case-results" data-reveal style = "--reveal-i: 2" >
< h3 > Results</ h3 >
< ul >
{% for point in tp_results %}< li >< span class = "sf-tp-case-check" aria-hidden = "true" > {{ icon('check', size='12') }}</ span > {{ point }}</ li > {% endfor %}
</ ul >
</ div >
{% endif %}
</ div >
</ div >
</ section >
{% if tp_case_products %}
< section class = "section section--soft sf-tp-case-products" >
< div class = "wrap" >
< div class = "sf-tp-section-head" data-reveal >
< div >
< span class = "eyebrow" > APPLICATIONS</ span >
< h2 > Recommended products</ h2 >
</ div >
</ div >
< div class = "sf-tp-card-grid" >
{% for tp_item in tp_case_products %}
< article class = "sf-tp-card" data-reveal style = "--reveal-i: {{ loop.index0 % 4 }}" >
< div class = "sf-tp-card-media" > {{ cover(tp_item, 'product') }}</ div >
< div class = "sf-tp-card-body" >
< h3 > {{ tp_item.title }}</ h3 >
< p > {{ (tp_item.summary or 'Published specifications available on request.').split('.')[0] }}.</ p >
< a class = "sf-tp-more" href = "{{ safe_href(tp_item.route) }}" > View details {{ icon('arrow-right', cls='sf-tp-icon--sm') }}</ a >
</ div >
</ article >
{% endfor %}
</ div >
</ div >
</ section >
{% endif %}
{% if tp_case_others %}
< section class = "section sf-tp-case-related" >
< div class = "wrap" >
< div class = "sf-tp-section-head" data-reveal >
< div >
< span class = "eyebrow" > OUR PROJECTS</ span >
< h2 > Other projects</ h2 >
</ div >
< a class = "sf-tp-more" href = "/cases/" > View all projects {{ icon('arrow-right', cls='sf-tp-icon--sm') }}</ a >
</ div >
< div class = "sf-tp-card-grid" >
{% for tp_item in tp_case_others[:4] %}
< article class = "sf-tp-card" data-reveal style = "--reveal-i: {{ loop.index0 % 4 }}" >
< div class = "sf-tp-card-media" > {{ cover(tp_item, 'case') }}</ div >
< div class = "sf-tp-card-body" >
< h3 > {{ tp_item.title }}</ h3 >
< p > {{ (tp_item.summary or 'Project reference available on request.').split('.')[0] }}.</ p >
< a class = "sf-tp-more" href = "{{ safe_href(tp_item.route) }}" > View details {{ icon('arrow-right', cls='sf-tp-icon--sm') }}</ a >
</ div >
</ article >
{% endfor %}
</ div >
</ div >
</ section >
{% endif %}