fix: trade-pro review fixes — drop shadow blocks.css, English presets, 7-item fallback nav

- remove themes/trade-pro/blocks.css (52-byte placeholder shadowed the
  platform 7KB block stylesheet via copy_blocks_css) and drop it from
  manifest styles; Phase 3 brings real component styles
- page-presets.json: all editor/bootstrap copy translated to trade B2B
  English; ids, block types, structure and hrefs identical to industrial
- fallback nav widened to all 7 default sections (Brands/Cases restored)
  so the documented false-positive window only relabels, never drops
  coverage; comment added next to the tp_needs_en_nav set
- test anchors '>Products<' on the built home page

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-10-22 18:40:49 +08:00
parent 5797638caf
commit 2a2f943bf4
6 changed files with 68 additions and 62 deletions
@@ -375,6 +375,7 @@ def test_theme_color_map_covers_trade_pro():
3. **spec §6 "渲染快照"以 E2E 页面断言实现**(构建后逐页 200 + 结构选择器 + 文案断言),不另建 Jinja 快照测试文件。 3. **spec §6 "渲染快照"以 E2E 页面断言实现**(构建后逐页 200 + 结构选择器 + 文案断言),不另建 Jinja 快照测试文件。
4. **/api/themes(main.py:267)经 core.THEMES 动态化自动生效**,不设专项测试(catalog 由既有测试覆盖)。 4. **/api/themes(main.py:267)经 core.THEMES 动态化自动生效**,不设专项测试(catalog 由既有测试覆盖)。
5. **前端入口 option 文案**:三个 HTML 下拉用"Trade Pro · 外贸 B2B(英文)"中文风格与各文件现状一致(theme-gallery 用英文)。 5. **前端入口 option 文案**:三个 HTML 下拉用"Trade Pro · 外贸 B2B(英文)"中文风格与各文件现状一致(theme-gallery 用英文)。
6. **平台数据层中文残留(Task 5 质量审查发现)**:bootstrap 生成的 8 个标准页(/about/ /contact/ /products/ /news/ 等)的 `<title>`、`<h1>`、面包屑来自平台造的中文标题(关于我们/联系我们/产品中心…),主题层无法翻译用户数据。Phase 3 视觉验收时接受(真实站点内容为英文导入数据时自然英文),若 bootstrap 英文化成为需求属平台任务另行立项。
## 风险与回退 ## 风险与回退
+1
View File
@@ -110,6 +110,7 @@ def test_trade_pro_builds_real_site(factory):
home = factory.get(f'/preview/{sid}/{bid}/') home = factory.get(f'/preview/{sid}/{bid}/')
assert home.status_code == 200, home.text[:400] assert home.status_code == 200, home.text[:400]
assert 'lang="en"' in home.text assert 'lang="en"' in home.text
assert '>Products<' in home.text # English fallback nav actually rendered
assert '>首页<' not in home.text assert '>首页<' not in home.text
assert '<meta name="theme-color" content="#0b3d91"' in home.text assert '<meta name="theme-color" content="#0b3d91"' in home.text
-1
View File
@@ -1 +0,0 @@
/* trade-pro component styles: filled in Phase 3 */
+1 -1
View File
@@ -5,7 +5,7 @@
"version": "1.0.0", "version": "1.0.0",
"style": "international-b2b", "style": "international-b2b",
"entry": "pro.html", "entry": "pro.html",
"styles": ["theme.css", "blocks.css"], "styles": ["theme.css"],
"page_templates": ["home","about","contact","listing","category","product","article","brand","case","service","faq","standard","notfound"], "page_templates": ["home","about","contact","listing","category","product","article","brand","case","service","faq","standard","notfound"],
"blocks": ["hero","richtext","features","stats","collection","image_text","gallery","faq","cta","attributes","spacer","layout","carousel","video","tabs","pricing","map","form_link"], "blocks": ["hero","richtext","features","stats","collection","image_text","gallery","faq","cta","attributes","spacer","layout","carousel","video","tabs","pricing","map","form_link"],
"responsive": true, "responsive": true,
+58 -58
View File
@@ -4,10 +4,10 @@
"id": "0cdf18bf7f", "id": "0cdf18bf7f",
"type": "hero", "type": "hero",
"visible": true, "visible": true,
"title": "工程质量,值得信赖", "title": "Trusted Quality for Global Buyers",
"subtitle": "INDUSTRIAL ENGINEERING", "subtitle": "INTERNATIONAL B2B SOURCING",
"description": "{{site.tagline}}", "description": "{{site.tagline}}",
"button": "查看产品", "button": "View Products",
"href": "/product/", "href": "/product/",
"align": "left" "align": "left"
}, },
@@ -15,19 +15,19 @@
"id": "f846a2ff6b", "id": "f846a2ff6b",
"type": "features", "type": "features",
"visible": true, "visible": true,
"title": "制造与服务能力", "title": "Trade capabilities & service",
"items": [ "items": [
{ {
"title": "专业服务", "title": "Professional service",
"text": "从咨询到交付" "text": "From inquiry to delivery"
}, },
{ {
"title": "品质保障", "title": "Quality assurance",
"text": "严格的质量流程" "text": "Rigorous quality processes"
}, },
{ {
"title": "全球网络", "title": "Global network",
"text": "连接不同市场" "text": "Connecting markets worldwide"
} }
] ]
}, },
@@ -35,33 +35,33 @@
"id": "ff4655d684", "id": "ff4655d684",
"type": "collection", "type": "collection",
"visible": true, "visible": true,
"title": "工业产品系列", "title": "Trade catalogue",
"subtitle": "PRODUCT SOLUTIONS", "subtitle": "PRODUCT SOLUTIONS",
"source": "product", "source": "product",
"limit": 6, "limit": 6,
"columns": 3, "columns": 3,
"button": "查看全部", "button": "View All",
"href": "/product/" "href": "/product/"
}, },
{ {
"id": "4355daaba0", "id": "4355daaba0",
"type": "image_text", "type": "image_text",
"visible": true, "visible": true,
"title": "工程标准与服务流程", "title": "Standards & working process",
"subtitle": "QUALITY FIRST", "subtitle": "QUALITY FIRST",
"description": "展示业务流程和服务理念。", "description": "How we work and what we stand for.",
"image": "", "image": "",
"image_side": "right", "image_side": "right",
"button": "了解更多", "button": "Learn More",
"href": "/about/" "href": "/about/"
}, },
{ {
"id": "9e5056370d", "id": "9e5056370d",
"type": "cta", "type": "cta",
"visible": true, "visible": true,
"title": "获取专业产品方案", "title": "Get a tailored product solution",
"subtitle": "告诉我们您的需求,我们将提供适合的方案。", "subtitle": "Tell us what you need and we will propose the right solution.",
"button": "联系我们", "button": "Contact Us",
"href": "/contact/" "href": "/contact/"
} }
], ],
@@ -70,31 +70,31 @@
"id": "8ced1e0493", "id": "8ced1e0493",
"type": "image_text", "type": "image_text",
"visible": true, "visible": true,
"title": "认识我们", "title": "Who we are",
"subtitle": "OUR APPROACH", "subtitle": "OUR APPROACH",
"description": "展示业务流程和服务理念。", "description": "How we work and what we stand for.",
"image": "", "image": "",
"image_side": "right", "image_side": "right",
"button": "了解更多", "button": "Learn More",
"href": "/about/" "href": "/about/"
}, },
{ {
"id": "52b6064084", "id": "52b6064084",
"type": "stats", "type": "stats",
"visible": true, "visible": true,
"title": "我们的实力", "title": "Our strength",
"items": [ "items": [
{ {
"value": "50,000+", "value": "50,000+",
"label": "服务案例" "label": "Projects delivered"
}, },
{ {
"value": "70+", "value": "70+",
"label": "市场覆盖" "label": "Markets served"
}, },
{ {
"value": "30+", "value": "30+",
"label": "合作伙伴" "label": "Partners worldwide"
} }
] ]
}, },
@@ -102,19 +102,19 @@
"id": "cf39bcb75d", "id": "cf39bcb75d",
"type": "features", "type": "features",
"visible": true, "visible": true,
"title": "我们的优势", "title": "Why choose us",
"items": [ "items": [
{ {
"title": "专业服务", "title": "Professional service",
"text": "从咨询到交付" "text": "From inquiry to delivery"
}, },
{ {
"title": "品质保障", "title": "Quality assurance",
"text": "严格的质量流程" "text": "Rigorous quality processes"
}, },
{ {
"title": "全球网络", "title": "Global network",
"text": "连接不同市场" "text": "Connecting markets worldwide"
} }
] ]
} }
@@ -124,16 +124,16 @@
"id": "597f6ffb08", "id": "597f6ffb08",
"type": "richtext", "type": "richtext",
"visible": true, "visible": true,
"title": "联系我们", "title": "Contact us",
"body": "<p>请填写企业联系方式与地址。</p>" "body": "<p>Add your company contact details and address here.</p>"
}, },
{ {
"id": "8c02c61415", "id": "8c02c61415",
"type": "cta", "type": "cta",
"visible": true, "visible": true,
"title": "欢迎联系", "title": "Get in touch",
"subtitle": "告诉我们您的需求,我们将提供适合的方案。", "subtitle": "Tell us what you need and we will propose the right solution.",
"button": "联系我们", "button": "Contact Us",
"href": "/contact/" "href": "/contact/"
} }
], ],
@@ -142,12 +142,12 @@
"id": "2c3106baf6", "id": "2c3106baf6",
"type": "collection", "type": "collection",
"visible": true, "visible": true,
"title": "工业产品目录", "title": "Product catalogue",
"subtitle": "为客户提供适合的解决方案", "subtitle": "The right solutions for every buyer",
"source": "product", "source": "product",
"limit": 24, "limit": 24,
"columns": 3, "columns": 3,
"button": "查看全部", "button": "View All",
"href": "/product/" "href": "/product/"
} }
], ],
@@ -156,34 +156,34 @@
"id": "42925dc8e3", "id": "42925dc8e3",
"type": "image_text", "type": "image_text",
"visible": true, "visible": true,
"title": "产品介绍", "title": "Product overview",
"subtitle": "OUR APPROACH", "subtitle": "OUR APPROACH",
"description": "{{page.summary}}", "description": "{{page.summary}}",
"image": "{{page.cover}}", "image": "{{page.cover}}",
"image_side": "right", "image_side": "right",
"button": "了解更多", "button": "Learn More",
"href": "/about/" "href": "/about/"
}, },
{ {
"id": "503266af35", "id": "503266af35",
"type": "attributes", "type": "attributes",
"visible": true, "visible": true,
"title": "产品规格与参数" "title": "Specifications"
}, },
{ {
"id": "b2b1f5293c", "id": "b2b1f5293c",
"type": "richtext", "type": "richtext",
"visible": true, "visible": true,
"title": "产品详情", "title": "Product details",
"body": "{{page.body}}" "body": "{{page.body}}"
}, },
{ {
"id": "3837f66074", "id": "3837f66074",
"type": "cta", "type": "cta",
"visible": true, "visible": true,
"title": "开启新的合作", "title": "Start a new partnership",
"subtitle": "告诉我们您的需求,我们将提供适合的方案。", "subtitle": "Tell us what you need and we will propose the right solution.",
"button": "联系我们", "button": "Contact Us",
"href": "/contact/" "href": "/contact/"
} }
], ],
@@ -206,19 +206,19 @@
"description": "{{page.summary}}", "description": "{{page.summary}}",
"image": "{{page.cover}}", "image": "{{page.cover}}",
"image_side": "right", "image_side": "right",
"button": "了解更多", "button": "Learn More",
"href": "/about/" "href": "/about/"
}, },
{ {
"id": "b3faf08170", "id": "b3faf08170",
"type": "collection", "type": "collection",
"visible": true, "visible": true,
"title": "品牌产品", "title": "Brand products",
"subtitle": "为客户提供适合的解决方案", "subtitle": "The right solutions for every buyer",
"source": "product", "source": "product",
"limit": 6, "limit": 6,
"columns": 3, "columns": 3,
"button": "查看全部", "button": "View All",
"href": "/product/" "href": "/product/"
} }
], ],
@@ -236,9 +236,9 @@
"id": "59383d762e", "id": "59383d762e",
"type": "cta", "type": "cta",
"visible": true, "visible": true,
"title": "页面暂时无法访问", "title": "Page not available",
"subtitle": "告诉我们您的需求,我们将提供适合的方案。", "subtitle": "Tell us what you need and we will propose the right solution.",
"button": "返回首页", "button": "Back to Home",
"href": "/" "href": "/"
} }
], ],
@@ -251,7 +251,7 @@
}, },
{ {
"type": "richtext", "type": "richtext",
"title": "项目概述", "title": "Project overview",
"body": "{{page.body}}" "body": "{{page.body}}"
} }
], ],
@@ -263,21 +263,21 @@
}, },
{ {
"type": "cta", "type": "cta",
"title": "了解更多", "title": "Learn more",
"href": "/contact/" "href": "/contact/"
} }
], ],
"faq": [ "faq": [
{ {
"type": "faq", "type": "faq",
"title": "常见问题", "title": "Frequently asked questions",
"items": [] "items": []
} }
], ],
"category": [ "category": [
{ {
"type": "collection", "type": "collection",
"title": "分类产品", "title": "Products in this category",
"source": "product", "source": "product",
"limit": 24 "limit": 24
} }
+6 -1
View File
@@ -9,7 +9,12 @@
guarantees, so no fallback link can become a broken link. #} guarantees, so no fallback link can become a broken link. #}
{% set tp_default_hrefs=['/','/about/','/brands/','/cases/','/contact/','/news/','/products/'] %} {% set tp_default_hrefs=['/','/about/','/brands/','/cases/','/contact/','/news/','/products/'] %}
{% set tp_needs_en_nav=(not chrome_is_custom) and (nav|map(attribute='route')|list|sort==tp_default_hrefs) %} {% set tp_needs_en_nav=(not chrome_is_custom) and (nav|map(attribute='route')|list|sort==tp_default_hrefs) %}
{% set tp_nav=[{'title':'Home','route':'/'},{'title':'Products','route':'/products/'},{'title':'News','route':'/news/'},{'title':'About','route':'/about/'},{'title':'Contact','route':'/contact/'}] if tp_needs_en_nav else nav %} {# Known false-positive window: the legacy nav editor can save settings.nav with
custom titles but no published site design (chrome_is_custom stays false). If
such a nav happens to keep exactly the default 7 hrefs, its titles are
overridden by the English fallback below. Mitigated (not eliminated) by
keeping all 7 default sections so only the labels change, never coverage. #}
{% set tp_nav=[{'title':'Home','route':'/'},{'title':'Products','route':'/products/'},{'title':'Brands','route':'/brands/'},{'title':'News','route':'/news/'},{'title':'Cases','route':'/cases/'},{'title':'About','route':'/about/'},{'title':'Contact','route':'/contact/'}] if tp_needs_en_nav else nav %}
{% if chrome_is_custom %}<div class="pro-utility"{% if not chrome.header.show_announcement %} hidden{% endif %}><div class="pro-wrap"><span>{{ chrome.header.announcement }}</span><span>{{ site.tagline or site.name }}</span></div></div>{% else %}<div class="pro-utility"><div class="pro-wrap"><span>GLOBAL SOURCING · QUALITY · DELIVERY</span><span>INTERNATIONAL B2B SOLUTIONS</span></div></div>{% endif %} {% if chrome_is_custom %}<div class="pro-utility"{% if not chrome.header.show_announcement %} hidden{% endif %}><div class="pro-wrap"><span>{{ chrome.header.announcement }}</span><span>{{ site.tagline or site.name }}</span></div></div>{% else %}<div class="pro-utility"><div class="pro-wrap"><span>GLOBAL SOURCING · QUALITY · DELIVERY</span><span>INTERNATIONAL B2B SOLUTIONS</span></div></div>{% endif %}
<header class="sf-site-head pro-header"><div class="pro-wrap pro-head-inner"><a class="pro-logo" href="/" aria-label="{{site.name}} home">{% if safe_image(site.logo) %}<img class="pro-brand-logo" src="{{safe_image(site.logo)}}" alt="{{site.name}} Logo">{% else %}<span class="pro-logo-symbol">▣</span>{% endif %}<span class="pro-logo-name">{{site.name}}<small> GLOBAL B2B</small></span></a><button class="pro-mobile-toggle" type="button" data-pro-menu aria-controls="pro-navigation" aria-expanded="false" aria-label="Open navigation">☰</button><nav id="pro-navigation" class="pro-navigation" aria-label="Main navigation">{% for link in tp_nav %}{% if link.children %}<div class="pro-nav-group"><a href="{{link.route}}">{{link.title}}</a><button type="button" class="pro-nav-disclose" aria-expanded="false" aria-label="Expand {{link.title}} submenu">▾</button><div class="pro-nav-children" hidden>{% for child in link.children %}<a href="{{child.route}}">{{child.title}}</a>{% for leaf in child.children %}<a class="pro-nav-leaf" href="{{leaf.route}}">— {{leaf.title}}</a>{% endfor %}{% endfor %}</div></div>{% else %}<a href="{{link.route}}">{{link.title}}</a>{% endif %}{% endfor %}{% if chrome.header.show_search %}<a class="pro-search-link" href="/search/">Search ⌕</a>{% endif %}</nav><button class="pro-catalog-toggle" type="button" data-pro-catalog aria-controls="pro-mega-content" aria-expanded="false">Products ▾</button>{% if chrome_is_custom %}{% if chrome.header.show_cta %}<a href="{{chrome.header.cta_href}}" class="sf-tp-btn pro-header-cta">{{chrome.header.cta_text}} <span>↗</span></a>{% endif %}{% else %}<a href="/contact/" class="sf-tp-btn pro-header-cta">Request a Quote <span>↗</span></a>{% endif %}</div>{% if categories %}<div class="pro-mega pro-wrap" data-pro-mega id="pro-mega-content" hidden><span>Product categories</span><div>{% for cat in categories[:12] %}<a href="{{cat.url}}">{{cat.name}} ↗</a>{% endfor %}</div></div>{% endif %}</header> <header class="sf-site-head pro-header"><div class="pro-wrap pro-head-inner"><a class="pro-logo" href="/" aria-label="{{site.name}} home">{% if safe_image(site.logo) %}<img class="pro-brand-logo" src="{{safe_image(site.logo)}}" alt="{{site.name}} Logo">{% else %}<span class="pro-logo-symbol">▣</span>{% endif %}<span class="pro-logo-name">{{site.name}}<small> GLOBAL B2B</small></span></a><button class="pro-mobile-toggle" type="button" data-pro-menu aria-controls="pro-navigation" aria-expanded="false" aria-label="Open navigation">☰</button><nav id="pro-navigation" class="pro-navigation" aria-label="Main navigation">{% for link in tp_nav %}{% if link.children %}<div class="pro-nav-group"><a href="{{link.route}}">{{link.title}}</a><button type="button" class="pro-nav-disclose" aria-expanded="false" aria-label="Expand {{link.title}} submenu">▾</button><div class="pro-nav-children" hidden>{% for child in link.children %}<a href="{{child.route}}">{{child.title}}</a>{% for leaf in child.children %}<a class="pro-nav-leaf" href="{{leaf.route}}">— {{leaf.title}}</a>{% endfor %}{% endfor %}</div></div>{% else %}<a href="{{link.route}}">{{link.title}}</a>{% endif %}{% endfor %}{% if chrome.header.show_search %}<a class="pro-search-link" href="/search/">Search ⌕</a>{% endif %}</nav><button class="pro-catalog-toggle" type="button" data-pro-catalog aria-controls="pro-mega-content" aria-expanded="false">Products ▾</button>{% if chrome_is_custom %}{% if chrome.header.show_cta %}<a href="{{chrome.header.cta_href}}" class="sf-tp-btn pro-header-cta">{{chrome.header.cta_text}} <span>↗</span></a>{% endif %}{% else %}<a href="/contact/" class="sf-tp-btn pro-header-cta">Request a Quote <span>↗</span></a>{% endif %}</div>{% if categories %}<div class="pro-mega pro-wrap" data-pro-mega id="pro-mega-content" hidden><span>Product categories</span><div>{% for cat in categories[:12] %}<a href="{{cat.url}}">{{cat.name}} ↗</a>{% endfor %}</div></div>{% endif %}</header>
{% if not designer_replace %}{% include 'trade-pro/pages/' ~ kind ~ '.html' %}{% endif %} {% if not designer_replace %}{% include 'trade-pro/pages/' ~ kind ~ '.html' %}{% endif %}