feat: port cms contact layout into trade-pro (info/form/no-fake-submit)
Task 10f. contact.html rebuilt from contact.astro + LeadForm.astro: PageHero (breadcrumb/cover bg) -> 0.85/1.25 info+form-card grid -> rich body section (body only). No-fake-submit dual form: configured HTTPS form_endpoint renders external form (name/email/message + pro-honeypot, 10b contract); unconfigured renders no <form> at all, guidance card with real mailto when footer_email exists. Contact items render only with real fields (email mailto; no fabricated phone/address), cms map band dropped (no address data source). CSS appended to pro.css with own 900/620 media blocks; new test test_trade_pro_contact_layout_structure covers both shapes. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,95 @@
|
||||
<section class="pro-inner-hero pro-info-hero"><div class="pro-wrap"><span class="pro-eyebrow">GET IN TOUCH</span><h1>{{page.title}}</h1><p>{{page.summary}}</p></div></section>
|
||||
<section class="pro-section pro-info-section"><div class="pro-wrap pro-info-grid"><div><span class="pro-eyebrow">CONNECT / CONTACT</span><h2>Let's start the conversation.</h2>{% if footer_email %}<a class="pro-contact-email" href="mailto:{{footer_email}}">{{footer_email}} {{ icon('arrow-right') }}</a>{% else %}<p class="pro-muted">Set the official business email in the site admin console first.</p>{% endif %}</div><div class="pro-info-copy">{{body_copy(content,page)}}{% if page.cover %}<img class="pro-info-photo" src="{{safe_image(page.cover)}}" alt="{{page.title}}">{% endif %}</div></div></section>
|
||||
{% if form_endpoint %}
|
||||
<section class="pro-section"><div class="pro-wrap pro-inquiry-wrap"><div><span class="pro-eyebrow">CONTACT FORM</span><h2>Send a business enquiry</h2><p>Submissions go directly to the external form service configured by the site administrator.</p></div>
|
||||
<form class="pro-inquiry" action="{{form_endpoint}}" method="POST"><label>Name <input name="name" autocomplete="name" required maxlength="100"></label><label>Email <input name="email" type="email" autocomplete="email" required maxlength="180"></label><label>Message <textarea name="message" required minlength="6" maxlength="5000"></textarea></label><input name="website" tabindex="-1" autocomplete="off" class="pro-honeypot" aria-hidden="true"><button type="submit" class="sf-tp-btn">Submit enquiry {{ icon('arrow-right') }}</button><p>Form submissions are handled by the external service; review its privacy and spam-filtering settings.</p></form></div></section>
|
||||
{# trade-pro contact — cms 联系页设计移植(Task 10f)。
|
||||
区块序列对照 D:/project/cms/runtimes/astro-site-runtime/src/pages/[locale]/contact.astro
|
||||
+ src/components/LeadForm.astro(像素基准 dist/hesupipe/en/contact/):
|
||||
PageHero(面包屑 + 封面底图 + 眉题/h1/导语)→ 联系信息/表单双栏
|
||||
(0.85fr 信息列 + 1.25fr 灰底表单卡)→ 富文本正文(body 存在才渲染)。
|
||||
与 cms 的结构决策:
|
||||
1. 无假提交纪律(核心差异):cms LeadForm 提交到自家 control-api;
|
||||
平台表单必须由管理员配置外部 HTTPS 服务(contact-settings API
|
||||
双层校验 + make_context 渲染层回退)。form_endpoint 存在 → 渲染
|
||||
外部表单(name/email/message + pro-honeypot 蜜罐,10b 产品页
|
||||
询盘区同款契约);不存在 → 不渲染任何 <form>,表单位换引导卡
|
||||
(真实邮箱 mailto 优先;无邮箱给通用引导 + /products/ CTA)。
|
||||
2. 联系信息条目有真实字段才渲染:平台上下文只有 footer_email
|
||||
(邮箱 mailto + mail 图标)。cms 词典的电话/地址/营业时间是
|
||||
HESU 真实数据,平台无对应字段——绝不虚构,以两条通用服务承诺
|
||||
(响应时效/采购对接,全主题既有口径)补足列表节奏。地图带同理
|
||||
不移植:Google 嵌入指向公司真实地址,无地址数据源即无地图。
|
||||
结尾 Cta 带不重复渲染:pro.html 全局 pro-end-cta 对 contact 页
|
||||
本就输出(cms Cta 也是「回联系页」自指按钮,无增量信息)。
|
||||
3. 正文:cms 无独立正文区(infoText 为单段配置文案,平台由静态
|
||||
引导语对应);WP 迁移的 contact 页常带富文本 body,渲染为正文
|
||||
区(10d sf-tp-article-body 排版层双挂,无 body 整段隐藏)。 #}
|
||||
<section class="sf-tp-page-hero sf-tp-contact-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><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">CONTACT US</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-contact">
|
||||
<div class="wrap sf-tp-contact-grid">
|
||||
<div class="sf-tp-contact-info" data-reveal>
|
||||
<span class="eyebrow">CONTACT INFORMATION</span>
|
||||
<h2>Let's start the conversation</h2>
|
||||
<p>For enquiries about products, specifications or export orders, reach the team through the channels below.</p>
|
||||
<div class="sf-tp-contact-list">
|
||||
{% if footer_email %}
|
||||
<div class="sf-tp-contact-item">
|
||||
<div class="icon-circle" aria-hidden="true">{{ icon('mail') }}</div>
|
||||
<div><strong>Email</strong><p><a href="mailto:{{ footer_email }}">{{ footer_email }}</a></p></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="sf-tp-contact-item">
|
||||
<div class="icon-circle" aria-hidden="true">{{ icon('check') }}</div>
|
||||
<div><strong>Response time</strong><p>Replies within one business day.</p></div>
|
||||
</div>
|
||||
<div class="sf-tp-contact-item">
|
||||
<div class="icon-circle" aria-hidden="true">{{ icon('phone') }}</div>
|
||||
<div><strong>Sourcing desk</strong><p>One contact from inquiry to container loading.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sf-tp-contact-form" data-reveal style="--reveal-i: 1">
|
||||
{% if form_endpoint %}
|
||||
{# 已配置外部表单服务(HTTPS 双层校验通过):cms LeadForm 形态 ——
|
||||
标题 + 引导语 + 纵向字段栅格;蜜罐隐藏(.pro-honeypot,10b 同款) #}
|
||||
<h2>Send us a message</h2>
|
||||
<p>Fill out the form below and we will get back to you shortly.</p>
|
||||
<form action="{{ form_endpoint }}" method="POST">
|
||||
<label>Name <input name="name" autocomplete="name" required maxlength="100"></label>
|
||||
<label>Email <input name="email" type="email" autocomplete="email" required maxlength="180"></label>
|
||||
<label>Message <textarea name="message" required minlength="6" maxlength="5000"></textarea></label>
|
||||
<input name="website" tabindex="-1" autocomplete="off" class="pro-honeypot" aria-hidden="true">
|
||||
<button type="submit" class="sf-tp-btn">Send message {{ icon('arrow-right') }}</button>
|
||||
<p class="sf-tp-contact-note">Submissions are handled by the external form service configured by the site administrator; review its privacy and spam-filtering settings.</p>
|
||||
</form>
|
||||
{% else %}
|
||||
{# 无假提交:未配置外部表单服务 → 不渲染任何 <form>。有真实邮箱给
|
||||
mailto 直达;无邮箱给通用引导 + 产品目录 CTA(不虚构任何联系方式) #}
|
||||
<h2>Send us a message</h2>
|
||||
{% if footer_email %}
|
||||
<p>The online form is not activated on this site yet. Email the team directly — replies within one business day.</p>
|
||||
<a class="sf-tp-btn" href="mailto:{{ footer_email }}">Email {{ footer_email }} {{ icon('arrow-right') }}</a>
|
||||
{% else %}
|
||||
<p>The online enquiry form is not activated on this site yet. Published specifications are available on the catalogue pages while the enquiry channel is being set up.</p>
|
||||
<a class="sf-tp-btn sf-tp-btn--ghost" href="/products/">Browse products {{ icon('arrow-right') }}</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% if content %}
|
||||
<section class="section section--soft sf-tp-contact-body-section">
|
||||
<div class="wrap">
|
||||
<div class="sf-tp-contact-body sf-tp-article-body" data-reveal>{{ body_copy(content, page) }}</div>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
@@ -491,3 +491,43 @@
|
||||
.sf-theme-trade-pro .sf-tp-about-facility figcaption{padding:9px 10px}
|
||||
.sf-theme-trade-pro .sf-tp-about-facility .sf-tp-tag{font-size:10px}
|
||||
}
|
||||
|
||||
/* ── Task 10f:contact 联系页(contact.astro + LeadForm.astro 移植)──
|
||||
源 src/pages/[locale]/contact.astro:联系信息/表单双栏(0.85fr 信息列 +
|
||||
1.25fr 灰底 form-card)+ LeadForm(引导语 + 纵向字段栅格 + 提交按钮)。
|
||||
共享组件复用:sf-tp-page-hero/breadcrumb(10c 内页 hero)、
|
||||
sf-tp-article-body(10d 富文本排版层双挂);表单卡与 10b 询盘表单卡
|
||||
同构(cms 同一 LeadForm 组件),字段样式走 theme.css 元素基线,
|
||||
本块只补 contact 专属布局(双栏比、信息列表、图标实底圆)。 */
|
||||
|
||||
.sf-theme-trade-pro .sf-tp-contact-grid{display:grid;grid-template-columns:0.85fr 1.25fr;gap:calc(var(--sf-tp-space-16) + var(--sf-tp-space-6));align-items:start}
|
||||
.sf-theme-trade-pro .sf-tp-contact-info>p{color:var(--sf-tp-color-text-muted)}
|
||||
/* 信息列表(cms contact-list):图标圆 + 标题/值两列行 */
|
||||
.sf-theme-trade-pro .sf-tp-contact-list{display:grid;gap:var(--sf-tp-space-6);margin-block-start:var(--sf-tp-space-8)}
|
||||
.sf-theme-trade-pro .sf-tp-contact-item{display:grid;grid-template-columns:var(--sf-tp-space-12) 1fr;gap:var(--sf-tp-space-4);align-items:center}
|
||||
/* cms icon-solid:品牌实底圆覆写默认 brand-soft 形态(居中 auto 边距归零) */
|
||||
.sf-theme-trade-pro .sf-tp-contact-item .icon-circle{margin:0;background:var(--sf-tp-color-brand-primary);color:var(--sf-tp-color-text-on-brand)}
|
||||
.sf-theme-trade-pro .sf-tp-contact-item strong{display:block;margin-block-end:var(--sf-tp-space-1)}
|
||||
.sf-theme-trade-pro .sf-tp-contact-item p{margin:0;color:var(--sf-tp-color-text-muted);font-size:var(--sf-tp-font-size-sm)}
|
||||
.sf-theme-trade-pro .sf-tp-contact-item a{color:inherit;word-break:break-all}
|
||||
.sf-theme-trade-pro .sf-tp-contact-item a:hover{color:var(--sf-tp-color-text-link)}
|
||||
/* 表单卡(cms form-card + lead-text):灰底圆角;两形态共用(外部表单/
|
||||
无表单引导卡),卡内引导语 muted(cms .lead-text 间距) */
|
||||
.sf-theme-trade-pro .sf-tp-contact-form{background:var(--sf-tp-color-surface-muted);padding:calc(var(--sf-tp-space-8) + var(--sf-tp-space-1));border-radius:var(--sf-tp-radius-sm)}
|
||||
.sf-theme-trade-pro .sf-tp-contact-form>p{color:var(--sf-tp-color-text-muted);margin-block-end:var(--sf-tp-space-6)}
|
||||
.sf-theme-trade-pro .sf-tp-contact-form form{display:grid;gap:var(--sf-tp-space-4)}
|
||||
.sf-theme-trade-pro .sf-tp-contact-form .sf-tp-btn{justify-self:start}
|
||||
.sf-theme-trade-pro .sf-tp-contact-form textarea{min-height:110px}
|
||||
.sf-theme-trade-pro .sf-tp-contact-note{font-size:var(--sf-tp-font-size-xs);color:var(--sf-tp-color-text-muted);margin:0}
|
||||
|
||||
/* ── contact 响应式(cms 断点 900/620;767 无 contact 专属规则——内页
|
||||
hero 的 767 竖版由 10c 既有块覆盖。折叠规则收在本任务媒体块内
|
||||
(10c 教训:同特异性按源顺序取胜)── */
|
||||
@media (max-width: 900px){
|
||||
.sf-theme-trade-pro .sf-tp-contact-grid{grid-template-columns:1fr}
|
||||
}
|
||||
@media (max-width: 620px){
|
||||
.sf-theme-trade-pro .sf-tp-contact-list{gap:16px}
|
||||
.sf-theme-trade-pro .sf-tp-contact-item{grid-template-columns:40px 1fr;gap:10px}
|
||||
.sf-theme-trade-pro .sf-tp-contact-form{padding:20px}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user