From 8884e100f9532f19c63f973d4e56077f07c92202 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E5=BF=B5?= Date: Mon, 26 Oct 2026 09:43:17 +0800 Subject: [PATCH] upgrade: adopt V8.31.1 (theme 1.3/1.4 redesigns, editor deep-canvas, guided launch, component library) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Overlay 190 upstream items (V8.22→8.31) preserving trade-pro theme, registry tests, and design docs. Re-applied full patch set on identical anchors (discovery/env_for/blocks.css/type-mapping/locale-override/ theme_color/frontend entries/test_theme_pro_v3 mods) plus compose pins. Verified: theme suites 35/35; dual-baseline full run 415 passed vs pristine 386+29 ours, FAILED-set diff EMPTY (same 10 Windows env fails). Live: container 8.31.1-dev.1 healthy, hesupipe 192 entries intact, trade-pro build 203 pages 0 errors. Co-Authored-By: Claude Code --- .github/workflows/ci.yml | 9 +- .updiff.txt | 200 +++++ README.md | 136 ++++ README_V8_26.md | 32 + README_V8_28.md | 40 + README_V8_29.md | 45 ++ README_V8_30.md | 48 ++ README_V8_31.md | 53 ++ README_V8_31_1.md | 11 + app/blueprints.py | 7 +- app/builder.py | 22 + app/factory_api.py | 36 + app/main.py | 32 +- app/reusables.py | 285 ++++++- app/site_design_v87.py | 126 +++- app/static/auto31.js | 1 + app/static/editor-helpers.js | 116 ++- app/static/editor.css | 68 ++ app/static/editor.js | 452 +++++++++-- app/static/pro.js | 4 + app/static/studio-canvas-bridge.js | 147 ++++ app/static/studio-experience-v829.js | 46 ++ app/static/workspace-guide.js | 35 + app/static/workspace-launch.js | 22 + app/static/workspace.css | 41 + app/static/workspace.js | 180 ++++- app/templates/editor.html | 59 +- app/templates/workspace.html | 24 +- app/version.py | 2 +- compose.enterprise.yaml | 4 +- compose.yaml | 5 +- docs/V8_22_ADVANCED_VISUAL_STUDIO.md | 31 + docs/V8_23_ADVANCED_STUDIO.md | 50 ++ docs/V8_24_DEEP_NESTED_STUDIO.md | 59 ++ docs/V8_25_SHARED_DESIGN_SYSTEM.md | 91 +++ docs/V8_26_GLOBAL_DESIGN.md | 32 + docs/V8_27_USER_FRIENDLY_WORKSPACE.md | 73 ++ docs/V8_28_GUIDED_LAUNCH_CENTER.md | 67 ++ ...dio_V8_22_画布级可视化编辑器_交互演示.html | 21 + ...tudio_V8_23_嵌套组件编辑器_可交互预览.html | 13 + ...o_V8_24_深层嵌套可视化编辑器_交互演示.html | 54 ++ examples/V8_25_公共组件_版本与同步演示.html | 14 + examples/V8_26_全站设计与导航_交互预览.html | 703 ++++++++++++++++++ .../V8_27_新手友好建站工作台_交互演示.html | 404 ++++++++++ examples/V8_28_简洁上线操作中心_交互演示.html | 508 +++++++++++++ .../V8_29_主题与可视化编辑_离线操作演示.html | 5 + examples/V8_30_四套主题_真实页面交互预览.html | 2 + ...1_1_汽车主题性能与语义化图标_离线演示.html | 622 ++++++++++++++++ examples/V8_31_汽车主题_完整页面交互预览.html | 4 + examples/v830-built-sites/BUILD_REPORT.json | 242 ++++++ .../v830-built-sites/automotive/.htaccess | 2 + examples/v830-built-sites/automotive/404.html | 12 + .../automotive/about/index.html | 47 ++ .../automotive/assets/blocks.css | 29 + .../automotive/assets/commercial.css | 84 +++ .../automotive/assets/custom.css | 1 + .../automotive/assets/factory.css | 27 + .../automotive/assets/pro-base.css | 21 + .../automotive/assets/pro.css | 92 +++ .../v830-built-sites/automotive/assets/pro.js | 72 ++ .../automotive/assets/site-runtime.js | 31 + .../automotive/assets/theme.css | 4 + .../automotive/assets/visual/hero.svg | 1 + .../automotive/brand/index.html | 41 + .../automotive/brands/arc/index.html | 38 + .../automotive/brands/index.html | 41 + .../automotive/brands/mono/index.html | 30 + .../automotive/brands/nova/index.html | 38 + .../automotive/case/index.html | 41 + .../automotive/cases/1/index.html | 12 + .../automotive/cases/2/index.html | 12 + .../automotive/cases/3/index.html | 12 + .../automotive/cases/index.html | 41 + .../categories/term-79e34764f8ce/index.html | 29 + .../categories/term-8d6647722ef3/index.html | 29 + .../categories/term-95acf900fafc/index.html | 29 + .../categories/term-a68a8656a4dc/index.html | 29 + .../automotive/commercial-readiness.json | 34 + .../automotive/contact/index.html | 16 + .../automotive/faq/index.html | 13 + .../v830-built-sites/automotive/index.html | 89 +++ .../automotive/news/1/index.html | 13 + .../automotive/news/2/index.html | 13 + .../automotive/news/3/index.html | 13 + .../automotive/news/index.html | 41 + .../automotive/nginx-snippet.conf | 4 + .../automotive/post/index.html | 41 + .../automotive/product/index.html | 81 ++ .../automotive/products/1/index.html | 17 + .../automotive/products/2/index.html | 17 + .../automotive/products/3/index.html | 17 + .../automotive/products/4/index.html | 17 + .../automotive/products/5/index.html | 17 + .../automotive/products/6/index.html | 17 + .../automotive/products/7/index.html | 17 + .../automotive/products/8/index.html | 17 + .../automotive/products/index.html | 81 ++ .../v830-built-sites/automotive/robots.txt | 3 + .../automotive/search-index.json | 1 + .../automotive/search/index.html | 13 + .../automotive/service/index.html | 25 + .../automotive/services/index.html | 13 + .../automotive/services/solution/index.html | 13 + .../automotive/siteforge-report.json | 27 + .../v830-built-sites/automotive/sitemap.xml | 37 + examples/v830-built-sites/corporate/.htaccess | 2 + examples/v830-built-sites/corporate/404.html | 12 + .../corporate/about/index.html | 47 ++ .../corporate/assets/blocks.css | 29 + .../corporate/assets/commercial.css | 84 +++ .../corporate/assets/custom.css | 1 + .../corporate/assets/factory.css | 27 + .../corporate/assets/pro-base.css | 21 + .../v830-built-sites/corporate/assets/pro.css | 89 +++ .../v830-built-sites/corporate/assets/pro.js | 72 ++ .../corporate/assets/site-runtime.js | 31 + .../corporate/assets/theme.css | 4 + .../corporate/assets/visual/hero.svg | 1 + .../corporate/brand/index.html | 41 + .../corporate/brands/arc/index.html | 38 + .../corporate/brands/index.html | 41 + .../corporate/brands/mono/index.html | 30 + .../corporate/brands/nova/index.html | 38 + .../corporate/case/index.html | 41 + .../corporate/cases/1/index.html | 12 + .../corporate/cases/2/index.html | 12 + .../corporate/cases/3/index.html | 12 + .../corporate/cases/index.html | 41 + .../categories/term-79e34764f8ce/index.html | 29 + .../categories/term-8d6647722ef3/index.html | 29 + .../categories/term-95acf900fafc/index.html | 29 + .../categories/term-a68a8656a4dc/index.html | 29 + .../corporate/commercial-readiness.json | 34 + .../corporate/contact/index.html | 16 + .../v830-built-sites/corporate/faq/index.html | 13 + .../v830-built-sites/corporate/index.html | 73 ++ .../corporate/news/1/index.html | 13 + .../corporate/news/2/index.html | 13 + .../corporate/news/3/index.html | 13 + .../corporate/news/index.html | 41 + .../corporate/nginx-snippet.conf | 4 + .../corporate/post/index.html | 41 + .../corporate/product/index.html | 81 ++ .../corporate/products/1/index.html | 17 + .../corporate/products/2/index.html | 17 + .../corporate/products/3/index.html | 17 + .../corporate/products/4/index.html | 17 + .../corporate/products/5/index.html | 17 + .../corporate/products/6/index.html | 17 + .../corporate/products/7/index.html | 17 + .../corporate/products/8/index.html | 17 + .../corporate/products/index.html | 81 ++ .../v830-built-sites/corporate/robots.txt | 3 + .../corporate/search-index.json | 1 + .../corporate/search/index.html | 13 + .../corporate/service/index.html | 25 + .../corporate/services/index.html | 13 + .../corporate/services/solution/index.html | 13 + .../corporate/siteforge-report.json | 27 + .../v830-built-sites/corporate/sitemap.xml | 37 + examples/v830-built-sites/index.html | 2 + .../v830-built-sites/industrial/.htaccess | 2 + examples/v830-built-sites/industrial/404.html | 12 + .../industrial/about/index.html | 47 ++ .../industrial/assets/blocks.css | 29 + .../industrial/assets/commercial.css | 84 +++ .../industrial/assets/custom.css | 1 + .../industrial/assets/factory.css | 27 + .../industrial/assets/pro-base.css | 21 + .../industrial/assets/pro.css | 89 +++ .../v830-built-sites/industrial/assets/pro.js | 72 ++ .../industrial/assets/site-runtime.js | 31 + .../industrial/assets/theme.css | 4 + .../industrial/assets/visual/hero.svg | 1 + .../industrial/brand/index.html | 41 + .../industrial/brands/arc/index.html | 38 + .../industrial/brands/index.html | 41 + .../industrial/brands/mono/index.html | 30 + .../industrial/brands/nova/index.html | 38 + .../industrial/case/index.html | 41 + .../industrial/cases/1/index.html | 12 + .../industrial/cases/2/index.html | 12 + .../industrial/cases/3/index.html | 12 + .../industrial/cases/index.html | 41 + .../categories/term-79e34764f8ce/index.html | 29 + .../categories/term-8d6647722ef3/index.html | 29 + .../categories/term-95acf900fafc/index.html | 29 + .../categories/term-a68a8656a4dc/index.html | 29 + .../industrial/commercial-readiness.json | 34 + .../industrial/contact/index.html | 16 + .../industrial/faq/index.html | 13 + .../v830-built-sites/industrial/index.html | 89 +++ .../industrial/news/1/index.html | 13 + .../industrial/news/2/index.html | 13 + .../industrial/news/3/index.html | 13 + .../industrial/news/index.html | 41 + .../industrial/nginx-snippet.conf | 4 + .../industrial/post/index.html | 41 + .../industrial/product/index.html | 81 ++ .../industrial/products/1/index.html | 17 + .../industrial/products/2/index.html | 17 + .../industrial/products/3/index.html | 17 + .../industrial/products/4/index.html | 17 + .../industrial/products/5/index.html | 17 + .../industrial/products/6/index.html | 17 + .../industrial/products/7/index.html | 17 + .../industrial/products/8/index.html | 17 + .../industrial/products/index.html | 81 ++ .../v830-built-sites/industrial/robots.txt | 3 + .../industrial/search-index.json | 1 + .../industrial/search/index.html | 13 + .../industrial/service/index.html | 25 + .../industrial/services/index.html | 13 + .../industrial/services/solution/index.html | 13 + .../industrial/siteforge-report.json | 27 + .../v830-built-sites/industrial/sitemap.xml | 37 + examples/v830-built-sites/minimal/.htaccess | 2 + examples/v830-built-sites/minimal/404.html | 12 + .../v830-built-sites/minimal/about/index.html | 47 ++ .../minimal/assets/blocks.css | 29 + .../minimal/assets/commercial.css | 84 +++ .../minimal/assets/custom.css | 1 + .../minimal/assets/factory.css | 27 + .../minimal/assets/pro-base.css | 21 + .../v830-built-sites/minimal/assets/pro.css | 90 +++ .../v830-built-sites/minimal/assets/pro.js | 72 ++ .../minimal/assets/site-runtime.js | 31 + .../v830-built-sites/minimal/assets/theme.css | 4 + .../minimal/assets/visual/hero.svg | 1 + .../v830-built-sites/minimal/brand/index.html | 41 + .../minimal/brands/arc/index.html | 38 + .../minimal/brands/index.html | 41 + .../minimal/brands/mono/index.html | 30 + .../minimal/brands/nova/index.html | 38 + .../v830-built-sites/minimal/case/index.html | 41 + .../minimal/cases/1/index.html | 12 + .../minimal/cases/2/index.html | 12 + .../minimal/cases/3/index.html | 12 + .../v830-built-sites/minimal/cases/index.html | 41 + .../categories/term-79e34764f8ce/index.html | 29 + .../categories/term-8d6647722ef3/index.html | 29 + .../categories/term-95acf900fafc/index.html | 29 + .../categories/term-a68a8656a4dc/index.html | 29 + .../minimal/commercial-readiness.json | 34 + .../minimal/contact/index.html | 16 + .../v830-built-sites/minimal/faq/index.html | 13 + examples/v830-built-sites/minimal/index.html | 64 ++ .../minimal/news/1/index.html | 13 + .../minimal/news/2/index.html | 13 + .../minimal/news/3/index.html | 13 + .../v830-built-sites/minimal/news/index.html | 41 + .../minimal/nginx-snippet.conf | 4 + .../v830-built-sites/minimal/post/index.html | 41 + .../minimal/product/index.html | 81 ++ .../minimal/products/1/index.html | 17 + .../minimal/products/2/index.html | 17 + .../minimal/products/3/index.html | 17 + .../minimal/products/4/index.html | 17 + .../minimal/products/5/index.html | 17 + .../minimal/products/6/index.html | 17 + .../minimal/products/7/index.html | 17 + .../minimal/products/8/index.html | 17 + .../minimal/products/index.html | 81 ++ examples/v830-built-sites/minimal/robots.txt | 3 + .../minimal/search-index.json | 1 + .../minimal/search/index.html | 13 + .../minimal/service/index.html | 25 + .../minimal/services/index.html | 13 + .../minimal/services/solution/index.html | 13 + .../minimal/siteforge-report.json | 27 + examples/v830-built-sites/minimal/sitemap.xml | 37 + reports/V8_22_验收报告.html | 1 + reports/V8_22_验收报告.json | 117 +++ reports/V8_22_验收报告.md | 62 ++ reports/V8_23_集成验收.html | 1 + reports/V8_25_summary.json | 15 + reports/V8_25_验收报告.html | 24 + reports/V8_25_验收报告.md | 47 ++ reports/V8_30_mobile_browser_audit.json | 6 + reports/V8_30_主题设计与兼容验收.html | 1 + reports/V8_31_汽车主题验收报告.html | 2 + reports/v823-regression/result.json | 227 ++++++ reports/v824-regression/result.json | 227 ++++++ reports/v825-regression/result.json | 236 ++++++ reports/v826-regression/result.json | 237 ++++++ reports/v826/V8_26_集成验收.html | 7 + reports/v826/summary.json | 12 + reports/v827/V8_27_集成验收报告.html | 7 + reports/v827/v827-create-wizard-mobile.png | Bin 0 -> 164763 bytes reports/v827/v827-guided-mobile.png | Bin 0 -> 166956 bytes reports/v827/v827-guided-workspace.png | Bin 0 -> 222170 bytes reports/v828/V8_28_evidence.json | 293 ++++++++ reports/v828/V8_28_集成验收报告.html | 6 + reports/v828/V8_28_集成验收摘要.md | 11 + reports/v828/launch-desktop.png | Bin 0 -> 255073 bytes reports/v828/launch-mobile.png | Bin 0 -> 202804 bytes reports/v829-browser/result.json | 8 + reports/v829-browser/v829-demo-offline.png | Bin 0 -> 136440 bytes reports/v829-browser/v829-studio-desktop.png | Bin 0 -> 142763 bytes reports/v829-browser/v829-studio-phone.png | Bin 0 -> 59475 bytes reports/v829-regression/result.json | 266 +++++++ reports/v829/V8_29_主题与编辑器验收报告.html | 1 + reports/v829/summary.json | 54 ++ reports/v830-regression/batch-01.json | 10 + reports/v830-regression/batch-02.json | 10 + reports/v830-regression/batch-03.json | 10 + reports/v830-regression/batch-04.json | 10 + reports/v830-regression/batch-05.json | 10 + reports/v830-regression/batch-06.json | 10 + reports/v830-regression/batch-07.json | 10 + reports/v830-regression/batch-08.json | 10 + reports/v830-regression/batch-09.json | 10 + reports/v830-regression/batch-10.json | 10 + reports/v830-regression/batch-11.json | 10 + reports/v830-regression/batch-12.json | 10 + reports/v830-regression/batch-13.json | 10 + reports/v830-regression/batch-14.json | 10 + reports/v830-regression/batch-15.json | 10 + reports/v830-regression/batch-16.json | 10 + reports/v830-regression/batch-17.json | 10 + reports/v830-regression/batch-18.json | 10 + reports/v830-regression/batch-19.json | 10 + reports/v830-regression/batch-20.json | 10 + reports/v830-regression/batch-21.json | 10 + reports/v830-regression/batch-22.json | 10 + reports/v830-regression/batch-23.json | 10 + reports/v830-regression/batch-24.json | 10 + reports/v830-regression/batch-25.json | 10 + reports/v831/auto-home-desktop.png | Bin 0 -> 893385 bytes reports/v831/auto-home-mobile.png | Bin 0 -> 566670 bytes reports/v831/auto-product-desktop.png | Bin 0 -> 534212 bytes reports/v831/automotive-home-desktop.png | Bin 0 -> 401012 bytes reports/v831/automotive-home-phone.png | Bin 0 -> 200472 bytes reports/v831/automotive-product-desktop.png | Bin 0 -> 259239 bytes reports/v831/browser_results.json | 281 +++++++ reports/v8311/V8_31_1_性能与图标验收报告.html | 9 + reports/v8311/automotive-v8311-desktop.png | Bin 0 -> 793099 bytes reports/v8311/automotive-v8311-mobile.png | Bin 0 -> 476288 bytes reports/v8311/perf_icons_result.json | 59 ++ reports/v8311/performance_comparison.json | 70 ++ scripts/browser_guide_v827.py | 85 +++ scripts/browser_launch_v828.py | 80 ++ scripts/browser_studio_v829.py | 111 +++ scripts/check.ps1 | 5 +- scripts/check.sh | 7 +- scripts/init_config.py | 2 +- scripts/install_into_art_design_pro.py | 2 +- scripts/make_theme_demo_v830.py | 71 ++ scripts/make_theme_demo_v8311.py | 71 ++ scripts/regression_v821.py | 2 +- scripts/regression_v823.py | 27 + scripts/regression_v824.py | 27 + scripts/regression_v825.py | 27 + scripts/regression_v826.py | 27 + scripts/regression_v827.py | 27 + scripts/regression_v828.py | 27 + scripts/regression_v829.py | 27 + scripts/regression_v830.py | 31 + scripts/regression_v8311.py | 28 + scripts/report_v825.py | 32 + scripts/report_v828.py | 53 ++ .../studio_canvas_isolated_browser_v822.py | 48 ++ scripts/studio_canvas_smoke_v822.py | 78 ++ scripts/studio_nested_browser_v823.py | 33 + scripts/studio_nested_browser_v824.py | 40 + scripts/verify_art_design_pro_v819.py | 2 +- scripts/verify_release.py | 2 +- tests/test_core_v4.py | 2 +- tests/test_deep_nested_v824.py | 106 +++ tests/test_editor_easy_v8212.py | 7 +- tests/test_factory_v2.py | 5 +- tests/test_nested_helpers_v823.cjs | 22 + tests/test_nested_v823.py | 57 ++ tests/test_theme_pro_v3.py | 10 +- tests/test_v822_canvas.py | 22 + tests/test_v825_shared_components.py | 209 ++++++ tests/test_v826_global_design.py | 104 +++ tests/test_v827_guided_workspace.py | 33 + tests/test_v828_launch_center.py | 37 + tests/test_v829_theme_studio.py | 59 ++ tests/test_v830_real_pages.py | 60 ++ tests/test_v8311_performance_icons.py | 64 ++ tests/test_v831_automotive_ref.py | 79 ++ tests/test_workspace_v810.py | 2 +- tests/test_workspace_v812.py | 6 +- tests_js/deep_nested_v824.test.cjs | 51 ++ tests_js/editor_ux.test.cjs | 32 + tests_js/studio-experience-v829.test.cjs | 37 + tests_js/workspace_guide_v827.test.cjs | 16 + tests_js/workspace_launch_v828.test.cjs | 18 + themes/_professional_components.html | 8 +- themes/automotive/auto-icons.svg | 26 + themes/automotive/manifest.json | 6 +- themes/automotive/pages/about.html | 6 +- themes/automotive/pages/article.html | 3 +- themes/automotive/pages/brand.html | 4 +- themes/automotive/pages/case.html | 2 +- themes/automotive/pages/category.html | 3 +- themes/automotive/pages/contact.html | 13 +- themes/automotive/pages/faq.html | 2 +- themes/automotive/pages/home.html | 18 +- themes/automotive/pages/listing.html | 5 +- themes/automotive/pages/notfound.html | 2 +- themes/automotive/pages/product.html | 7 +- themes/automotive/pages/service.html | 2 +- themes/automotive/pages/standard.html | 2 +- themes/automotive/pro.css | 194 +++++ themes/automotive/pro.html | 26 +- themes/automotive/theme.css | 3 + themes/automotive/versions/1.0.0/pro.html | 2 +- .../automotive/versions/1.1.0/manifest.json | 54 ++ .../versions/1.1.0/page-presets.json | 285 +++++++ .../versions/1.1.0/pages/about.html | 2 + .../versions/1.1.0/pages/article.html | 1 + .../versions/1.1.0/pages/brand.html | 1 + .../automotive/versions/1.1.0/pages/case.html | 1 + .../versions/1.1.0/pages/category.html | 2 + .../versions/1.1.0/pages/contact.html | 7 + .../automotive/versions/1.1.0/pages/faq.html | 2 + .../automotive/versions/1.1.0/pages/home.html | 4 + .../versions/1.1.0/pages/listing.html | 2 + .../versions/1.1.0/pages/notfound.html | 1 + .../versions/1.1.0/pages/product.html | 3 + .../versions/1.1.0/pages/search.html | 2 + .../versions/1.1.0/pages/service.html | 2 + .../versions/1.1.0/pages/standard.html | 2 + themes/automotive/versions/1.1.0/pro.css | 8 + themes/automotive/versions/1.1.0/pro.html | 13 + themes/automotive/versions/1.1.0/site.html | 13 + themes/automotive/versions/1.1.0/theme.css | 1 + .../automotive/versions/1.1.0/visual/hero.svg | 1 + .../automotive/versions/1.2.0/manifest.json | 54 ++ .../versions/1.2.0/page-presets.json | 285 +++++++ .../versions/1.2.0/pages/about.html | 2 + .../versions/1.2.0/pages/article.html | 1 + .../versions/1.2.0/pages/brand.html | 1 + .../automotive/versions/1.2.0/pages/case.html | 1 + .../versions/1.2.0/pages/category.html | 2 + .../versions/1.2.0/pages/contact.html | 7 + .../automotive/versions/1.2.0/pages/faq.html | 2 + .../automotive/versions/1.2.0/pages/home.html | 4 + .../versions/1.2.0/pages/listing.html | 2 + .../versions/1.2.0/pages/notfound.html | 1 + .../versions/1.2.0/pages/product.html | 3 + .../versions/1.2.0/pages/search.html | 2 + .../versions/1.2.0/pages/service.html | 2 + .../versions/1.2.0/pages/standard.html | 2 + themes/automotive/versions/1.2.0/pro.css | 24 + themes/automotive/versions/1.2.0/pro.html | 13 + themes/automotive/versions/1.2.0/site.html | 13 + themes/automotive/versions/1.2.0/theme.css | 4 + .../automotive/versions/1.2.0/visual/hero.svg | 1 + .../automotive/versions/1.3.0/manifest.json | 54 ++ .../versions/1.3.0/page-presets.json | 285 +++++++ .../versions/1.3.0/pages/about.html | 4 + .../versions/1.3.0/pages/article.html | 2 + .../versions/1.3.0/pages/brand.html | 1 + .../automotive/versions/1.3.0/pages/case.html | 1 + .../versions/1.3.0/pages/category.html | 2 + .../versions/1.3.0/pages/contact.html | 6 + .../automotive/versions/1.3.0/pages/faq.html | 2 + .../automotive/versions/1.3.0/pages/home.html | 6 + .../versions/1.3.0/pages/listing.html | 6 + .../versions/1.3.0/pages/notfound.html | 1 + .../versions/1.3.0/pages/product.html | 4 + .../versions/1.3.0/pages/search.html | 2 + .../versions/1.3.0/pages/service.html | 2 + .../versions/1.3.0/pages/standard.html | 2 + themes/automotive/versions/1.3.0/pro.css | 92 +++ themes/automotive/versions/1.3.0/pro.html | 13 + themes/automotive/versions/1.3.0/site.html | 13 + themes/automotive/versions/1.3.0/theme.css | 4 + .../automotive/versions/1.3.0/visual/hero.svg | 1 + .../automotive/versions/1.4.0/manifest.json | 54 ++ .../versions/1.4.0/page-presets.json | 285 +++++++ .../versions/1.4.0/pages/about.html | 4 + .../versions/1.4.0/pages/article.html | 2 + .../versions/1.4.0/pages/brand.html | 3 + .../automotive/versions/1.4.0/pages/case.html | 1 + .../versions/1.4.0/pages/category.html | 1 + .../versions/1.4.0/pages/contact.html | 6 + .../automotive/versions/1.4.0/pages/faq.html | 2 + .../automotive/versions/1.4.0/pages/home.html | 14 + .../versions/1.4.0/pages/listing.html | 3 + .../versions/1.4.0/pages/notfound.html | 1 + .../versions/1.4.0/pages/product.html | 4 + .../versions/1.4.0/pages/search.html | 2 + .../versions/1.4.0/pages/service.html | 2 + .../versions/1.4.0/pages/standard.html | 2 + themes/automotive/versions/1.4.0/pro.css | 188 +++++ themes/automotive/versions/1.4.0/pro.html | 26 + themes/automotive/versions/1.4.0/site.html | 13 + themes/automotive/versions/1.4.0/theme.css | 4 + .../automotive/versions/1.4.0/visual/hero.svg | 1 + themes/corporate/manifest.json | 6 +- themes/corporate/pages/about.html | 6 +- themes/corporate/pages/article.html | 3 +- themes/corporate/pages/contact.html | 13 +- themes/corporate/pages/home.html | 2 + themes/corporate/pages/listing.html | 8 +- themes/corporate/pages/product.html | 7 +- themes/corporate/pro.css | 82 ++ themes/corporate/theme.css | 3 + themes/corporate/versions/1.1.0/manifest.json | 54 ++ .../versions/1.1.0/page-presets.json | 285 +++++++ .../corporate/versions/1.1.0/pages/about.html | 2 + .../versions/1.1.0/pages/article.html | 1 + .../corporate/versions/1.1.0/pages/brand.html | 1 + .../corporate/versions/1.1.0/pages/case.html | 1 + .../versions/1.1.0/pages/category.html | 2 + .../versions/1.1.0/pages/contact.html | 7 + .../corporate/versions/1.1.0/pages/faq.html | 2 + .../corporate/versions/1.1.0/pages/home.html | 4 + .../versions/1.1.0/pages/listing.html | 2 + .../versions/1.1.0/pages/notfound.html | 1 + .../versions/1.1.0/pages/product.html | 3 + .../versions/1.1.0/pages/search.html | 2 + .../versions/1.1.0/pages/service.html | 2 + .../versions/1.1.0/pages/standard.html | 2 + themes/corporate/versions/1.1.0/pro.css | 7 + themes/corporate/versions/1.1.0/pro.html | 13 + themes/corporate/versions/1.1.0/site.html | 12 + themes/corporate/versions/1.1.0/theme.css | 1 + .../corporate/versions/1.1.0/visual/hero.svg | 1 + themes/corporate/versions/1.2.0/manifest.json | 54 ++ .../versions/1.2.0/page-presets.json | 285 +++++++ .../corporate/versions/1.2.0/pages/about.html | 2 + .../versions/1.2.0/pages/article.html | 1 + .../corporate/versions/1.2.0/pages/brand.html | 1 + .../corporate/versions/1.2.0/pages/case.html | 1 + .../versions/1.2.0/pages/category.html | 2 + .../versions/1.2.0/pages/contact.html | 7 + .../corporate/versions/1.2.0/pages/faq.html | 2 + .../corporate/versions/1.2.0/pages/home.html | 4 + .../versions/1.2.0/pages/listing.html | 2 + .../versions/1.2.0/pages/notfound.html | 1 + .../versions/1.2.0/pages/product.html | 3 + .../versions/1.2.0/pages/search.html | 2 + .../versions/1.2.0/pages/service.html | 2 + .../versions/1.2.0/pages/standard.html | 2 + themes/corporate/versions/1.2.0/pro.css | 23 + themes/corporate/versions/1.2.0/pro.html | 13 + themes/corporate/versions/1.2.0/site.html | 12 + themes/corporate/versions/1.2.0/theme.css | 4 + .../corporate/versions/1.2.0/visual/hero.svg | 1 + themes/industrial/manifest.json | 6 +- themes/industrial/pages/about.html | 6 +- themes/industrial/pages/article.html | 3 +- themes/industrial/pages/contact.html | 13 +- themes/industrial/pages/home.html | 2 + themes/industrial/pages/listing.html | 8 +- themes/industrial/pages/product.html | 7 +- themes/industrial/pro.css | 82 ++ themes/industrial/theme.css | 3 + .../industrial/versions/1.1.0/manifest.json | 54 ++ .../versions/1.1.0/page-presets.json | 285 +++++++ .../versions/1.1.0/pages/about.html | 2 + .../versions/1.1.0/pages/article.html | 1 + .../versions/1.1.0/pages/brand.html | 1 + .../industrial/versions/1.1.0/pages/case.html | 1 + .../versions/1.1.0/pages/category.html | 2 + .../versions/1.1.0/pages/contact.html | 7 + .../industrial/versions/1.1.0/pages/faq.html | 2 + .../industrial/versions/1.1.0/pages/home.html | 4 + .../versions/1.1.0/pages/listing.html | 2 + .../versions/1.1.0/pages/notfound.html | 1 + .../versions/1.1.0/pages/product.html | 3 + .../versions/1.1.0/pages/search.html | 2 + .../versions/1.1.0/pages/service.html | 2 + .../versions/1.1.0/pages/standard.html | 2 + themes/industrial/versions/1.1.0/pro.css | 7 + themes/industrial/versions/1.1.0/pro.html | 13 + themes/industrial/versions/1.1.0/site.html | 12 + themes/industrial/versions/1.1.0/theme.css | 1 + .../industrial/versions/1.1.0/visual/hero.svg | 1 + .../industrial/versions/1.2.0/manifest.json | 54 ++ .../versions/1.2.0/page-presets.json | 285 +++++++ .../versions/1.2.0/pages/about.html | 2 + .../versions/1.2.0/pages/article.html | 1 + .../versions/1.2.0/pages/brand.html | 1 + .../industrial/versions/1.2.0/pages/case.html | 1 + .../versions/1.2.0/pages/category.html | 2 + .../versions/1.2.0/pages/contact.html | 7 + .../industrial/versions/1.2.0/pages/faq.html | 2 + .../industrial/versions/1.2.0/pages/home.html | 4 + .../versions/1.2.0/pages/listing.html | 2 + .../versions/1.2.0/pages/notfound.html | 1 + .../versions/1.2.0/pages/product.html | 3 + .../versions/1.2.0/pages/search.html | 2 + .../versions/1.2.0/pages/service.html | 2 + .../versions/1.2.0/pages/standard.html | 2 + themes/industrial/versions/1.2.0/pro.css | 23 + themes/industrial/versions/1.2.0/pro.html | 13 + themes/industrial/versions/1.2.0/site.html | 12 + themes/industrial/versions/1.2.0/theme.css | 4 + .../industrial/versions/1.2.0/visual/hero.svg | 1 + themes/minimal/manifest.json | 6 +- themes/minimal/pages/about.html | 6 +- themes/minimal/pages/article.html | 3 +- themes/minimal/pages/contact.html | 13 +- themes/minimal/pages/home.html | 2 + themes/minimal/pages/listing.html | 8 +- themes/minimal/pages/product.html | 7 +- themes/minimal/pro.css | 82 ++ themes/minimal/theme.css | 3 + themes/minimal/versions/1.1.0/manifest.json | 54 ++ .../minimal/versions/1.1.0/page-presets.json | 273 +++++++ .../minimal/versions/1.1.0/pages/about.html | 2 + .../minimal/versions/1.1.0/pages/article.html | 1 + .../minimal/versions/1.1.0/pages/brand.html | 1 + themes/minimal/versions/1.1.0/pages/case.html | 1 + .../versions/1.1.0/pages/category.html | 2 + .../minimal/versions/1.1.0/pages/contact.html | 7 + themes/minimal/versions/1.1.0/pages/faq.html | 2 + themes/minimal/versions/1.1.0/pages/home.html | 3 + .../minimal/versions/1.1.0/pages/listing.html | 2 + .../versions/1.1.0/pages/notfound.html | 1 + .../minimal/versions/1.1.0/pages/product.html | 3 + .../minimal/versions/1.1.0/pages/search.html | 2 + .../minimal/versions/1.1.0/pages/service.html | 2 + .../versions/1.1.0/pages/standard.html | 2 + themes/minimal/versions/1.1.0/pro.css | 8 + themes/minimal/versions/1.1.0/pro.html | 13 + themes/minimal/versions/1.1.0/site.html | 8 + themes/minimal/versions/1.1.0/theme.css | 1 + themes/minimal/versions/1.1.0/visual/hero.svg | 1 + themes/minimal/versions/1.2.0/manifest.json | 54 ++ .../minimal/versions/1.2.0/page-presets.json | 273 +++++++ .../minimal/versions/1.2.0/pages/about.html | 2 + .../minimal/versions/1.2.0/pages/article.html | 1 + .../minimal/versions/1.2.0/pages/brand.html | 1 + themes/minimal/versions/1.2.0/pages/case.html | 1 + .../versions/1.2.0/pages/category.html | 2 + .../minimal/versions/1.2.0/pages/contact.html | 7 + themes/minimal/versions/1.2.0/pages/faq.html | 2 + themes/minimal/versions/1.2.0/pages/home.html | 3 + .../minimal/versions/1.2.0/pages/listing.html | 2 + .../versions/1.2.0/pages/notfound.html | 1 + .../minimal/versions/1.2.0/pages/product.html | 3 + .../minimal/versions/1.2.0/pages/search.html | 2 + .../minimal/versions/1.2.0/pages/service.html | 2 + .../versions/1.2.0/pages/standard.html | 2 + themes/minimal/versions/1.2.0/pro.css | 24 + themes/minimal/versions/1.2.0/pro.html | 13 + themes/minimal/versions/1.2.0/site.html | 8 + themes/minimal/versions/1.2.0/theme.css | 4 + themes/minimal/versions/1.2.0/visual/hero.svg | 1 + 647 files changed, 20853 insertions(+), 271 deletions(-) create mode 100644 .updiff.txt create mode 100644 README_V8_26.md create mode 100644 README_V8_28.md create mode 100644 README_V8_29.md create mode 100644 README_V8_30.md create mode 100644 README_V8_31.md create mode 100644 README_V8_31_1.md create mode 100644 app/static/auto31.js create mode 100644 app/static/studio-canvas-bridge.js create mode 100644 app/static/studio-experience-v829.js create mode 100644 app/static/workspace-guide.js create mode 100644 app/static/workspace-launch.js create mode 100644 docs/V8_22_ADVANCED_VISUAL_STUDIO.md create mode 100644 docs/V8_23_ADVANCED_STUDIO.md create mode 100644 docs/V8_24_DEEP_NESTED_STUDIO.md create mode 100644 docs/V8_25_SHARED_DESIGN_SYSTEM.md create mode 100644 docs/V8_26_GLOBAL_DESIGN.md create mode 100644 docs/V8_27_USER_FRIENDLY_WORKSPACE.md create mode 100644 docs/V8_28_GUIDED_LAUNCH_CENTER.md create mode 100644 examples/Studio_V8_22_画布级可视化编辑器_交互演示.html create mode 100644 examples/Studio_V8_23_嵌套组件编辑器_可交互预览.html create mode 100644 examples/Studio_V8_24_深层嵌套可视化编辑器_交互演示.html create mode 100644 examples/V8_25_公共组件_版本与同步演示.html create mode 100644 examples/V8_26_全站设计与导航_交互预览.html create mode 100644 examples/V8_27_新手友好建站工作台_交互演示.html create mode 100644 examples/V8_28_简洁上线操作中心_交互演示.html create mode 100644 examples/V8_29_主题与可视化编辑_离线操作演示.html create mode 100644 examples/V8_30_四套主题_真实页面交互预览.html create mode 100644 examples/V8_31_1_汽车主题性能与语义化图标_离线演示.html create mode 100644 examples/V8_31_汽车主题_完整页面交互预览.html create mode 100644 examples/v830-built-sites/BUILD_REPORT.json create mode 100644 examples/v830-built-sites/automotive/.htaccess create mode 100644 examples/v830-built-sites/automotive/404.html create mode 100644 examples/v830-built-sites/automotive/about/index.html create mode 100644 examples/v830-built-sites/automotive/assets/blocks.css create mode 100644 examples/v830-built-sites/automotive/assets/commercial.css create mode 100644 examples/v830-built-sites/automotive/assets/custom.css create mode 100644 examples/v830-built-sites/automotive/assets/factory.css create mode 100644 examples/v830-built-sites/automotive/assets/pro-base.css create mode 100644 examples/v830-built-sites/automotive/assets/pro.css create mode 100644 examples/v830-built-sites/automotive/assets/pro.js create mode 100644 examples/v830-built-sites/automotive/assets/site-runtime.js create mode 100644 examples/v830-built-sites/automotive/assets/theme.css create mode 100644 examples/v830-built-sites/automotive/assets/visual/hero.svg create mode 100644 examples/v830-built-sites/automotive/brand/index.html create mode 100644 examples/v830-built-sites/automotive/brands/arc/index.html create mode 100644 examples/v830-built-sites/automotive/brands/index.html create mode 100644 examples/v830-built-sites/automotive/brands/mono/index.html create mode 100644 examples/v830-built-sites/automotive/brands/nova/index.html create mode 100644 examples/v830-built-sites/automotive/case/index.html create mode 100644 examples/v830-built-sites/automotive/cases/1/index.html create mode 100644 examples/v830-built-sites/automotive/cases/2/index.html create mode 100644 examples/v830-built-sites/automotive/cases/3/index.html create mode 100644 examples/v830-built-sites/automotive/cases/index.html create mode 100644 examples/v830-built-sites/automotive/categories/term-79e34764f8ce/index.html create mode 100644 examples/v830-built-sites/automotive/categories/term-8d6647722ef3/index.html create mode 100644 examples/v830-built-sites/automotive/categories/term-95acf900fafc/index.html create mode 100644 examples/v830-built-sites/automotive/categories/term-a68a8656a4dc/index.html create mode 100644 examples/v830-built-sites/automotive/commercial-readiness.json create mode 100644 examples/v830-built-sites/automotive/contact/index.html create mode 100644 examples/v830-built-sites/automotive/faq/index.html create mode 100644 examples/v830-built-sites/automotive/index.html create mode 100644 examples/v830-built-sites/automotive/news/1/index.html create mode 100644 examples/v830-built-sites/automotive/news/2/index.html create mode 100644 examples/v830-built-sites/automotive/news/3/index.html create mode 100644 examples/v830-built-sites/automotive/news/index.html create mode 100644 examples/v830-built-sites/automotive/nginx-snippet.conf create mode 100644 examples/v830-built-sites/automotive/post/index.html create mode 100644 examples/v830-built-sites/automotive/product/index.html create mode 100644 examples/v830-built-sites/automotive/products/1/index.html create mode 100644 examples/v830-built-sites/automotive/products/2/index.html create mode 100644 examples/v830-built-sites/automotive/products/3/index.html create mode 100644 examples/v830-built-sites/automotive/products/4/index.html create mode 100644 examples/v830-built-sites/automotive/products/5/index.html create mode 100644 examples/v830-built-sites/automotive/products/6/index.html create mode 100644 examples/v830-built-sites/automotive/products/7/index.html create mode 100644 examples/v830-built-sites/automotive/products/8/index.html create mode 100644 examples/v830-built-sites/automotive/products/index.html create mode 100644 examples/v830-built-sites/automotive/robots.txt create mode 100644 examples/v830-built-sites/automotive/search-index.json create mode 100644 examples/v830-built-sites/automotive/search/index.html create mode 100644 examples/v830-built-sites/automotive/service/index.html create mode 100644 examples/v830-built-sites/automotive/services/index.html create mode 100644 examples/v830-built-sites/automotive/services/solution/index.html create mode 100644 examples/v830-built-sites/automotive/siteforge-report.json create mode 100644 examples/v830-built-sites/automotive/sitemap.xml create mode 100644 examples/v830-built-sites/corporate/.htaccess create mode 100644 examples/v830-built-sites/corporate/404.html create mode 100644 examples/v830-built-sites/corporate/about/index.html create mode 100644 examples/v830-built-sites/corporate/assets/blocks.css create mode 100644 examples/v830-built-sites/corporate/assets/commercial.css create mode 100644 examples/v830-built-sites/corporate/assets/custom.css create mode 100644 examples/v830-built-sites/corporate/assets/factory.css create mode 100644 examples/v830-built-sites/corporate/assets/pro-base.css create mode 100644 examples/v830-built-sites/corporate/assets/pro.css create mode 100644 examples/v830-built-sites/corporate/assets/pro.js create mode 100644 examples/v830-built-sites/corporate/assets/site-runtime.js create mode 100644 examples/v830-built-sites/corporate/assets/theme.css create mode 100644 examples/v830-built-sites/corporate/assets/visual/hero.svg create mode 100644 examples/v830-built-sites/corporate/brand/index.html create mode 100644 examples/v830-built-sites/corporate/brands/arc/index.html create mode 100644 examples/v830-built-sites/corporate/brands/index.html create mode 100644 examples/v830-built-sites/corporate/brands/mono/index.html create mode 100644 examples/v830-built-sites/corporate/brands/nova/index.html create mode 100644 examples/v830-built-sites/corporate/case/index.html create mode 100644 examples/v830-built-sites/corporate/cases/1/index.html create mode 100644 examples/v830-built-sites/corporate/cases/2/index.html create mode 100644 examples/v830-built-sites/corporate/cases/3/index.html create mode 100644 examples/v830-built-sites/corporate/cases/index.html create mode 100644 examples/v830-built-sites/corporate/categories/term-79e34764f8ce/index.html create mode 100644 examples/v830-built-sites/corporate/categories/term-8d6647722ef3/index.html create mode 100644 examples/v830-built-sites/corporate/categories/term-95acf900fafc/index.html create mode 100644 examples/v830-built-sites/corporate/categories/term-a68a8656a4dc/index.html create mode 100644 examples/v830-built-sites/corporate/commercial-readiness.json create mode 100644 examples/v830-built-sites/corporate/contact/index.html create mode 100644 examples/v830-built-sites/corporate/faq/index.html create mode 100644 examples/v830-built-sites/corporate/index.html create mode 100644 examples/v830-built-sites/corporate/news/1/index.html create mode 100644 examples/v830-built-sites/corporate/news/2/index.html create mode 100644 examples/v830-built-sites/corporate/news/3/index.html create mode 100644 examples/v830-built-sites/corporate/news/index.html create mode 100644 examples/v830-built-sites/corporate/nginx-snippet.conf create mode 100644 examples/v830-built-sites/corporate/post/index.html create mode 100644 examples/v830-built-sites/corporate/product/index.html create mode 100644 examples/v830-built-sites/corporate/products/1/index.html create mode 100644 examples/v830-built-sites/corporate/products/2/index.html create mode 100644 examples/v830-built-sites/corporate/products/3/index.html create mode 100644 examples/v830-built-sites/corporate/products/4/index.html create mode 100644 examples/v830-built-sites/corporate/products/5/index.html create mode 100644 examples/v830-built-sites/corporate/products/6/index.html create mode 100644 examples/v830-built-sites/corporate/products/7/index.html create mode 100644 examples/v830-built-sites/corporate/products/8/index.html create mode 100644 examples/v830-built-sites/corporate/products/index.html create mode 100644 examples/v830-built-sites/corporate/robots.txt create mode 100644 examples/v830-built-sites/corporate/search-index.json create mode 100644 examples/v830-built-sites/corporate/search/index.html create mode 100644 examples/v830-built-sites/corporate/service/index.html create mode 100644 examples/v830-built-sites/corporate/services/index.html create mode 100644 examples/v830-built-sites/corporate/services/solution/index.html create mode 100644 examples/v830-built-sites/corporate/siteforge-report.json create mode 100644 examples/v830-built-sites/corporate/sitemap.xml create mode 100644 examples/v830-built-sites/index.html create mode 100644 examples/v830-built-sites/industrial/.htaccess create mode 100644 examples/v830-built-sites/industrial/404.html create mode 100644 examples/v830-built-sites/industrial/about/index.html create mode 100644 examples/v830-built-sites/industrial/assets/blocks.css create mode 100644 examples/v830-built-sites/industrial/assets/commercial.css create mode 100644 examples/v830-built-sites/industrial/assets/custom.css create mode 100644 examples/v830-built-sites/industrial/assets/factory.css create mode 100644 examples/v830-built-sites/industrial/assets/pro-base.css create mode 100644 examples/v830-built-sites/industrial/assets/pro.css create mode 100644 examples/v830-built-sites/industrial/assets/pro.js create mode 100644 examples/v830-built-sites/industrial/assets/site-runtime.js create mode 100644 examples/v830-built-sites/industrial/assets/theme.css create mode 100644 examples/v830-built-sites/industrial/assets/visual/hero.svg create mode 100644 examples/v830-built-sites/industrial/brand/index.html create mode 100644 examples/v830-built-sites/industrial/brands/arc/index.html create mode 100644 examples/v830-built-sites/industrial/brands/index.html create mode 100644 examples/v830-built-sites/industrial/brands/mono/index.html create mode 100644 examples/v830-built-sites/industrial/brands/nova/index.html create mode 100644 examples/v830-built-sites/industrial/case/index.html create mode 100644 examples/v830-built-sites/industrial/cases/1/index.html create mode 100644 examples/v830-built-sites/industrial/cases/2/index.html create mode 100644 examples/v830-built-sites/industrial/cases/3/index.html create mode 100644 examples/v830-built-sites/industrial/cases/index.html create mode 100644 examples/v830-built-sites/industrial/categories/term-79e34764f8ce/index.html create mode 100644 examples/v830-built-sites/industrial/categories/term-8d6647722ef3/index.html create mode 100644 examples/v830-built-sites/industrial/categories/term-95acf900fafc/index.html create mode 100644 examples/v830-built-sites/industrial/categories/term-a68a8656a4dc/index.html create mode 100644 examples/v830-built-sites/industrial/commercial-readiness.json create mode 100644 examples/v830-built-sites/industrial/contact/index.html create mode 100644 examples/v830-built-sites/industrial/faq/index.html create mode 100644 examples/v830-built-sites/industrial/index.html create mode 100644 examples/v830-built-sites/industrial/news/1/index.html create mode 100644 examples/v830-built-sites/industrial/news/2/index.html create mode 100644 examples/v830-built-sites/industrial/news/3/index.html create mode 100644 examples/v830-built-sites/industrial/news/index.html create mode 100644 examples/v830-built-sites/industrial/nginx-snippet.conf create mode 100644 examples/v830-built-sites/industrial/post/index.html create mode 100644 examples/v830-built-sites/industrial/product/index.html create mode 100644 examples/v830-built-sites/industrial/products/1/index.html create mode 100644 examples/v830-built-sites/industrial/products/2/index.html create mode 100644 examples/v830-built-sites/industrial/products/3/index.html create mode 100644 examples/v830-built-sites/industrial/products/4/index.html create mode 100644 examples/v830-built-sites/industrial/products/5/index.html create mode 100644 examples/v830-built-sites/industrial/products/6/index.html create mode 100644 examples/v830-built-sites/industrial/products/7/index.html create mode 100644 examples/v830-built-sites/industrial/products/8/index.html create mode 100644 examples/v830-built-sites/industrial/products/index.html create mode 100644 examples/v830-built-sites/industrial/robots.txt create mode 100644 examples/v830-built-sites/industrial/search-index.json create mode 100644 examples/v830-built-sites/industrial/search/index.html create mode 100644 examples/v830-built-sites/industrial/service/index.html create mode 100644 examples/v830-built-sites/industrial/services/index.html create mode 100644 examples/v830-built-sites/industrial/services/solution/index.html create mode 100644 examples/v830-built-sites/industrial/siteforge-report.json create mode 100644 examples/v830-built-sites/industrial/sitemap.xml create mode 100644 examples/v830-built-sites/minimal/.htaccess create mode 100644 examples/v830-built-sites/minimal/404.html create mode 100644 examples/v830-built-sites/minimal/about/index.html create mode 100644 examples/v830-built-sites/minimal/assets/blocks.css create mode 100644 examples/v830-built-sites/minimal/assets/commercial.css create mode 100644 examples/v830-built-sites/minimal/assets/custom.css create mode 100644 examples/v830-built-sites/minimal/assets/factory.css create mode 100644 examples/v830-built-sites/minimal/assets/pro-base.css create mode 100644 examples/v830-built-sites/minimal/assets/pro.css create mode 100644 examples/v830-built-sites/minimal/assets/pro.js create mode 100644 examples/v830-built-sites/minimal/assets/site-runtime.js create mode 100644 examples/v830-built-sites/minimal/assets/theme.css create mode 100644 examples/v830-built-sites/minimal/assets/visual/hero.svg create mode 100644 examples/v830-built-sites/minimal/brand/index.html create mode 100644 examples/v830-built-sites/minimal/brands/arc/index.html create mode 100644 examples/v830-built-sites/minimal/brands/index.html create mode 100644 examples/v830-built-sites/minimal/brands/mono/index.html create mode 100644 examples/v830-built-sites/minimal/brands/nova/index.html create mode 100644 examples/v830-built-sites/minimal/case/index.html create mode 100644 examples/v830-built-sites/minimal/cases/1/index.html create mode 100644 examples/v830-built-sites/minimal/cases/2/index.html create mode 100644 examples/v830-built-sites/minimal/cases/3/index.html create mode 100644 examples/v830-built-sites/minimal/cases/index.html create mode 100644 examples/v830-built-sites/minimal/categories/term-79e34764f8ce/index.html create mode 100644 examples/v830-built-sites/minimal/categories/term-8d6647722ef3/index.html create mode 100644 examples/v830-built-sites/minimal/categories/term-95acf900fafc/index.html create mode 100644 examples/v830-built-sites/minimal/categories/term-a68a8656a4dc/index.html create mode 100644 examples/v830-built-sites/minimal/commercial-readiness.json create mode 100644 examples/v830-built-sites/minimal/contact/index.html create mode 100644 examples/v830-built-sites/minimal/faq/index.html create mode 100644 examples/v830-built-sites/minimal/index.html create mode 100644 examples/v830-built-sites/minimal/news/1/index.html create mode 100644 examples/v830-built-sites/minimal/news/2/index.html create mode 100644 examples/v830-built-sites/minimal/news/3/index.html create mode 100644 examples/v830-built-sites/minimal/news/index.html create mode 100644 examples/v830-built-sites/minimal/nginx-snippet.conf create mode 100644 examples/v830-built-sites/minimal/post/index.html create mode 100644 examples/v830-built-sites/minimal/product/index.html create mode 100644 examples/v830-built-sites/minimal/products/1/index.html create mode 100644 examples/v830-built-sites/minimal/products/2/index.html create mode 100644 examples/v830-built-sites/minimal/products/3/index.html create mode 100644 examples/v830-built-sites/minimal/products/4/index.html create mode 100644 examples/v830-built-sites/minimal/products/5/index.html create mode 100644 examples/v830-built-sites/minimal/products/6/index.html create mode 100644 examples/v830-built-sites/minimal/products/7/index.html create mode 100644 examples/v830-built-sites/minimal/products/8/index.html create mode 100644 examples/v830-built-sites/minimal/products/index.html create mode 100644 examples/v830-built-sites/minimal/robots.txt create mode 100644 examples/v830-built-sites/minimal/search-index.json create mode 100644 examples/v830-built-sites/minimal/search/index.html create mode 100644 examples/v830-built-sites/minimal/service/index.html create mode 100644 examples/v830-built-sites/minimal/services/index.html create mode 100644 examples/v830-built-sites/minimal/services/solution/index.html create mode 100644 examples/v830-built-sites/minimal/siteforge-report.json create mode 100644 examples/v830-built-sites/minimal/sitemap.xml create mode 100644 reports/V8_22_验收报告.html create mode 100644 reports/V8_22_验收报告.json create mode 100644 reports/V8_22_验收报告.md create mode 100644 reports/V8_23_集成验收.html create mode 100644 reports/V8_25_summary.json create mode 100644 reports/V8_25_验收报告.html create mode 100644 reports/V8_25_验收报告.md create mode 100644 reports/V8_30_mobile_browser_audit.json create mode 100644 reports/V8_30_主题设计与兼容验收.html create mode 100644 reports/V8_31_汽车主题验收报告.html create mode 100644 reports/v823-regression/result.json create mode 100644 reports/v824-regression/result.json create mode 100644 reports/v825-regression/result.json create mode 100644 reports/v826-regression/result.json create mode 100644 reports/v826/V8_26_集成验收.html create mode 100644 reports/v826/summary.json create mode 100644 reports/v827/V8_27_集成验收报告.html create mode 100644 reports/v827/v827-create-wizard-mobile.png create mode 100644 reports/v827/v827-guided-mobile.png create mode 100644 reports/v827/v827-guided-workspace.png create mode 100644 reports/v828/V8_28_evidence.json create mode 100644 reports/v828/V8_28_集成验收报告.html create mode 100644 reports/v828/V8_28_集成验收摘要.md create mode 100644 reports/v828/launch-desktop.png create mode 100644 reports/v828/launch-mobile.png create mode 100644 reports/v829-browser/result.json create mode 100644 reports/v829-browser/v829-demo-offline.png create mode 100644 reports/v829-browser/v829-studio-desktop.png create mode 100644 reports/v829-browser/v829-studio-phone.png create mode 100644 reports/v829-regression/result.json create mode 100644 reports/v829/V8_29_主题与编辑器验收报告.html create mode 100644 reports/v829/summary.json create mode 100644 reports/v830-regression/batch-01.json create mode 100644 reports/v830-regression/batch-02.json create mode 100644 reports/v830-regression/batch-03.json create mode 100644 reports/v830-regression/batch-04.json create mode 100644 reports/v830-regression/batch-05.json create mode 100644 reports/v830-regression/batch-06.json create mode 100644 reports/v830-regression/batch-07.json create mode 100644 reports/v830-regression/batch-08.json create mode 100644 reports/v830-regression/batch-09.json create mode 100644 reports/v830-regression/batch-10.json create mode 100644 reports/v830-regression/batch-11.json create mode 100644 reports/v830-regression/batch-12.json create mode 100644 reports/v830-regression/batch-13.json create mode 100644 reports/v830-regression/batch-14.json create mode 100644 reports/v830-regression/batch-15.json create mode 100644 reports/v830-regression/batch-16.json create mode 100644 reports/v830-regression/batch-17.json create mode 100644 reports/v830-regression/batch-18.json create mode 100644 reports/v830-regression/batch-19.json create mode 100644 reports/v830-regression/batch-20.json create mode 100644 reports/v830-regression/batch-21.json create mode 100644 reports/v830-regression/batch-22.json create mode 100644 reports/v830-regression/batch-23.json create mode 100644 reports/v830-regression/batch-24.json create mode 100644 reports/v830-regression/batch-25.json create mode 100644 reports/v831/auto-home-desktop.png create mode 100644 reports/v831/auto-home-mobile.png create mode 100644 reports/v831/auto-product-desktop.png create mode 100644 reports/v831/automotive-home-desktop.png create mode 100644 reports/v831/automotive-home-phone.png create mode 100644 reports/v831/automotive-product-desktop.png create mode 100644 reports/v831/browser_results.json create mode 100644 reports/v8311/V8_31_1_性能与图标验收报告.html create mode 100644 reports/v8311/automotive-v8311-desktop.png create mode 100644 reports/v8311/automotive-v8311-mobile.png create mode 100644 reports/v8311/perf_icons_result.json create mode 100644 reports/v8311/performance_comparison.json create mode 100644 scripts/browser_guide_v827.py create mode 100644 scripts/browser_launch_v828.py create mode 100644 scripts/browser_studio_v829.py create mode 100644 scripts/make_theme_demo_v830.py create mode 100644 scripts/make_theme_demo_v8311.py create mode 100644 scripts/regression_v823.py create mode 100644 scripts/regression_v824.py create mode 100644 scripts/regression_v825.py create mode 100644 scripts/regression_v826.py create mode 100644 scripts/regression_v827.py create mode 100644 scripts/regression_v828.py create mode 100644 scripts/regression_v829.py create mode 100644 scripts/regression_v830.py create mode 100644 scripts/regression_v8311.py create mode 100644 scripts/report_v825.py create mode 100644 scripts/report_v828.py create mode 100644 scripts/studio_canvas_isolated_browser_v822.py create mode 100644 scripts/studio_canvas_smoke_v822.py create mode 100644 scripts/studio_nested_browser_v823.py create mode 100644 scripts/studio_nested_browser_v824.py create mode 100644 tests/test_deep_nested_v824.py create mode 100644 tests/test_nested_helpers_v823.cjs create mode 100644 tests/test_nested_v823.py create mode 100644 tests/test_v822_canvas.py create mode 100644 tests/test_v825_shared_components.py create mode 100644 tests/test_v826_global_design.py create mode 100644 tests/test_v827_guided_workspace.py create mode 100644 tests/test_v828_launch_center.py create mode 100644 tests/test_v829_theme_studio.py create mode 100644 tests/test_v830_real_pages.py create mode 100644 tests/test_v8311_performance_icons.py create mode 100644 tests/test_v831_automotive_ref.py create mode 100644 tests_js/deep_nested_v824.test.cjs create mode 100644 tests_js/studio-experience-v829.test.cjs create mode 100644 tests_js/workspace_guide_v827.test.cjs create mode 100644 tests_js/workspace_launch_v828.test.cjs create mode 100644 themes/automotive/auto-icons.svg create mode 100644 themes/automotive/versions/1.1.0/manifest.json create mode 100644 themes/automotive/versions/1.1.0/page-presets.json create mode 100644 themes/automotive/versions/1.1.0/pages/about.html create mode 100644 themes/automotive/versions/1.1.0/pages/article.html create mode 100644 themes/automotive/versions/1.1.0/pages/brand.html create mode 100644 themes/automotive/versions/1.1.0/pages/case.html create mode 100644 themes/automotive/versions/1.1.0/pages/category.html create mode 100644 themes/automotive/versions/1.1.0/pages/contact.html create mode 100644 themes/automotive/versions/1.1.0/pages/faq.html create mode 100644 themes/automotive/versions/1.1.0/pages/home.html create mode 100644 themes/automotive/versions/1.1.0/pages/listing.html create mode 100644 themes/automotive/versions/1.1.0/pages/notfound.html create mode 100644 themes/automotive/versions/1.1.0/pages/product.html create mode 100644 themes/automotive/versions/1.1.0/pages/search.html create mode 100644 themes/automotive/versions/1.1.0/pages/service.html create mode 100644 themes/automotive/versions/1.1.0/pages/standard.html create mode 100644 themes/automotive/versions/1.1.0/pro.css create mode 100644 themes/automotive/versions/1.1.0/pro.html create mode 100644 themes/automotive/versions/1.1.0/site.html create mode 100644 themes/automotive/versions/1.1.0/theme.css create mode 100644 themes/automotive/versions/1.1.0/visual/hero.svg create mode 100644 themes/automotive/versions/1.2.0/manifest.json create mode 100644 themes/automotive/versions/1.2.0/page-presets.json create mode 100644 themes/automotive/versions/1.2.0/pages/about.html create mode 100644 themes/automotive/versions/1.2.0/pages/article.html create mode 100644 themes/automotive/versions/1.2.0/pages/brand.html create mode 100644 themes/automotive/versions/1.2.0/pages/case.html create mode 100644 themes/automotive/versions/1.2.0/pages/category.html create mode 100644 themes/automotive/versions/1.2.0/pages/contact.html create mode 100644 themes/automotive/versions/1.2.0/pages/faq.html create mode 100644 themes/automotive/versions/1.2.0/pages/home.html create mode 100644 themes/automotive/versions/1.2.0/pages/listing.html create mode 100644 themes/automotive/versions/1.2.0/pages/notfound.html create mode 100644 themes/automotive/versions/1.2.0/pages/product.html create mode 100644 themes/automotive/versions/1.2.0/pages/search.html create mode 100644 themes/automotive/versions/1.2.0/pages/service.html create mode 100644 themes/automotive/versions/1.2.0/pages/standard.html create mode 100644 themes/automotive/versions/1.2.0/pro.css create mode 100644 themes/automotive/versions/1.2.0/pro.html create mode 100644 themes/automotive/versions/1.2.0/site.html create mode 100644 themes/automotive/versions/1.2.0/theme.css create mode 100644 themes/automotive/versions/1.2.0/visual/hero.svg create mode 100644 themes/automotive/versions/1.3.0/manifest.json create mode 100644 themes/automotive/versions/1.3.0/page-presets.json create mode 100644 themes/automotive/versions/1.3.0/pages/about.html create mode 100644 themes/automotive/versions/1.3.0/pages/article.html create mode 100644 themes/automotive/versions/1.3.0/pages/brand.html create mode 100644 themes/automotive/versions/1.3.0/pages/case.html create mode 100644 themes/automotive/versions/1.3.0/pages/category.html create mode 100644 themes/automotive/versions/1.3.0/pages/contact.html create mode 100644 themes/automotive/versions/1.3.0/pages/faq.html create mode 100644 themes/automotive/versions/1.3.0/pages/home.html create mode 100644 themes/automotive/versions/1.3.0/pages/listing.html create mode 100644 themes/automotive/versions/1.3.0/pages/notfound.html create mode 100644 themes/automotive/versions/1.3.0/pages/product.html create mode 100644 themes/automotive/versions/1.3.0/pages/search.html create mode 100644 themes/automotive/versions/1.3.0/pages/service.html create mode 100644 themes/automotive/versions/1.3.0/pages/standard.html create mode 100644 themes/automotive/versions/1.3.0/pro.css create mode 100644 themes/automotive/versions/1.3.0/pro.html create mode 100644 themes/automotive/versions/1.3.0/site.html create mode 100644 themes/automotive/versions/1.3.0/theme.css create mode 100644 themes/automotive/versions/1.3.0/visual/hero.svg create mode 100644 themes/automotive/versions/1.4.0/manifest.json create mode 100644 themes/automotive/versions/1.4.0/page-presets.json create mode 100644 themes/automotive/versions/1.4.0/pages/about.html create mode 100644 themes/automotive/versions/1.4.0/pages/article.html create mode 100644 themes/automotive/versions/1.4.0/pages/brand.html create mode 100644 themes/automotive/versions/1.4.0/pages/case.html create mode 100644 themes/automotive/versions/1.4.0/pages/category.html create mode 100644 themes/automotive/versions/1.4.0/pages/contact.html create mode 100644 themes/automotive/versions/1.4.0/pages/faq.html create mode 100644 themes/automotive/versions/1.4.0/pages/home.html create mode 100644 themes/automotive/versions/1.4.0/pages/listing.html create mode 100644 themes/automotive/versions/1.4.0/pages/notfound.html create mode 100644 themes/automotive/versions/1.4.0/pages/product.html create mode 100644 themes/automotive/versions/1.4.0/pages/search.html create mode 100644 themes/automotive/versions/1.4.0/pages/service.html create mode 100644 themes/automotive/versions/1.4.0/pages/standard.html create mode 100644 themes/automotive/versions/1.4.0/pro.css create mode 100644 themes/automotive/versions/1.4.0/pro.html create mode 100644 themes/automotive/versions/1.4.0/site.html create mode 100644 themes/automotive/versions/1.4.0/theme.css create mode 100644 themes/automotive/versions/1.4.0/visual/hero.svg create mode 100644 themes/corporate/versions/1.1.0/manifest.json create mode 100644 themes/corporate/versions/1.1.0/page-presets.json create mode 100644 themes/corporate/versions/1.1.0/pages/about.html create mode 100644 themes/corporate/versions/1.1.0/pages/article.html create mode 100644 themes/corporate/versions/1.1.0/pages/brand.html create mode 100644 themes/corporate/versions/1.1.0/pages/case.html create mode 100644 themes/corporate/versions/1.1.0/pages/category.html create mode 100644 themes/corporate/versions/1.1.0/pages/contact.html create mode 100644 themes/corporate/versions/1.1.0/pages/faq.html create mode 100644 themes/corporate/versions/1.1.0/pages/home.html create mode 100644 themes/corporate/versions/1.1.0/pages/listing.html create mode 100644 themes/corporate/versions/1.1.0/pages/notfound.html create mode 100644 themes/corporate/versions/1.1.0/pages/product.html create mode 100644 themes/corporate/versions/1.1.0/pages/search.html create mode 100644 themes/corporate/versions/1.1.0/pages/service.html create mode 100644 themes/corporate/versions/1.1.0/pages/standard.html create mode 100644 themes/corporate/versions/1.1.0/pro.css create mode 100644 themes/corporate/versions/1.1.0/pro.html create mode 100644 themes/corporate/versions/1.1.0/site.html create mode 100644 themes/corporate/versions/1.1.0/theme.css create mode 100644 themes/corporate/versions/1.1.0/visual/hero.svg create mode 100644 themes/corporate/versions/1.2.0/manifest.json create mode 100644 themes/corporate/versions/1.2.0/page-presets.json create mode 100644 themes/corporate/versions/1.2.0/pages/about.html create mode 100644 themes/corporate/versions/1.2.0/pages/article.html create mode 100644 themes/corporate/versions/1.2.0/pages/brand.html create mode 100644 themes/corporate/versions/1.2.0/pages/case.html create mode 100644 themes/corporate/versions/1.2.0/pages/category.html create mode 100644 themes/corporate/versions/1.2.0/pages/contact.html create mode 100644 themes/corporate/versions/1.2.0/pages/faq.html create mode 100644 themes/corporate/versions/1.2.0/pages/home.html create mode 100644 themes/corporate/versions/1.2.0/pages/listing.html create mode 100644 themes/corporate/versions/1.2.0/pages/notfound.html create mode 100644 themes/corporate/versions/1.2.0/pages/product.html create mode 100644 themes/corporate/versions/1.2.0/pages/search.html create mode 100644 themes/corporate/versions/1.2.0/pages/service.html create mode 100644 themes/corporate/versions/1.2.0/pages/standard.html create mode 100644 themes/corporate/versions/1.2.0/pro.css create mode 100644 themes/corporate/versions/1.2.0/pro.html create mode 100644 themes/corporate/versions/1.2.0/site.html create mode 100644 themes/corporate/versions/1.2.0/theme.css create mode 100644 themes/corporate/versions/1.2.0/visual/hero.svg create mode 100644 themes/industrial/versions/1.1.0/manifest.json create mode 100644 themes/industrial/versions/1.1.0/page-presets.json create mode 100644 themes/industrial/versions/1.1.0/pages/about.html create mode 100644 themes/industrial/versions/1.1.0/pages/article.html create mode 100644 themes/industrial/versions/1.1.0/pages/brand.html create mode 100644 themes/industrial/versions/1.1.0/pages/case.html create mode 100644 themes/industrial/versions/1.1.0/pages/category.html create mode 100644 themes/industrial/versions/1.1.0/pages/contact.html create mode 100644 themes/industrial/versions/1.1.0/pages/faq.html create mode 100644 themes/industrial/versions/1.1.0/pages/home.html create mode 100644 themes/industrial/versions/1.1.0/pages/listing.html create mode 100644 themes/industrial/versions/1.1.0/pages/notfound.html create mode 100644 themes/industrial/versions/1.1.0/pages/product.html create mode 100644 themes/industrial/versions/1.1.0/pages/search.html create mode 100644 themes/industrial/versions/1.1.0/pages/service.html create mode 100644 themes/industrial/versions/1.1.0/pages/standard.html create mode 100644 themes/industrial/versions/1.1.0/pro.css create mode 100644 themes/industrial/versions/1.1.0/pro.html create mode 100644 themes/industrial/versions/1.1.0/site.html create mode 100644 themes/industrial/versions/1.1.0/theme.css create mode 100644 themes/industrial/versions/1.1.0/visual/hero.svg create mode 100644 themes/industrial/versions/1.2.0/manifest.json create mode 100644 themes/industrial/versions/1.2.0/page-presets.json create mode 100644 themes/industrial/versions/1.2.0/pages/about.html create mode 100644 themes/industrial/versions/1.2.0/pages/article.html create mode 100644 themes/industrial/versions/1.2.0/pages/brand.html create mode 100644 themes/industrial/versions/1.2.0/pages/case.html create mode 100644 themes/industrial/versions/1.2.0/pages/category.html create mode 100644 themes/industrial/versions/1.2.0/pages/contact.html create mode 100644 themes/industrial/versions/1.2.0/pages/faq.html create mode 100644 themes/industrial/versions/1.2.0/pages/home.html create mode 100644 themes/industrial/versions/1.2.0/pages/listing.html create mode 100644 themes/industrial/versions/1.2.0/pages/notfound.html create mode 100644 themes/industrial/versions/1.2.0/pages/product.html create mode 100644 themes/industrial/versions/1.2.0/pages/search.html create mode 100644 themes/industrial/versions/1.2.0/pages/service.html create mode 100644 themes/industrial/versions/1.2.0/pages/standard.html create mode 100644 themes/industrial/versions/1.2.0/pro.css create mode 100644 themes/industrial/versions/1.2.0/pro.html create mode 100644 themes/industrial/versions/1.2.0/site.html create mode 100644 themes/industrial/versions/1.2.0/theme.css create mode 100644 themes/industrial/versions/1.2.0/visual/hero.svg create mode 100644 themes/minimal/versions/1.1.0/manifest.json create mode 100644 themes/minimal/versions/1.1.0/page-presets.json create mode 100644 themes/minimal/versions/1.1.0/pages/about.html create mode 100644 themes/minimal/versions/1.1.0/pages/article.html create mode 100644 themes/minimal/versions/1.1.0/pages/brand.html create mode 100644 themes/minimal/versions/1.1.0/pages/case.html create mode 100644 themes/minimal/versions/1.1.0/pages/category.html create mode 100644 themes/minimal/versions/1.1.0/pages/contact.html create mode 100644 themes/minimal/versions/1.1.0/pages/faq.html create mode 100644 themes/minimal/versions/1.1.0/pages/home.html create mode 100644 themes/minimal/versions/1.1.0/pages/listing.html create mode 100644 themes/minimal/versions/1.1.0/pages/notfound.html create mode 100644 themes/minimal/versions/1.1.0/pages/product.html create mode 100644 themes/minimal/versions/1.1.0/pages/search.html create mode 100644 themes/minimal/versions/1.1.0/pages/service.html create mode 100644 themes/minimal/versions/1.1.0/pages/standard.html create mode 100644 themes/minimal/versions/1.1.0/pro.css create mode 100644 themes/minimal/versions/1.1.0/pro.html create mode 100644 themes/minimal/versions/1.1.0/site.html create mode 100644 themes/minimal/versions/1.1.0/theme.css create mode 100644 themes/minimal/versions/1.1.0/visual/hero.svg create mode 100644 themes/minimal/versions/1.2.0/manifest.json create mode 100644 themes/minimal/versions/1.2.0/page-presets.json create mode 100644 themes/minimal/versions/1.2.0/pages/about.html create mode 100644 themes/minimal/versions/1.2.0/pages/article.html create mode 100644 themes/minimal/versions/1.2.0/pages/brand.html create mode 100644 themes/minimal/versions/1.2.0/pages/case.html create mode 100644 themes/minimal/versions/1.2.0/pages/category.html create mode 100644 themes/minimal/versions/1.2.0/pages/contact.html create mode 100644 themes/minimal/versions/1.2.0/pages/faq.html create mode 100644 themes/minimal/versions/1.2.0/pages/home.html create mode 100644 themes/minimal/versions/1.2.0/pages/listing.html create mode 100644 themes/minimal/versions/1.2.0/pages/notfound.html create mode 100644 themes/minimal/versions/1.2.0/pages/product.html create mode 100644 themes/minimal/versions/1.2.0/pages/search.html create mode 100644 themes/minimal/versions/1.2.0/pages/service.html create mode 100644 themes/minimal/versions/1.2.0/pages/standard.html create mode 100644 themes/minimal/versions/1.2.0/pro.css create mode 100644 themes/minimal/versions/1.2.0/pro.html create mode 100644 themes/minimal/versions/1.2.0/site.html create mode 100644 themes/minimal/versions/1.2.0/theme.css create mode 100644 themes/minimal/versions/1.2.0/visual/hero.svg diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6740a06..fc6c343 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,14 +28,14 @@ jobs: SITEFORGE_SESSION_SECRET: ci-only-session-key-not-for-production-with-entropy SITEFORGE_PG_PASSWORD: ci-only-test-postgresql-password run: | - SITEFORGE_REGRESSION_REPEAT=2 bash scripts/check.sh + bash scripts/check.sh python scripts/http_end_to_end.py - - name: Upload V8.21 regression evidence + - name: Upload V8.23 regression evidence if: always() uses: actions/upload-artifact@v4 with: - name: v821-regression-${{ matrix.python }} - path: reports/v821-regression* + name: v823-regression-${{ matrix.python }} + path: reports/v823-regression* if-no-files-found: ignore retention-days: 14 browser-smoke: @@ -58,6 +58,7 @@ jobs: run: | mkdir -p reports/browser python scripts/browser_smoke.py reports/browser + python scripts/studio_nested_browser_v823.py - name: Upload browser screenshots if: always() uses: actions/upload-artifact@v4 diff --git a/.updiff.txt b/.updiff.txt new file mode 100644 index 0000000..196cf35 --- /dev/null +++ b/.updiff.txt @@ -0,0 +1,200 @@ +Files ./.github/workflows/ci.yml and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/.github/workflows/ci.yml differ +Files ./.gitignore and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/.gitignore differ +Files ./README.md and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/README.md differ +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1: README_V8_26.md +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1: README_V8_28.md +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1: README_V8_29.md +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1: README_V8_30.md +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1: README_V8_31.md +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1: README_V8_31_1.md +Only in .: SHA256SUMS.txt +Files ./app/blueprints.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/blueprints.py differ +Files ./app/builder.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/builder.py differ +Files ./app/core.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/core.py differ +Files ./app/factory_api.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/factory_api.py differ +Files ./app/main.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/main.py differ +Files ./app/multilingual.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/multilingual.py differ +Files ./app/reusables.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/reusables.py differ +Files ./app/site_design_v87.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/site_design_v87.py differ +Files ./app/static/admin.js and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/static/admin.js differ +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/static: auto31.js +Files ./app/static/editor-helpers.js and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/static/editor-helpers.js differ +Files ./app/static/editor.css and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/static/editor.css differ +Files ./app/static/editor.js and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/static/editor.js differ +Files ./app/static/factory-v2.js and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/static/factory-v2.js differ +Files ./app/static/pro.js and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/static/pro.js differ +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/static: studio-canvas-bridge.js +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/static: studio-experience-v829.js +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/static: workspace-guide.js +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/static: workspace-launch.js +Files ./app/static/workspace.css and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/static/workspace.css differ +Files ./app/static/workspace.js and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/static/workspace.js differ +Files ./app/templates/admin.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/templates/admin.html differ +Files ./app/templates/editor.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/templates/editor.html differ +Files ./app/templates/theme-gallery.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/templates/theme-gallery.html differ +Files ./app/templates/workspace.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/templates/workspace.html differ +Files ./app/theme_pro.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/theme_pro.py differ +Files ./app/theme_store.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/theme_store.py differ +Files ./app/v8_workflows.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/v8_workflows.py differ +Files ./app/version.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/app/version.py differ +Files ./compose.enterprise.yaml and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/compose.enterprise.yaml differ +Files ./compose.yaml and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/compose.yaml differ +Only in ./docs: COMPLETION_PLAN.md +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/docs: V8_22_ADVANCED_VISUAL_STUDIO.md +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/docs: V8_23_ADVANCED_STUDIO.md +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/docs: V8_24_DEEP_NESTED_STUDIO.md +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/docs: V8_25_SHARED_DESIGN_SYSTEM.md +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/docs: V8_26_GLOBAL_DESIGN.md +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/docs: V8_27_USER_FRIENDLY_WORKSPACE.md +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/docs: V8_28_GUIDED_LAUNCH_CENTER.md +Only in ./docs: superpowers +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/examples: Studio_V8_22_画布级可视化编辑器_交互演示.html +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/examples: Studio_V8_23_嵌套组件编辑器_可交互预览.html +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/examples: Studio_V8_24_深层嵌套可视化编辑器_交互演示.html +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/examples: V8_25_公共组件_版本与同步演示.html +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/examples: V8_26_全站设计与导航_交互预览.html +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/examples: V8_27_新手友好建站工作台_交互演示.html +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/examples: V8_28_简洁上线操作中心_交互演示.html +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/examples: V8_29_主题与可视化编辑_离线操作演示.html +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/examples: V8_30_四套主题_真实页面交互预览.html +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/examples: V8_31_1_汽车主题性能与语义化图标_离线演示.html +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/examples: V8_31_汽车主题_完整页面交互预览.html +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/examples: v830-built-sites +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: V8_22_验收报告.html +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: V8_22_验收报告.json +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: V8_22_验收报告.md +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: V8_23_集成验收.html +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: V8_25_summary.json +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: V8_25_验收报告.html +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: V8_25_验收报告.md +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: V8_30_mobile_browser_audit.json +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: V8_30_主题设计与兼容验收.html +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: V8_31_汽车主题验收报告.html +Only in ./reports: mobile-v8213-browser-console.log +Only in ./reports: v8213-final-regression_logs +Only in ./reports: v8213-regression_logs +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: v823-regression +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: v824-regression +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: v825-regression +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: v826 +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: v826-regression +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: v827 +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: v828 +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: v829 +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: v829-browser +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: v829-regression +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: v830-regression +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: v831 +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: v8311 +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: v8311-regression +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: v8311-regression-part1.log +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/reports: v8311_regression_run.log +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: browser_guide_v827.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: browser_launch_v828.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: browser_studio_v829.py +Files ./scripts/check.ps1 and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts/check.ps1 differ +Files ./scripts/check.sh and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts/check.sh differ +Files ./scripts/init_config.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts/init_config.py differ +Files ./scripts/install_into_art_design_pro.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts/install_into_art_design_pro.py differ +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: make_theme_demo_v830.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: make_theme_demo_v8311.py +Files ./scripts/regression_v821.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts/regression_v821.py differ +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: regression_v823.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: regression_v824.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: regression_v825.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: regression_v826.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: regression_v827.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: regression_v828.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: regression_v829.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: regression_v830.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: regression_v8311.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: report_v825.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: report_v828.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: studio_canvas_isolated_browser_v822.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: studio_canvas_smoke_v822.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: studio_nested_browser_v823.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts: studio_nested_browser_v824.py +Files ./scripts/verify_art_design_pro_v819.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts/verify_art_design_pro_v819.py differ +Files ./scripts/verify_release.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/scripts/verify_release.py differ +Files ./tests/test_core_v4.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests/test_core_v4.py differ +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests: test_deep_nested_v824.py +Files ./tests/test_editor_easy_v8212.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests/test_editor_easy_v8212.py differ +Files ./tests/test_factory_v2.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests/test_factory_v2.py differ +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests: test_nested_helpers_v823.cjs +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests: test_nested_v823.py +Files ./tests/test_theme_pro_v3.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests/test_theme_pro_v3.py differ +Only in ./tests: test_theme_registry.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests: test_v822_canvas.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests: test_v825_shared_components.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests: test_v826_global_design.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests: test_v827_guided_workspace.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests: test_v828_launch_center.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests: test_v829_theme_studio.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests: test_v830_real_pages.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests: test_v8311_performance_icons.py +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests: test_v831_automotive_ref.py +Files ./tests/test_workspace_v810.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests/test_workspace_v810.py differ +Files ./tests/test_workspace_v812.py and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests/test_workspace_v812.py differ +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests_js: deep_nested_v824.test.cjs +Files ./tests_js/editor_ux.test.cjs and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests_js/editor_ux.test.cjs differ +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests_js: studio-experience-v829.test.cjs +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests_js: workspace_guide_v827.test.cjs +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/tests_js: workspace_launch_v828.test.cjs +Files ./themes/_professional_components.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/_professional_components.html differ +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive: auto-icons.svg +Files ./themes/automotive/manifest.json and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/manifest.json differ +Files ./themes/automotive/pages/about.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/pages/about.html differ +Files ./themes/automotive/pages/article.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/pages/article.html differ +Files ./themes/automotive/pages/brand.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/pages/brand.html differ +Files ./themes/automotive/pages/case.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/pages/case.html differ +Files ./themes/automotive/pages/category.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/pages/category.html differ +Files ./themes/automotive/pages/contact.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/pages/contact.html differ +Files ./themes/automotive/pages/faq.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/pages/faq.html differ +Files ./themes/automotive/pages/home.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/pages/home.html differ +Files ./themes/automotive/pages/listing.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/pages/listing.html differ +Files ./themes/automotive/pages/notfound.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/pages/notfound.html differ +Files ./themes/automotive/pages/product.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/pages/product.html differ +Files ./themes/automotive/pages/service.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/pages/service.html differ +Files ./themes/automotive/pages/standard.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/pages/standard.html differ +Files ./themes/automotive/pro.css and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/pro.css differ +Files ./themes/automotive/pro.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/pro.html differ +Files ./themes/automotive/theme.css and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/theme.css differ +Files ./themes/automotive/versions/1.0.0/pro.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/versions/1.0.0/pro.html differ +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/versions: 1.1.0 +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/versions: 1.2.0 +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/versions: 1.3.0 +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/automotive/versions: 1.4.0 +Files ./themes/corporate/manifest.json and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/corporate/manifest.json differ +Files ./themes/corporate/pages/about.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/corporate/pages/about.html differ +Files ./themes/corporate/pages/article.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/corporate/pages/article.html differ +Files ./themes/corporate/pages/contact.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/corporate/pages/contact.html differ +Files ./themes/corporate/pages/home.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/corporate/pages/home.html differ +Files ./themes/corporate/pages/listing.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/corporate/pages/listing.html differ +Files ./themes/corporate/pages/product.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/corporate/pages/product.html differ +Files ./themes/corporate/pro.css and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/corporate/pro.css differ +Files ./themes/corporate/theme.css and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/corporate/theme.css differ +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/corporate/versions: 1.1.0 +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/corporate/versions: 1.2.0 +Files ./themes/industrial/manifest.json and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/industrial/manifest.json differ +Files ./themes/industrial/pages/about.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/industrial/pages/about.html differ +Files ./themes/industrial/pages/article.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/industrial/pages/article.html differ +Files ./themes/industrial/pages/contact.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/industrial/pages/contact.html differ +Files ./themes/industrial/pages/home.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/industrial/pages/home.html differ +Files ./themes/industrial/pages/listing.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/industrial/pages/listing.html differ +Files ./themes/industrial/pages/product.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/industrial/pages/product.html differ +Files ./themes/industrial/pro.css and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/industrial/pro.css differ +Files ./themes/industrial/theme.css and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/industrial/theme.css differ +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/industrial/versions: 1.1.0 +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/industrial/versions: 1.2.0 +Files ./themes/minimal/manifest.json and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/minimal/manifest.json differ +Files ./themes/minimal/pages/about.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/minimal/pages/about.html differ +Files ./themes/minimal/pages/article.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/minimal/pages/article.html differ +Files ./themes/minimal/pages/contact.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/minimal/pages/contact.html differ +Files ./themes/minimal/pages/home.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/minimal/pages/home.html differ +Files ./themes/minimal/pages/listing.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/minimal/pages/listing.html differ +Files ./themes/minimal/pages/product.html and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/minimal/pages/product.html differ +Files ./themes/minimal/pro.css and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/minimal/pro.css differ +Files ./themes/minimal/theme.css and C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/minimal/theme.css differ +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/minimal/versions: 1.1.0 +Only in C:/Users/30997/Downloads/SiteForge_Factory_V5_Web_Docker/SiteForge_Enterprise_V8_31_1/themes/minimal/versions: 1.2.0 +Only in ./themes: trade-pro diff --git a/README.md b/README.md index f589527..bf3cd56 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,139 @@ +# SiteForge Enterprise V8.31.0-dev.1 + +本轮汽车主题按 [Magic Bridge Auto](https://magicbridgeauto.com/) 的导航及选车体验进行行业化重设计,完整说明见 [`README_V8_31.md`](README_V8_31.md)。保留汽车旧主题快照及其他三套主题。 + +--- + +# SiteForge Enterprise V8.30.0-dev.1 + +最新交付说明:[`README_V8_30.md`](README_V8_30.md)。 + +--- + +# SiteForge Enterprise V8.29.0-dev.1 — 主题与可视化编辑器体验优化 + +新功能及测试见 [README_V8_29.md](README_V8_29.md)。此版本以 V8.28 完整源码为基线,保留其全部业务能力。 + +--- + +# SiteForge Enterprise V8.28.0-dev.1 — 引导式上线中心 + +> V8.27 全量源码基础上的集成增量;保留原四套主题、移动端、WordPress、公共组件、编辑器和 Worker。上线向导不跳过任何服务端审批、质量或发布检查。 + +# SiteForge Enterprise V8.27.0-dev.1 — 简洁后台与新手建站向导 + +> 当前状态:**开发集成版,不能据此认定生产上线验收完成。** 在 V8.26 完整源码上新增三步建站创建、按实际内容/任务记录显示的上线操作指引、精简网站概览和手机布局适配;保留 V8.26 公共组件、全站设计、WordPress 迁移和发布能力。 +> +> 详细说明:`docs/V8_27_USER_FRIENDLY_WORKSPACE.md`。本轮隔离回归按模块 379 项通过,但一次性/组合分批检查有超时与旧断言迁移;真实 Art Design Pro 编译、PostgreSQL/Redis 及生产发布仍待验收。 + +## 快速体验 + +- 独立交互演示:`examples/V8_27_新手友好建站工作台_交互演示.html`(模拟网络,只展示流程) +- 源码后台入口:`/` → 「创建网站」或选中网站后「建站操作指引」 +- 本轮截图与测试报告:`reports/v827/` + +## 快速验证 + +```bash +python -m pytest -q tests/test_v827_guided_workspace.py +node --test tests_js/*.test.cjs +python scripts/http_end_to_end.py +python scripts/browser_guide_v827.py +``` + +--- + +# SiteForge Enterprise V8.26.0-dev.1 + +最新版说明请先阅读 [README_V8_26.md](README_V8_26.md)。以下为历史版本说明。 + +--- + +# SiteForge Enterprise V8.25.0-dev.1 — 公共组件与全站设计协作基础 + +> **交付状态:开发集成版。** 本版基于 V8.24 完整源码,在现有编辑器加入公共组件版本快照、关联插入、引用页预检、选择性同步到草稿及历史恢复。**不会自动改已发布网站**,需要按原有草稿审核、构建与部署流程完成上线。 + +## V8.25 本轮功能 + +- 组件库“复制插入” / “关联插入”两种选择;关联插入在区块内记录版本与内容指纹。 +- 不可变源组件版本快照、更新版本乐观锁、查看历史与恢复为新版本;已有组件自动补“当前版本”快照。 +- 在一个站点内查看关联引用页面,识别本地修改、已是最新版及发布冲突。 +- 选择性同步到一个或多个页面**新草稿**:完整预检校验、批次事务、失败整批回滚、独立历史审计,不更改现有在线内容。 +- 属性栏“解除关联”保留当前区块,避免以后参与公共组件同步。 +- 四套内置主题、移动端抽屉与底部 Tabs、两层嵌套编辑器、WordPress 迁移、SEO、Worker 和发布接口保持兼容。 + +[离线交互演示](examples/V8_25_公共组件_版本与同步演示.html) · [完整功能与安全说明](docs/V8_25_SHARED_DESIGN_SYSTEM.md) · [本轮验收报告](reports/V8_25_验收报告.html) + +```bash +python -m pytest -q tests/test_v825_shared_components.py +node --test tests_js/*.test.cjs +python scripts/http_end_to_end.py +python scripts/regression_v825.py --timeout 55 --group-size 2 +``` + +**验收限制:** 生产 PostgreSQL/Redis、多 Worker、远程发布与回滚、官方 Art Design Pro 工程编译以及已登录后台的真实浏览器验收未完成;隔离 Chromium 仅验证离线交互演示。 + +--- + +# SiteForge Enterprise V8.24.0-dev.1 — 深层画布编辑与复用组件体验 + +> **交付状态:开发集成版**。在 V8.23 完整项目上继续开发;原数据库结构、四套主题、移动端抽屉菜单、底部 Tabs 与静态发布机制保持兼容。本版本没有执行生产环境部署。 + +## 本轮新增 + +1. **第二层可视化编辑**:在双层布局中点击组件,直接编辑、复制、上下排序、删除,并以层级路径显示所选内容。 +2. **直接创建内层内容**:可添加内层布局及第二层内容组件,不需要手工填写 JSON。 +3. **独立响应式布局**:为内层布局设置桌面列宽、列间距、手机 1/2 列、平板 1/2/3 列。 +4. **图片选取更加准确**:本站素材库、上传图片应用到当前支持图片的组件,而非误写外层布局。 +5. **组件库更好用**:可保存当前选中的内层组件,插入组件副本;跨页面自动联动仍未实现。 +6. **验收工具与演示**:新增深层操作 Python/Node 测试、HTTP+Worker 测试、隔离 Chromium 演示、独立分组回归入口。 + +- [打开离线交互预览](examples/Studio_V8_24_深层嵌套可视化编辑器_交互演示.html) +- [V8.24 技术说明](docs/V8_24_DEEP_NESTED_STUDIO.md) +- [回归机器可读结果](reports/v824-regression/result.json) + +```bash +bash scripts/check.sh +python scripts/http_end_to_end.py +python scripts/studio_nested_browser_v824.py +``` + +**限制:** 当前只支持既有两层 layout 深度;组件库为复制副本而非跨站点实时同步。生产 PostgreSQL/Redis、官方 Art Design Pro 编译和登录后的真实浏览器 E2E 均未完成验收。 + +--- + +# SiteForge Enterprise V8.23.0-dev.1 — 嵌套组件与响应式可视化编辑 + +> **交付状态:开发集成版。** 基于 **V8.22.0-dev.1 完整源码**继续开发;未覆盖原版本或任何正式网站的数据。此次更新保持原有 HTML 构建、SEO、四套主题、抽屉导航及可选底部 Tabs 的数据兼容性。 + +## V8.23 本轮完成 + +1. **列内组件画布直接操作**:支持在多列布局中选中直接子组件、复制、删除、同列上下移动;标题/简介(适用组件)可双击直接修改。使用父布局 ID + 子组件 ID 的白名单校验,不接收任意执行命令。 +2. **直观的嵌套属性编辑**:选中列内组件后,右侧“内容”面板展开对应的标题、文字、图片路径、链接等普通输入表单,不再强制在“响应式”面板翻找组件。 +3. **桌面布局快捷预设**:等宽两列、左宽右窄、左窄右宽;列间距 0–64px。平板/手机各自的列数、跨列、顺序、显隐继续独立配置。 +4. **草稿与历史版本兼容**:仍沿用 schema 白名单、原有版本快照、乐观锁、草稿保存和发布审批流程。嵌套组件操作不执行线上构建或发布。 +5. **回归与离线演示**:新增 Node 安全操作测试、嵌套接口测试和真实 Chromium 沙箱交互测试,另提供无需服务器的交互演示。 + +## 快速验证 + +```bash +bash scripts/check.sh +python scripts/http_end_to_end.py +python scripts/studio_nested_browser_v823.py +# 单独测试 Node 嵌套组件操作安全性 +node tests/test_nested_helpers_v823.cjs +``` + +## 查看与使用 + +- 后台入口:`/editor/{site_id}/{entry_id}` → 在页面中添加“多列自由布局” → 添加列内组件 → 画布上点选或双击文字 → 右侧编辑 → 保存草稿。 +- [离线交互演示](examples/Studio_V8_23_嵌套组件编辑器_可交互预览.html)(仅演示数据,保存按钮不修改后端)。 +- [开发与验收报告](docs/V8_23_ADVANCED_STUDIO.md);[分批回归日志](reports/v823-regression/result.json)。 + +**仍未完成**:任意深度的子节点直接编辑、公共组件跨页面联动、真正自由定位的布局、Art Design Pro 官方工程编译、生产 PostgreSQL/Redis/Docker 实测以及真实后台 Chromium localhost 端到端验收。已测试的是多列布局直接子组件和受限沙箱交互,不应描述为完整自由设计器或生产可上线。 + +--- + # SiteForge Enterprise V8.21.3 — 四套内置主题手机端统一优化 > **状态:开发集成版**。从 V8.21.2 完整源码升级;原站点与数据未覆盖。四套内置主题统一支持抽屉菜单,可选的 1–5 项手机底栏 Tabs 默认关闭。正式生产的域名部署、Apple/Android 真机与 Art Design Pro 官方构建仍需独立验收。 diff --git a/README_V8_26.md b/README_V8_26.md new file mode 100644 index 0000000..52e9880 --- /dev/null +++ b/README_V8_26.md @@ -0,0 +1,32 @@ +# SiteForge Enterprise V8.26.0-dev.1 — 全站设计与公共组件维护 + +**交付等级:开发集成版,非生产正式版。** 在 V8.25 全量源码上增量开发,保留已有的 WordPress、四套主题、移动端抽屉导航、可选 Tabs、公共组件版本/同步、草稿审批及静态构建。 + +## 这次实际增加了什么 + +- **更容易找到**:编辑器左侧增加“编辑全站菜单、页眉与页脚”入口。 +- **可视化管理全站导航**:编辑名称、站内路径,创建最多三级菜单,添加、上下排序、删除;不必手写 JSON。所有改动仍通过原来的导航结构白名单与路径安全校验。 +- **发布差异审核**:保存草稿后检查相对于当前发布设置的字段差异,检查页眉、导航、页脚、设计令牌、手机 Tabs 与响应式设置。用户确认后调用带审核令牌的独立发布接口;修改草稿会使旧审核令牌失效。 +- **全站发布历史与安全恢复**:查看历史快照,将发布前或发布后的版本恢复为新草稿;恢复带当前正式配置哈希/草稿版本双重防护,绝不直接改线上网站。 +- **继续保留安全边界**:仅站点 Owner 可执行审核发布;Editor 可修改/恢复草稿;Viewer 只读;数据和历史完全按 site_id 隔离。 + +## 用户操作(正式系统) + +启动 SiteForge 后打开一个网站的页面编辑器 → 左侧点击“编辑全站菜单、页眉与页脚” → 调整导航与页眉、页脚、手机 Tabs → 保存全站草稿 → 点击“审核差异并发布” → 检查变更清单后确认。正式网页仍需重新构建、发布审批和远端部署。 + +## 测试命令 + +```bash +python -m pytest -q tests/test_v826_global_design.py tests/test_site_design_v87.py +node --check app/static/editor.js +node --test tests_js/*.test.cjs +python scripts/http_end_to_end.py +python scripts/regression_v826.py --timeout 55 --group-size 2 +python scripts/verify_release.py +``` + +详见 `docs/V8_26_GLOBAL_DESIGN.md`、`reports/v826/V8_26_集成验收.html` 与 `examples/V8_26_全站设计与导航_交互预览.html`。离线演示使用模拟数据,不会连接正式管理后台。 + +## 尚未完成的正式验收 + +官方 Art Design Pro 完整工程编译;正式后台登录后的真实 Chromium E2E;PostgreSQL/Redis 多 Worker、灾备恢复;真实 SFTP/S3/Agent 正式发布、CDN 和生产安全审计,均不应标为已通过。 diff --git a/README_V8_28.md b/README_V8_28.md new file mode 100644 index 0000000..c744091 --- /dev/null +++ b/README_V8_28.md @@ -0,0 +1,40 @@ +# SiteForge Enterprise V8.28.0-dev.1 + +## 本轮内容 + +V8.27 基线之上新增“检查并上线”中心,使用者按六步完成网站版本选择、人工预览、提交独立审批、发布前检查、服务器部署和真实网站核对。 + +- 修复旧侧边导航按钮无法响应点击的问题。 +- 规范“生成与预览”与“检查并上线”的导航分工,原高级发布操作仍可通过折叠入口访问。 +- 严格区分审批待处理/已通过、发布检查通过/部署队列、部署记录/公网实际验收。 +- 当前版本未批准、未人工核对、目标未配置、检查结果不匹配时,禁止从新手向导提交部署;后端继续执行自身权限与质量校验。 +- 更换网站、构建版本或目标环境后不复用旧检查状态,避免重复审批及快速重复部署。 +- 手机端表单与操作步骤适配,支持离线交互演示。 + +## 文件入口 + +- `examples/V8_28_简洁上线操作中心_交互演示.html`:直接打开;演示是模拟数据,绝不操作真实服务器。 +- `docs/V8_28_GUIDED_LAUNCH_CENTER.md`:功能说明、使用步骤、后端安全约束及验证边界。 +- `reports/v828/V8_28_集成验收报告.html`:验收汇总及 24 批详细结果。 +- `reports/v828-regression/`:初次运行的原始日志;第 22 批旧菜单断言更新后的复测记录单独保留。 + +## 验收结果(开发隔离环境) + +- 原项目 Python 48 模块,最终验证 **383 项通过**;24 批中初次 23 批通过,1 批旧断言修复后 13 项复测通过,未关闭失败为 0。 +- JavaScript 单元测试 **35 项通过**。 +- HTTP + Worker 实际建站、静态构建、ZIP 与预览检查通过。 +- 真 Chromium 原工作台 JS + 模拟 API,独立审批状态、预检、部署任务与 390px 手机布局通过。 +- Art Design Pro 官方工程实际编译,真实 PostgreSQL/Redis 多 Worker,公网发布与回滚、灾备演练仍**未验收**,不能视为生产正式版。 + +## 快速执行 + +```bash +node --test tests_js/*.test.cjs +python -m pytest -q tests/test_v828_launch_center.py tests/test_v827_guided_workspace.py +python scripts/http_end_to_end.py +python scripts/browser_launch_v828.py +python scripts/verify_release.py +python scripts/regression_v828.py --group-size 2 --timeout 25 +``` + +不要将模拟浏览器环境“部署成功”的提示理解为真实服务器已经部署。当前真实发布仍必须由两个不同有权限用户独立审批,通过发布前置条件校验,并由 Worker 触发远程部署。 diff --git a/README_V8_29.md b/README_V8_29.md new file mode 100644 index 0000000..94adefd --- /dev/null +++ b/README_V8_29.md @@ -0,0 +1,45 @@ +# SiteForge Enterprise V8.29.0-dev.1 — 主题与编辑器体验优化 + +**开发基线**:V8.28.0-dev.1 完整源码。此次保留原有后台、静态建站、WordPress 迁移、发布审批、四套移动端抽屉菜单与可选 Tabs、两层组件编辑、公共组件及历史版本。 + +## 这次有哪些实质变化? + +1. 四套内置主题(汽车、工业、企业、简约)升级至 `1.2.0`:优化移动端留白、标题缩放、图片卡片比例、焦点反馈、动作幅度和小屏阅读。不会改变旧站 URL、SEO 数据或已发布内容。 +2. 每套主题的原版 `1.1.0` 已保存到 `themes//versions/1.1.0/`。**已固定 1.1.0 的网站仍能用相应旧主题构建**;升级到 1.2.0 需要明确应用新主题。 +3. 编辑器新增「主题效果」:可比较四套主题 × 六种示例页面 × 三种设备宽度;仅用于比较最新主题示例,不会改动当前页面、主题锁定版本或正式站点。手机端可通过「更多 → 比较四套主题效果」进入。 +4. 左侧「添加内容」改成按用途分类并搜索(常用内容 / 图片与展示 / 产品与业务 / 复杂布局),减少从一长串区块中查找的成本。 +5. 右侧「样式」增加清爽白底、柔和浅底、重点深底三项快捷方案;基于现有受控的 `background`、`text_color` 和 `padding` 字段,支持撤销/保存草稿。 +6. 顶部补充撤销、重做可见快捷入口;手机顶栏两行排布,修复 390px 宽度下「更多」按钮被挤出视口的问题。 + +## 用户操作路径 + +- 修改当前页面:进入编辑器 → 点击画布区块 → 右侧修改内容或快速外观 → 查看电脑/平板/手机 → 保存草稿 → 发布设计。 +- 对比主题:点击「主题效果」→ 选择主题、页面类型与设备 → 确认后在网站管理中正式应用(预览不会替你更换主题)。 +- 发布到正式网站:发布设计并不等于线上部署;仍需静态构建、审批、发布前检查、正式部署与公网核验。 + +## 执行检查 + +```bash +python -m compileall -q app +python scripts/verify_release.py +python scripts/http_end_to_end.py +node --test tests_js/*.test.cjs +node tests/test_nested_helpers_v823.cjs +python -m pytest -q tests/test_v829_theme_studio.py +python scripts/regression_v829.py --timeout 45 --group-size 2 +# 隔离浏览器:使用真实 HTML/JS/CSS + 测试替身,不会操作真实用户数据 +python scripts/browser_studio_v829.py +``` + +**浏览器验收范围**:真实 Chromium 测试使用编辑器本身的 DOM/CSS/JS,模拟 API 数据;能够验证组件搜索、主题弹窗打开/切换、外观预设、撤销、390px 手机布局,但不等于已登录正式服务器后的浏览器端到端验收。受当前环境管理员策略限制,本轮不能完整访问 localhost / 测试域名进行真实登录浏览器测试。另使用真实 FastAPI + Worker 做了 HTTP/ZIP/预览的独立集成验收。 + +**生产验收仍未关闭**:Art Design Pro 官方完整项目编译、真实 PostgreSQL/Redis、多 Worker 与远程发布/恢复需在对应实际环境测试;此次不宣称生产级完成。 + +- 原项目完整回归:**25 批,387 个 Python 用例通过,0 失败批次**(记录在 `reports/v829-regression/`)。 +- Node.js 全部已配置测试:**39 项通过**(包含 4 项本轮新测试)。 +- HTTP+Worker 隔离 E2E:通过。 +- Chromium 隔离交互:桌面与 390px 手机通过,无脚本异常;本机 HTTP 直接访问由于浏览器策略受限,未通过该方式验收。 + +## 版本及兼容说明 + +现有 SQLite/PostgreSQL 业务 Schema、草稿结构、接口权限与构建/发布动作未改变。主题 v1.2.0 属于显式版本升级,用户可继续固定 v1.1.0;手动迁移主题后仍应逐页检查自定义内容、图片、移动端样式与 SEO。旧版本目录不得在部署升级时直接删除。 diff --git a/README_V8_30.md b/README_V8_30.md new file mode 100644 index 0000000..3ae7ca2 --- /dev/null +++ b/README_V8_30.md @@ -0,0 +1,48 @@ +# SiteForge Enterprise V8.30.0-dev.1 — 四套主题真实页面设计升级 + +> 基于 V8.29 完整源码开发;本轮仅优化内置主题、内页布局、旧版本存档和预览/验收,不改变数据库结构,不重写用户 URL/SEO/媒体数据。 + +## 这轮真正改了什么 + +四套主题各自升级为 `1.3.0`。这次不只是配色变化: + +| 主题 | 首页 | 列表 | 详情 | 文章 | 关于 | 联系 | +|---|---|---|---|---|---|---| +| 汽车与出行 | 深色宽幅车型视觉、精选产品 | 深色目录开场与车型筛选 | 图片优先、车系标签与参数 | 深蓝编辑式头图 | 企业叙事、真实服务/案例 | 业务咨询、真实邮箱或受控表单 | +| 工业建材 | 类别和产品体系 | 浅蓝技术目录 | 产品图、技术参数侧栏 | 技术文档式头部 | 产品与项目能力介绍 | 材料/工程需求咨询 | +| 企业商务 | 专业品牌叙事 | 业务目录、留白 | 信息和视觉分层 | 新闻/洞察阅读 | 企业故事与已发布业务 | 简洁商务联系 | +| 极简展示 | 大字排版、精选作品 | 编辑式目录 | 极简图片与描述 | 杂志式文章 | 品牌故事与作品 | 极简联系卡 | + +**内容真实性:** 可自动显示的数据,只来自真实已发布内容。没有真实案例、服务、参数或联系方式时,不会冒充存在;示例站点使用明确标注的虚构内容。 + +### 历史版本安全 + +- V8.29 的 `1.2.0` 四套主题已完整保存到 `themes//versions/1.2.0/`,旧 `1.1.0/1.0.0/0.3.0` 保持不变。 +- 固定在旧主题版本的站点继续构建旧布局,不会因为程序升级而自动换成 v1.3.0。 +- 新主题必须在网站后台主动选择与确认。 +- 原有页面 URL、Canonical、SEO 与移动端抽屉导航、可选 Tabs 功能不变。 + +### 页面预览 + +打开 `examples/V8_30_四套主题_真实页面交互预览.html`,可以切换 **4 套主题 × 6 类真实静态页面 × 电脑/平板/手机**。内置演示数据,不会连接或修改用户站点;其中的视觉图片是演示占位符,正式使用时请添加真实产品与工程照片。 + +### 开发与检查 + +```bash +python scripts/verify_release.py +python -m pytest -q tests/test_v830_real_pages.py tests/test_theme_pro_v3.py tests/test_v829_theme_studio.py +node --test tests_js/*.test.cjs +python scripts/http_end_to_end.py +# 可分批继续,避免历史长流程在某些环境中被中断 +python scripts/regression_v830.py --start 1 --end 25 --group-size 2 --timeout 40 +# 在隔离环境执行,切勿使用生产 SITEFORGE_DATA_DIR +PYTHONPATH=. SITEFORGE_DATA_DIR=/tmp/v830-demo SITEFORGE_DEMO_OUT=/tmp/v830-sites python scripts/make_theme_demo_v830.py +``` + +### 本轮实际结果 + +- **25 个独立 Python 批次,390 项用例通过;0 个失败批次。** 明细在 `reports/v830-regression/`。 +- JavaScript 39 项通过;HTTP 登录/CSRF/建站/Worker 构建/ZIP/预览通过。 +- 每套主题各生成 36 个静态页面,4 套共 144 个;质量检查 **0 错误**。 +- 真实 Chromium:4 主题 × 6 页面 × 375/390/430px = 72 组合,**0 横向溢出、0 脚本错误**。详情在 `reports/V8_30_mobile_browser_audit.json`。 +- 未进行真实 iOS/Android 实机验证、Art Design Pro 官方编译、PostgreSQL/Redis 生产环境、正式域名上线或大型真实企业图片素材验收;本版为开发集成版,不可将本地测试宣称为生产验收。 diff --git a/README_V8_31.md b/README_V8_31.md new file mode 100644 index 0000000..449b801 --- /dev/null +++ b/README_V8_31.md @@ -0,0 +1,53 @@ +# SiteForge Enterprise V8.31.0-dev.1 — 汽车主题行业化重设计 + +## 目标与范围 + +依据获授权参考网站 https://magicbridgeauto.com/ 的汽车出口内容组织方式,将汽车主题从偏概念视觉,调整为以客户选车、品牌筛选、车型参数和询盘为中心的商用网站。**只参考信息架构、导航交互与视觉层次,不抓取或复制参考站的文案、车型数据、图片及 Logo。** + +本次是 SiteForge **完整源码**中的汽车主题升级,不是另起一个独立 HTML。主题发布版本为 `automotive@1.4.0`,平台版本 `8.31.0-dev.1`。工业、企业及极简三套主题继续保留 `1.3.0`。 + +## 用户直接感知到的变化 + +- **导航更清晰**:固定醒目的“首页、产品、品牌、资讯、案例、关于、联系”,品牌/分类大菜单使用实际数据;在手机端仍通过右侧抽屉进入。 +- **首页更聚焦选车**:横幅主信息、车型快速搜索、品牌入口、精选车型、选车/出口服务、公司介绍、资讯案例和询盘 CTA。 +- **车型列表可快速查找**:`?q=` 搜索参数支持静态页面本地搜索,与已有筛选器协同工作;没有使用必须联网的动态查询服务。 +- **品牌独立页**:品牌介绍、品牌车型和相关内容分层展示;品牌菜单仅展示网站内真实存在的品牌项。 +- **车型详情**:车型主图、缩略图图库、型号标签、参数和联系入口分区;真实图片与规格来自站点数据。 +- **关于、联系等内页**:沿用 V8.30 已优化的业务内容区域,整体视觉匹配新汽车风格。 +- **移动端**:宽幅内容转单列,车型卡片使用两列,继续保留抽屉菜单、可选底部 Tabs。按钮、点击区域和标题间距优化。 + +## 重要兼容性修复 + +已有站点可能将汽车主题版本固定为 `1.3.0` 甚至更早版本。在 V8.30 中,此类站点可能仅使用旧版 CSS、却错误包含最新页面片段。本轮修复模板解析:**优先加载固定版本存档里的页面模板**。`themes/automotive/versions/1.0.0`、`1.1.0`、`1.2.0`、`1.3.0` 均保留,旧站不会被强制升级。已固定旧版站点需由用户明确切换至 `1.4.0` 后才会采用新页面。 + +## 实际体验 + +- 独立预览:`examples/V8_31_汽车主题_完整页面交互预览.html`(支持七种页面类型、电脑/平板/手机切换) +- 真正由 SiteForge 静态生成的页面视觉截图:`reports/v831/auto-home-desktop.png`、`auto-home-mobile.png`、`auto-product-desktop.png` +- 可视化验收:`reports/V8_31_汽车主题验收报告.html` + +> 演示数据为虚构;未提供有效车辆图片时,保留主题占位区,避免冒用参考网站的车辆照片。实际网站应在内容管理中上传真实车辆图片、品牌资料、商品规格、询盘联系方式,再检查上线效果。 + +## 测试 + +```bash +python -m pytest -q tests/test_v831_automotive_ref.py tests/test_v830_real_pages.py tests/test_theme_pro_v3.py tests/test_v829_theme_studio.py +node --test tests_js/*.test.cjs +python scripts/http_end_to_end.py +python scripts/verify_release.py +# 分批历史回归,避免长时间同进程测试相互干扰 +python scripts/regression_v829.py --group-size 2 --timeout 35 +``` + +可选演示构建: + +```bash +PYTHONPATH=. SITEFORGE_DATA_DIR=/tmp/siteforge-v831-demo SITEFORGE_DEMO_OUT=/tmp/siteforge-v831-static \ + python scripts/make_theme_demo_v830.py +``` + +已进行四主题样站静态构建、汽车六类页面在 375/390/430/768/1440px 宽度下的 Chromium 检测,并对品牌大菜单、车型过滤、手机抽屉执行交互检查。完整数据请查看 HTML 验收报告与 `reports/v831/browser_results.json`。 + +## 仍需由真实业务决定的内容 + +此版本不等于对参考网站数据的逐条复制,也不等于取得了全部原站品牌/车型资料。若需要与 magicbridgeauto.com 业务数据 **1:1** 一致,应通过站点数据迁移系统额外导出并核对菜单层级、车型图片、规格及品牌关系。正式 Art Design Pro 完整工程编译、生产 PostgreSQL/Redis、远程上线和真实设备浏览器验收仍需独立完成。 diff --git a/README_V8_31_1.md b/README_V8_31_1.md new file mode 100644 index 0000000..59b8aa1 --- /dev/null +++ b/README_V8_31_1.md @@ -0,0 +1,11 @@ +# V8.31.1 汽车主题:速度与语义化图标 + +- **汽车主题** `1.4.1`,SiteForge `8.31.1-dev.1`。升级前自动存档汽车 `1.4.0`;固定旧主题的网站不会被升级。 +- 首页、导航、品牌目录、车型列表/详情、新闻和咨询入口采用自托管 SVG 图标集,避免大量同样的箭头。仅分页与方向操作保留箭头。图标配文字,不以图标单独表达含义。 +- 仅 `automotive@1.4.1` 静态输出:原 7 个 CSS 请求合并为 `assets/auto-compiled.css`,原 3 个 JS 请求合并为 `assets/auto-compiled.js`;顺序与旧版保持一致。额外有可浏览器缓存的 `assets/auto-icons.svg`。 +- 首页车型大图设置高优先级并异步解码;车型详情主图不再错误地懒加载;卡片和画廊缩略图保留按需加载。 +- 无外部 SVG 字体/CDN 引用;主题关键内容结构、路由与移动端抽屉和底部 Tabs 保留。 +- CSS 原文件与 JS 原文件仍存在于 ZIP,方便调试和版本兼容;页面仅引用合并资源。不承诺比 1.4.0 更小的源代码总量,重点改善请求数与首屏资源优先级。 +- 上线前仍应优化真实车型图片(AVIF/WebP、按宽度提供 `srcset`)、正确缓存/压缩头、CDN 回源;这些依赖真实服务器配置与内容素材,不能由本地模拟测试证明生产提速。 + +验证:`python -m pytest -q tests/test_v8311_performance_icons.py`; `python scripts/http_end_to_end.py`; `node --test tests_js/*.test.cjs`。 diff --git a/app/blueprints.py b/app/blueprints.py index f9f9568..dd9a451 100644 --- a/app/blueprints.py +++ b/app/blueprints.py @@ -104,9 +104,14 @@ def validate_blocks(blocks): if not re.fullmatch('[a-zA-Z0-9_-]{4,50}',ident) or ident in found:raise ValueError('区块 ID 缺失或重复') found.add(ident) spec=BLOCKS[block['type']] - allowed=set(spec['fields'])|{'id','type','visible','style'} + allowed=set(spec['fields'])|{'id','type','visible','style','shared_ref'} normalized={key:val for key,val in block.items() if key in allowed} normalized['id']=ident + if 'shared_ref' in normalized: + ref=normalized['shared_ref'] + if not isinstance(ref,dict) or set(ref)!={'id','version','hash'} or not isinstance(ref['id'],str) or not re.fullmatch(r'[a-zA-Z0-9_-]{8,64}',ref['id']) or type(ref['version']) is not int or not 1<=ref['version']<=1000000 or not isinstance(ref['hash'],str) or not re.fullmatch('[a-f0-9]{64}',ref['hash']): + raise ValueError('无效的公共组件引用') + normalized['shared_ref']={'id':ref['id'],'version':ref['version'],'hash':ref['hash']} if 'style' in normalized: style=normalized['style'] if not isinstance(style,dict):raise ValueError('样式必须为对象') diff --git a/app/builder.py b/app/builder.py index 2179b45..d09554e 100644 --- a/app/builder.py +++ b/app/builder.py @@ -204,6 +204,7 @@ def build(site_id,mirror=False): if visuals.is_dir(): shutil.copytree(visuals,dist/'assets'/'visual',dirs_exist_ok=True) shutil.copy2(ROOT/'app'/'static'/'pro.js',dist/'assets'/'pro.js') + shutil.copy2(ROOT/'app'/'static'/'auto31.js',dist/'assets'/'auto31.js') if (theme_dir/'pro.css').exists(): shutil.copy2(theme_dir/'pro.css',dist/'assets'/'pro.css') else: @@ -226,6 +227,7 @@ def build(site_id,mirror=False): f'.btn,.primary,.request,.button,.nav-btn{{background-color:{accent};border-radius:{button}}}' f'body .sf-canvas h1{{font-size:clamp(2.5rem,5vw,calc(4.8rem * var(--sf-heading-scale)))}}') (dist/'assets'/'custom.css').write_text(theme_css+responsive.site_css(records)+site_design_v87.responsive_css(site_design_v87.published(settings)),encoding='utf-8') + # For installed theme packages, Jinja loads only the trusted included template. professional_template=(theme_dir/'pro.html').exists() if professional_template and site['theme'] not in theme_pro.THEMES: @@ -393,6 +395,26 @@ def build(site_id,mirror=False): (dist/'404.html').write_text(missing_html,encoding='utf-8') # A complete static search page is packaged for every theme, not a live API. static_site.write_assets(dist,local_records) + # V8.31.1: only the opt-in automotive theme uses the single-request asset + # bundles. Older pinned theme versions retain their exact original HTML and + # resource order, so existing sites are not silently changed. + if site['theme']=='automotive' and (theme_dir/'manifest.json').is_file() and json.loads((theme_dir/'manifest.json').read_text(encoding='utf-8')).get('version')=='1.4.1': + # Preserve CSS cascade by concatenating precisely in template order. + css_names=('theme.css','blocks.css','factory.css','pro-base.css','pro.css','commercial.css','custom.css') + for resource in css_names: + if not (dist/'assets'/resource).is_file(): + raise ValueError('汽车资源缺失: '+resource) + (dist/'assets'/'auto-compiled.css').write_text( + '\n'.join((dist/'assets'/name).read_text(encoding='utf-8') for name in css_names),encoding='utf-8') + js_names=('site-runtime.js','pro.js','auto31.js') + for resource in js_names: + if not (dist/'assets'/resource).is_file(): + raise ValueError('汽车脚本资源缺失: '+resource) + (dist/'assets'/'auto-compiled.js').write_text( + '\n;\n'.join((dist/'assets'/name).read_text(encoding='utf-8') for name in js_names),encoding='utf-8') + shutil.copy2(theme_dir/'auto-icons.svg',dist/'assets'/'auto-icons.svg') + + if '/search/' not in route_set: search_file=dist/'search'/'index.html' search_file.parent.mkdir(parents=True,exist_ok=True) diff --git a/app/factory_api.py b/app/factory_api.py index a94518a..054f47f 100644 --- a/app/factory_api.py +++ b/app/factory_api.py @@ -277,6 +277,36 @@ def theme_preview_pro_css(theme_id:str,version:str=''): asset=folder/'pro.css' return Response(asset.read_text(encoding='utf-8') if asset.exists() else '',media_type='text/css') +@router.get('/themes/{theme_id}/preview.bundle.css') +def preview_automotive_bundle_css(theme_id:str,version:str=''): + """Read-only editor preview: same cascade as the static automotive build.""" + from fastapi.responses import Response + from . import static_site + folder=theme_store.resolve(theme_id,version or None) + if theme_id != 'automotive' or not (folder/'auto-icons.svg').is_file(): + raise HTTPException(404,'此主题没有优化资源包') + names=[folder/'theme.css',static_site.ASSETS/'blocks.css',static_site.ASSETS/'factory.css', + static_site.ASSETS/'pro-base.css',folder/'pro.css',static_site.ASSETS/'commercial.css'] + return Response('\n'.join(p.read_text(encoding='utf-8') for p in names), media_type='text/css') + +@router.get('/themes/{theme_id}/preview.bundle.js') +def preview_automotive_bundle_js(theme_id:str,version:str=''): + from fastapi.responses import Response + from . import static_site + folder=theme_store.resolve(theme_id,version or None) + if theme_id != 'automotive' or not (folder/'auto-icons.svg').is_file(): + raise HTTPException(404,'此主题没有优化资源包') + names=[static_site.ASSETS/name for name in ('site-runtime.js','pro.js','auto31.js')] + return Response('\n;\n'.join(p.read_text(encoding='utf-8') for p in names),media_type='application/javascript') + +@router.get('/themes/{theme_id}/preview.icons.svg') +def preview_automotive_icons(theme_id:str,version:str=''): + from fastapi.responses import Response + folder=theme_store.resolve(theme_id,version or None) + if theme_id != 'automotive' or not (folder/'auto-icons.svg').is_file(): + raise HTTPException(404,'此主题没有此图标集') + return Response((folder/'auto-icons.svg').read_bytes(),media_type='image/svg+xml',headers={'Cache-Control':'public,max-age=300'}) + @router.get('/themes/{theme_id}/visual/hero.svg') def theme_preview_hero(theme_id:str,version:str=''): from fastapi.responses import Response @@ -319,6 +349,12 @@ def theme_preview(theme_id:str,version:str='',page_type:str='home'): context=theme_pro.make_context(site,page,records,'home' if page_type=='home' else ('notfound' if page_type=='notfound' else 'detail'),[]) context.update(custom_blocks=Markup(''),has_custom=False,noindex=page_type=='notfound',theme_overrides=True) html=env.get_template('pro.html').render(**context) + if theme_id=='automotive' and (directory/'auto-icons.svg').is_file(): + ver=version or theme_store.latest(theme_id) + root=f'/api/factory/themes/automotive/preview' + html=html.replace('assets/auto-compiled.css',f'{root}.bundle.css?version={ver}') + html=html.replace('assets/auto-compiled.js',f'{root}.bundle.js?version={ver}') + html=html.replace('assets/auto-icons.svg#',f'{root}.icons.svg?version={ver}#') html=html.replace('assets/pro-base.css','/ui/pro-base.css').replace('assets/pro.js','/ui/pro.js').replace('assets/commercial.css','/ui/commercial.css') html=html.replace('assets/pro.css',f'/api/factory/themes/{theme_id}/preview.pro.css?version={version or theme_store.latest(theme_id)}') html=html.replace('assets/theme-overrides.css',f'/api/factory/themes/{theme_id}/preview.css?version={version or theme_store.latest(theme_id)}') diff --git a/app/main.py b/app/main.py index f3285a3..6bf2907 100644 --- a/app/main.py +++ b/app/main.py @@ -544,34 +544,10 @@ def editor_preview(site_id:str,entry_id:str,payload:BlueprintPayload): html=_re.sub(r']*>', '', html) html=_re.sub(r']*>', '', html) html=html.replace('','') - bridge = r'''''' + # External trusted bridge is injected only into the sandboxed editor preview; + # production/static builds never include authoring controls. + bridge_source=(ROOT/'app'/'static'/'studio-canvas-bridge.js').read_text(encoding='utf-8') + bridge='' # The static site's /media/ assets are hosted by the admin at # /local-media/{site}/. Rewrite only the editor response, never builds. html=html.replace('src="/media/',f'src="/local-media/{site_id}/') diff --git a/app/reusables.py b/app/reusables.py index 31a3060..21870a6 100644 --- a/app/reusables.py +++ b/app/reusables.py @@ -1,11 +1,39 @@ -"""Site-scoped reusable editor component library with versioned snapshots.""" +"""Versioned, site-scoped reusable blocks with opt-in, draft-only propagation. + +Published pages are NEVER rewritten by a shared-component update. A linked +instance is a validated, materialized block with shared_ref metadata. Updates +require a fresh preview token, exact page revision and an unmodified instance. +""" +from __future__ import annotations +import copy +import hashlib import json -from fastapi import APIRouter,Body,HTTPException,Request -from . import db,enterprise,blueprints +import re +import uuid +from fastapi import APIRouter, Body, HTTPException, Request +from . import db, enterprise, blueprints, studio_v86 from .core import uid router=APIRouter(prefix='/api/sites',tags=['Reusable Components']) + +def canonical(value): + return json.dumps(value,ensure_ascii=False,sort_keys=True,separators=(',',':')) + + +def _content(block): + """Content fingerprint independent of generated instance IDs and provenance.""" + def strip(item): + if isinstance(item,dict):return {k:strip(v) for k,v in item.items() if k not in ('id','shared_ref')} + if isinstance(item,list):return [strip(v) for v in item] + return item + return strip(block) + + +def fingerprint(block): + return hashlib.sha256(canonical(_content(block)).encode()).hexdigest() + + def setup(): with db.connect() as c: c.executescript('''CREATE TABLE IF NOT EXISTS reusable_components( @@ -13,41 +41,252 @@ def setup(): name TEXT NOT NULL,version INTEGER NOT NULL DEFAULT 1,block_json TEXT NOT NULL, updated_at TEXT NOT NULL); CREATE INDEX IF NOT EXISTS idx_reuse_site ON reusable_components(site_id); + CREATE TABLE IF NOT EXISTS reusable_component_versions( + component_id TEXT NOT NULL REFERENCES reusable_components(id) ON DELETE CASCADE, + version INTEGER NOT NULL,block_json TEXT NOT NULL,snapshot_hash TEXT NOT NULL, + created_at TEXT NOT NULL,PRIMARY KEY(component_id,version)); ''') + # Safe additive migration of old version-1 reusable blocks. + legacy=c.execute('SELECT id,version,block_json,updated_at FROM reusable_components').fetchall() + for row in legacy: + block=json.loads(row['block_json']) + c.execute('''INSERT INTO reusable_component_versions + (component_id,version,block_json,snapshot_hash,created_at) + VALUES(?,?,?,?,?) ON CONFLICT(component_id,version) DO NOTHING''', + (row['id'],row['version'],row['block_json'],fingerprint(block),row['updated_at'])) + + +def _component(site_id,component_id,c=None): + sql='SELECT * FROM reusable_components WHERE site_id=? AND id=?' + row=c.execute(sql,(site_id,component_id)).fetchone() if c else db.one(sql,(site_id,component_id)) + if not row:raise HTTPException(404,'本站组件不存在') + return dict(row) + + +def _validate_block(block): + try: + validated=blueprints.validate_blocks([block])[0] + except (ValueError,TypeError) as exc:raise HTTPException(400,str(exc)) + # A library source is an independent snapshot. Embedded source links are + # removed recursively; only insertion as a linked instance adds provenance. + def detach(node): + node.pop('shared_ref',None) + if node.get('type')=='layout': + for col in node.get('columns',[]): + for sub in col.get('blocks',[]):detach(sub) + detach(validated) + return validated + + +def _name(value): + name=str(value or '').strip() + if not name or len(name)>100:raise HTTPException(400,'组件名称需要1–100个字符') + return name + + +def versions(site_id,component_id): + _component(site_id,component_id) + rows=db.rows('''SELECT version,snapshot_hash,created_at FROM reusable_component_versions + WHERE component_id=? ORDER BY version DESC''',(component_id,)) + return {'items':rows} + @router.get('/{site_id}/components') def all_components(request:Request,site_id:str): enterprise.require(request,site_id,'viewer') - return [{**r,'block':json.loads(r.pop('block_json'))} for r in db.rows( - 'SELECT * FROM reusable_components WHERE site_id=? ORDER BY updated_at DESC',(site_id,))] + return [{**r,'block':json.loads(r['block_json']), 'snapshot_hash':fingerprint(json.loads(r['block_json']))} + for r in db.rows('SELECT * FROM reusable_components WHERE site_id=? ORDER BY updated_at DESC',(site_id,))] + @router.post('/{site_id}/components') def save_component(request:Request,site_id:str,payload:dict=Body(...)): enterprise.require(request,site_id,'editor') - name=str(payload.get('name','')).strip()[:100] - if not name:raise HTTPException(400,'组件名称不能为空') - try:block=blueprints.validate_blocks([payload.get('block')])[0] - except (ValueError,TypeError) as exc:raise HTTPException(400,str(exc)) - cid=uid() - db.insert('INSERT INTO reusable_components VALUES (?,?,?,?,?,?)', - (cid,site_id,name,1,json.dumps(block,ensure_ascii=False),db.now())) - return {'id':cid,'name':name,'version':1,'block':block} + name=_name(payload.get('name')) + block=_validate_block(payload.get('block')) + # Saved library snapshots must not retain a reference to a different component. + block.pop('shared_ref',None) + cid=uid();now=db.now();encoded=canonical(block);sha=fingerprint(block) + with db.connect() as c: + c.execute('INSERT INTO reusable_components VALUES (?,?,?,?,?,?)',(cid,site_id,name,1,encoded,now)) + c.execute('INSERT INTO reusable_component_versions VALUES (?,?,?,?,?)',(cid,1,encoded,sha,now)) + return {'id':cid,'name':name,'version':1,'block':block,'snapshot_hash':sha} + @router.put('/{site_id}/components/{component_id}') def update_component(request:Request,site_id:str,component_id:str,payload:dict=Body(...)): enterprise.require(request,site_id,'editor') - current=db.one('SELECT * FROM reusable_components WHERE site_id=? AND id=?',(site_id,component_id)) - if not current:raise HTTPException(404) - if payload.get('expected_version')!=current['version']:raise HTTPException(409,'组件已被修改,请重新加载') - try:block=blueprints.validate_blocks([payload.get('block')])[0] - except (ValueError,TypeError) as exc:raise HTTPException(400,str(exc)) - db.execute('UPDATE reusable_components SET name=?,block_json=?,version=?,updated_at=? WHERE id=? AND site_id=?', - (str(payload.get('name') or current['name'])[:100],json.dumps(block,ensure_ascii=False),current['version']+1,db.now(),component_id,site_id)) - return {'id':component_id,'version':current['version']+1} + block=_validate_block(payload.get('block'));block.pop('shared_ref',None) + with db.connect() as c: + row=_component(site_id,component_id,c) + rev=payload.get('expected_version') + if type(rev) is not int or rev!=row['version']:raise HTTPException(409,'组件版本已改变,请重新加载') + version=rev+1;name=_name(payload.get('name') if payload.get('name') is not None else row['name']) + encoded=canonical(block);now=db.now() + cur=c.execute('''UPDATE reusable_components SET name=?,block_json=?,version=?,updated_at=? + WHERE id=? AND site_id=? AND version=?''',(name,encoded,version,now,component_id,site_id,rev)) + if cur.rowcount!=1:raise HTTPException(409,'组件已由其他用户修改') + c.execute('INSERT INTO reusable_component_versions VALUES (?,?,?,?,?)', + (component_id,version,encoded,fingerprint(block),now)) + return {'id':component_id,'version':version,'snapshot_hash':fingerprint(block),'published_unchanged':True} + @router.delete('/{site_id}/components/{component_id}') def delete_component(request:Request,site_id:str,component_id:str): enterprise.require(request,site_id,'editor') - if not db.execute('DELETE FROM reusable_components WHERE site_id=? AND id=?',(site_id,component_id)): - raise HTTPException(404) + _component(site_id,component_id) + # Reject deletion while linked instances exist; preserve historical versions. + if _references(site_id,component_id):raise HTTPException(409,'组件仍被页面引用,请先解除引用') + db.execute('DELETE FROM reusable_components WHERE site_id=? AND id=?',(site_id,component_id)) return {'deleted':True} + + +@router.get('/{site_id}/components/{component_id}/versions') +def api_versions(request:Request,site_id:str,component_id:str): + enterprise.require(request,site_id,'viewer') + return versions(site_id,component_id) + + +@router.get('/{site_id}/components/{component_id}/versions/{version}') +def api_version(request:Request,site_id:str,component_id:str,version:int): + enterprise.require(request,site_id,'viewer') + _component(site_id,component_id) + row=db.one('SELECT * FROM reusable_component_versions WHERE component_id=? AND version=?',(component_id,version)) + if not row:raise HTTPException(404,'版本不存在') + block=json.loads(row['block_json']) + if fingerprint(block)!=row['snapshot_hash']:raise HTTPException(409,'历史快照完整性校验失败') + return {'version':version,'block':block,'snapshot_hash':row['snapshot_hash']} + + +def _walk(rows): + for block in rows: + yield block + if block.get('type')=='layout': + for col in block.get('columns',[]):yield from _walk(col.get('blocks',[])) + + +def _replace_in_tree(rows,block_id,replacement): + for i,block in enumerate(rows): + if block.get('id')==block_id: + rows[i]=replacement;return True + if block.get('type')=='layout': + for col in block.get('columns',[]): + if _replace_in_tree(col['blocks'],block_id,replacement):return True + return False + + +def _references(site_id,component_id): + # Bounded scan; site ownership is enforced at query boundary. + all_pages=db.rows('SELECT * FROM entries WHERE site_id=?',(site_id,)) + drafts={r['entry_id']:r for r in db.rows('SELECT * FROM studio_drafts WHERE site_id=?',(site_id,))} + found=[] + for page in all_pages: + draft=drafts.get(page['id']) + plan=json.loads(draft['blueprint_json']) if draft else json.loads(page['meta_json'] or '{}') + for block in _walk(plan.get('blocks',[])): + meta=block.get('shared_ref') + if isinstance(meta,dict) and meta.get('id')==component_id: + found.append({'entry_id':page['id'],'route':page['route'],'title':page['title'], + 'block_id':block['id'],'current_version':meta.get('version'), + 'local_modified':fingerprint(block)!=meta.get('hash'), + 'draft_revision':draft['revision'] if draft else 0, + 'base_hash':draft['base_hash'] if draft else studio_v86._hash(page), + 'has_draft':bool(draft),'conflict':bool(draft and draft['base_hash']!=studio_v86._hash(page))}) + return found + + +def _preview(site_id,component_id): + component=_component(site_id,component_id) + refs=_references(site_id,component_id) + for item in refs: + item['up_to_date']=item['current_version']==component['version'] + item['eligible']=not item['local_modified'] and not item['conflict'] and not item['up_to_date'] + item['reason']=('存在页面发布冲突' if item['conflict'] else '页面有本地修改' if item['local_modified'] + else '已是最新版' if item['up_to_date'] else '') + # Token includes all page revisions and instance fingerprints; replay of stale + # preview after any page or component changes is rejected. + proof={'component':component_id,'version':component['version'],'references':refs} + token=hashlib.sha256(canonical(proof).encode()).hexdigest() + return {'component':{'id':component_id,'name':component['name'],'version':component['version']}, + 'references':refs,'plan_token':token,'warning':'同步仅写入新草稿,不自动发布或部署'} + + +@router.get('/{site_id}/components/{component_id}/usage') +def api_usage(request:Request,site_id:str,component_id:str): + enterprise.require(request,site_id,'viewer') + return _preview(site_id,component_id) + + +def _copy_into(snapshot,original,component_id,version): + block=copy.deepcopy(snapshot) + def fresh(node,root=False): + node['id']=original['id'] if root else uuid.uuid4().hex[:10] + node.pop('shared_ref',None) + if node.get('type')=='layout': + for col in node.get('columns',[]): + for sub in col.get('blocks',[]):fresh(sub) + fresh(block,True) + block['shared_ref']={'id':component_id,'version':version,'hash':fingerprint(block)} + return block + + +@router.post('/{site_id}/components/{component_id}/sync') +def api_sync(request:Request,site_id:str,component_id:str,payload:dict=Body(...)): + enterprise.require(request,site_id,'editor') + selected=payload.get('entry_ids') + if not isinstance(selected,list) or not selected or len(selected)>100 or len(set(selected))!=len(selected) or any(not isinstance(s,str) for s in selected): + raise HTTPException(400,'选择1–100个不同页面') + preview=_preview(site_id,component_id) + if payload.get('plan_token')!=preview['plan_token']:raise HTTPException(409,'预检已过期,请重新查看引用页面') + chosen=set(selected) + available={r['entry_id'] for r in preview['references'] if r['eligible']} + if not chosen.issubset(available):raise HTTPException(409,'包含已修改、存在冲突或不可同步的页面') + component=_component(site_id,component_id) + current=blueprints.validate_blocks([json.loads(component['block_json'])])[0] + # Restrict to exactly one linked instance per page per request for now. + # When one page has multiple references, sync all eligible instances atomically. + updated=[] + expected_pages={r['entry_id']:(r['draft_revision'],r['base_hash']) for r in preview['references'] if r['entry_id'] in chosen} + with db.connect() as c: + # Lock the read/compare/write window. PostgreSQL uses an advisory + # transaction lock through the compatibility adapter. + c.execute('BEGIN IMMEDIATE') + newest=_component(site_id,component_id,c) + if newest['version']!=component['version']: + raise HTTPException(409,'组件源版本发生变化') + for entry_id in selected: + page=c.execute('SELECT * FROM entries WHERE site_id=? AND id=?',(site_id,entry_id)).fetchone() + if not page:raise HTTPException(409,'页面已删除,请重新预检') + draft=c.execute('SELECT * FROM studio_drafts WHERE site_id=? AND entry_id=?',(site_id,entry_id)).fetchone() + old_hash=studio_v86._hash(dict(page)) + expected_page_revision,expected_base=expected_pages[entry_id] + if expected_base!=old_hash or (draft['revision'] if draft else 0)!=expected_page_revision: + raise HTTPException(409,'页面版本已变化,重新预检后同步') + if draft and draft['base_hash']!=old_hash:raise HTTPException(409,'页面内容已变化') + plan=json.loads(draft['blueprint_json']) if draft else { + 'blocks':json.loads(page['meta_json'] or '{}').get('blocks',[]), + 'page_template':json.loads(page['meta_json'] or '{}').get('page_template','home' if page['route']=='/' else 'standard'), + 'layout_mode':json.loads(page['meta_json'] or '{}').get('layout_mode','append')} + did=0 + for block in list(_walk(plan['blocks'])): + ref=block.get('shared_ref') + if isinstance(ref,dict) and ref.get('id')==component_id: + if fingerprint(block)!=ref.get('hash') or ref.get('version')==component['version']: + raise HTTPException(409,'引用发生变化,请重新预检') + if not _replace_in_tree(plan['blocks'],block['id'],_copy_into(current,block,component_id,component['version'])): + raise HTTPException(409,'组件位置发生变化') + did+=1 + if not did:raise HTTPException(409,'页面已经没有组件引用') + plan=studio_v86._validate(plan) + expected=draft['revision'] if draft else 0 + rev=expected+1 + if draft: + cur=c.execute('''UPDATE studio_drafts SET revision=?,blueprint_json=?,updated_at=? + WHERE site_id=? AND entry_id=? AND revision=? AND base_hash=?''', + (rev,canonical(plan),db.now(),site_id,entry_id,expected,draft['base_hash'])) + if cur.rowcount!=1:raise HTTPException(409,'草稿并发冲突') + else: + c.execute('INSERT INTO studio_drafts VALUES (?,?,?,?,?,?)', + (site_id,entry_id,rev,old_hash,canonical(plan),db.now())) + studio_v86._journal(c,site_id,entry_id,rev,'draft',plan,enterprise.actor(request)) + updated.append({'entry_id':entry_id,'revision':rev,'instances':did}) + return {'updated':updated,'published_unchanged':True,'build_required_after_publish':True} diff --git a/app/site_design_v87.py b/app/site_design_v87.py index f8b6fae..e74dcf5 100644 --- a/app/site_design_v87.py +++ b/app/site_design_v87.py @@ -198,9 +198,10 @@ def write(site_id,payload): (site_id,revision+1,base,json.dumps(plan,ensure_ascii=False),db.now())) return {'saved':True,'state':'draft','revision':revision+1,'build_unchanged':True} -def publish(site_id,expected_revision,actor): +def publish(site_id,expected_revision,actor,expected_plan_token=None): site=_site(site_id) with db.connect() as c: + c.execute('BEGIN IMMEDIATE') draft=c.execute('SELECT * FROM site_design_drafts WHERE site_id=?',(site_id,)).fetchone() if not draft:raise HTTPException(409,'尚无全站设计草稿') if type(expected_revision) is not int or expected_revision!=draft['revision']: @@ -210,6 +211,10 @@ def publish(site_id,expected_revision,actor): if draft['base_hash']!=_hash(settings):raise HTTPException(409,'网站信息已变更,请重新审核') before=published(settings) config=validate(json.loads(draft['config_json'])) + if expected_plan_token is not None: + proof=_review_token(site_id,draft['revision'],settings,config) + if not isinstance(expected_plan_token,str) or not __import__('hmac').compare_digest(expected_plan_token,proof): + raise HTTPException(409,'审核预览已过期,请重新查看差异后确认') settings['site_design']=config settings['design_tokens']=config['tokens'] # Keep old nav/settings for non-professional legacy templates too. @@ -223,6 +228,87 @@ def publish(site_id,expected_revision,actor): c.execute('DELETE FROM site_design_drafts WHERE site_id=?',(site_id,)) return {'published':True,'publication_id':publication_id,'build_required':True} +# V8.26 - reviewable, immutable full-site design changes. This workflow uses +# the existing site_design_drafts/publications tables: no destructive migration. +REVIEW_SECTIONS = ('header', 'nav', 'footer', 'mobile_tabs', 'tokens', 'responsive') + + +def _changes(before, after): + """Return a bounded, deterministic, safe structured diff for human review.""" + old, new = validate(before), validate(after) + rows = [] + def inspect(path, a, b): + if a == b: + return + if isinstance(a, dict) and isinstance(b, dict): + for key in sorted(set(a) | set(b)): + inspect(path + '.' + key, a.get(key), b.get(key)) + elif isinstance(a, list) and isinstance(b, list): + # Lists (menu order) are atomic to avoid obscuring a move as deletes. + rows.append({'field': path, 'before': a, 'after': b}) + else: + rows.append({'field': path, 'before': a, 'after': b}) + for section in REVIEW_SECTIONS: + inspect(section, old[section], new[section]) + return rows + + +def _review_token(site_id, revision, live_settings, draft_config): + payload={'site_id':site_id,'revision':revision, + 'settings_hash':_hash(live_settings), 'draft':validate(draft_config)} + return hashlib.sha256(json.dumps(payload,ensure_ascii=False, + sort_keys=True,separators=(',',':')).encode()).hexdigest() + + +def review(site_id): + with db.connect() as c: + site=c.execute('SELECT settings_json FROM sites WHERE id=?',(site_id,)).fetchone() + if not site:raise HTTPException(404,'网站不存在') + draft=c.execute('SELECT * FROM site_design_drafts WHERE site_id=?',(site_id,)).fetchone() + if not draft:raise HTTPException(409,'没有待审核的全站设计草稿') + settings=json.loads(site['settings_json'] or '{}') + if draft['base_hash']!=_hash(settings):raise HTTPException(409,'网站设置已经修改,请先处理草稿冲突') + proposed=validate(json.loads(draft['config_json'])) + delta=_changes(published(settings),proposed) + sections=[name for name in REVIEW_SECTIONS if any( + r['field']==name or r['field'].startswith(name+'.') for r in delta)] + return {'revision':draft['revision'], 'changed_fields':delta, + 'changed_sections':sections, 'change_count':len(delta), + 'affected_scope':'entire_site_next_build', + 'published_site_unchanged':True, + 'plan_token':_review_token(site_id,draft['revision'],settings,proposed)} + + +def restore_publication(site_id,publication_id,which,expected_revision,expected_live_hash): + """Restore a historical snapshot as a NEW draft, never touch live settings.""" + if which not in ('before','after'):raise HTTPException(400,'恢复来源仅支持 before 或 after') + if type(expected_revision) is not int:raise HTTPException(400,'需要草稿版本号') + if not isinstance(expected_live_hash,str) or len(expected_live_hash)!=64: + raise HTTPException(400,'需要当前全站发布版本指纹') + with db.connect() as c: + c.execute('BEGIN IMMEDIATE') + site=c.execute('SELECT settings_json FROM sites WHERE id=?',(site_id,)).fetchone() + if not site:raise HTTPException(404,'网站不存在') + historic=c.execute('SELECT * FROM site_design_publications WHERE site_id=? AND id=?', + (site_id,publication_id)).fetchone() + if not historic:raise HTTPException(404,'发布记录不存在') + settings=json.loads(site['settings_json'] or '{}') + live_hash=_hash(settings) + if live_hash!=expected_live_hash:raise HTTPException(409,'全站发布版本已变化,请重新载入') + raw=historic['old_config_json'] if which=='before' else historic['new_config_json'] + plan=validate(json.loads(raw)) + old=c.execute('SELECT revision FROM site_design_drafts WHERE site_id=?',(site_id,)).fetchone() + current=old['revision'] if old else 0 + if expected_revision!=current:raise HTTPException(409,'草稿版本已变化,请重新加载') + new_rev=current+1 + c.execute('INSERT INTO site_design_drafts(site_id,revision,base_hash,config_json,updated_at) ' + 'VALUES(?,?,?,?,?) ON CONFLICT(site_id) DO UPDATE SET ' + 'revision=excluded.revision,base_hash=excluded.base_hash, ' + 'config_json=excluded.config_json,updated_at=excluded.updated_at', + (site_id,new_rev,live_hash,json.dumps(plan,ensure_ascii=False),db.now())) + return {'restored_as_draft':True,'revision':new_rev,'published_unchanged':True} + + def responsive_css(config): r=validate(config)['responsive'] tablet=r['tablet_gap'];mobile=r['mobile_gap'];padding=r['mobile_container_padding'] @@ -276,3 +362,41 @@ def api_history(request:Request,site_id:str): _site(site_id) return db.rows('''SELECT id,site_id,actor,revision,published_at FROM site_design_publications WHERE site_id=? ORDER BY published_at DESC LIMIT 50''',(site_id,)) + +@router.get('/{site_id}/site-design/review') +def api_review(request:Request,site_id:str): + enterprise.require(request,site_id,'viewer') + return review(site_id) + + +@router.post('/{site_id}/site-design/publish-reviewed') +def api_publish_reviewed(request:Request,site_id:str,payload:dict=Body(...)): + enterprise.require(request,site_id,'owner') + return publish(site_id,payload.get('expected_revision'),enterprise.actor(request), + payload.get('plan_token','')) + + +@router.get('/{site_id}/site-design/publications/{publication_id}') +def api_publication(request:Request,site_id:str,publication_id:str): + enterprise.require(request,site_id,'viewer') + _site(site_id) + row=db.one('SELECT * FROM site_design_publications WHERE site_id=? AND id=?', + (site_id,publication_id)) + if not row:raise HTTPException(404,'发布版本不存在') + old=validate(json.loads(row['old_config_json'])) + new=validate(json.loads(row['new_config_json'])) + return {'id':row['id'],'published_at':row['published_at'],'actor':row['actor'], + 'before':old,'after':new,'changes':_changes(old,new)} + + +@router.get('/{site_id}/site-design/live-hash') +def api_live_hash(request:Request,site_id:str): + enterprise.require(request,site_id,'viewer') + return {'live_hash':_hash(_settings(_site(site_id)))} + + +@router.post('/{site_id}/site-design/publications/{publication_id}/restore') +def api_restore_publication(request:Request,site_id:str,publication_id:str,payload:dict=Body(...)): + enterprise.require(request,site_id,'editor') + return restore_publication(site_id,publication_id,payload.get('snapshot'), + payload.get('expected_revision'),payload.get('expected_live_hash')) diff --git a/app/static/auto31.js b/app/static/auto31.js new file mode 100644 index 0000000..ed2e30f --- /dev/null +++ b/app/static/auto31.js @@ -0,0 +1 @@ +'use strict';(()=>{document.querySelectorAll('.auto31-search').forEach(form=>{form.addEventListener('submit',()=>{const input=form.querySelector('input[name=q]');if(input)input.value=input.value.trim().slice(0,120);});});})(); diff --git a/app/static/editor-helpers.js b/app/static/editor-helpers.js index f0db99e..ba4d43a 100644 --- a/app/static/editor-helpers.js +++ b/app/static/editor-helpers.js @@ -35,5 +35,119 @@ function shouldAcceptPreview(requestedPage,requestedSeq,currentPage,currentSeq){ return requestedPage===currentPage&&requestedSeq===currentSeq; } - return {reorder,duplicate,filterBlocks,historyState,clampNumber,shouldAcceptPreview}; + function findTopIndex(rows,id){return Array.isArray(rows)&&typeof id==='string'?rows.findIndex(b=>b.id===id):-1;} + function reorderById(rows,sourceId,targetId){ + const from=findTopIndex(rows,sourceId),to=findTopIndex(rows,targetId); + return from<0||to<0||from===to?null:reorder(rows,from,to); + } + function adjacentWidths(block,widths){ + if(!block||block.type!=='layout'||!Array.isArray(block.columns)||!Array.isArray(widths)||widths.length!==block.columns.length)return null; + const validated=widths.map(v=>Number(v)); + if(validated.some(v=>!Number.isFinite(v)||v<.5||v>4))return null; + // Keep the same type and field shape expected by blueprints.validate_blocks. + return validated.map(v=>Math.round(v*100)/100); + } + function safeCanvasCommand(command,rows,types){ + if(!command||typeof command!=='object'||typeof command.blockId!=='string'||command.blockId.length>150)return false; + const i=findTopIndex(rows,command.blockId); + if(i<0)return false; + const actions=['select','edit','up','down','add-after','duplicate','delete','reorder','resize-columns','inline-text']; + if(!actions.includes(command.action))return false; + if(command.action==='reorder')return findTopIndex(rows,command.targetId)>=0; + if(command.action==='resize-columns')return !!adjacentWidths(rows[i],command.widths); + if(command.action==='inline-text')return (command.field==='title'||command.field==='description')&& + typeof command.value==='string'&&command.value.length<=500&&types?.[rows[i].type]?.fields?.includes(command.field); + return true; + } + // V8.24: resolve the actual parent of a nested child from the validated tree. + // A client message supplies stable IDs, never trusted indexes or an editable path. + // Renderer accepts at most two layout levels; a bounded walk avoids malformed cycles. + function findNestedChild(rows,parentId,childId){ + if(typeof parentId!=='string'||typeof childId!=='string'||!Array.isArray(rows)|| + !parentId||!childId||parentId===childId)return null; + for(let rootIndex=0;rootIndex2)return null; + for(let ci=0;ci2)return null; + for(const col of layout.columns||[]){ + for(const child of col.blocks||[]){ + if(child?.id===childId)return findNestedChild(rows,layout.id,childId); + if(child?.type==='layout'){ + const match=visit(child,depth+1); + if(match)return match; + } + } + } + return null; + } + return visit(root,0); + } + function findLayout(rows,layoutId){ + if(typeof layoutId!=='string'||!Array.isArray(rows))return null; + const topIndex=findTopIndex(rows,layoutId); + if(topIndex>=0)return rows[topIndex].type==='layout'?{layout:rows[topIndex],rootIndex:topIndex,depth:0}:null; + for(let i=0;i4)return null; + if(preset==='equal')return Array(count).fill(1); + if(count!==2)return null; + if(preset==='left-wide')return [2,1]; + if(preset==='right-wide')return [1,2]; + return null; + } + function moveNested(block,columnIndex,childIndex,direction){ + if(!block||block.type!=='layout'||![-1,1].includes(direction))return null; + const list=block.columns?.[columnIndex]?.blocks; + return Array.isArray(list)?reorder(list,childIndex,childIndex+direction):null; + } + return {reorder,duplicate,filterBlocks,historyState,clampNumber,shouldAcceptPreview,findTopIndex,reorderById,adjacentWidths,safeCanvasCommand,findNestedChild,findChildInRoot,findLayout,safeNestedCanvasCommand,layoutPreset,moveNested}; }); diff --git a/app/static/editor.css b/app/static/editor.css index 1701094..047c1cd 100644 --- a/app/static/editor.css +++ b/app/static/editor.css @@ -88,3 +88,71 @@ iframe{min-height:590px;height:calc(100vh - 224px)} /* Accessible repeated-item forms for galleries, carousels, FAQs and features */ .sf-array-editor{display:grid;gap:10px}.sf-array-hint{font-size:11px;line-height:1.6;color:#8391a3;margin:0 0 4px}.sf-array-card{border:1px solid #e5eaf0;background:#fafbfd;padding:11px;border-radius:10px}.sf-array-card-head{display:flex;align-items:center;justify-content:space-between;gap:7px;margin-bottom:12px}.sf-array-card-head b{font-size:12px;color:#586a7f}.sf-array-card-head div{display:flex;gap:3px}.sf-array-card-head button{border:1px solid #e2e7ed;border-radius:5px;color:#6c7a8e;background:white;padding:4px 7px;font-size:11px}.sf-array-card-head button:last-child{color:#b95d62}.sf-array-card-head button:disabled{opacity:.3;cursor:not-allowed}.sf-array-field{display:block!important;margin:10px 0!important;font-size:11px!important;font-weight:650!important}.sf-array-field input,.sf-array-field textarea{display:block;width:100%;margin-top:5px;background:white}.sf-array-field textarea{min-height:65px}.sf-array-add{border:1px dashed #e5a77c;border-radius:9px;background:#fff8f2;color:#be672a;padding:13px 9px;font-size:12px;font-weight:800} + +/* V8.22 canvas-level authoring with no change to published templates */ +.sf-insert-hint{margin:8px 12px;padding:10px 12px;background:#fff3e8;color:#aa5525;font-size:12px;border:1px solid #f0bd98;border-radius:9px;line-height:1.6} +.sf-insert-hint[hidden]{display:none!important} +.preview-head .preview-note{max-width:350px;font-size:11px;color:#67778b} +#sitePreview:focus-visible{outline:2px solid #e77b37;outline-offset:2px} + +/* V8.23 child-first layout inspector */ +.sf-nested-edit{margin:5px 0 20px;display:grid;gap:9px}.sf-nested-card{border:1px solid #e3e9f0;border-radius:10px;padding:10px;background:#fbfcfd}.sf-nested-card.active{border-color:#42a8b9;background:#f2fbfd}.sf-nested-heading{display:flex;align-items:center;justify-content:space-between;gap:6px}.sf-nested-heading>button{border:0;background:none;font-size:12px;color:#36556e;font-weight:750;text-align:left;cursor:pointer}.sf-nested-heading span{display:flex;gap:4px}.sf-nested-heading span button,.sf-nested-actions button{border:1px solid #d8e4eb;background:white;border-radius:6px;padding:5px 9px;color:#36556e;cursor:pointer}.sf-nested-heading button:disabled{opacity:.3;cursor:not-allowed}.sf-nested-field{display:block;margin:10px 0;color:#536477;font-size:12px}.sf-nested-field input{display:block;margin-top:6px;width:100%;padding:10px;border:1px solid #d7e3e9;border-radius:7px;font-size:12px}.sf-nested-actions{display:flex;gap:6px;margin:10px 0 2px}.sf-nested-actions button:last-child{color:#b44549}.sf-layout-presets{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:6px;margin:9px 0 18px}.sf-layout-presets button{white-space:normal;padding:10px 5px;border:1px solid #e5b995;border-radius:8px;background:#fff8f3;color:#945325;font-size:11px;cursor:pointer}.sf-layout-presets button:disabled{opacity:.4;cursor:not-allowed} + +/* V8.25: friendly shared-component management, scoped to editor only. */ +.sf-shared-palette-row{border:1px solid #e4e8ef;background:white;border-radius:9px;padding:10px;display:grid;gap:8px;font-size:12px} +.sf-shared-palette-row strong{display:flex;justify-content:space-between;gap:7px} +.sf-shared-palette-row small{color:#8594a8} +.sf-shared-palette-row>div{display:flex;gap:7px} +.sf-shared-palette-row button,.sf-shared-actions button{border:1px solid #e0e4e9;border-radius:7px;background:#fff;padding:7px 9px;cursor:pointer;color:#364759} +.sf-shared-palette-row button:last-child{background:#fff3e8;color:#b95a23;border-color:#eac7ae} +.sf-shared-dialog{width:min(780px,96vw);max-height:88vh;overflow:auto;border:1px solid #e3e7ec;border-radius:16px;padding:24px;box-shadow:0 20px 60px #263a5430;color:#334155} +.sf-shared-dialog::backdrop{background:#0e203b70} +.sf-shared-dialog-head{display:flex;align-items:center;justify-content:space-between;gap:12px} +.sf-shared-dialog h2{margin:5px 0 12px;font-size:22px}.sf-shared-dialog h3{margin:18px 0 10px} +.sf-shared-card{display:flex;justify-content:space-between;gap:14px;border:1px solid #e3e8ee;border-radius:10px;padding:13px;margin:10px 0;align-items:center} +.sf-shared-card>div:first-child{display:grid;gap:4px}.sf-shared-card small,.sf-shared-usage small{display:block;color:#64748b;font-size:11px;margin-top:5px} +.sf-shared-actions{display:flex;flex-wrap:wrap;gap:6px} +.sf-shared-usage{display:flex;align-items:center;gap:12px;padding:12px;border:1px solid #e2e7ed;border-radius:9px;margin:7px 0;cursor:pointer} +.sf-shared-usage:has(input:disabled){opacity:.6;cursor:not-allowed} +#sharedComponentDetail{margin-top:22px;border-top:1px solid #e2e7ed;padding-top:12px} +#sharedComponentDetail>.ui-btn{margin-top:14px} +@media(max-width:700px){.sf-shared-card{display:grid}.sf-shared-dialog{padding:15px}} + +.sf-share-info{border:1px solid #f0cfb5;background:#fff8f1;padding:13px;border-radius:10px;margin:12px 0;color:#955023;font-size:12px}.sf-share-info p{line-height:1.5} + +.sf-shared-history{display:flex;justify-content:space-between;align-items:center;gap:10px;border-bottom:1px solid #edf0f4;padding:10px 0;font-size:12px;flex-wrap:wrap} + +/* V8.26 global design navigation, review and restoration */ +.sf-visual-nav{padding:15px;border:1px solid #e2e8f0;border-radius:12px;background:#fafcff} +.sf-visual-nav-header{display:flex;flex-wrap:wrap;justify-content:space-between;gap:8px;margin-bottom:12px} +.sf-visual-nav-header span,.sf-visual-nav-help{font-size:12px;color:#64748b} +.sf-nav-item{padding:8px;margin-bottom:6px;border:1px solid #dde5ed;background:#fff;border-radius:10px;display:flex;align-items:center;flex-wrap:wrap;gap:6px} +.sf-nav-item input{min-width:100px;flex:1 1 135px;padding:8px;border:1px solid #cbd5e1;border-radius:7px} +.sf-nav-action{font-size:12px!important;padding:6px 9px!important} +.sf-global-review{width:min(720px,95vw);max-height:85vh;overflow:auto;border:1px solid #dce5ed;border-radius:16px;padding:24px;box-shadow:0 18px 54px #132c4540} +.sf-review-change{padding:12px;border:1px solid #dfe6ee;border-radius:10px;margin:9px 0;background:#f9fbfe;overflow-wrap:anywhere} +.sf-review-change p{font-size:12px;color:#64748b;margin:7px 0;white-space:pre-wrap} +.sf-review-buttons{display:flex;justify-content:flex-end;gap:10px;margin-top:16px} +@media(max-width:600px){.sf-nav-item{margin-left:0!important}.sf-global-review{padding:16px}} + +.sf-global-entry{display:flex;flex-direction:column;gap:6px;padding:12px;border:1px solid #f1d7bf;border-radius:10px;background:#fffaf5;margin-bottom:12px}.sf-global-entry button{font-weight:650;text-align:left}.sf-global-entry small{color:#876c56;font-size:11px} + +/* V8.29: discoverable content palette and safe theme comparison */ +.sf-palette-filter{display:flex;gap:6px;margin:12px 13px 6px}.sf-palette-filter input{min-width:0;flex:1;border:1px solid #d8e2ed;border-radius:9px;padding:10px;font-size:12px}.sf-palette-filter button{border:1px solid #dee6ee;border-radius:8px;background:#f7f9fc;color:#53657a;font-size:11px;padding:0 9px}.sf-palette-summary{font-size:11px;color:#657487;padding:2px 14px 9px}.sf-palette-categories{display:block;padding:0 12px 12px}.sf-palette-group{margin-bottom:12px}.sf-palette-group h4{font-size:12px;color:#4a5870;margin:6px 3px 9px;font-weight:700}.sf-palette-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.sf-palette-grid button{min-height:54px;border:1px solid #e3e9ef;background:white;padding:10px;border-radius:10px;display:flex;gap:8px;align-items:center;text-align:left;color:#35445b;font-size:12px;font-weight:600;line-height:1.4;cursor:pointer}.sf-palette-grid button:hover{background:#fff6ee;border-color:#e8a576}.sf-palette-grid button span{font-size:18px;flex-shrink:0;color:#b9652f}.sf-palette-empty{font-size:12px;color:#697b90;padding:10px}.sf-history-quick{border:1px solid #e0e6ed;background:white;color:#49596a;border-radius:8px;min-width:32px;height:34px;font-size:20px;cursor:pointer}.sf-history-quick:disabled{opacity:.35;cursor:not-allowed}.sf-theme-preview-entry{white-space:nowrap;color:#43576d}.sf-theme-showcase{width:min(1150px,96vw);height:min(94vh,900px);max-height:94vh;border:1px solid #dce3eb;border-radius:17px;overflow:auto;background:white;padding:0;box-shadow:0 25px 80px #10284148}.sf-theme-showcase::backdrop{background:#1424389c}.sf-showcase-head{display:flex;justify-content:space-between;align-items:start;gap:16px;padding:20px 24px 13px;border-bottom:1px solid #e5eaf0}.sf-showcase-head small{color:#b65c2d;font-weight:700}.sf-showcase-head h2{font-size:21px;margin:7px 0}.sf-showcase-head p{font-size:12px;color:#697b90;margin:0}.sf-showcase-tools{display:flex;gap:12px;align-items:end;flex-wrap:wrap;padding:14px 24px}.sf-showcase-tools label{display:grid;gap:5px;font-size:12px;font-weight:600;color:#43566c}.sf-showcase-tools select{border:1px solid #dce3ed;border-radius:8px;padding:9px 14px;min-width:145px;background:white}.sf-showcase-device{display:flex;gap:5px;margin-left:auto;background:#eef2f6;border-radius:8px;padding:4px}.sf-showcase-device button{padding:8px 12px;border:0;background:transparent;color:#596b7e;border-radius:6px;cursor:pointer}.sf-showcase-device button[aria-pressed=true]{background:#fff;color:#ad5c28;box-shadow:0 1px 6px #122c4419;font-weight:700}.sf-showcase-status{margin:0 24px 10px;color:#64748b;font-size:12px}.sf-showcase-stage{height:min(55vh,520px);overflow:auto;background:#eef1f5;padding:15px;display:flex;align-items:stretch;justify-content:center}.sf-showcase-frame{min-width:0;max-width:100%;height:100%;transition:width .18s ease;background:white;box-shadow:0 9px 30px #21334c20}.sf-showcase-frame iframe{display:block;width:100%;height:100%;min-height:0;border:0;background:white}.sf-showcase-footer{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:14px 24px;border-top:1px solid #e5eaf0}.sf-showcase-footer span{color:#718195;font-size:12px}.sf-theme-showcase button:focus-visible,.sf-theme-showcase select:focus-visible,.sf-palette-filter input:focus-visible,.sf-history-quick:focus-visible{outline:3px solid #eeab77;outline-offset:2px}@media(max-width:1100px){.sf-theme-preview-entry{font-size:11px;padding:8px!important}}@media(max-width:700px){.sf-theme-preview-entry{font-size:0;min-width:32px;padding:6px!important}.sf-theme-preview-entry::before{content:'◫';font-size:17px}.sf-showcase-head,.sf-showcase-tools,.sf-showcase-footer{padding:12px}.sf-showcase-stage{height:55vh;padding:8px}.sf-showcase-footer{flex-direction:column;align-items:start}.sf-showcase-device{margin-left:0}}@media(prefers-reduced-motion:reduce){.sf-showcase-frame{transition:none}} + +.sf-style-presets{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:6px;margin:9px 0 17px}.sf-style-presets button{border:1px solid #dae2eb;border-radius:9px;background:#fff;padding:10px 5px;min-height:48px;font-size:11px;color:#364459;cursor:pointer}.sf-style-presets button:nth-child(2){background:#f0f3f8}.sf-style-presets button:nth-child(3){background:#26374d;color:#fff}.sf-style-presets button:focus-visible{outline:3px solid #efa971;outline-offset:2px} +/* Prevent translated, closed inspector drawers from widening the mobile viewport. */ +@media(max-width:1060px){html,body{max-width:100%;overflow-x:clip}} +/* V8.29 mobile authoring: two deliberate toolbar rows, never horizontal-scrolling actions. */ +@media(max-width:720px){ + .studio-top.sf-easy-top{height:auto;min-height:100px;flex-wrap:wrap;justify-content:space-between;align-content:center;padding:7px 9px;gap:5px} + .studio-top.sf-easy-top .brand,.studio-top.sf-easy-top .file-name,.studio-top.sf-easy-top .sf-history-quick,.studio-top.sf-easy-top .sf-theme-preview-entry{display:none!important} + .studio-top.sf-easy-top .sf-pane-controls{order:1;flex:0 0 auto} + .studio-top.sf-easy-top #saveDraftButton{order:2;flex:0 0 auto} + .studio-top.sf-easy-top #publishDesignButton{order:3;flex:0 0 auto} + .studio-top.sf-easy-top .studio-actions{order:4;flex:0 0 auto} + .studio-top.sf-easy-top .sf-easy-device{order:5;flex:1 1 100%;display:flex;justify-content:center;margin:0} + .studio-top.sf-easy-top .sf-easy-device .icon-btn{flex:1;max-width:115px} + .studio-body .left-pane,.studio-body .right-pane{top:140px!important} + .studio-actions-menu{right:0;max-width:calc(100vw - 18px)} +} diff --git a/app/static/editor.js b/app/static/editor.js index 6e45c85..723ce5d 100644 --- a/app/static/editor.js +++ b/app/static/editor.js @@ -10,19 +10,296 @@ const toast=(s,err=false)=>{const t=$('#toast');t.textContent=s;t.style.backgrou const activePage=()=>pages.find(e=>e.id===pageId); const editorTools=window.SiteForgeEditorHelpers; let libraryOpen=false; -let inspectorTab='content',blockSearch='',previewRequest=0,previewController=null,savePromise=null,lastContinuousEdit=0; +let sharedPreview=null; +let siteNavDraft=[],siteDesignReviewToken=null; +let selectedChildId=null; +let inspectorTab='content',paletteSearch='',blockSearch='',previewRequest=0,previewController=null,savePromise=null,lastContinuousEdit=0,insertAfterId=null; let snapshots=[],snapshotCursor=-1,draggedChild=null,draftRevision=0,siteDesign=null,siteDesignRevision=0,siteDesignPreview=null; function recordSnapshot(){const current=JSON.stringify({blocks,kind,layoutMode});if(snapshotCursor>=0 && snapshots[snapshotCursor]===current)return;snapshots=snapshots.slice(0,snapshotCursor+1);snapshots.push(current);if(snapshots.length>75)snapshots.shift();snapshotCursor=snapshots.length-1} -function restoreSnapshot(index){if(index<0||index>=snapshots.length)return;snapshotCursor=index;const state=JSON.parse(snapshots[index]);blocks=state.blocks;kind=state.kind;layoutMode=state.layoutMode;selected=Math.min(selected,blocks.length-1);$('#pageTemplate').value=kind;$('#layoutMode').value=layoutMode;dirty=true;$('#saveStatus').textContent='未保存更改';$('#saveStatus').classList.add('dirty');Studio.updateHistoryButtons();Studio.draw();Studio.refreshPreview()} +function restoreSnapshot(index){if(index<0||index>=snapshots.length)return;snapshotCursor=index;const state=JSON.parse(snapshots[index]);blocks=state.blocks;kind=state.kind;layoutMode=state.layoutMode;selected=Math.min(selected,blocks.length-1);selectedChildId=null;$('#pageTemplate').value=kind;$('#layoutMode').value=layoutMode;dirty=true;$('#saveStatus').textContent='未保存更改';$('#saveStatus').classList.add('dirty');Studio.updateHistoryButtons();Studio.draw();Studio.refreshPreview()} const Studio={ + highlightCanvas(){const block=blocks[selected];const frame=$('#sitePreview');if(block&&frame?.contentWindow)frame.contentWindow.postMessage({source:'siteforge-studio-host',action:'highlight',blockId:block.id,childId:selectedChildId},'*')}, + showInsertHint(){const box=$('#sfInsertHint');if(!box)return;const item=blocks.find(x=>x.id===insertAfterId);box.hidden=!item;box.textContent=item?'正在「'+(item.title||schema?.blocks[item.type]?.name||'当前区块')+'」下方插入:选择一种内容。':''}, + beginAddAfter(blockId){if(editorTools.findTopIndex(blocks,blockId)<0)return;insertAfterId=blockId;Studio.showInsertHint();Studio.toggleLibrary(true);document.body.classList.add('show-structure');document.body.classList.remove('show-inspector');$('#sfAddBlock').scrollIntoView({behavior:'smooth',block:'nearest'})}, + canvasCommand(command){ + if(String(command?.action||'').startsWith('child-')){Studio.childCanvasCommand(command);return;} + if(command?.action==='resize-columns'){ + const nestedLayout=editorTools.findLayout(blocks,command.blockId); + if(!nestedLayout)return; + const widths=editorTools.adjacentWidths(nestedLayout.layout,command.widths); + if(!widths)return; + if(nestedLayout.layout.columns.every((c,k)=>Math.abs(c.width-widths[k])<.001))return; + nestedLayout.layout.columns.forEach((c,k)=>c.width=widths[k]); + selected=nestedLayout.rootIndex; + selectedChildId=nestedLayout.depth?command.blockId:null; + Studio.modified();Studio.draw();return; + } + if(!editorTools.safeCanvasCommand(command,blocks,schema.blocks))return; + const i=editorTools.findTopIndex(blocks,command.blockId),block=blocks[i]; + if(command.action==='select'||command.action==='edit'){Studio.select(i);if(command.action==='edit'){inspectorTab='content';Studio.applyInspectorTab();}return;} + if(command.action==='up'||command.action==='down'){Studio.moveBlock(i,command.action==='up'?-1:1);return;} + if(command.action==='add-after'){Studio.beginAddAfter(command.blockId);return;} + if(command.action==='duplicate'){Studio.duplicate(i);return;} + if(command.action==='delete'){Studio.remove(i);return;} + if(command.action==='reorder'){ + const to=editorTools.findTopIndex(blocks,command.targetId); + const next=editorTools.reorderById(blocks,command.blockId,command.targetId); + if(!next)return;blocks=next;selected=to;Studio.modified();Studio.draw();return; + } + if(command.action==='resize-columns'){ + const widths=editorTools.adjacentWidths(block,command.widths); + if(!widths)return; + if(block.columns.every((c,k)=>Math.abs(c.width-widths[k])<.001))return; + block.columns.forEach((col,j)=>col.width=widths[j]);selected=i; + Studio.modified();Studio.inspector();return; + } + if(command.action==='inline-text'){ + if(block[command.field]===command.value)return; + block[command.field]=command.value;selected=i;Studio.modified();Studio.draw(); + toast('文字已修改,记得保存草稿'); + } + }, + childCanvasCommand(command){ + if(!editorTools.safeNestedCanvasCommand(command,blocks,schema.blocks))return; + const found=editorTools.findNestedChild(blocks,command.blockId,command.childId); + if(!found)return; + const {parentIndex,parent,columnIndex,childIndex,child}=found; + if(command.action==='child-select'||command.action==='child-edit'){ + selected=parentIndex;selectedChildId=child.id;inspectorTab='content';Studio.draw();Studio.highlightCanvas(); + const card=document.querySelector('#sf-nested-active');card?.scrollIntoView({block:'nearest'}); + if(window.matchMedia('(max-width:1060px)').matches)document.body.classList.add('show-inspector'); + return; + } + if(command.action==='child-inline-text'){ + if(child[command.field]===command.value)return; + child[command.field]=command.value;selected=parentIndex;selectedChildId=child.id; + Studio.modified();Studio.draw();return; + } + if(command.action==='child-delete'){ + if(!confirm('确定删除这一列中的组件?'))return; + parent.columns[columnIndex].blocks.splice(childIndex,1);selectedChildId=null; + }else if(command.action==='child-duplicate'){ + const copy=editorTools.duplicate(child,()=>crypto.randomUUID().replace(/-/g,'').slice(0,10)); + parent.columns[columnIndex].blocks.splice(childIndex+1,0,copy);selectedChildId=copy.id; + }else{ + const next=editorTools.moveNested(parent,columnIndex,childIndex,command.action==='child-up'?-1:1); + if(!next)return;parent.columns[columnIndex].blocks=next;selectedChildId=child.id; + } + selected=parentIndex;Studio.modified();Studio.draw(); + }, + setLayoutGap(value){const block=blocks[selected];if(!block||block.type!=='layout')return;block.gap=Math.max(0,Math.min(64,Math.round(Number(value)||0)));Studio.modified();Studio.inspector()}, + setLayoutPreset(preset){ + const block=blocks[selected];const widths=editorTools.layoutPreset(block,preset); + if(!widths)return toast('当前列数不支持这种预设',true); + block.columns.forEach((col,i)=>col.width=widths[i]);Studio.modified();Studio.inspector(); + }, + // One inspector for both levels, with a readable path back to the parent. + childQuickEditor(layout){ + if(layout.type!=='layout')return ''; + const cards=[]; + const walk=(container,trail=[],depth=0)=>{ + if(depth>2)return; + container.columns.forEach((column,ci)=>(column.blocks||[]).forEach((child,ri)=>{ + const active=selectedChildId===child.id; + const label=schema.blocks[child.type]?.name||child.type; + const breadcrumb=[...trail,`第${ci+1}列`].join(' › '); + cards.push(`
`); + if(active){ + if(child.type==='layout'){ + cards.push(`
内层布局 · ${child.columns.length} 列
${child.columns.length===2?``:''}
`); + }else{ + const fields=(schema.blocks[child.type]?.fields||[]).filter(k=>['title','subtitle','description','image','button','href'].includes(k)); + fields.forEach(key=>cards.push(``)); + } + if(child.type==='layout'){ + child.columns.forEach((col,index)=>cards.push(`
第 ${index+1} 列${['richtext','image_text','features','cta'].map(t=>``).join('')}
`)); + } + cards.push(``); + if(schema.blocks[child.type]?.fields?.includes('image')){ + cards.push(``); + } + cards.push(`
`); + } + cards.push('
'); + if(child.type==='layout')walk(child,[...trail,`第${ci+1}列 · 内层布局`],depth+1); + })); + }; + walk(layout); + return `
画布组件 · 选择任意一层内容直接编辑
${cards.join('')||'

当前没有子组件,请添加内容。

'}
`; + }, + setNestedLayoutPreset(layoutId,preset){ + const found=editorTools.findLayout(blocks,layoutId); + if(!found||found.rootIndex!==selected||found.depth!==1)return; + const widths=editorTools.layoutPreset(found.layout,preset); + if(!widths)return toast('当前内层列数不支持此预设',true); + found.layout.columns.forEach((c,k)=>c.width=widths[k]);selectedChildId=layoutId; + Studio.modified();Studio.draw(); + }, + setNestedLayoutGap(layoutId,value){ + const found=editorTools.findLayout(blocks,layoutId); + if(!found||found.rootIndex!==selected||found.depth!==1)return; + found.layout.gap=Math.round(Math.max(0,Math.min(64,Number(value)||0))); + selectedChildId=layoutId;Studio.modified();Studio.draw(); + }, + addNestedChild(layoutId,columnIndex,type){ + const found=editorTools.findLayout(blocks,layoutId); + if(!found||found.rootIndex!==selected||found.depth!==1)return; + // A second-level layout cannot contain another layout. Use only the safe + // declarative blocks offered in the UI and validate limits before mutation. + if(!['richtext','image_text','features','cta'].includes(type)|| + !Number.isInteger(columnIndex)||columnIndex<0||columnIndex>=found.layout.columns.length)return; + const column=found.layout.columns[columnIndex]; + if(column.blocks.length>=60)return toast('这一列的组件数量已达到限制',true); + const item=structuredClone(schema.blocks[type].defaults); + item.id=crypto.randomUUID().replace(/-/g,'').slice(0,10); + item.type=type;item.visible=true; + column.blocks.push(item);selectedChildId=item.id; + Studio.modified();Studio.draw(); + toast('已添加内层组件,请在右侧修改内容'); + }, + setNestedDeviceColumns(layoutId,device,value){ + if(!['mobile','tablet'].includes(device))return; + const found=editorTools.findLayout(blocks,layoutId); + if(!found||found.rootIndex!==selected||found.depth!==1)return; + const max=device==='mobile'?2:3; + const count=Math.max(1,Math.min(max,Math.round(Number(value)||1))); + found.layout[device+'_columns']=count; + found.layout.columns.forEach(c=>c[device+'_span']=Math.min(count,c[device+'_span']||1)); + selectedChildId=layoutId;Studio.modified();Studio.draw(); + }, + selectChild(childId){const root=blocks[selected];const found=editorTools.findChildInRoot(blocks,root?.id,childId);if(!found)return;Studio.childCanvasCommand({action:'child-select',blockId:found.parent.id,childId})}, + childFieldById(childId,key,value){ + const parent=blocks[selected];const found=editorTools.findChildInRoot(blocks,parent?.id,childId); + if(!found||!schema.blocks[found.child.type]?.fields?.includes(key)||!['title','subtitle','description','image','button','href'].includes(key))return; + found.child[key]=String(value).slice(0,1500);selectedChildId=childId;Studio.modified(true); + }, async init(){try{csrf=(await api('/api/auth/me')).csrf;site=await api(`/api/sites/${siteId}`);pages=await api(`/api/sites/${siteId}/entries`);schema=await api('/api/editor/blocks');$('#siteName').textContent=site.name;const select=$('#pageSelect');select.innerHTML=pages.map(e=>``).join('');for(let [k,v] of Object.entries(schema.page_templates))$('#pageTemplate').innerHTML+=``;Studio.renderPalette();await Studio.loadReusables();await Studio.choosePage(pageId||pages[0]?.id)}catch(e){toast('初始化失败:'+e.message,true);console.error(e)}}, - async choosePage(id){if(savePromise){toast('保存仍在进行,请稍后切换页面',true);$('#pageSelect').value=pageId;return}if(dirty&&!confirm('当前页面尚未保存,确定切换?')){$('#pageSelect').value=pageId;return}pageId=id;$('#pageSelect').value=id;const data=await api(`/api/sites/${siteId}/pages/${id}/studio-draft`);draftRevision=data.revision;blocks=data.blocks.map(b=>structuredClone(b));kind=data.page_template;layoutMode=data.layout_mode||'append';$('#layoutMode').value=layoutMode;selected=blocks.length?0:-1;$('#pageTemplate').value=kind;$('#pageName').textContent=data.entry.title;$('#routeDisplay').textContent=data.entry.route;dirty=false;snapshots=[];snapshotCursor=-1;lastContinuousEdit=0;blockSearch='';$('#blockSearch').value='';recordSnapshot();Studio.updateHistoryButtons();$('#saveStatus').textContent=draftRevision?'草稿 v'+draftRevision:'未修改';$('#saveStatus').classList.remove('dirty');Studio.draw();Studio.refreshPreview()}, - async loadReusables(){try{reusables=await api(`/api/sites/${siteId}/components`);$('#reusablePalette').innerHTML=reusables.map(x=>``).join('')||'暂无保存的组件'}catch(e){console.warn(e)}}, - async saveReusable(){const block=blocks[selected];if(!block)return toast('请先选择一个区块',true);const name=prompt('为此组件命名',block.title||schema.blocks[block.type]?.name);if(!name?.trim())return;try{await api(`/api/sites/${siteId}/components`,req('POST',{name,block}));await Studio.loadReusables();toast('组件已保存到本站组件库')}catch(e){toast(e.message,true)}}, - insertReusable(id){const saved=reusables.find(x=>x.id===id);if(!saved)return;const copy=editorTools.duplicate(saved.block,()=>crypto.randomUUID().replace(/-/g,'').slice(0,10));blocks.push(copy);selected=blocks.length-1;Studio.modified();Studio.draw();}, - renderPalette(){let p=$('#palette');p.innerHTML=Object.entries(schema.blocks).map(([key,b])=>``).join('')}, - toggleLibrary(force){libraryOpen=typeof force==='boolean'?force:!libraryOpen;const el=$('#sfLibraryPanel'),btn=$('#sfAddBlock');if(el)el.hidden=!libraryOpen;if(btn){btn.setAttribute('aria-expanded',String(libraryOpen));btn.textContent=libraryOpen?'× 收起区块库':'+ 添加内容区块'};Studio.updateGuidance()}, + async choosePage(id){if(savePromise){toast('保存仍在进行,请稍后切换页面',true);$('#pageSelect').value=pageId;return}if(dirty&&!confirm('当前页面尚未保存,确定切换?')){$('#pageSelect').value=pageId;return}pageId=id;selectedChildId=null;insertAfterId=null;Studio.showInsertHint();$('#pageSelect').value=id;const data=await api(`/api/sites/${siteId}/pages/${id}/studio-draft`);draftRevision=data.revision;blocks=data.blocks.map(b=>structuredClone(b));kind=data.page_template;layoutMode=data.layout_mode||'append';$('#layoutMode').value=layoutMode;selected=blocks.length?0:-1;$('#pageTemplate').value=kind;$('#pageName').textContent=data.entry.title;$('#routeDisplay').textContent=data.entry.route;dirty=false;snapshots=[];snapshotCursor=-1;lastContinuousEdit=0;blockSearch='';$('#blockSearch').value='';recordSnapshot();Studio.updateHistoryButtons();$('#saveStatus').textContent=draftRevision?'草稿 v'+draftRevision:'未修改';$('#saveStatus').classList.remove('dirty');Studio.draw();Studio.refreshPreview()}, + async loadReusables(){try{reusables=await api(`/api/sites/${siteId}/components`);$('#reusablePalette').innerHTML=reusables.map(x=>`
${html(x.name)} v${x.version}
`).join('')||'暂无保存的组件'}catch(e){console.warn(e)}}, + async saveReusable(){ + const root=blocks[selected]; + const found=selectedChildId?editorTools.findChildInRoot(blocks,root?.id,selectedChildId):null; + if(selectedChildId&&!found)return toast('当前子组件已失效,请重新选中后保存',true); + const block=found?.child||root; + if(!block)return toast('请先选择需要保存的组件',true); + const name=prompt('为此组件命名',block.title||schema.blocks[block.type]?.name); + if(!name?.trim())return; + try{await api(`/api/sites/${siteId}/components`,req('POST',{name,block})); + await Studio.loadReusables();toast('已保存独立组件副本,其他页面不会自动更新'); + }catch(e){toast('保存组件失败:'+e.message,true)} + }, + insertReusable(id,linked=false){ + const saved=reusables.find(x=>x.id===id);if(!saved)return; + const copy=editorTools.duplicate(saved.block,()=>crypto.randomUUID().replace(/-/g,'').slice(0,10)); + if(linked)copy.shared_ref={id:saved.id,version:saved.version,hash:saved.snapshot_hash}; + const root=blocks[selected]; + const found=selectedChildId?editorTools.findChildInRoot(blocks,root?.id,selectedChildId):null; + if(selectedChildId&&!found)return toast('当前子组件已失效,请重新选中后插入',true); + // A nested reusable must never introduce a third layout container level. + // Layout templates remain insertable as top-level blocks. + if(found && copy.type!=='layout'){ + const parent=found.child.type==='layout'?found.child:found.parent; + const column=found.child.type==='layout'?parent.columns[0]:parent.columns[found.columnIndex]; + if(!column||column.blocks.length>=60)return toast('此列已达到组件数量限制',true); + const after=found.child.type==='layout'?column.blocks.length:found.childIndex+1; + column.blocks.splice(after,0,copy); + selected=found.parentIndex;selectedChildId=copy.id; + }else{ + const foundIndex=insertAfterId?editorTools.findTopIndex(blocks,insertAfterId):-1; + const at=foundIndex>=0?foundIndex+1:blocks.length; + if(blocks.length>=60)return toast('页面顶层最多60个组件',true); + blocks.splice(at,0,copy);selected=at;selectedChildId=null; + } + insertAfterId=null;Studio.showInsertHint();Studio.modified();Studio.draw();Studio.toggleLibrary(false); + toast(linked?'已关联公共组件:修改源组件后仍需要审核并选择同步':'已插入独立组件副本;不会自动跟随更新'); + }, + detachShared(){ + const item=selectedChildId?editorTools.findChildInRoot(blocks,blocks[selected]?.id,selectedChildId)?.child:blocks[selected]; + if(!item?.shared_ref)return toast('当前区块未关联公共组件',true); + if(!confirm('解除关联后,本区块仍保留当前内容,但以后不会参与公共组件同步。确定吗?'))return; + delete item.shared_ref;Studio.modified();Studio.draw();toast('已解除关联。请保存草稿'); + }, + async showSharedComponents(){ + if(!reusables.length)await Studio.loadReusables(); + const dlg=$('#sharedComponentModal');if(!dlg.open)dlg.showModal();sharedPreview=null; + $('#sharedComponentBody').innerHTML=reusables.map(x=>`
${html(x.name)}当前版本 v${x.version} · 不会自动更新页面
`).join('')||'

暂无公共组件。先在页面里选择一个区块,再通过左侧「保存当前组件」创建。

'; + }, + async sharedVersions(id){ + try{const r=await api(`/api/sites/${siteId}/components/${encodeURIComponent(id)}/versions`); + $('#sharedComponentDetail').innerHTML='

组件历史版本

恢复历史不会覆盖已有版本,而是创建新的源组件版本。

'+r.items.map(x=>`
v${x.version} · ${html(x.created_at)} · SHA ${html(x.snapshot_hash.slice(0,12))}
`).join(''); + }catch(e){toast(e.message,true)} + }, + async sharedRestore(id,version){ + const current=reusables.find(x=>x.id===id); + if(!current)return toast('组件信息已过期,请重新加载',true); + if(!confirm(`将历史 v${version} 的内容恢复为全新的组件版本?所有网站页面仍保持不变。`))return; + try{const snapshot=await api(`/api/sites/${siteId}/components/${encodeURIComponent(id)}/versions/${version}`); + await api(`/api/sites/${siteId}/components/${encodeURIComponent(id)}`,req('PUT',{ + name:current.name,expected_version:current.version,block:snapshot.block})); + await Studio.loadReusables();await Studio.showSharedComponents();await Studio.sharedVersions(id); + toast('历史组件已恢复为新的源版本,请检查页面后再同步'); + }catch(e){toast('恢复失败:'+e.message,true)} + }, + async sharedReplace(id){ + const chosen=selectedChildId?editorTools.findChildInRoot(blocks,blocks[selected]?.id,selectedChildId)?.child:blocks[selected]; + const current=reusables.find(x=>x.id===id);if(!chosen||!current)return toast('请先选择页面中的区块',true); + if(!confirm(`将当前选中的区块保存为「${current.name}」的新版本?已发布页面不会变化。`))return; + try{await api(`/api/sites/${siteId}/components/${encodeURIComponent(id)}`,req('PUT',{ + name:current.name,expected_version:current.version,block:chosen})); + await Studio.loadReusables();await Studio.showSharedComponents();toast('新版本已保存。请检查引用页面后选择性同步'); + }catch(e){toast(e.message,true)} + }, + async sharedUsage(id){ + try{sharedPreview=await api(`/api/sites/${siteId}/components/${encodeURIComponent(id)}/usage`); + const preview=sharedPreview; + $('#sharedComponentDetail').innerHTML=`

${html(preview.component.name)} · 同步前检查

只同步勾选的页面,并新建草稿;已发布网站不会立即变动。

`+ + (preview.references.length?preview.references.map(x=>``).join(''):'

尚无关联页面。插入时请选择「关联插入」。

')+ + ''; + }catch(e){toast('读取引用失败:'+e.message,true)} + }, + async sharedApply(){ + if(!sharedPreview)return; + if(dirty)return toast('请先保存当前页面修改,再进行组件同步',true); + const ids=[...new Set([...document.querySelectorAll('.sf-shared-select:checked')].map(x=>x.value))]; + if(!ids.length)return toast('请先选择可以同步的页面',true); + if(!confirm(`确认更新 ${ids.length} 个页面的设计草稿?已发布页面不变,稍后需要逐页审核发布。`))return; + try{const id=sharedPreview.component.id; + const resp=await api(`/api/sites/${siteId}/components/${encodeURIComponent(id)}/sync`,req('POST',{plan_token:sharedPreview.plan_token,entry_ids:ids})); + $('#sharedComponentModal').close();sharedPreview=null; + if(ids.includes(pageId))await Studio.choosePage(pageId); + toast(`已为 ${resp.updated.length} 个页面保存新草稿;请分别检查并发布`); + }catch(e){toast('同步取消:'+e.message,true);await Studio.sharedUsage(sharedPreview.component.id)} + }, + renderPalette(){ + const panel=$('#palette'),summary=$('#paletteSummary');if(!panel||!schema?.blocks)return; + const grouped=window.SiteForgeStudioExperience.groupBlocks(schema.blocks,paletteSearch); + const order=[['basic','常用内容'],['visual','图片与展示'],['business','产品与业务'],['advanced','复杂布局']]; + panel.innerHTML=order.map(([type,title])=>{ + const items=grouped[type]||[];if(!items.length)return ''; + return `

${title}

${items.map(({key,block})=>``).join('')}
`; + }).join('')||'

没有找到对应组件,试试“文字”或“图片”。

'; + summary.textContent='找到 '+Object.values(grouped).reduce((n,x)=>n+x.length,0)+' 个可添加组件'; + }, + filterPalette(value){paletteSearch=String(value||'').slice(0,70);Studio.renderPalette()}, + clearPaletteSearch(){paletteSearch='';const inp=$('#paletteSearch');if(inp){inp.value='';inp.focus()}Studio.renderPalette()}, + showThemePreview(){const dialog=$('#themePreviewModal');if(!dialog)return;const current=['automotive','industrial','corporate','minimal'].includes(site?.theme)?site.theme:'corporate';$('#themePreviewTheme').value=current;if(!dialog.open)dialog.showModal();Studio.themeDevice('desktop');Studio.updateThemePreview()}, + closeThemePreview(){const dialog=$('#themePreviewModal');if(dialog?.open)dialog.close();const frame=$('#themePreviewFrame');if(frame)frame.removeAttribute('src')}, + themeDevice(device){ + const width={desktop:'100%',tablet:'780px',phone:'390px'}[device];if(!width)return; + $('#themePreviewFrameShell').style.width=width; + document.querySelectorAll('[data-theme-device]').forEach(btn=>btn.setAttribute('aria-pressed',String(btn.dataset.themeDevice===device))); + }, + updateThemePreview(){ + const theme=$('#themePreviewTheme')?.value,page=$('#themePreviewPage')?.value; + const url=window.SiteForgeStudioExperience.previewUrl(theme,page); + if(!url)return; + const frame=$('#themePreviewFrame'),status=$('#themePreviewStatus');if(!frame)return; + status.textContent='正在加载主题示例…(不影响已保存的页面)'; + frame.onload=()=>{if($('#themePreviewModal')?.open)status.textContent='已加载示例。可切换主题、页面类型和设备继续比较。'}; + frame.onerror=()=>{status.textContent='示例加载失败,请稍后重试。'}; + frame.src=url; + }, toggleLibrary(force){libraryOpen=typeof force==='boolean'?force:!libraryOpen;const el=$('#sfLibraryPanel'),btn=$('#sfAddBlock');if(el)el.hidden=!libraryOpen;if(btn){btn.setAttribute('aria-expanded',String(libraryOpen));btn.textContent=libraryOpen?'× 收起区块库':'+ 添加内容区块'};Studio.updateGuidance()}, showHelp(){const dlg=$('#sfGuideDialog');if(dlg&&!dlg.open)dlg.showModal()}, updateGuidance(){const one=$('#sfStep1'),two=$('#sfStep2'),three=$('#sfStep3');if(!one||!two||!three)return;one.classList.toggle('active',selected<0||libraryOpen);two.classList.toggle('active',selected>=0&&!dirty&&!libraryOpen);three.classList.toggle('active',dirty);}, draw(){ @@ -39,10 +316,10 @@ const Studio={ changeInspectorTab(tab){if(!['content','style','responsive'].includes(tab))return;inspectorTab=tab;Studio.applyInspectorTab()}, applyInspectorTab(){for(const key of ['content','style','responsive']){const active=key===inspectorTab;const btn=$('#tab'+key.charAt(0).toUpperCase()+key.slice(1));btn?.setAttribute('aria-selected',String(active));const pane=$('[data-inspector-section="'+key+'"]');if(pane)pane.hidden=!active}}, togglePane(which){const type=which==='left'?'show-structure':'show-inspector';document.body.classList.toggle(type);if(type==='show-structure')document.body.classList.remove('show-inspector');else document.body.classList.remove('show-structure');}, - updateHistoryButtons(){const state=editorTools.historyState(snapshots,snapshotCursor);$('#studioUndo').disabled=!state.canUndo;$('#studioRedo').disabled=!state.canRedo}, + updateHistoryButtons(){const state=editorTools.historyState(snapshots,snapshotCursor);for(const id of ['#studioUndo','#quickUndo']){const el=$(id);if(el)el.disabled=!state.canUndo}for(const id of ['#studioRedo','#quickRedo']){const el=$(id);if(el)el.disabled=!state.canRedo}}, - select(i){selected=i;Studio.draw();if(window.matchMedia('(max-width:950px)').matches){document.body.classList.add('show-inspector');document.body.classList.remove('show-structure')}}, - add(type){let data=structuredClone(schema.blocks[type].defaults);data.id=crypto.randomUUID().replace(/-/g,'').slice(0,10);data.type=type;data.visible=true;blocks.push(data);selected=blocks.length-1;Studio.modified();Studio.draw();Studio.toggleLibrary(false);if(window.matchMedia('(max-width:950px)').matches){document.body.classList.add('show-inspector');document.body.classList.remove('show-structure')}}, + select(i){selected=i;selectedChildId=null;Studio.draw();if(window.matchMedia('(max-width:950px)').matches){document.body.classList.add('show-inspector');document.body.classList.remove('show-structure')}}, + add(type){let data=structuredClone(schema.blocks[type].defaults);data.id=crypto.randomUUID().replace(/-/g,'').slice(0,10);data.type=type;data.visible=true;const found=insertAfterId?editorTools.findTopIndex(blocks,insertAfterId):-1;const at=found>=0?found+1:blocks.length;blocks.splice(at,0,data);selected=at;insertAfterId=null;Studio.showInsertHint();Studio.modified();Studio.draw();Studio.toggleLibrary(false);if(window.matchMedia('(max-width:950px)').matches){document.body.classList.add('show-inspector');document.body.classList.remove('show-structure')}}, duplicate(i){const b=editorTools.duplicate(blocks[i],()=>crypto.randomUUID().replace(/-/g,'').slice(0,10));blocks.splice(i+1,0,b);selected=i+1;Studio.modified();Studio.draw()}, remove(i){if(!confirm('确定删除这个区块?'))return;blocks.splice(i,1);selected=Math.min(i,blocks.length-1);Studio.modified();Studio.draw()}, drag(e,i){e.dataTransfer.setData('text/plain',String(i));e.dataTransfer.effectAllowed='move';e.currentTarget.classList.add('dragging')}, @@ -64,9 +341,17 @@ const Studio={ removeItem(field,index){const rows=blocks[selected]?.[field];if(!Array.isArray(rows)||!rows[index])return;rows.splice(index,1);Studio.modified();Studio.inspector()}, moveItem(field,index,by){const rows=blocks[selected]?.[field],target=index+by;if(!Array.isArray(rows)||target<0||target>=rows.length)return;[rows[index],rows[target]]=[rows[target],rows[index]];Studio.modified();Studio.inspector()}, jsonField(key,value){try{let data=JSON.parse(value);if(!Array.isArray(data))throw Error('必须为数组');Studio.fieldQuiet(key,data);$('#jsonError').textContent='✓ JSON 格式有效';$('#jsonError').style.color='#238460'}catch(e){$('#jsonError').textContent='JSON 格式有误:'+e.message;$('#jsonError').style.color='#bf5a58'}}, - styleField(key,value){const b=blocks[selected];b.style={...(b.style||{}),[key]:value};Studio.modified()}, + styleField(key,value){const b=blocks[selected];if(!b)return;b.style={...(b.style||{}),[key]:value};Studio.modified()}, + applyStylePreset(preset){ + const block=blocks[selected];if(!block)return; + const style=window.SiteForgeStudioExperience.stylePreset(site?.theme,preset); + if(!style)return; + block.style={...(block.style||{}),...style}; + Studio.modified();Studio.inspector(); + toast('已应用区块外观,保存草稿前可以撤销'); + }, inspector(){let target=$('#inspector');let b=blocks[selected];$('#blockTypeLabel').textContent=b?schema.blocks[b.type].name:'页面';if(!b){target.innerHTML='
还没有选中内容

先到左侧选择一个区块,或点击“添加内容区块”。

';return}const spec=schema.blocks[b.type];let out=`

${html(spec.name)}

`; - for(const field of spec.fields){let value=b[field]??'',label=({title:'标题',subtitle:'副标题',description:'简介',image:'图片地址',body:'正文 HTML',button:'按钮文字',href:'跳转路径',source:'绑定内容类型',limit:'显示条数',columns:'每行列数',items:'重复条目',images:'画廊图片',image_side:'图片方向',align:'标题对齐',height:'间隔高度'})[field]||field; + for(const field of spec.fields.filter(f=>b.type!=='layout'||!['columns','gap','tablet_columns','mobile_columns'].includes(f))){let value=b[field]??'',label=({title:'标题',subtitle:'副标题',description:'简介',image:'图片地址',body:'正文 HTML',button:'按钮文字',href:'跳转路径',source:'绑定内容类型',limit:'显示条数',columns:'每行列数',items:'重复条目',images:'画廊图片',image_side:'图片方向',align:'标题对齐',height:'间隔高度'})[field]||field; out+=`
`; if(field==='items'||field==='images')out+=Studio.arrayEditor(field,value,b.type); else if(field==='source')out+=`网站已有内容将自动绑定并生成卡片。`; @@ -77,9 +362,10 @@ const Studio={ if(['title','subtitle','description','image','body'].includes(field))out+='可输入 {{site.name}}、{{page.title}} 等变量。'; out+='
'; } + if(b.type==='layout')out+=Studio.childQuickEditor(b); out+='
'; if(b.type==='layout'){ - out+=`
列内组件 · 按设备排版

分别调整平板/手机的列数、顺序、跨度与显隐。保存草稿后在设备预览切换查看效果。

`; + out+=`
快捷布局

常用排版一键设置,也可直接拖动画布中的列宽分隔线。

手机与平板

选 1 列更适合手机阅读。以下设置只影响对应设备,不更改桌面列宽。

`; b.columns.forEach((column,ci)=>{ out+=`
第${ci+1}列
`; out+=`
`; @@ -88,12 +374,14 @@ const Studio={ if(b.columns.length>1){out+=``} out+='
'; }); - out+=`
${['richtext','image_text','collection','cta','features'].map(t=>``).join('')}
`; + out+=`
${['richtext','image_text','collection','cta','features','layout'].map(t=>``).join('')}
`; }); out+=''; } out+=`
响应式样式
`; - out+=`
外观设置
`; + out+=`
快速设置外观

不必先调色值:选择样式后会立即更新预览,也可以撤销。

自定义外观
`; + const sharing=selectedChildId?editorTools.findChildInRoot(blocks,b.id,selectedChildId)?.child?.shared_ref:b.shared_ref; + if(sharing)out+=`
已关联公共组件 · v${html(sharing.version)}

此区块将来可以按需同步新版。直接修改后会被视为本地定制。

`; out+='
'; target.innerHTML=out;Studio.applyInspectorTab(); }, @@ -115,7 +403,7 @@ const Studio={ try{ const doc=await api(`/api/sites/${siteId}/pages/${page}/editor-preview`,{...req('POST',{blocks,page_template:kind,layout_mode:layoutMode,site_design:siteDesignPreview}),signal:previewController.signal}); if(!editorTools.shouldAcceptPreview(page,seq,pageId,previewRequest))return; - frame.srcdoc=doc;$('#previewState').textContent='实时预览 · 已更新';$('#previewDot').classList.remove('loading','error'); + frame.onload=()=>Studio.highlightCanvas();frame.srcdoc=doc;$('#previewState').textContent='实时预览 · 已更新';$('#previewDot').classList.remove('loading','error'); }catch(e){ if(!editorTools.shouldAcceptPreview(page,seq,pageId,previewRequest)||e.name==='AbortError')return; $('#previewState').textContent='预览更新失败';$('#previewDot').classList.remove('loading');$('#previewDot').classList.add('error');toast('预览失败:'+e.message,true); @@ -161,6 +449,23 @@ const Studio={ async discardDraft(){if(!draftRevision)return;if(!confirm('确定放弃草稿?'))return;try{await api(`/api/sites/${siteId}/pages/${pageId}/studio-draft`,{method:'DELETE'});dirty=false;await Studio.choosePage(pageId);toast('草稿已放弃')}catch(e){toast(e.message,true)}}, dragChild(event,col,index){draggedChild={container:selected,col,index};event.dataTransfer.setData('application/siteforge-child','1');event.dataTransfer.effectAllowed='move';event.stopPropagation()}, dropChild(event,destCol){if(!draggedChild)return;event.preventDefault();event.stopPropagation();const drag=draggedChild;draggedChild=null;const src=blocks[drag.container],dest=blocks[selected];if(!src||!dest||src.type!=='layout'||dest.type!=='layout')return;const moved=src.columns?.[drag.col]?.blocks.splice(drag.index,1)[0];if(!moved)return;dest.columns[destCol].blocks.push(moved);Studio.modified();Studio.draw()}, + drawSiteNav(){ + const root=$('#siteNavRows');root.replaceChildren(); + const draw=(items,depth=0)=>items.forEach((node,index)=>{ + const line=document.createElement('div');line.className='sf-nav-item';line.style.marginLeft=`${depth*16}px`; + const title=document.createElement('input');title.placeholder='菜单名称';title.maxLength=48;title.value=node.title||'';title.setAttribute('aria-label','菜单名称');title.oninput=()=>node.title=title.value; + const route=document.createElement('input');route.placeholder='/products/';route.value=node.route||'/';route.setAttribute('aria-label','站内路径');route.oninput=()=>node.route=route.value; + line.append(title,route); + const op=(label,fn)=>{const button=document.createElement('button');button.type='button';button.className='ui-btn ghost sf-nav-action';button.textContent=label;button.onclick=fn;line.append(button)}; + if(depth<2)op('+ 子菜单',()=>{node.children=node.children||[];node.children.push({title:'新菜单',route:'/',children:[]});Studio.drawSiteNav()}); + if(index)op('↑',()=>{[items[index-1],items[index]]=[items[index],items[index-1]];Studio.drawSiteNav()}); + if(index{[items[index+1],items[index]]=[items[index],items[index+1]];Studio.drawSiteNav()}); + op('删除',()=>{items.splice(index,1);Studio.drawSiteNav()}); + root.append(line);if(node.children?.length)draw(node.children,depth+1); + }); + draw(siteNavDraft); + }, + addSiteNav(){siteNavDraft.push({title:'新菜单',route:'/',children:[]});Studio.drawSiteNav()}, async showSiteDesign(){try{ const result=await api(`/api/sites/${siteId}/site-design`); siteDesign=result.config;siteDesignRevision=result.revision;siteDesignPreview=structuredClone(siteDesign); @@ -168,7 +473,7 @@ const Studio={ for(const [name,value] of Object.entries(h)){const el=form.elements.namedItem(name);if(el){if(el.type==='checkbox')el.checked=value;else el.value=value}} for(const [name,value] of Object.entries(f)){const key='footer_'+name,el=form.elements.namedItem(key);if(el){if(el.type==='checkbox')el.checked=value;else el.value=value}} for(const [name,value] of Object.entries(r)){const el=form.elements.namedItem(name);if(el){if(el.type==='checkbox')el.checked=value;else el.value=value}} - form.elements.namedItem('nav').value=JSON.stringify(siteDesign.nav,null,2); + siteNavDraft=structuredClone(siteDesign.nav||[]);Studio.drawSiteNav(); form.elements.namedItem('mobile_tabs_enabled').checked=Boolean(siteDesign.mobile_tabs?.enabled); Studio.drawMobileTabs(siteDesign.mobile_tabs?.items||[]); Studio.toggleMobileTabsForm(); @@ -194,8 +499,7 @@ const Studio={ collectSiteDesign(){const form=$('#siteDesignForm');if(!siteDesign)throw Error('请先打开全站设计'); const v=(n)=>form.elements.namedItem(n).value; const yes=(n)=>form.elements.namedItem(n).checked; - let nav;try{nav=JSON.parse(v('nav'))}catch(e){throw Error('导航必须是合法 JSON:'+e.message)} - if(!Array.isArray(nav))throw Error('导航必须是数组'); + const nav=structuredClone(siteNavDraft); const tabs=[...$('#mobileTabsRows').children].map(row=>({title:row.querySelector('.mt-title').value.trim(),icon:row.querySelector('.mt-icon').value,route:row.querySelector('.mt-route').value.trim(),action:row.querySelector('.mt-action').value})); if(yes('mobile_tabs_enabled')&&!tabs.length)throw Error('开启底部 Tabs 后,请至少添加一个按钮'); return {tokens:structuredClone(siteDesign.tokens),mobile_tabs:{enabled:yes('mobile_tabs_enabled'),items:tabs},header:{announcement:v('announcement'),show_announcement:yes('show_announcement'),show_search:yes('show_search'), @@ -211,12 +515,73 @@ const Studio={ siteDesignRevision=saved.revision;siteDesign=config;siteDesignPreview=structuredClone(config); $('#siteDesignStatus').textContent=`草稿 v${siteDesignRevision} 已保存,正式构建保持不变`;toast('全站设计草稿保存成功');return true; }catch(e){toast('全站草稿保存失败:'+e.message,true);return false}}, - async publishSiteDesign(){if(!confirm('发布全站设计会影响该站所有页面的下一次静态构建。确定继续?'))return; + async publishSiteDesign(){ if(!await Studio.saveSiteDesign())return; - try{await api(`/api/sites/${siteId}/site-design/publish`,req('POST',{expected_revision:siteDesignRevision})); - siteDesignRevision=0;$('#siteDesignStatus').textContent='全站设计已发布,请重新构建网站'; - $('#siteDesignModal').close();await Studio.refreshPreview();toast('全站设计已发布;现有上线网站仍不改变'); - }catch(e){toast('发布失败:'+e.message,true)}}, + try{ + const review=await api(`/api/sites/${siteId}/site-design/review`); + siteDesignReviewToken=review.plan_token; + const box=$('#siteDesignReviewBody');box.replaceChildren(); + const lead=document.createElement('p');lead.textContent=`草稿 v${review.revision} · ${review.change_count} 处字段变更 · 影响本站下一次构建的全部页面`;box.append(lead); + if(!review.change_count){const empty=document.createElement('p');empty.textContent='没有任何实际配置变化。可以返回编辑。';box.append(empty);} + review.changed_fields.forEach(change=>{ + const article=document.createElement('article');article.className='sf-review-change'; + const label=document.createElement('strong');label.textContent=Studio.designFieldLabel(change.field);article.append(label); + const old=document.createElement('p');old.textContent='原配置:'+Studio.formatDesignDifference(change.before,change.field); + const newer=document.createElement('p');newer.textContent='新配置:'+Studio.formatDesignDifference(change.after,change.field); + article.append(old,newer);box.append(article); + }); + $('#siteDesignReviewModal').showModal(); + }catch(e){toast('审核预览失败:'+e.message,true)} + }, + designFieldLabel(key){const names={header:'页眉',footer:'页脚',nav:'网站导航',mobile_tabs:'手机底部导航',tokens:'全站风格',responsive:'响应式布局',announcement:'提示文字',show_announcement:'显示提示栏',show_search:'显示搜索',show_cta:'显示联系按钮',cta_text:'按钮文字',cta_href:'按钮地址',description:'介绍文字',email:'邮箱',title:'标题',items:'导航项目',enabled:'是否启用'};return key.split('.').map(v=>names[v]||v).join(' · ')}, + formatDesignDifference(value,field=''){ + if(typeof value==='boolean')return value?'已开启':'已关闭'; + if(value==null)return '未设置'; + if(field==='nav'&&Array.isArray(value)){ + const parts=[];const walk=(items,depth)=>items.forEach(n=>{parts.push(' '.repeat(depth)+(n.title||'未命名')+' → '+(n.route||'/'));walk(n.children||[],depth+1)});walk(value,0); + return parts.length?parts.join('\n'):'(未配置导航)'; + } + if(field==='mobile_tabs'&&value&&typeof value==='object'){ + return value.enabled?'已启用:'+(value.items||[]).map(v=>v.title+' → '+(v.action==='menu'?'打开菜单':v.route)).join(' · '):'未启用'; + } + if(Array.isArray(value))return value.map(v=>typeof v==='object'?(v.title||JSON.stringify(v)):v).join('、')||'空列表'; + const text=typeof value==='string'?value:JSON.stringify(value); + return text.length>440?text.slice(0,440)+'…':text; + }, + async confirmReviewedSiteDesign(){ + if(!siteDesignReviewToken)return toast('请先查看发布差异',true); + try{ + await api(`/api/sites/${siteId}/site-design/publish-reviewed`,req('POST',{ + expected_revision:siteDesignRevision,plan_token:siteDesignReviewToken})); + siteDesignReviewToken=null;siteDesignRevision=0;siteDesignPreview=null; + $('#siteDesignReviewModal').close();$('#siteDesignModal').close(); + $('#siteDesignStatus').textContent='全站设计已发布到内容库,下一次构建后生效'; + await Studio.refreshPreview();toast('全站设计已审核并发布,请构建及部署网站。'); + }catch(e){toast('发布失败:'+e.message,true)} + }, + async showSiteDesignHistory(){ + try{ + const items=await api(`/api/sites/${siteId}/site-design/publications`),box=$('#siteDesignHistoryBody');box.replaceChildren(); + if(!items.length){box.textContent='尚无发布记录';} + for(const item of items){ + const row=document.createElement('div');row.className='sf-review-change'; + const title=document.createElement('strong');title.textContent=`${item.published_at} · 版本 ${item.revision}`;row.append(title); + const show=document.createElement('button');show.type='button';show.className='ui-btn ghost';show.textContent='查看变更'; + show.onclick=async()=>{try{const detail=await api(`/api/sites/${siteId}/site-design/publications/${item.id}`);const p=document.createElement('p');p.textContent=detail.changes.map(x=>x.field).join('、')||'无字段变化';row.append(p);show.disabled=true;}catch(e){toast(e.message,true)}}; + const restore=document.createElement('button');restore.type='button';restore.className='ui-btn ghost';restore.textContent='恢复为新草稿'; + restore.onclick=async()=>{ + if(!confirm('确认以这个历史版本生成新的全站设计草稿?不会直接更改线上页面。'))return; + try{const live=await api(`/api/sites/${siteId}/site-design/live-hash`); + await api(`/api/sites/${siteId}/site-design/publications/${item.id}/restore`,req('POST',{ + snapshot:'after',expected_revision:siteDesignRevision,expected_live_hash:live.live_hash})); + $('#siteDesignHistoryModal').close();await Studio.showSiteDesign();toast('历史版本已恢复为新草稿,请检查后发布'); + }catch(e){toast(e.message,true)} + }; + row.append(show,restore);box.append(row); + } + $('#siteDesignHistoryModal').showModal(); + }catch(e){toast(e.message,true)} + }, async discardSiteDesign(){if(!confirm('确定删除尚未发布的全站草稿?'))return; try{await api(`/api/sites/${siteId}/site-design`,{method:'DELETE'});siteDesignPreview=null; await Studio.showSiteDesign();await Studio.refreshPreview();toast('全站草稿已放弃') @@ -227,14 +592,25 @@ const Studio={ setColumnDevice(i,key,value){const b=blocks[selected];if(!b||b.type!=='layout')return;const col=b.columns[i];if(!col)return;col[key]=value;Studio.modified();Studio.inspector()}, addColumn(){const b=blocks[selected];if(!b||b.type!=='layout'||b.columns.length>=4)return;b.columns.push({width:1,blocks:[]});Studio.modified();Studio.inspector()}, removeColumn(i){const b=blocks[selected];if(!b||b.type!=='layout'||b.columns.length<=1)return;if(b.columns[i].blocks.length&&!confirm('这一列含有组件,确认删除?'))return;b.columns.splice(i,1);Studio.modified();Studio.inspector()}, - setColumnWidth(i,value){const b=blocks[selected];if(!b||b.type!=='layout')return;b.columns[i].width=Math.max(.5,Math.min(4,Number(value)||1));Studio.modified()}, + setColumnWidth(i,value){const b=blocks[selected];if(!b||b.type!=='layout'||!b.columns[i])return;b.columns[i].width=Math.round(Math.max(.5,Math.min(4,Number(value)||1))*100)/100;Studio.modified();Studio.inspector()}, addChild(i,type){const b=blocks[selected];if(!b||b.type!=='layout')return;const item=structuredClone(schema.blocks[type].defaults);item.type=type;item.id=crypto.randomUUID().replace(/-/g,'').slice(0,10);item.visible=true;b.columns[i].blocks.push(item);Studio.modified();Studio.inspector()}, removeChild(i,j){const b=blocks[selected];if(!b||b.type!=='layout')return;b.columns[i].blocks.splice(j,1);Studio.modified();Studio.inspector()}, childField(i,j,key,value){const b=blocks[selected];if(!b||b.type!=='layout')return;b.columns[i].blocks[j][key]=value;Studio.modified()}, moveChild(ci,ri,target){const b=blocks[selected];if(!b||b.type!=='layout'||target<0||target>=b.columns.length)return;let [component]=b.columns[ci].blocks.splice(ri,1);b.columns[target].blocks.push(component);Studio.modified();Studio.inspector()}, async chooseMedia(){try{const data=await api(`/api/sites/${siteId}/media`);const grid=$('#siteMediaGrid');grid.replaceChildren();if(!data.length){grid.textContent='暂无上传图片。可先在当前组件中上传图片。'}for(const item of data){const button=document.createElement('button');button.type='button';button.style.cssText='border:1px solid #e2e8f0;border-radius:9px;background:white;padding:7px;cursor:pointer';const img=document.createElement('img');img.alt=item.name;img.loading='lazy';img.style.cssText='width:100%;height:105px;object-fit:contain';img.src=`/local-media/${encodeURIComponent(siteId)}/${encodeURIComponent(item.name)}`;const label=document.createElement('small');label.textContent=item.name;label.style.cssText='display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap';button.append(img,label);button.addEventListener('click',()=>Studio.applyMedia(item.url));grid.append(button)}$('#siteMediaModal').showModal()}catch(e){toast(e.message,true)}}, - applyMedia(url){const b=blocks[selected];if(!b)return;if(b.type==='gallery'){b.images=[...(b.images||[]),{url,alt:''}]}else if(b.type==='carousel'){b.items=[...(b.items||[]),{image:url,alt:'',caption:''}]}else{b.image=url}Studio.modified();Studio.draw();$('#siteMediaModal').close();toast('已应用素材到草稿')}, - async uploadImage(file){if(!file)return;try{const form=new FormData();form.append('file',file);let r=await api(`/api/sites/${siteId}/media`,{method:'POST',body:form});Studio.field('image',r.url);toast('图片已上传,保存页面后参与构建')}catch(e){toast(e.message,true)}}, + applyMedia(url){ + const root=blocks[selected];if(!root)return; + const found=selectedChildId?editorTools.findChildInRoot(blocks,root.id,selectedChildId):null; + if(selectedChildId&&!found)return toast('当前子组件已失效,请重新选中后添加图片',true); + const block=found?.child||root; + const fields=schema?.blocks?.[block.type]?.fields||[]; + if(block.type==='gallery')block.images=[...(block.images||[]),{url,alt:''}]; + else if(block.type==='carousel')block.items=[...(block.items||[]),{image:url,alt:'',caption:''}]; + else if(fields.includes('image'))block.image=url; + else return toast('选中的组件不支持图片,请先选择一个图片组件',true); + Studio.modified();Studio.draw();$('#siteMediaModal').close();toast('已应用素材到草稿'); + }, + async uploadImage(file){if(!file)return;try{const form=new FormData();form.append('file',file);let r=await api(`/api/sites/${siteId}/media`,{method:'POST',body:form});Studio.applyMedia(r.url);toast('图片已上传,保存页面后参与构建')}catch(e){toast(e.message,true)}}, async buildSite(){if(dirty||draftRevision||siteDesignRevision)return toast('有尚未发布的页面或全站草稿,请先发布,再构建网站',true);try{ toast('已提交后台构建任务');const task=await api(`/api/sites/${siteId}/builds`,req('POST',{mirror_images:false})); for(let i=0;i<240;i++){ @@ -250,22 +626,10 @@ window.addEventListener('DOMContentLoaded',()=>Studio.init()); window.addEventListener('beforeunload',e=>{if(dirty){e.preventDefault();e.returnValue='';}}); window.addEventListener('message',event=>{ - const frame=document.querySelector('#sitePreview'); - if(!frame||event.source!==frame.contentWindow)return; - const data=event.data||{}; - if(data.source==='siteforge-select-block'){ - if(typeof data.blockId!=='string'||data.blockId.length>150)return; - const findTop=rows=>{for(let i=0;icol.blocks?.some(child=>child.id===data.blockId)))return i}return -1}; - const index=findTop(blocks);if(index>=0){selected=index;Studio.draw();if(window.matchMedia('(max-width:1060px)').matches){document.body.classList.add('show-inspector');document.body.classList.remove('show-structure')}} - return; - } - if(data.source!=='siteforge-inline-editor')return; - const findChild=rows=>{for(const row of rows){if(row.id===data.blockId)return {block:row,parent:row};if(row.type==='layout'){for(const col of row.columns||[]){const child=findChild(col.blocks||[]);if(child)return {block:child.block,parent:row};}}}return null}; - const found=findChild(blocks),b=found?.block; - if(!b||!['title','description'].includes(data.field)||typeof data.value!=='string')return; - b[data.field]=data.value.slice(0,500); - selected=blocks.indexOf(found.parent);Studio.modified();Studio.draw(); - toast('已修改文字,点击保存页面写入数据库'); + const frame=document.querySelector('#sitePreview'); + if(!frame||event.source!==frame.contentWindow)return; + const data=event.data; + if(data?.source==='siteforge-studio-canvas')Studio.canvasCommand(data); }); window.addEventListener('keydown',event=>{ diff --git a/app/static/pro.js b/app/static/pro.js index 9cf100d..4474b62 100644 --- a/app/static/pro.js +++ b/app/static/pro.js @@ -65,6 +65,10 @@ const q=panel.querySelector('[data-pro-filter-search]'),b=panel.querySelector('[data-pro-filter-brand]'),c=panel.querySelector('[data-pro-filter-category]'),count=panel.querySelector('[data-pro-filter-count]'); function options(sel,key){const vals=[...new Set(cards.map(x=>x.dataset[key]||'').filter(Boolean))].sort();vals.forEach(x=>sel.add(new Option(x,x)));if(!vals.length)sel.closest('label').hidden=true;} options(b,'brand');options(c,'category'); + // Support shareable searches from automotive homepage without changing page URLs. + const params=new URLSearchParams(window.location.search); + if(q && params.has('q')) q.value=(params.get('q')||'').slice(0,120); + if(b && params.has('brand') && [...b.options].some(o=>o.value===params.get('brand'))) b.value=params.get('brand'); function run(){const str=q.value.trim().toLocaleLowerCase();let visible=0; cards.forEach(el=>{const hit=el.textContent.toLocaleLowerCase().includes(str)&&(!b.value||el.dataset.brand===b.value)&&(!c.value||el.dataset.category===c.value);el.hidden=!hit;visible+=Number(hit);});count.textContent=`共 ${visible} 条`;blank.hidden=visible!==0;} [q,b,c].forEach(x=>x.addEventListener(x===q?'input':'change',run));run(); diff --git a/app/static/studio-canvas-bridge.js b/app/static/studio-canvas-bridge.js new file mode 100644 index 0000000..bf5cc9a --- /dev/null +++ b/app/static/studio-canvas-bridge.js @@ -0,0 +1,147 @@ +/* V8.22 trusted, sandboxed studio canvas bridge. No arbitrary user code. */ +(function(){ + 'use strict'; + const source='siteforge-studio-canvas'; + const list=()=>Array.from(document.querySelectorAll('.sf-section[data-block]')).filter(n=>!n.parentElement.closest('.sf-section[data-block]')); + const send=(action,id,extra={})=>parent.postMessage({source,action,blockId:id,...extra},'*'); + let active='', dragging='',resize=null; + const all=()=>Array.from(document.querySelectorAll('.sf-section[data-block]')); + const style=document.createElement('style'); + style.textContent=` + .sf-section[data-block]{position:relative} + .sf-section[data-block].sf-canvas-selected{outline:2px solid #ec7c35!important;outline-offset:-2px} + .sf-section[data-block].sf-canvas-drop{box-shadow:inset 0 4px 0 #ef8741!important} + .sf-section[data-block]:hover{outline:1px dashed #eb995a;outline-offset:-1px} + .sf-canvas-toolbar{position:absolute;right:7px;top:5px;z-index:2147480000;display:none;align-items:center;gap:3px;padding:5px;background:#263447;color:#fff;border-radius:9px;box-shadow:0 5px 20px #20304450;font:12px/1.4 system-ui,sans-serif;white-space:nowrap;pointer-events:auto} + .sf-canvas-selected>.sf-canvas-toolbar,.sf-section[data-block]:hover>.sf-canvas-toolbar,.sf-canvas-toolbar:focus-within{display:flex} + .sf-canvas-toolbar button{background:transparent;color:inherit;border:0;cursor:pointer;padding:5px 7px;border-radius:5px;font:inherit} + .sf-canvas-toolbar button:hover,.sf-canvas-toolbar button:focus-visible{background:#52687e;outline:1px solid #fff6} + .sf-canvas-toolbar .sf-canvas-drag{cursor:grab;background:#496174} + .sf-canvas-toolbar .sf-canvas-danger:hover{background:#ab4d46} + .sf-section.sf-canvas-child-selected{outline:2px solid #0e97ac!important;outline-offset:-2px} + .sf-nested-toolbar{position:absolute;top:6px;left:6px;z-index:2147480001;display:none;gap:3px;background:#126c80;color:#fff;padding:5px;border-radius:8px;font:12px system-ui;pointer-events:auto} + .sf-canvas-child-selected>.sf-nested-toolbar,.sf-section[data-block]:hover>.sf-nested-toolbar,.sf-nested-toolbar:focus-within{display:flex} + .sf-nested-toolbar button{color:#fff;background:transparent;border:0;border-radius:5px;cursor:pointer;padding:5px 7px} + .sf-nested-toolbar button:hover,.sf-nested-toolbar button:focus-visible{background:#248ea4;outline:1px solid #fff6} + .sf-canvas-hint{position:fixed;bottom:12px;left:50%;transform:translateX(-50%);background:#1c293ee8;color:white;padding:9px 13px;border-radius:9px;z-index:2147480000;font:12px system-ui;pointer-events:none} + .sf-layout-grid{position:relative} + .sf-canvas-resize{position:absolute;z-index:2147480000;top:4px;bottom:4px;width:12px;transform:translateX(-50%);cursor:col-resize;touch-action:none;opacity:0;display:flex;align-items:center;justify-content:center} + .sf-canvas-resize:after{content:'⋮';background:#e77632;color:white;box-shadow:0 2px 8px #2225;border-radius:8px;font:20px/26px system-ui;text-align:center;width:19px;min-width:19px} + .sf-section:hover .sf-canvas-resize,.sf-canvas-resize:focus-visible,.sf-canvas-resize.sf-resizing{opacity:1} + [contenteditable].sf-canvas-editing{outline:2px dashed #df7435!important;border-radius:3px;cursor:text!important} + @media(max-width:820px){.sf-canvas-resize{display:none!important}} + `; + document.head.appendChild(style); + const types={title:'h1,h2',description:'.sf-hero-copy p,.sf-image-text p,.sf-cta-wrap p'}; + function activate(id,notify=true){ + active=id||'';for(const el of all())el.classList.toggle('sf-canvas-selected',el.dataset.block===id); + if(notify&&id)send('select',id); + } + const topSections=list(); + for(const block of topSections){ + const id=block.dataset.block; + const bar=document.createElement('div');bar.className='sf-canvas-toolbar';bar.setAttribute('role','toolbar');bar.setAttribute('aria-label','区块快捷操作'); + const controls=[['↕','拖动区块','drag'],['✎','编辑区块','edit'],['↑','上移区块','up'],['↓','下移区块','down'],['+','在下方添加区块','add-after'],['⧉','复制区块','duplicate'],['×','删除区块','delete']]; + for(const [txt,label,action] of controls){ + const b=document.createElement('button');b.type='button';b.textContent=txt;b.title=label;b.setAttribute('aria-label',label);b.dataset.action=action; + if(action==='drag'){b.draggable=true;b.className='sf-canvas-drag';b.addEventListener('dragstart',e=>{dragging=id;e.dataTransfer.setData('text/plain',id);e.dataTransfer.effectAllowed='move';e.stopPropagation()});b.addEventListener('dragend',()=>{dragging='';list().forEach(el=>el.classList.remove('sf-canvas-drop'))})} + else {if(action==='delete')b.className='sf-canvas-danger';b.addEventListener('click',e=>{e.preventDefault();e.stopPropagation();activate(id,false);send(action,id)})} + bar.appendChild(b); + } + block.prepend(bar); + block.addEventListener('click',event=>{ + if(event.target.closest('.sf-canvas-toolbar,.sf-canvas-resize'))return; + if(event.target.closest('a'))event.preventDefault(); + activate(id); + }); + block.addEventListener('dragover',event=>{if(!dragging)return;event.preventDefault();event.stopPropagation();block.classList.add('sf-canvas-drop')}); + block.addEventListener('dragleave',event=>{if(!block.contains(event.relatedTarget))block.classList.remove('sf-canvas-drop')}); + block.addEventListener('drop',event=>{if(!dragging)return;event.preventDefault();event.stopPropagation();block.classList.remove('sf-canvas-drop');if(dragging!==id)send('reorder',dragging,{targetId:id});dragging=''}); + } + // Rich text is not edited as plain text: modifying sanitized HTML would lose formatting. + for(const section of topSections){ + const id=section.dataset.block; + for(const [field,selector] of Object.entries(types)){ + const target=section.querySelector(selector);if(!target||target.closest('.sf-section[data-block]')!==section)continue; + target.title='双击直接修改'+(field==='title'?'标题':'描述'); + target.addEventListener('dblclick',event=>{ + event.stopPropagation();activate(id);const before=target.textContent; + target.contentEditable='true';target.classList.add('sf-canvas-editing');target.focus(); + let closed=false; + const finish=commit=>{ + if(closed)return;closed=true;target.removeAttribute('contenteditable');target.classList.remove('sf-canvas-editing'); + const value=target.textContent.replace(/\r/g,'').trim(); + if(!commit)target.textContent=before; + else if(value!==before&&value.length<=500)send('inline-text',id,{field,value}); + else if(value.length>500)target.textContent=before; + }; + target.addEventListener('blur',()=>finish(true),{once:true}); + target.addEventListener('keydown',e=>{if(e.key==='Escape'){e.preventDefault();finish(false);target.blur()}if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();target.blur()} }); + }); + } + } + // Children of every nested layout (including second-level content) are selectable. The parent + // checks IDs against the current schema and rejects forged/obsolete events. + const nested=Array.from(document.querySelectorAll('.sf-layout-column > .sf-section[data-block]')); + for(const child of nested){ + const layout=child.closest('.sf-layout-grid[data-layout]'); + if(!layout)continue; + const parentId=layout.dataset.layout,childId=child.dataset.block; + const push=(action,extra={})=>send(action,parentId,{childId,...extra}); + const toolbar=document.createElement('div');toolbar.className='sf-nested-toolbar';toolbar.setAttribute('role','toolbar');toolbar.setAttribute('aria-label','列内组件操作'); + for(const [symbol,label,action] of [['✎','编辑子组件','child-edit'],['↑','上移子组件','child-up'],['↓','下移子组件','child-down'],['⧉','复制子组件','child-duplicate'],['×','删除子组件','child-delete']]){ + const button=document.createElement('button');button.type='button';button.textContent=symbol;button.setAttribute('aria-label',label); + button.addEventListener('click',event=>{event.preventDefault();event.stopPropagation();push(action)}); + toolbar.appendChild(button); + } + child.prepend(toolbar); + child.addEventListener('click',event=>{if(event.target.closest('.sf-nested-toolbar'))return;if(event.target.closest('a'))event.preventDefault();event.stopPropagation();push('child-select')}); + // Only plain text fields are inline editable; rich HTML remains in the form. + for(const [field,selector] of Object.entries(types)){ + const node=child.querySelector(selector); + if(!node||node.closest('.sf-section[data-block]')!==child)continue; + node.title='双击编辑列内'+(field==='title'?'标题':'描述'); + node.addEventListener('dblclick',event=>{ + event.stopPropagation();push('child-select');const original=node.textContent; + node.contentEditable='true';node.classList.add('sf-canvas-editing');node.focus();let complete=false; + const finish=save=>{if(complete)return;complete=true;node.removeAttribute('contenteditable');node.classList.remove('sf-canvas-editing');const text=node.textContent.replace(/\r/g,'').trim();if(!save||text.length>500)node.textContent=original;else if(text!==original)push('child-inline-text',{field,value:text})}; + node.addEventListener('blur',()=>finish(true),{once:true}); + node.addEventListener('keydown',e=>{if(e.key==='Escape'){e.preventDefault();finish(false);node.blur()}if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();node.blur()}}); + }); + } + } + // Desktop-only handles keep the total adjacent width stable and never free-position blocks. + for(const grid of document.querySelectorAll('.sf-layout-grid[data-layout]')){ + const id=grid.dataset.layout; + const cols=Array.from(grid.children).filter(el=>el.classList.contains('sf-layout-column')); + if(cols.length<2)continue; + for(let i=0;i{const a=cols[i].getBoundingClientRect(),g=grid.getBoundingClientRect();handle.style.left=(a.right-g.left+parseFloat(getComputedStyle(grid).columnGap||'0')/2)+'px'}; + grid.appendChild(handle);place(); + handle.addEventListener('pointerdown',e=>{ + if(e.button!==0||matchMedia('(max-width:820px)').matches)return; + e.stopPropagation();e.preventDefault();handle.setPointerCapture(e.pointerId);handle.classList.add('sf-resizing'); + const raw=grid.style.getPropertyValue('--sf-layout-cols').trim().split(/\s+/).map(x=>parseFloat(x)||1); + const start=e.clientX,span=Math.max(50,cols[i].getBoundingClientRect().width+cols[i+1].getBoundingClientRect().width); + resize={id,i,raw,start,span};activate(id); + }); + handle.addEventListener('pointermove',e=>{ + if(!resize||resize.i!==i)return; + const v=resize.raw.slice(),total=v[i]+v[i+1];const delta=(e.clientX-resize.start)/resize.span*total; + v[i]=Math.round(Math.min(4,Math.max(.5,resize.raw[i]+delta))*100)/100; + v[i+1]=Math.round(Math.min(4,Math.max(.5,total-v[i]))*100)/100; + if(Math.abs(v[i]+v[i+1]-total)>0.011)return; + grid.style.setProperty('--sf-layout-cols',v.map(x=>x+'fr').join(' '));place(); + }); + const done=e=>{if(!resize||resize.i!==i)return;const raw=grid.style.getPropertyValue('--sf-layout-cols').trim().split(/\s+/).map(x=>parseFloat(x)||1);resize=null;handle.classList.remove('sf-resizing');send('resize-columns',id,{widths:raw});}; + handle.addEventListener('pointerup',done);handle.addEventListener('pointercancel',()=>{resize=null;handle.classList.remove('sf-resizing')}); + handle.addEventListener('keydown',e=>{if(e.key!=='ArrowLeft'&&e.key!=='ArrowRight')return;e.preventDefault();const w=grid.style.getPropertyValue('--sf-layout-cols').trim().split(/\s+/).map(x=>parseFloat(x)||1);const delta=e.key==='ArrowRight'?.1:-.1;const total=w[i]+w[i+1];const first=Math.round(Math.min(4,Math.max(.5,w[i]+delta))*100)/100,second=Math.round((total-first)*100)/100;if(second<.5||second>4)return;w[i]=first;w[i+1]=second;grid.style.setProperty('--sf-layout-cols',w.map(x=>x+'fr').join(' '));place();send('resize-columns',id,{widths:w})}); + new ResizeObserver(place).observe(grid); + } + } + window.addEventListener('message',event=>{ + if(event.source!==parent||event.data?.source!=='siteforge-studio-host')return; + if(event.data.action==='highlight'&&typeof event.data.blockId==='string'){activate(event.data.blockId,false);for(const n of nested)n.classList.toggle('sf-canvas-child-selected',n.dataset.block===event.data.childId);} + }); +})(); diff --git a/app/static/studio-experience-v829.js b/app/static/studio-experience-v829.js new file mode 100644 index 0000000..08ab7c4 --- /dev/null +++ b/app/static/studio-experience-v829.js @@ -0,0 +1,46 @@ +/* SiteForge V8.29: presentation-only studio helpers. No persisted-schema changes. */ +'use strict'; +(function(root){ + const themes=new Set(['automotive','industrial','corporate','minimal']); + const pages=new Set(['home','listing','product','article','about','contact']); + const categories={ + visual:new Set(['hero','banner','carousel','gallery','image','image_text','image-grid','video','slider']), + business:new Set(['collection','products','product_list','brand_wall','brands','features','stats','testimonials','faq','contact','form','cta','map']), + advanced:new Set(['layout','columns','tabs','accordion','html-embed','embed','spacer','divider']) + }; + function categoryOf(key){for(const [name,ids] of Object.entries(categories))if(ids.has(key))return name;return 'basic'} + function groupBlocks(blocks,query=''){ + const result={basic:[],visual:[],business:[],advanced:[]}; + const q=String(query).trim().toLocaleLowerCase().slice(0,70); + for(const [key,block] of Object.entries(blocks||{})){ + if(!block||typeof block!=='object')continue; + const text=[key,block.name,block.description].join(' ').toLocaleLowerCase(); + if(q&&!text.includes(q))continue; + result[categoryOf(key)].push({key,block}); + } + return result; + } + function previewUrl(theme,page){ + if(!themes.has(theme)||!pages.has(page))return null; + return `/api/factory/themes/${theme}/preview?page_type=${page}`; + } + /* Only CSS-token values accepted by the existing server-side block validator. */ + const designPalettes={ + automotive:['#ffffff','#14283d','#f3f6f9','#102e47'], + industrial:['#ffffff','#193f59','#eef5f8','#104a6d'], + corporate:['#ffffff','#262d58','#f4f3fb','#34397b'], + minimal:['#faf9f5','#292924','#f0efe9','#30302c'] + }; + function stylePreset(theme,preset){ + const [base,ink,soft,dark]=designPalettes[themes.has(theme)?theme:'corporate']; + switch(preset){ + case 'clean':return {background:base,text_color:ink,padding:72}; + case 'soft':return {background:soft,text_color:ink,padding:58}; + case 'feature':return {background:dark,text_color:'#ffffff',padding:90}; + default:return null; + } + } + const api=Object.freeze({categoryOf,groupBlocks,previewUrl,stylePreset}); + if(typeof module!=='undefined'&&module.exports)module.exports=api; + if(root)root.SiteForgeStudioExperience=api; +})(typeof window!=='undefined'?window:null); diff --git a/app/static/workspace-guide.js b/app/static/workspace-guide.js new file mode 100644 index 0000000..d2a598a --- /dev/null +++ b/app/static/workspace-guide.js @@ -0,0 +1,35 @@ +/* V8.27: pure journey model. Display only server-observed milestones as complete. */ +(function(root,factory){ + const api=factory(); + if(typeof module==='object'&&module.exports)module.exports=api; + else root.SiteForgeJourney=api; +})(typeof window!=='undefined'?window:this,function(){ + 'use strict'; + const successful=new Set(['complete','completed','done','success']); + const active=new Set(['queued','running','retrying']); + function parse(t){const d=Date.parse(t||'');return Number.isFinite(d)?d:null} + function plan(input){ + const site=input?.site||null, entries=input?.entries||[], builds=input?.builds||[], jobs=input?.jobs||[], history=input?.delivery?.history||[]; + if(!site)return {ready:false,steps:[],next:null,completed:0,hasBuild:false,live:false}; + const userEntries=entries.filter(e=>e.source!=='starter' && e.status!=='draft'); + const manuallyEditedHome=entries.some(e=>e.route==='/'&&e.status!=='draft'&&e.source==='starter'&&parse(e.updated_at)!==null&&parse(e.created_at)!==null&&parse(e.updated_at)>parse(e.created_at)+1000); + const hasContent=userEntries.length>0||manuallyEditedHome; + const lastBuild=builds.filter(x=>successful.has(x.status)).sort((a,b)=>(parse(b.created_at)||0)-(parse(a.created_at)||0))[0]||null; + const anyRunning=jobs.some(x=>active.has(x.state)); + const changeTimes=[site.updated_at,...entries.filter(e=>e.status!=='draft').map(e=>e.updated_at)].map(parse).filter(x=>x!==null); + const changedAfterBuild=!!lastBuild&&changeTimes.some(x=>{const built=parse(lastBuild.created_at);return built!==null&&x>built+1000}); + const hasBuild=!!lastBuild; + const live=history.some(x=>x.target==='production' && !!x.release_id && !x.is_rollback); + const domain=Boolean((site.domain||'').trim()); + const steps=[ + {id:'site',label:'创建网站',hint:'网站已经建立,基础资料可以随时修改。',view:'settings',done:true,optional:false}, + {id:'content',label:'准备网站内容',hint:hasContent?'已有人工添加的正式内容。':'添加页面、产品或导入旧站内容。新建时自带的示例首页不代表内容已准备好。',view:site.mode==='migration'?'import':'content',done:hasContent,optional:false}, + {id:'design',label:'调整网站样式',hint:'可视化修改页面、页眉、导航和手机布局;设计需人工确认。',view:'design',done:false,optional:true}, + {id:'build',label:'生成并预览网站',hint:anyRunning?'后台正在生成,请在构建页面查看结果。':!hasBuild?'生成静态页面后,再检查预览与质量报告。':changedAfterBuild?'已有构建版本,但内容可能已更新,请检查是否需要重新构建。':'已有构建版本;仍需人工检查预览、图片和 SEO。',view:'build',done:hasBuild&&!changedAfterBuild,optional:false}, + {id:'review',label:'审核并正式上线',hint:live?'存在正式发布记录,请核对目标网址是否正确显示。':'正式上线前需要发布条件检查、独立审批与服务器部署。',view:'launch',done:live,optional:false} + ]; + const next=steps.find(s=>!s.optional&&!s.done)||steps[4]; + return {ready:true,steps,next,completed:steps.filter(s=>!s.optional&&s.done).length,hasBuild,changedAfterBuild,live,domain,anyRunning}; + } + return {plan}; +}); diff --git a/app/static/workspace-launch.js b/app/static/workspace-launch.js new file mode 100644 index 0000000..bfda441 --- /dev/null +++ b/app/static/workspace-launch.js @@ -0,0 +1,22 @@ +/* V8.28: untrusted display state only; final authorization always on server. */ +(function(root,factory){const api=factory();if(typeof module==='object'&&module.exports)module.exports=api;else root.SiteForgeLaunch=api;})(typeof window!=='undefined'?window:this,function(){ + 'use strict'; + const finished=new Set(['complete','completed','done','success']); + function plan({site=null,build=null,requests=[],requestsKnown=false,delivery={},target='staging',previewChecked=false,preflight=null}={}){ + const version=build&&finished.has(build.status)?build:null; + const bids=version?.id; + const rows=Array.isArray(requests)?requests.filter(x=>x.build_id===bids):[]; + const approval=rows.some(x=>x.state==='approved')?'approved':rows.some(x=>x.state==='pending')?'pending':rows.some(x=>x.state==='rejected')?'rejected':requestsKnown&&Array.isArray(requests)?'none':'unknown'; + const safeTarget=['staging','production'].includes(target)?target:'staging'; + const preflightReady=Boolean(version&&preflight?.siteId===site?.id&&preflight?.buildId===version.id&&preflight?.target===safeTarget&&preflight?.ready===true); + const preflightMessage=preflightReady?'服务器已通过检查,部署时还会重新验证。':preflight?.siteId===site?.id&&preflight?.buildId===bids?preflight.message:'尚未完成此版本的发布前检查'; + const configured=delivery?.configured?.[safeTarget]===true; + const canDeploy=Boolean(version&&previewChecked&&approval==='approved'&&preflightReady&&configured); + const history=Array.isArray(delivery?.history)?delivery.history:[]; + const matches=history.filter(x=>x.target===safeTarget&&x.release_id&&x.build_id===bids); + return {approval,canDeploy,preflightReady,preflightMessage,hasRemoteRecord:matches.length>0, + remoteDescription:matches.length?'存在当前版本的部署记录,但尚需实际访问确认。':'尚无当前版本在该环境的部署记录。',configured, + target:safeTarget,hasBuild:!!version}; + } + return {plan}; +}); diff --git a/app/static/workspace.css b/app/static/workspace.css index a3f3fb9..51918cf 100644 --- a/app/static/workspace.css +++ b/app/static/workspace.css @@ -3,4 +3,45 @@ /* V8.12: task progress and dangerous actions, consistent focus and mobile sizing */ .btn-danger{border:1px solid #f1c3c7;color:#a92840;background:#fff5f6}.btn-danger:hover{background:#feecee}.btn:disabled{opacity:.55;cursor:not-allowed}.build-row{min-width:0}.build-meta{overflow-wrap:anywhere}.site-card:focus-visible,.quick-card:focus-visible{outline:3px solid #80aaf6;outline-offset:2px}@media(max-width:570px){.build-row{align-items:flex-start;flex-wrap:wrap}.build-row>.inline-actions{width:100%;padding-left:0}.site-picker-wrap select{max-width:130px}} +/* V8.27 guided creation and actionable journey. Keep the original admin styling. */ +[hidden]{display:none!important} +.sf-create-dialog .modal-inner{max-width:650px}.sf-create-dialog .modal-top h2{margin-bottom:4px} +.sf-create-progress{list-style:none;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:2px 0 22px;padding:0} +.sf-create-progress li{border-bottom:3px solid #dde6f1;padding:9px 2px 11px;color:#8391a3;text-align:center;font-size:12px} +.sf-create-progress li[aria-current=step]{border-color:var(--blue);color:var(--blue);font-weight:750} +.sf-create-step h3{font-size:19px;margin:10px 0}.sf-guide-desc{font-size:13px;color:var(--muted);line-height:1.7;margin:6px 0 24px} +.sf-required{font-size:11px;color:#aa4c3f}.sf-create-summary{border:1px solid #dbe5f0;border-radius:12px;background:#f8fafc;padding:13px 18px;margin:15px 0 22px} +.sf-create-summary p{margin:10px 0;overflow-wrap:anywhere}.sf-guide-safety{border-radius:10px;background:#eff5ff;color:#4a6282;padding:13px 15px;line-height:1.7;margin:18px 0} +.sf-create-error{color:#ab2537;background:#fff2f2;border:1px solid #f4cbd0;padding:11px;border-radius:8px} +.sf-journey-prompt,.sf-journey-intro{display:flex;align-items:center;justify-content:space-between;gap:22px;background:white;border:1px solid var(--line);border-radius:14px;padding:20px 24px;margin:16px 0} +.sf-journey-prompt p,.sf-journey-intro p{line-height:1.65;color:var(--muted);margin:7px 0 0}.sf-journey-intro h2{font-size:24px;margin:5px 0}.sf-journey-eyebrow{color:var(--muted);font-size:12px} +.sf-journey-progress{display:grid;text-align:center;border-radius:12px;background:#eff5ff;padding:13px 20px;min-width:130px} +.sf-journey-progress strong{font-size:28px;color:var(--blue)}.sf-journey-progress span{font-size:11px;color:var(--muted)} +.sf-journey-list{margin:16px 0 22px;padding:0;list-style:none;display:grid;gap:10px} +.sf-journey-step{display:grid;grid-template-columns:38px minmax(0,1fr) auto;gap:18px;align-items:center;background:white;border:1px solid var(--line);border-radius:13px;padding:17px 19px} +.sf-journey-step.is-next{border-color:#aac1f2;box-shadow:0 0 0 2px #eff5ff} +.sf-journey-number{width:34px;height:34px;border:1px solid #dde5ef;border-radius:50%;background:#f4f7fa;display:grid;place-items:center;color:#6b788b;font-weight:700} +.sf-journey-step.is-done .sf-journey-number{background:#e7f7f0;color:#16835a;border-color:#cbebde} +.sf-journey-title{display:flex;align-items:center;gap:12px;flex-wrap:wrap} +.sf-journey-title strong{font-size:15px}.sf-journey-title span{color:#6b7b8d;font-size:11px} +.sf-journey-step p{color:var(--muted);font-size:12px;line-height:1.65;margin:6px 0 0} +.sf-journey-after,.sf-journey-notice{background:white;border:1px solid var(--line);border-radius:13px;padding:20px 22px;margin:16px 0} +.sf-journey-after h2{font-size:17px;margin:0 0 14px}.sf-glossary-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px} +.sf-glossary-grid p{margin:0;padding:12px;background:#f7f9fc;border-radius:9px}.sf-glossary-grid strong{display:block;margin-bottom:6px}.sf-glossary-grid span{display:block;color:var(--muted);font-size:12px;line-height:1.7} +.sf-journey-notice{background:#fffdf6;color:#705d35;line-height:1.8} +@media(max-width:680px){.sf-journey-step{grid-template-columns:34px minmax(0,1fr);gap:11px}.sf-journey-step>.btn{grid-column:2;width:max-content}.sf-journey-intro,.sf-journey-prompt{flex-direction:column;align-items:stretch}.sf-glossary-grid{grid-template-columns:1fr}.sf-journey-progress{max-width:190px}} +/* V8.28: calm, readable launch center for nontechnical users */ +.sf-launch-hero{background:#fff;border:1px solid var(--line);border-radius:14px;padding:23px;display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:19px} +.sf-launch-hero h2{margin:5px 0;font-size:22px}.sf-launch-hero p{margin:5px 0;color:var(--muted);line-height:1.65;max-width:700px} +.sf-launch-hero>strong{padding:9px 14px;background:#edf3ff;color:#245ac6;border-radius:30px;white-space:nowrap;font-size:12px} +.sf-launch-step{display:grid;grid-template-columns:40px minmax(0,1fr);gap:17px;background:#fff;border:1px solid var(--line);border-radius:14px;padding:20px 22px;margin-bottom:12px} +.sf-launch-step.is-ready{border-color:#b4e2cf}.sf-launch-index{width:34px;height:34px;border-radius:50%;background:#eef3fb;color:#38577f;display:grid;place-items:center;font-weight:750} +.sf-launch-step.is-ready .sf-launch-index{background:#e0f5eb;color:#197a54}.sf-launch-detail{min-width:0}.sf-launch-detail h2{margin:1px 0 6px;font-size:16px} +.sf-launch-detail>p{color:var(--muted);font-size:13px;margin:0 0 14px;line-height:1.7} +.sf-launch-controls{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.sf-launch-field{display:grid;gap:6px;font-size:12px;font-weight:650;color:#495d73;min-width:200px;max-width:350px} +.sf-launch-field select{width:100%}.sf-launch-check{display:flex;align-items:center;gap:8px;font-size:12px;color:#425572;padding:10px;border-radius:8px;background:#f6f9fd} +.sf-launch-check input{width:18px;height:18px;flex-shrink:0}.sf-launch-status{font-size:12px;color:#657589;max-width:600px} +.sf-launch-notice{padding:16px 18px;border-radius:10px;background:#edf3ff;color:#244f82;margin:15px 0;line-height:1.75} +@media(max-width:620px){.sf-launch-hero{flex-direction:column;align-items:start}.sf-launch-step{padding:16px;gap:11px;grid-template-columns:32px minmax(0,1fr)}.sf-launch-controls{align-items:stretch;flex-direction:column}.sf-launch-field,.sf-launch-controls>.btn{width:100%;max-width:none}.sf-launch-check{align-items:start}} + .theme-preview.trade-pro{background:linear-gradient(125deg,#0b3d91,#3d6dc1);color:#e8f1fb}.site-icon.trade-pro{background:#e8f1fb;color:#0b3d91} diff --git a/app/static/workspace.js b/app/static/workspace.js index e9b78a5..35fd141 100644 --- a/app/static/workspace.js +++ b/app/static/workspace.js @@ -7,8 +7,8 @@ const typeName={page:'页面',product:'产品',vehicle:'车型',post:'新闻',br const fmtDate=t=>{if(!t)return '—';const d=new Date(t);return Number.isNaN(d.getTime())?String(t).slice(0,16):d.toLocaleDateString('zh-CN',{year:'numeric',month:'2-digit',day:'2-digit'})}; const sfSiteKey='siteforge:selected-site'; const sfRemember=id=>{try{if(id)localStorage.setItem(sfSiteKey,id)}catch{}}; -const state={sites:[],site:null,entries:[],builds:[],jobs:[],view:'home',csrf:'',search:'',typ:'',loading:false,job:null,selectionToken:0,building:false,delivery:{jobs:[],history:[],configured:{}},language:{group:null,sites:[],units:[]},languageGroups:[],languageEntries:[]}; -const headings={home:'工作台',sites:'我的网站',overview:'网站概览',content:'内容与页面',design:'外观与设计',import:'导入与迁移',build:'构建与交付',languages:'多语言管理',settings:'网站设置'}; +const state={launchDeploying:false,releaseRequestSeq:0,releaseRequests:[],releaseRequestsKnown:false,launchBuildId:'',launchTarget:'staging',launchReview:false,launchPreflight:null,sites:[],site:null,entries:[],builds:[],jobs:[],view:'home',csrf:'',search:'',typ:'',loading:false,job:null,selectionToken:0,building:false,delivery:{jobs:[],history:[],configured:{}},language:{group:null,sites:[],units:[]},languageGroups:[],languageEntries:[]}; +const headings={home:'工作台',sites:'我的网站',guide:'建站操作指引',launch:'上线操作中心',overview:'网站概览',content:'内容与页面',design:'外观与设计',import:'导入与迁移',build:'生成与预览',languages:'多语言管理',settings:'网站设置'}; async function api(url,method='GET',data=null,extraHeaders={}){ const headers={...extraHeaders};if(method!=='GET'&&method!=='HEAD')headers['X-SiteForge-CSRF']=state.csrf; let body=data;if(data!=null && !(data instanceof FormData)){headers['Content-Type']='application/json';body=JSON.stringify(data)} @@ -49,20 +49,74 @@ function sites(){return htmlHeading('我的网站','统一管理所有网站项 function currentSite(){return !!state.site} function noSite(){return htmlHeading('请先选择一个网站','选择现有网站或创建新网站,才能继续进行内容编辑、迁移和构建。')+emptyState('尚未选择网站','点击右上角选择网站,或直接创建一个新的企业网站。',actionButton('+ 创建网站','new-site'))} function latestDone(){return state.builds.find(b=>['done','complete','success','completed'].includes(b.status))||null} -function overview(){const s=state.site;if(!s)return noSite();const count=state.entries.length;const build=latestDone();const hasContent=buildReadyStep();const hasDomain=!!s.domain;const steps=[ - {title:'建立网站',desc:'选择行业主题并创建项目',done:true,view:'settings'}, - {title:'准备内容',desc:'添加页面、产品或导入旧数据',done:hasContent,view:'content'}, - {title:'调整设计',desc:'可反复完善主题、导航和移动端样式',optional:true,view:'design'}, - {title:'构建并检查',desc:'生成静态网站,查看质量报告',done:!!build,view:'build'}]; - const next=!hasContent?steps[1]:!build?steps[3]:null; - return htmlHeading(s.name,'这里显示真实的内容和构建状态。设计可随时调整,正式上线需要单独审核。',actionButton('↗ 构建网站','build-now'))+ - `
${next?'建议下一步:'+next.title:'网站已经生成过构建版本'}

${next?next.desc:'内容或设计有修改时,重新构建并检查新版即可。'}。${!hasDomain?'正式域名还未填写;测试预览不受影响。':''}

`+ - `
${stat('网站内容',count,'▧')}${stat('已构建版本',state.builds.length,'↗')}${stat('当前主题',themeName[s.theme]||'企业品牌','◈')}${stat('域名状态',hasDomain?'已填写':'待设置','◎')}
`+ - `

四步完成网站制作

步骤反映已有数据,设计可以随时修改,不会虚报“设计完成”。

`+ - `
${steps.map((step,i)=>`
${step.done?'✓':step.optional?'◈':i+1}

${step.title}${step.optional?'(持续优化)':''}

${step.desc}

`).join('')}
`+ - `

常用操作

通常只需要下面三个入口。

`+ - `
${overviewShortcut('content','▧','添加和编辑内容','管理页面、产品、新闻和案例。')}${overviewShortcut('design','◈','修改网站样式','更换主题、编辑页面和移动端样式。')}${overviewShortcut('build','↗','查看和下载网站','查看任务状态、预览及下载静态网站。')}
`; +function overview(){ + const s=state.site;if(!s)return noSite(); + const journey=window.SiteForgeJourney?.plan({site:s,entries:state.entries,builds:state.builds,jobs:state.jobs,delivery:state.delivery}); + const next=journey?.next||{label:'查看操作指引',hint:'检查各步骤是否已经完成。',view:'guide'}; + const contentCount=state.entries.filter(e=>e.source!=='starter').length; + return htmlHeading(s.name,'所有网站操作都从这里开始;保存内容、生成网站和正式上线是不同的步骤。',``)+ + `
建议下一步

${esc(next.label)}

${esc(next.hint)}

`+ + `
${stat('人工添加的内容',contentCount,'▧')}${stat('静态构建版本',state.builds.length,'↗')}${stat('当前主题',themeName[s.theme]||'企业品牌','◈')}${stat('正式域名',s.domain?'已填写':'未设置','◎')}
`+ + `

最常用的三项操作

不需要了解技术细节,选择你想完成的事情即可。

`+ + `
${overviewShortcut('content','▧','修改文字和产品','填写网站内容,修改已经创建的页面。')}${overviewShortcut('design','◈','调整网页外观','编辑图片、版式、导航和手机端。')}${overviewShortcut('launch','↗','检查并上线网站','一步一步完成预览、审批和正式部署。')}
`+ + `
关于上线:页面编辑和保存不会自动修改线上网站。上线仍需生成静态版本、检查、独立审批和部署。
`; } +function guide(){ + if(!currentSite())return noSite(); + const journey=window.SiteForgeJourney?.plan({site:state.site,entries:state.entries,builds:state.builds,jobs:state.jobs,delivery:state.delivery}); + if(!journey)return htmlHeading('建站操作指引','操作引导暂时无法加载,请刷新网页。'); + const checked=journey.completed; + const rows=journey.steps.map((step,i)=>{ + const label=step.optional?'可选:随时完善':step.done?'已记录完成':step.id===journey.next.id?'建议现在进行':'等待前面的步骤'; + return `
  • + +
    ${esc(step.label)}${esc(label)}
    +

    ${esc(step.hint)}

    + +
  • `; + }).join(''); + return htmlHeading('建站操作指引','按照实际操作顺序完成网站制作,系统只根据已保存的数据与任务记录显示进度。')+ + `
    当前项目

    ${esc(state.site.name)}

    ${esc(journey.next.hint)}

    +
    ${checked}/4已记录的必要步骤
    +
      ${rows}
    +

    保存、构建和上线有什么不同?

    +

    保存内容把修改写入管理系统,外部访客还看不到新版。

    +

    生成网站制作一份可预览、可下载的静态网站版本。

    +

    检查与审批核对页面、图片、网址和 SEO,并取得相应审批。

    +

    正式上线把批准的版本部署到正式服务器,再核对公网访问。

    +
    重要说明:${journey.live?'系统发现正式发布记录,但无法仅凭该记录确认当前公网网站可访问,请人工检查实际域名。':'当前没有可确认的正式发布记录;生成 ZIP 或点击“发布设计”都不代表网站已上线。'}${journey.changedAfterBuild?' 网站内容在最近一次构建后可能有变化,建议重新构建并预览。':''}${!journey.domain?' 正式域名尚未填写,不影响预览。':''}
    `; +} +// V8.28 guided delivery: one deliberate action per stage, existing secure APIs only. +function launch(){ + if(!currentSite())return noSite(); + const buildList=state.builds.filter(b=>b.status==='complete'); + const selection=buildList.find(b=>b.id===state.launchBuildId)||buildList[0]||null; + const selected=selection?.id||''; + if(selected&&!state.launchBuildId){state.launchBuildId=selected;state.launchReview=false;state.launchPreflight=null;} + const requests=state.releaseRequests.filter(r=>r.build_id===selected); + const result=window.SiteForgeLaunch?.plan({site:state.site,build:selection,requests,requestsKnown:state.releaseRequestsKnown, + delivery:state.delivery,target:state.launchTarget,previewChecked:state.launchReview,preflight:state.launchPreflight}); + const row=(index,name,body,controls,kind='')=>`
    ${index}

    ${esc(name)}

    ${esc(body)}

    ${controls}
    `; + const buildOptions=buildList.map(b=>``).join(''); + const select=``; + const checked=Boolean(state.launchReview&&selected); + const canRequestApproval=Boolean(selected&&checked&&state.releaseRequestsKnown&&['none','rejected'].includes(result?.approval)); + const preview=selected?`打开网站预览 ↗`:``; + const approvalText=result?.approval==='approved'?'已由其他审核人批准。':result?.approval==='pending'?'已提交审批,请由其他有审核权限的人员处理。':result?.approval==='rejected'?'最近申请被驳回,请解决问题后重新申请。':!state.releaseRequestsKnown?'审批记录暂时无法确认,请刷新或到审批中心查询。':'尚无已批准的申请。'; + const config=Boolean(state.delivery.configured?.[state.launchTarget]); + const domainUrl=/^https:\/\/[^\s<>]+$/i.test(state.site.domain||'')?state.site.domain:''; + const deploymentText=state.launchTarget==='production'?'正式环境':'测试环境'; + return htmlHeading('上线操作中心','按顺序完成检查和审核,每一步都解释操作用途。网站不会因为保存、预览或提交审批而自动上线。',``)+ + `
    当前网站

    ${esc(state.site.name)}

    上线属于独立审批和服务器部署流程;如有不确定之处,可以随时离开,已经保存的记录不会消失。

    ${result?.approval==='approved'?'已获审批':result?.approval==='pending'?'等待审批':selected?'准备上线':'请先构建'}
    `+ + row('1','选择网站版本','选择已生成成功、准备交付的静态版本。内容有变更时需要重新构建。',select+``,selected?'is-ready':'')+ + row('2','预览网站并检查质量','在新窗口检查页面、图片、移动端、链接和 SEO。质量报告是自动检查,仍需要人工确认。',preview+``,checked?'is-ready':'')+ + row('3','提交给其他人审批',approvalText,`查看审批中心 ↗`,result?.approval==='approved'?'is-ready':'')+ + row('4','检查正式发布条件','审批通过后,再检查构建质量、旧站迁移复核和发布归档是否满足条件。',`${esc(result?.preflightMessage||'尚未完成此版本的发布前检查')}`,result?.preflightReady?'is-ready':'')+ + row('5','提交服务器部署','只有目标环境已配置、审批通过且发布前检查成功,才能从这里提交部署任务。',`${state.delivery.unavailable?'无法读取发布目标状态,请刷新或联系管理员。':config?'目标服务器已配置':'当前环境没有配置可用的发布目标,请联系管理员。'}`,result?.hasRemoteRecord?'is-ready':'')+ + row('6','核对网站是否真正上线','提交部署只是创建任务。请确认任务成功,再在真实域名检查页面和联系表单。',`${domainUrl?`打开正式域名 ↗`:''}

    ${esc(result?.remoteDescription||'未确认有当前环境的部署记录。')} 系统不会仅凭发布记录声称公网验收通过。

    `)+ + `
    注意:这里的确认只影响当前操作界面,正式发布仍由服务器重新验证权限、审批、质量、文件和目标配置。页面预览正常也不代表公网已上线。
    ${esc(state.launchMessage||'')}
    `; +} + function content(){if(!currentSite())return noSite();let arr=state.entries.filter(e=>(!state.typ||e.type===state.typ)&&(!state.search||`${e.title} ${e.route}`.toLowerCase().includes(state.search.toLowerCase()))); return htmlHeading('内容与页面','所有网页、产品、车型和新闻都在这里维护,保存后重新构建即可更新网站。',actionButton('+ 添加内容','new-entry'))+ `

    内容列表

    共 ${state.entries.length} 条内容。点击“设计页面”可进行可视化排版。

    `+ @@ -80,20 +134,20 @@ function imports(){if(!currentSite())return noSite();return htmlHeading('导入 `
    迁移旧网站请注意:如果需要保留旧 URL、原有 SEO、复杂插件字段和全部图片,请优先使用 WordPress 迁移工作台,而不是仅上传一个内容文件。
    `; } function builds(){if(!currentSite())return noSite();const latest=latestDone();const pending=activeJobs();const first=pending[0]; - return htmlHeading('构建与交付','网站构建由独立 Worker 执行。离开页面或刷新后仍可查看任务状态。',``)+ + return htmlHeading('生成与预览','先生成网站版本,确认效果后再使用上线操作中心提交审批。任务会在后台执行。',``)+ `
    ${first?'当前:'+buildStatusLabel(first.state):latest?'已有构建版本,可以预览':'还没有已完成的网站构建'}

    ${first?'当前任务 '+esc(first.id.slice(0,12))+';Worker 在后台执行,您可以关闭此页面。':'内容或设计有更新时,重新生成网站版本。'}

    `+ `

    后台任务

    可以查看任务状态。仅取消当前仍在队列或运行中的构建。

    ${esc(state.job||'')}
    `+ (state.jobs.length?state.jobs.slice(0,8).map(j=>`
    ${j.state==='done'?'✓':j.state==='failed'?'!':'◷'}

    ${esc(buildStatusLabel(j.state))}

    ${esc(fmtDate(j.created_at))} · 任务 ${esc(j.id.slice(0,12))}${j.state==='failed'&&j.error?' · '+esc(j.error):''}

    ${['queued','running','retrying'].includes(j.state)?``:''}
    `).join(''):'

    当前网站还没有后台构建任务。

    ')+`
    `+ `

    构建版本

    建议先预览和核对质量报告,再下载 ZIP。预览不代表正式发布。

    `+ (state.builds.length?state.builds.slice(0,20).map(b=>`
    ${['done','completed','success','complete'].includes(b.status)?'✓':'◷'}

    ${esc(fmtDate(b.created_at))} · ${esc(b.total_pages||'—')} 个页面

    版本 ${esc(b.id.slice(0,12))} · ${esc(b.status||'未知')}

    ${['done','completed','success','complete'].includes(b.status)?`预览 ↗下载 ZIP`:'尚未完成,暂不能下载'}
    `).join(''):emptyState('尚无完成版本','准备好网站数据后,在上方提交构建任务。'))+ `
    `+ - `

    正式发布与回滚

    先完成质量检查与独立审批,Worker 负责上传、校验和切换版本。没有配置目标服务器时不能发布。

    审批与复核工具 ↗
    + `
    下一步:预览检查后提交审批

    完成构建后,请在上线操作中心按照步骤检查质量、提交审批并部署。

    高级:直接进行发布和历史版本回滚

    正式发布与回滚

    先完成质量检查与独立审批,Worker 负责上传、校验和切换版本。没有配置目标服务器时不能发布。

    审批与复核工具 ↗

    最近发布任务

    ${(state.delivery.jobs||[]).length?state.delivery.jobs.slice(0,8).map(j=>`
    ${j.kind==='remote_rollback'?'回滚':'部署'} · ${esc(buildStatusLabel(j.state))}

    ${esc(j.id.slice(0,12))} · ${esc(j.created_at)}${j.error?' · '+esc(j.error):''}

    ${['queued','running','retrying'].includes(j.state)?``:''}
    `).join(''):'

    暂无发布任务。

    '} -

    已发布版本

    ${(state.delivery.history||[]).length?state.delivery.history.slice(0,8).map(r=>`
    ${esc(r.target)} · ${esc(r.release_id)}

    构建 ${esc(r.build_id.slice(0,12))} · ${esc(r.deployed_at)}

    `).join(''):'

    当前没有远程部署记录。

    '}
    `; +

    已发布版本

    ${(state.delivery.history||[]).length?state.delivery.history.slice(0,8).map(r=>`
    ${esc(r.target)} · ${esc(r.release_id)}

    构建 ${esc(r.build_id.slice(0,12))} · ${esc(r.deployed_at)}

    `).join(''):'

    当前没有远程部署记录。

    '}
    `; } function settings(){if(!currentSite())return noSite();const s=state.site;return htmlHeading('网站设置','这里只管理公司资料、域名与站点属性。网页样式请到“外观与设计”修改。')+ `

    基本资料

    没有域名也可以制作与预览网站,正式上线前再填写即可。

    `; @@ -125,29 +179,93 @@ async function submitLanguageUnit(ev){ev.preventDefault();const d=Object.fromEnt async function submitLanguageLink(ev){ev.preventDefault();const d=Object.fromEntries(new FormData(ev.target));try{await api('/api/i18n/groups/'+state.language.group.group_id+'/units/'+encodeURIComponent(d.unit_id)+'/members','POST',{site_id:d.site_id,entry_id:d.entry_id,state:d.state});toast('内容翻译关系已保存');await loadLanguage()}catch(e){notifyError(e)}} function rerender(){const area=$('#mainContent');const selected=state.view;$('#breadcrumbTitle').textContent=headings[selected]||'工作台';$('#sideSiteName').textContent=state.site?.name||'请先选择网站'; document.querySelectorAll('[data-view].nav-item').forEach(el=>{const yes=el.dataset.view===selected;el.classList.toggle('active',yes);yes?el.setAttribute('aria-current','page'):el.removeAttribute('aria-current')}); - area.innerHTML=({home,sites,overview,content,design,import:imports,build:builds,languages,settings}[selected]||home)(); + area.innerHTML=({home,sites,overview,guide,launch,content,design,import:imports,build:builds,languages,settings}[selected]||home)(); } async function loadSites(){state.sites=await api('/api/sites');const picker=$('#sitePicker'),prev=state.site?.id||'';picker.innerHTML=''+state.sites.map(s=>``).join('');picker.value=state.sites.some(s=>s.id===prev)?prev:''} -async function readDelivery(siteId){try{return await api(`/api/production/sites/${encodeURIComponent(siteId)}/delivery-status`)}catch(e){return {jobs:[],history:[],configured:{}}}} +async function readDelivery(siteId){try{return await api(`/api/production/sites/${encodeURIComponent(siteId)}/delivery-status`)}catch(e){return {jobs:[],history:[],configured:{},unavailable:true}}} async function readJobs(siteId){try{return await api(`/api/enterprise/sites/${encodeURIComponent(siteId)}/jobs`)}catch(e){if(![403,404].includes(Number(e.status)))console.warn('加载任务状态失败',e);return []}} async function selectSite(id,go='overview',historyMode='push'){ const token=++state.selectionToken; - if(!id){state.site=null;state.entries=[];state.builds=[];state.jobs=[];state.delivery={jobs:[],history:[],configured:{}};state.job=null;state.view=go==='home'?'home':'sites';$('#sitePicker').value='';rerender();if(historyMode!=='none')rememberView(historyMode==='replace');return} + if(!id){state.site=null;resetLaunch();state.entries=[];state.builds=[];state.jobs=[];state.delivery={jobs:[],history:[],configured:{}};state.job=null;state.view=go==='home'?'home':'sites';$('#sitePicker').value='';rerender();if(historyMode!=='none')rememberView(historyMode==='replace');return} if(!state.sites.some(x=>x.id===id)){toast('该网站不在您的可见列表中',true);return} try{const [site,entries,builds,jobs,delivery]=await Promise.all([api(`/api/sites/${encodeURIComponent(id)}`),api(`/api/sites/${encodeURIComponent(id)}/entries`),api(`/api/sites/${encodeURIComponent(id)}/builds`),readJobs(id),readDelivery(id)]); if(token!==state.selectionToken)return; - state.site=site;sfRemember(id);state.entries=entries;state.builds=builds;state.jobs=jobs;state.delivery=delivery;state.job=null;state.view=go;state.search='';state.typ='';$('#sitePicker').value=id;rerender();if(historyMode!=='none')rememberView(historyMode==='replace');if(go==='languages')loadLanguage();closeMobile();window.scrollTo({top:0,behavior:'instant'}); + state.site=site;resetLaunch();sfRemember(id);state.entries=entries;state.builds=builds;state.jobs=jobs;state.delivery=delivery;state.job=null;state.view=go;state.search='';state.typ='';$('#sitePicker').value=id;rerender();if(historyMode!=='none')rememberView(historyMode==='replace');if(go==='languages')loadLanguage();if(go==='launch')loadReleaseRequests();closeMobile();window.scrollTo({top:0,behavior:'instant'}); }catch(e){if(token===state.selectionToken)notifyError(e)} } -function navigate(to,historyMode='push'){if(!state.site&&!['home','sites'].includes(to)){state.view='sites';rerender();toast('请先选择网站项目');return}state.view=to;rerender();closeMobile();if(historyMode!=='none')rememberView(historyMode==='replace');if(to==='build')refreshBuilds();if(to==='languages')loadLanguage();window.scrollTo({top:0,behavior:'instant'})} -async function refreshBuilds(){const id=state.site?.id;if(!id)return;try{const previouslyRunning=activeJobs().length>0;const [jobs,builds,delivery]=await Promise.all([readJobs(id),api(`/api/sites/${encodeURIComponent(id)}/builds`),readDelivery(id)]);if(state.site?.id!==id)return;state.jobs=jobs;state.builds=builds;state.delivery=delivery;if(previouslyRunning&&!activeJobs().length){const last=jobs[0];state.job=last?.state==='done'?'后台构建已完成,请预览并查看质量报告。':last?.state==='failed'?'本次构建失败,请在任务中心检查原因。':last?.state==='cancelled'?'本次构建已取消。':null}if(state.view==='build')rerender()}catch(e){notifyError(e)}} +function navigate(to,historyMode='push'){if(!state.site&&!['home','sites'].includes(to)){state.view='sites';rerender();toast('请先选择网站项目');return}state.view=to;rerender();closeMobile();if(historyMode!=='none')rememberView(historyMode==='replace');if(to==='build'||to==='launch')refreshBuilds();if(to==='launch')loadReleaseRequests();if(to==='languages')loadLanguage();window.scrollTo({top:0,behavior:'instant'})} +async function refreshBuilds(){const id=state.site?.id;if(!id)return;try{const previouslyRunning=activeJobs().length>0;const [jobs,builds,delivery]=await Promise.all([readJobs(id),api(`/api/sites/${encodeURIComponent(id)}/builds`),readDelivery(id)]);if(state.site?.id!==id)return;state.jobs=jobs;state.builds=builds;state.delivery=delivery;if(state.view==='launch'){const selected=state.launchBuildId;const stillValid=builds.some(b=>b.id===selected&&b.status==='complete');if(selected&&!stillValid){state.launchBuildId='';state.launchReview=false;state.launchPreflight=null;state.launchMessage='原先选择的构建版本已不可用,请重新选择并核对。'}}if(previouslyRunning&&!activeJobs().length){const last=jobs[0];state.job=last?.state==='done'?'后台构建已完成,请预览并查看质量报告。':last?.state==='failed'?'本次构建失败,请在任务中心检查原因。':last?.state==='cancelled'?'本次构建已取消。':null}if(['build','launch'].includes(state.view))rerender()}catch(e){notifyError(e)}} +function resetLaunch(){state.releaseRequestSeq++;state.launchDeploying=false;state.releaseRequests=[];state.releaseRequestsKnown=false;state.launchBuildId='';state.launchTarget='staging';state.launchReview=false;state.launchPreflight=null;state.launchMessage=''} +async function loadReleaseRequests(){const siteId=state.site?.id;if(!siteId)return;const seq=++state.releaseRequestSeq;try{ + const rows=await api(`/api/factory/sites/${encodeURIComponent(siteId)}/release-requests`); + if(state.site?.id!==siteId||seq!==state.releaseRequestSeq)return; + state.releaseRequests=Array.isArray(rows)?rows:[];state.releaseRequestsKnown=true; + }catch(e){if(state.site?.id!==siteId||seq!==state.releaseRequestSeq)return;state.releaseRequestsKnown=false;state.releaseRequests=[];if(![403,404].includes(Number(e.status)))console.warn('读取审批记录失败',e)} + if(state.view==='launch')rerender(); +} +async function launchRefresh(){if(!state.site)return;const siteId=state.site.id;await Promise.all([refreshBuilds(),loadReleaseRequests()]);if(state.site?.id!==siteId)return;state.launchMessage='状态已刷新。审批记录、部署任务及公网验收是不同状态。';rerender()} +function launchPickBuild(id){const known=state.builds.some(b=>b.id===id&&b.status==='complete');state.launchBuildId=known?id:'';state.launchReview=false;state.launchPreflight=null;state.launchMessage='切换构建版本后,请重新检查预览并获取审批。';rerender()} +function launchPickTarget(target){if(!['staging','production'].includes(target))return;state.launchTarget=target;state.launchPreflight=null;state.launchMessage='已切换目标环境。发布前检查将重新确认。';rerender()} +function launchChosenBuild(){const id=state.launchBuildId||state.builds.find(b=>b.status==='complete')?.id;if(!id)throw Error('请先生成一个完整的静态构建版本');return id} +async function launchRequestApproval(){const sid=state.site?.id,bid=launchChosenBuild();if(!state.launchReview)throw Error('请先检查网站预览并勾选人工核对');if(!state.releaseRequestsKnown)throw Error('审批状态读取失败,请刷新后再操作');if(state.releaseRequests.some(r=>r.build_id===bid&&['pending','approved'].includes(r.state)))throw Error('当前版本已经存在审批申请,无需重复提交');if(!confirm('确定为此构建版本提交独立审批吗?提交后必须由另一位审核人员批准。'))return; + const r=await api(`/api/factory/sites/${encodeURIComponent(sid)}/release-requests`,'POST',{build_id:bid});if(state.site?.id!==sid)return; + state.launchMessage=`已创建审批申请 ${r.id},当前仍在等待他人审核。`; + await loadReleaseRequests();rerender(); +} +async function launchPreflight(){const sid=state.site?.id,bid=launchChosenBuild(),target=state.launchTarget;if(!state.launchReview)throw Error('请先完成人工预览检查'); + const r=await api(`/api/production/sites/${encodeURIComponent(sid)}/preflight/${encodeURIComponent(bid)}`);if(state.site?.id!==sid||state.launchTarget!==target||launchChosenBuild()!==bid)return; + state.launchPreflight={siteId:sid,buildId:bid,ready:r.ready===true,message:r.message||'',target}; + state.launchMessage=r.ready?'发布前检查通过;提交任务时服务器仍会再次校验。':'尚不能发布:'+r.message; + rerender(); +} +async function launchDeploy(){const sid=state.site?.id,bid=launchChosenBuild(),target=state.launchTarget;const approvals=state.releaseRequests.filter(r=>r.build_id===bid); + const model=window.SiteForgeLaunch?.plan({site:state.site,build:state.builds.find(b=>b.id===bid),requests:approvals,requestsKnown:state.releaseRequestsKnown,delivery:state.delivery,target,previewChecked:state.launchReview,preflight:state.launchPreflight}); + if(!model?.canDeploy)throw Error('请先完成预览检查、独立审批、发布前检查,并确认目标服务器已配置'); + if(state.launchDeploying)return; + if(!confirm(`确定将版本 ${bid.slice(0,12)} 提交到${target==='production'?'正式':'测试'}环境吗?这会触发服务器部署。`))return; + state.launchDeploying=true;rerender(); + try{const r=await api(`/api/production/sites/${encodeURIComponent(sid)}/deploy`,'POST',{build_id:bid,target},{'Idempotency-Key':crypto.randomUUID()});if(state.site?.id!==sid)return; + await launchRefresh();state.launchMessage=`部署任务 ${r.id} 已进入后台队列。请刷新任务后,再核查真实网站。`; + }finally{if(state.site?.id===sid){state.launchDeploying=false;rerender();}} +} +async function launchReport(id){const sid=state.site?.id;if(!sid||!state.builds.some(b=>b.id===id))return;const r=await api(`/api/sites/${encodeURIComponent(sid)}/builds/${encodeURIComponent(id)}/report`);if(state.site?.id!==sid||state.view!=='launch')return; + const t=$('#launchReport');if(!t)return;t.innerHTML=`

    版本质量报告

    HTML 页面:${esc(r.pages||0)} · 警告 ${esc((r.warnings||[]).length)} 项

    ${r.warnings?.length?`
      ${r.warnings.slice(0,20).map(w=>`
    • ${esc(w)}
    • `).join('')}
    `:'

    自动检查未返回警告,仍需核对业务内容和手机页面。

    '}
    `; +} function openModal(name){const node=$('#'+name);node.showModal();node.querySelector('input:not([type=hidden]),select')?.focus()} function closeModal(name){$('#'+name)?.close()} function openEntry(id){const form=$('#entryForm');form.reset();form.elements.entry_id.value='';$('#entryModalTitle').textContent=id?'修改内容':'添加内容';if(id){const e=state.entries.find(x=>x.id===id);if(!e)return toast('这条内容不存在',true);for(const field of ['title','route','summary','body','seo_title','seo_description','type','status']){if(form.elements[field])form.elements[field].value=e[field]||''}form.elements.entry_id.value=id}openModal('entryModal')} async function saveEntry(ev){ev.preventDefault();if(!state.site)return;const el=ev.currentTarget;const data=Object.fromEntries(new FormData(el));const id=data.entry_id;delete data.entry_id; if(!data.route?.trim())delete data.route; try{await api(`/api/sites/${state.site.id}/entries${id?'/'+encodeURIComponent(id):''}`,id?'PATCH':'POST',data);closeModal('entryModal');toast(id?'内容已更新':'内容已添加');await selectSite(state.site.id,'content')}catch(e){notifyError(e)}} -async function saveSite(ev){ev.preventDefault();try{const f=ev.currentTarget;const data=Object.fromEntries(new FormData(f));const s=await api('/api/sites','POST',data);closeModal('siteModal');toast('网站创建成功,现在可以添加内容');await loadSites();await selectSite(s.id,'overview')}catch(e){notifyError(e)}} +let createStep=0; +function createValidate(){ + const f=$('#siteForm'),name=f.elements.name.value.trim(),domain=f.elements.domain.value.trim(); + if(!name){return '请填写网站名称。'} + if(name.length>150)return '网站名称过长,请缩短后再继续。'; + if(domain&&!/^https:\/\/[^\s/]+(?:[\/?#][^\s]*)?$/i.test(domain))return '正式域名请填写完整的 https:// 地址,或先留空。'; + return ''; +} +function renderCreateStep(){ + const form=$('#siteForm');if(!form)return; + form.querySelectorAll('[data-create-step]').forEach(el=>{el.hidden=Number(el.dataset.createStep)!==createStep}); + form.querySelectorAll('[data-create-indicator]').forEach(el=>{const current=Number(el.dataset.createIndicator)===createStep;if(current)el.setAttribute('aria-current','step');else el.removeAttribute('aria-current')}); + $('#createProgressText').textContent=`第 ${createStep+1} 步,共 3 步 · ${['填写信息','选择风格','确认创建'][createStep]}`; + $('#createBack').hidden=createStep===0; + $('#createNext').hidden=createStep===2; + $('#createNext').textContent=createStep===0?'下一步:选择风格 →':'下一步:确认信息 →'; + $('#createSubmit').hidden=createStep!==2; + $('#createError').hidden=true; + if(createStep===2){const data=Object.fromEntries(new FormData(form));$('#createSummary').innerHTML=`

    网站名称:${esc(data.name)}

    网站类型:${esc(({new:'全新制作网站',migration:'迁移旧站',hybrid:'旧站内容重新设计'})[data.mode]||data.mode)}

    网站风格:${esc(themeName[data.theme]||'企业品牌')}

    `} +} +function openCreateWizard(){const form=$('#siteForm');form.reset();createStep=0;renderCreateStep();openModal('siteModal')} +async function saveSite(ev){ev.preventDefault();const error=createValidate();if(error){$('#createError').textContent=error;$('#createError').hidden=false;return} + if(createStep!==2){createStep=2;renderCreateStep();return} + const button=$('#createSubmit');if(button.disabled)return;button.disabled=true;button.textContent='正在创建…'; + try{const data=Object.fromEntries(new FormData(ev.currentTarget));const s=await api('/api/sites','POST',data);closeModal('siteModal');toast('网站已建立,下一步请完善真实内容');await loadSites();await selectSite(s.id,'guide')} + catch(e){notifyError(e);$('#createError').textContent=e.message||'创建失败,请重试';$('#createError').hidden=false} + finally{button.disabled=false;button.textContent='确认创建网站'} +} + async function setTheme(theme){if(!state.site||theme===state.site.theme)return;if(!confirm(`切换到「${themeName[theme]}」?网站内容及已有 URL 将保持不变,外观会在下次构建后更新。`))return;try{await api(`/api/sites/${state.site.id}`,'PATCH',{theme});toast('主题已切换,重新构建后生效');await selectSite(state.site.id,'design')}catch(e){notifyError(e)}} async function saveSettings(ev){ev.preventDefault();try{await api(`/api/sites/${state.site.id}`,'PATCH',Object.fromEntries(new FormData(ev.currentTarget)));toast('网站设置已保存');await loadSites();await selectSite(state.site.id,'settings')}catch(e){notifyError(e)}} async function importFile(ev){ev.preventDefault();try{if(!state.site)return;const form=new FormData(ev.currentTarget);if(!form.get('file')?.name)throw Error('请选择文件');if(!confirm('将文件内容直接写入当前网站,重复路径默认跳过。需要预演和批次回滚请先使用高级导入。确认继续?'))return;const result=await api(`/api/sites/${state.site.id}/import`,'POST',form);const box=$('#importSummary');box.hidden=false;box.textContent=`导入完成:新增 ${result.imported||0} 条,更新 ${result.updated||0} 条,跳过 ${result.skipped||0} 条。错误 ${result.errors?.length||0} 条。`;toast('导入已完成');await refreshSiteKeepView()}catch(e){notifyError(e)}} @@ -178,23 +296,25 @@ function closeMobile(){$('#sideMenu').classList.remove('open');$('#mobileBackdro async function init(){try{const me=await api('/api/auth/me');state.csrf=me.csrf;await loadSites();const health=await api('/api/health');$('#appVersion').textContent='版本 '+health.version; // Restore URL first, then a previously selected site *only* after verifying /api/sites. const params=new URLSearchParams(location.search),requested=params.get('site'); - const target=params.get('view');const allowed=new Set(['home','sites','overview','content','design','import','build','languages','settings']); + const target=params.get('view');const allowed=new Set(['home','sites','overview','guide','launch','content','design','import','build','languages','settings']); let stored='';try{stored=localStorage.getItem(sfSiteKey)||''}catch{} const chosen=[requested,stored].find(id=>id&&state.sites.some(x=>x.id===id)); if(chosen){await selectSite(chosen,allowed.has(target)?target:'overview','replace')} else {state.view=target==='sites'?'sites':'home';rerender();rememberView(true)} }catch(e){notifyError(e);$('#mainContent').innerHTML=emptyState('后台加载失败',e.message,'')}} // Delegated UI interactions keep navigation and form actions centrally auditable. -document.addEventListener('click',async ev=>{const control=ev.target.closest('[data-action]');if(!control)return;const action=control.dataset.action;try{if(action==='navigate')navigate(control.dataset.view);if(action==='language-refresh')await loadLanguage();if(action==='new-site')openModal('siteModal');if(action==='select-site')await selectSite(control.dataset.id);if(action==='new-entry')openEntry();if(action==='edit-entry')openEntry(control.dataset.id);if(action==='set-theme')await setTheme(control.dataset.theme);if(action==='build-now')await buildNow();if(action==='refresh-builds')await refreshBuilds();if(action==='check-readiness')await checkReadiness();if(action==='cancel-job')await cancelJob(control.dataset.id);if(action==='report')await showReport(control.dataset.id);if(action==='release-preflight')await releasePreflight();if(action==='release-approval')await releaseApproval();if(action==='release-deploy')await releaseDeploy();if(action==='release-rollback')await releaseRollback(control.dataset.target,control.dataset.id)}catch(e){notifyError(e)}}); +document.addEventListener('click',async ev=>{const sidebar=ev.target.closest('.nav-item[data-view]');if(sidebar&&!sidebar.hasAttribute('data-action')){navigate(sidebar.dataset.view);return;}const control=ev.target.closest('[data-action]');if(!control)return;const action=control.dataset.action;try{if(action==='navigate')navigate(control.dataset.view);if(action==='language-refresh')await loadLanguage();if(action==='new-site')openCreateWizard();if(action==='select-site')await selectSite(control.dataset.id);if(action==='new-entry')openEntry();if(action==='edit-entry')openEntry(control.dataset.id);if(action==='set-theme')await setTheme(control.dataset.theme);if(action==='build-now')await buildNow();if(action==='refresh-builds')await refreshBuilds();if(action==='check-readiness')await checkReadiness();if(action==='cancel-job')await cancelJob(control.dataset.id);if(action==='report')await showReport(control.dataset.id);if(action==='release-preflight')await releasePreflight();if(action==='release-approval')await releaseApproval();if(action==='release-deploy')await releaseDeploy();if(action==='release-rollback')await releaseRollback(control.dataset.target,control.dataset.id);if(action==='launch-refresh')await launchRefresh();if(action==='launch-build')await buildNow();if(action==='launch-report')await launchReport(control.dataset.id);if(action==='launch-request-approval')await launchRequestApproval();if(action==='launch-preflight')await launchPreflight();if(action==='launch-deploy')await launchDeploy()}catch(e){notifyError(e)}}); document.addEventListener('click',ev=>{const btn=ev.target.closest('[data-close]');if(btn)closeModal(btn.dataset.close)}); $('#siteForm').addEventListener('submit',saveSite);$('#entryForm').addEventListener('submit',saveEntry); document.addEventListener('submit',ev=>{if(ev.target.id==='settingsForm')saveSettings(ev);if(ev.target.id==='importForm')importFile(ev);if(ev.target.id==='langGroupForm')submitLanguageGroup(ev);if(ev.target.id==='langJoinForm')submitLanguageJoin(ev);if(ev.target.id==='langUnitForm')submitLanguageUnit(ev);if(ev.target.id==='langLinkForm')submitLanguageLink(ev)}); document.addEventListener('input',ev=>{if(ev.target.id==='contentSearch'){state.search=ev.target.value;const cursor=ev.target.selectionStart;const type=state.typ;rerender();const el=$('#contentSearch');el.focus();el.setSelectionRange(cursor,cursor);state.typ=type}}); -document.addEventListener('change',ev=>{if(ev.target.id==='contentType'){state.typ=ev.target.value;rerender()}if(ev.target.id==='langMemberSite')loadLanguageEntries(ev.target.value)}); +document.addEventListener('change',ev=>{if(ev.target.id==='launchBuildSelect')launchPickBuild(ev.target.value);if(ev.target.id==='launchTarget')launchPickTarget(ev.target.value);if(ev.target.id==='launchReviewCheck'){state.launchReview=ev.target.checked;state.launchPreflight=null;rerender()}if(ev.target.id==='contentType'){state.typ=ev.target.value;rerender()}if(ev.target.id==='langMemberSite')loadLanguageEntries(ev.target.value)}); $('#sitePicker').addEventListener('change',ev=>selectSite(ev.target.value)); -window.addEventListener('popstate',async()=>{const p=new URLSearchParams(location.search);const site=p.get('site'),view=p.get('view')||'home';const allowed=['home','sites','overview','content','design','import','build','languages','settings'];if(site&&state.sites.some(s=>s.id===site))await selectSite(site,allowed.includes(view)?view:'overview','none');else{state.selectionToken++;state.site=null;state.entries=[];state.jobs=[];state.builds=[];state.view=view==='sites'?'sites':'home';rerender()}}); +window.addEventListener('popstate',async()=>{const p=new URLSearchParams(location.search);const site=p.get('site'),view=p.get('view')||'home';const allowed=['home','sites','overview','guide','launch','content','design','import','build','languages','settings'];if(site&&state.sites.some(s=>s.id===site))await selectSite(site,allowed.includes(view)?view:'overview','none');else{state.selectionToken++;resetLaunch();state.site=null;state.entries=[];state.jobs=[];state.builds=[];state.view=view==='sites'?'sites':'home';rerender()}}); setInterval(()=>{if(!document.hidden&&state.view==='build'&&activeJobs().length)refreshBuilds()},5000); -$('#newSiteTop').addEventListener('click',()=>openModal('siteModal')); +$('#newSiteTop').addEventListener('click',openCreateWizard); +$('#createNext').addEventListener('click',()=>{const error=createValidate();if(error){$('#createError').textContent=error;$('#createError').hidden=false;return}createStep=Math.min(2,createStep+1);renderCreateStep()}); +$('#createBack').addEventListener('click',()=>{createStep=Math.max(0,createStep-1);renderCreateStep()}); $('#logoutBtn').addEventListener('click',async()=>{try{await api('/api/auth/logout','POST');location.href='/login'}catch(e){notifyError(e)}}); $('#menuToggle').addEventListener('click',()=>{const open=$('#sideMenu').classList.toggle('open');$('#mobileBackdrop').classList.toggle('open',open);$('#menuToggle').setAttribute('aria-expanded',String(open))}); $('#mobileBackdrop').addEventListener('click',closeMobile); diff --git a/app/templates/editor.html b/app/templates/editor.html index 37e47bf..89215af 100644 --- a/app/templates/editor.html +++ b/app/templates/editor.html @@ -1,9 +1,10 @@ -SiteForge Studio · 可视化建站 +SiteForge Studio · 可视化建站
    ◈
    SiteForge页面编辑
    加载中页面编辑器
    +
    @@ -13,10 +14,11 @@ 读取中… -
    更多 ▾
    + +
    更多 ▾
    - + @@ -24,32 +26,39 @@
    -
    只需 3 步
    ① 选择或添加区块→② 修改右侧内容→③ 保存并发布
    +
    只需 3 步
    ① 点击页面中的内容→② 直接编辑或调整布局→③ 保存并发布
    -
    实时预览/修改后自动预览 · 不会直接改变线上网站
    +
    实时预览/单击区块或列内组件即可编辑 · 拖动 ⠿ 可排序 · 拖动列间分隔线可调宽
    + +
    仅预览 · 不修改网站内容

    选择适合网站的主题效果

    先比较布局和手机显示效果,再决定是否到「网站设计」中应用主题。

    +
    +

    示例使用主题最新版本,可能与你网站锁定的主题版本不同。不会修改当前页面。

    + +
    新手指南

    3 分钟学会编辑页面

    1. 先选页面

      左侧顶部切换要编辑的页面;选择现有内容区块,或点击橙色的“添加内容区块”。

    2. 修改内容

      在右侧“内容”里改标题、文案和图片;切换“样式”或“手机/平板”调整外观。中间自动展示效果。

    3. 保存草稿,再发布

      点击右上角“保存草稿”可以保留工作。核对后点击“发布设计”,它会更新内容库;正式网站还需要执行静态构建和部署。

    @@ -70,9 +79,13 @@ - +
    +
    网站菜单直接编辑文字和链接,支持三级菜单
    + + +

    点击“添加子菜单”即可建立下拉菜单。使用 ↑ ↓ 排序;保存草稿前会校验路径。

    + +
    全站页脚 @@ -100,11 +113,24 @@ - + +
    + +

    全站设计发布审核

    +

    本次变更将在下一次静态构建后影响本站所有页面,线上已发布网站不会立即改变。

    +
    +
    +
    +
    + +

    全站设计历史

    恢复历史版本只会生成新草稿,不修改已上线的网站。

    +
    + +

    本站图片素材库

    选择图片后更新当前组件;保存草稿、发布设计后才会参与静态构建。

    @@ -116,5 +142,10 @@
    + +
    全站设计系统

    公共组件管理

    +

    选择组件查看版本和引用页面。更新组件源文件不会自动改变任何已发布网站。

    +
    +
    diff --git a/app/templates/workspace.html b/app/templates/workspace.html index a08dd11..be0a5f5 100644 --- a/app/templates/workspace.html +++ b/app/templates/workspace.html @@ -1,7 +1,7 @@ SiteForge · 网站工作台 - +
    @@ -38,7 +40,21 @@
    - + diff --git a/app/version.py b/app/version.py index f995492..c3ce4d0 100644 --- a/app/version.py +++ b/app/version.py @@ -1,5 +1,5 @@ """Single source of truth for the SiteForge platform release identity.""" import os -VERSION = "8.21.3-dev.1" +VERSION = "8.31.1-dev.1" PLATFORM_NAME = "SiteForge Factory" BUILD_SHA = os.environ.get("SITEFORGE_GIT_SHA", "unknown").strip()[:40] or "unknown" diff --git a/compose.enterprise.yaml b/compose.enterprise.yaml index f886952..c26f966 100644 --- a/compose.enterprise.yaml +++ b/compose.enterprise.yaml @@ -6,7 +6,7 @@ services: dockerfile: Dockerfile.enterprise args: SITEFORGE_GIT_SHA: ${SITEFORGE_GIT_SHA:-unknown} - image: siteforge/web:8.21.3-dev.1 + image: siteforge/web:8.31.0-dev.1 init: true restart: unless-stopped ports: @@ -48,7 +48,7 @@ services: retries: 3 start_period: 30s worker: - image: siteforge/web:8.21.3-dev.1 + image: siteforge/web:8.31.0-dev.1 command: ['python','-m','app.worker'] init: true restart: unless-stopped diff --git a/compose.yaml b/compose.yaml index 7b28d6b..2967ebb 100644 --- a/compose.yaml +++ b/compose.yaml @@ -6,7 +6,7 @@ services: dockerfile: Dockerfile args: SITEFORGE_GIT_SHA: ${SITEFORGE_GIT_SHA:-unknown} - image: siteforge/web:8.21.3-dev.1 + image: siteforge/web:8.31.0-dev.1 init: true restart: unless-stopped ports: @@ -16,7 +16,6 @@ services: SITEFORGE_MAX_PENDING_JOBS: ${SITEFORGE_MAX_PENDING_JOBS:-100} SITEFORGE_MAX_PENDING_JOBS_PER_SITE: ${SITEFORGE_MAX_PENDING_JOBS_PER_SITE:-5} SITEFORGE_OUTBOUND_PORTS: ${SITEFORGE_OUTBOUND_PORTS:-80,443} - SITEFORGE_BUILD_TIMEOUT_SECONDS: ${SITEFORGE_BUILD_TIMEOUT_SECONDS:-300} SITEFORGE_MYSQL_ALLOWED_HOSTS: ${SITEFORGE_MYSQL_ALLOWED_HOSTS:-} SITEFORGE_MYSQL_ALLOWED_TABLES: ${SITEFORGE_MYSQL_ALLOWED_TABLES:-} SITEFORGE_ADMIN_PASSWORD: ${SITEFORGE_ADMIN_PASSWORD:?Set SITEFORGE_ADMIN_PASSWORD in .env} @@ -46,7 +45,7 @@ services: retries: 3 start_period: 30s worker: - image: siteforge/web:8.21.3-dev.1 + image: siteforge/web:8.31.0-dev.1 depends_on: siteforge: {condition: service_started} init: true diff --git a/docs/V8_22_ADVANCED_VISUAL_STUDIO.md b/docs/V8_22_ADVANCED_VISUAL_STUDIO.md new file mode 100644 index 0000000..b0a5139 --- /dev/null +++ b/docs/V8_22_ADVANCED_VISUAL_STUDIO.md @@ -0,0 +1,31 @@ +# V8.22 高级可视化编辑器 — 开发实现说明 + +**继承基线**:SiteForge V8.21.3,四套主题与移动端导航不变。 + +## 文件 + +- `app/static/studio-canvas-bridge.js`:注入 sandbox iframe 的独立画布工具层。浏览器只传受限指令到上级编辑器;禁止执行任意 HTML/JS 指令。 +- `app/static/editor-helpers.js`:纯函数校验、按 ID 排序、列宽边界、画布命令白名单。 +- `app/static/editor.js`:受信 iframe 来源检查、按区块 ID 查找并操作草稿,撤销与版本继续复用原有机制。 +- `app/main.py`:编辑器预览 HTML 注入上述脚本,不向真实静态构建添加编辑工具。 +- `app/templates/editor.html`、`app/static/editor.css`:更清晰的引导和插入反馈。 +- `tests/test_v822_canvas.py`、`tests_js/editor_ux.test.cjs`:新增专项测试。 +- `scripts/studio_canvas_smoke_v822.py`:需要本机 HTTP 访问许可的真实 Chromium E2E。 +- `scripts/studio_canvas_isolated_browser_v822.py`:无需网络的真实 Chromium iframe 交互检查。 +- `examples/Studio_V8_22_画布级可视化编辑器_交互演示.html`:完全独立可打开、模拟数据。 + +## 操作 + +1. 登录后台选站点、打开「页面设计」。 +2. 点击画布区块显示橙色边框;顶部黑色工具栏可直接移动/拖拽、插入、复制或删除。 +3. 双击顶层区块标题(如 Hero 标题)改文字,Enter 确认、Esc 取消。 +4. 桌面端选择多列布局,用相邻列之间的橙色握柄拖动列宽,也可用方向键逐步调整。 +5. 切换平板/手机预览后检查样式,按原流程「保存草稿」→「发布设计」→「构建」→「部署」。 + +## 限制 + +- 保留声明式区块模型:不允许任意像素绝对定位和任意脚本插入。 +- 画布内层子组件尚不支持直接双击修改,需右侧属性编辑。 +- 列宽拖拽仅针对桌面端;平板/手机采用既有响应式字段。 +- 草稿发布到内容库并非直接上线,需要构建并通过发布审批。 +- 最终验收详情:`reports/V8_22_验收报告.md`。 diff --git a/docs/V8_23_ADVANCED_STUDIO.md b/docs/V8_23_ADVANCED_STUDIO.md new file mode 100644 index 0000000..971210d --- /dev/null +++ b/docs/V8_23_ADVANCED_STUDIO.md @@ -0,0 +1,50 @@ +# SiteForge V8.23 — 高级可视化编辑器第二阶段 + +**版本**:`8.23.0-dev.1` +**基线**:V8.22.0-dev.1 完整源码 +**阶段**:开发集成版;未通过生产环境验收 + +## 1. 用户操作方式 + +在站点工作台打开 `/editor/{site_id}/{entry_id}`,添加一个「多列自由布局」区块,并在任一列添加标题、图文组合或行动号召等子组件。 + +- 点击中间预览中的**列内组件**,右侧「内容」自动显示相应组件的普通属性表单。 +- 在组件上悬浮显示快捷工具条,允许复制、删除、同列上下排序。选中态使用蓝绿色边框与顶层橙色选中态区分。 +- 对支持纯文本编辑的标题/描述双击,直接输入。富文本 HTML 内容仍使用安全受控的富文本配置,不直接将 DOM 反写到数据模型。 +- 选中顶层多列布局,切换右侧「手机/平板」,可选择均分、左宽右窄、左窄右宽,并设置列间距、手机及平板列数、跨列、顺序和显隐。 +- 更改均属于未保存草稿。保存草稿后可以发布设计,但正式站点还需构建、审批与部署。 + +## 2. 实际文件修改 + +| 文件 | 改动 | +| --- | --- | +| `app/static/studio-canvas-bridge.js` | 列内直接子组件工具栏、选中与文字修改事件,继续使用 sandbox iframe | +| `app/static/editor-helpers.js` | 查找/校验父子 ID、子组件移动、布局预设等纯函数 | +| `app/static/editor.js` | 嵌套操作命令接收、内容属性卡片、列宽预设、草稿状态更新 | +| `app/static/editor.css` | 嵌套编辑卡片与预设按钮样式 | +| `app/templates/editor.html` | 画布帮助文案 | +| `tests/test_nested_v823.py` | 嵌套区块 Schema、草稿接口和安全界面回归 | +| `tests/test_nested_helpers_v823.cjs` | 过期 ID、拒绝非法操作、列宽、移动及复制安全检查 | +| `scripts/studio_nested_browser_v823.py` | Chromium 沙箱 `srcdoc` 直接交互验证 | +| `scripts/regression_v823.py` | 43 个测试模块独立分批执行及原始日志 | +| `scripts/check.sh`、`scripts/check.ps1`、CI | 加入新版回归入口、升级版本标识 | + +## 3. 兼容性与安全边界 + +1. 不改变已有 SQL Schema,不启用任意 HTML/JavaScript 组件,不修改静态站发布器对安全媒体与链接的控制。 +2. 父组件 ID 与子组件 ID 必须同时匹配当前页面内的真实布局。不存在的组件、非法字段与未知操作在父编辑器拒绝。 +3. 目前 **只支持多列布局直接子组件的画布操作**。更深层嵌套允许在后端声明式模型中存在,但尚不提供多层画布操作路径。 +4. 布局预设限于 2 列的左宽/右宽;1–4 列可使用等宽。当前未实现任意绝对定位、多组件跨列拖放或像素级自由布局。 +5. 组件库仍然是「复制一个快照到页面」模式,**不是跨站点引用、自动同步或协作编辑**;这部分不能算作完成。 +6. 浏览器传递操作通过 `iframe.contentWindow` 来源验证;沙箱仅设置 `allow-scripts`,不授予同源访问权限。保存/发布仍走已有认证、CSRF、修订冲突验证。 + +## 4. 验收记录 + +- 完整 Python 历史和新增回归:**43 个测试模块、352 项用例、15 个隔离批次,全部通过**,详见 `reports/v823-regression/`。 +- JavaScript 历史测试:9 项通过;另有嵌套 JS 专项断言脚本通过。 +- Chromium 隔离画布:点击子组件、复制、双击修改标题的事件链路通过。 +- HTML 离线交互演示:通过 Chromium `set_content` 执行检查,组件点击、标题编辑、列宽预设和设备切换无脚本错误。 +- HTTP + Worker:真实启动服务、登录/CSRF、建站、构建、ZIP 下载与预览全部通过。 +- **未通过/未执行**:Chromium 导航到 localhost 的真实后台 E2E,被运行环境管理员策略阻止;真实 Docker、PostgreSQL/Redis、生产服务器和官方 Art Design Pro 完整编译未在本轮执行。 + +**建议下一步**:完善复杂多层节点定位、可视化布局栅格和跨页面共享组件版本引用,然后把 Art Design Pro 官方工程加入真实集成编译和自动化浏览器测试。 diff --git a/docs/V8_24_DEEP_NESTED_STUDIO.md b/docs/V8_24_DEEP_NESTED_STUDIO.md new file mode 100644 index 0000000..254e807 --- /dev/null +++ b/docs/V8_24_DEEP_NESTED_STUDIO.md @@ -0,0 +1,59 @@ +# SiteForge Enterprise V8.24 — 深层布局编辑与内层组件复用 + +**版本:** 8.24.0-dev.1 +**状态:** 开发集成版。无需数据库结构迁移。来源:V8.23 完整项目源码。 + +## 1. 改造目标与边界 + +使使用者在编辑器中**看得到、选得中、改得了**两层多列布局: + +- 在顶层「多列布局」的第 1 层列中增加「内层布局」; +- 内层布局的各列可直接添加富文本、图文、优势、行动号召组件; +- 点击第二层组件(画布或右侧结构卡片),可以直接修改文字、复制、排序、删除; +- 内层布局本身支持等宽 / 左宽右窄 / 左窄右宽、列间距、手机和平板列数; +- 从站点媒体库选择图片时,应用到**正在选中的组件**,不误改上层布局; +- 可以将当前选中的列内组件保存到本站复用组件库,并在选中列内组件时将组件副本插入其后。 + +**限制:** 当前支持「外层 layout → 内层 layout → 内容块」,不开放第三层 layout(遵循原服务端 `blueprints.validate_blocks` 的嵌套深度限制)。组件库使用**复制入页**,不是跨页自动同步。不会添加任意 HTML、JavaScript、自由绝对定位、数据库新表或新的发布捷径。 + +## 2. 编辑器操作 + +1. 进入 `/editor/{site_id}/{entry_id}`,选中或添加「多列自由布局」。 +2. 在某一列点击「+ 内层布局」,右侧「画布组件」列表会显示内层布局。 +3. 选中内层布局,用「+ 富文本」「+ 图文组合」「+ 核心优势」「+ 行动号召」添加内容。 +4. 点击中间画布中的第二层组件、修改标题与描述。可点复制、上移、下移、删除。 +5. 选中内层布局,选择布局比例与手机/平板列数。更改外层设置不会覆写内层布局数据。 +6. 需要重复利用时,选中子组件,点击「☆ 保存当前组件到组件库」;再次选择组件库条目,复制进入所选列内。 +7. 保存草稿 → 审核设计 → 发布设计 → 执行静态构建;**仅点击发布设计不会直接更新正式网站**。 + +## 3. 代码变化 + +- `app/static/editor-helpers.js`:ID 安全定位(`findNestedChild`、`findChildInRoot`、`findLayout`),限制从画布传来的非法操作;客户端从不接受事件中夹带的数据库位置索引。 +- `app/static/editor.js`:任意已支持层级的点击编辑与树状卡片、内层响应式控件和添加操作、子组件素材选择及复用组件保存/插入。 +- `app/static/studio-canvas-bridge.js`:继续在受限 iframe 中分发可靠的 ID 消息,保留事件源比对和区块高亮。 +- `tests/test_deep_nested_v824.py`:静态渲染、草稿、预览、安全嵌套深度及组件库行为。 +- `tests_js/deep_nested_v824.test.cjs`:深层定位、非法命令、列宽和 ID 复制校验。 +- `scripts/studio_nested_browser_v824.py`:离线 Chromium 交互演示验收,**不是已登录后台浏览器 E2E**。 +- `scripts/regression_v824.py`:独立分批自动化回归、超时与原始日志。 + +## 4. 验证命令 + +```bash +python -m compileall -q app +node --check app/static/editor.js +node --test tests_js/*.test.cjs +python -m pytest tests/test_deep_nested_v824.py -q +python scripts/http_end_to_end.py +python scripts/studio_nested_browser_v824.py +python scripts/regression_v824.py --timeout 65 --group-size 2 +``` + +查看 `reports/v824-regression/result.json`。各模块进程相互隔离,但这不代替 Docker、PostgreSQL/Redis 及生产备份/发布验收。 + +## 5. 上线前阻断项 + +- 使用真实后台会话与正式 iframe,在常规浏览器完成点击、拖拽、撤销、保存、版本回滚流程;本轮的隔离 Chromium 演示不足以关闭此项。 +- 确认四套主题在全部页面的桌面/手机实际效果,尤其是内外层栅格混用与窄屏折行。 +- 测试大型页面接近 120 个区块上限、重复 ID、非法媒体 URL 与编辑冲突。 +- 官方 Art Design Pro 完整工程尚未随本项目提供,安装器不等于官方工程已完成编译。 +- 企业级 PostgreSQL、Redis、多 Worker、远端发布与恢复仍需部署环境的独立验收。 diff --git a/docs/V8_25_SHARED_DESIGN_SYSTEM.md b/docs/V8_25_SHARED_DESIGN_SYSTEM.md new file mode 100644 index 0000000..593e3de --- /dev/null +++ b/docs/V8_25_SHARED_DESIGN_SYSTEM.md @@ -0,0 +1,91 @@ +# SiteForge Enterprise V8.25 — 公共组件与选择性同步 + +**版本:** `8.25.0-dev.1` +**状态:** 开发集成版;在 V8.24 完整源码基础上增量开发。 +**生产约束:** 未经 PostgreSQL/Redis、正式浏览器登录和远程部署验收,不得标记为生产可上线。 + +## 目标和本轮交付 + +将原先的“复制一次、以后完全独立”的组件库升级为两个明确选项: + +- **复制插入:** 区块是当前页面的独立副本,未来不会随源组件更新。 +- **关联插入:** 页面保存一个合法的 `shared_ref`,用于之后**预检、挑选页面、生成新草稿**。不会在页面构建时远程引用组件,也不会在源组件修改时自动更改任何已发布页面。 + +新增源组件不可变版本快照、历史版本查询与恢复为新版、引用页面列表、本地修改检测、过期预检保护、跨站点隔离、事务式选择性同步、解除关联按钮。保留原四套主题、移动端抽屉导航与可选 Tabs、两层安全布局、URL/SEO、历史版本及独立静态发布。 + +## 管理入口与操作 + +1. 选择网站和页面 → 打开原来的 `/editor/{site_id}/{entry_id}`。 +2. 选中一个区块(也可以是双层多列布局中的列内组件) → “保存当前组件到组件库”。 +3. 左侧“添加内容” → “从我的组件库添加”,根据需要选择“复制”或“关联插入”。 +4. 顶部“更多 → 管理公共组件”,或左侧高级设置中的同名按钮。 +5. 选中公共组件 → 查看历史版本、查看引用/同步;可使用当前选中区块的内容创建新版本,也可以将一个历史快照“恢复为新版本”。历史版本不被覆盖。 +6. 检查引用页。**存在本地修改、发布冲突或已是最新版的页面不可直接勾选**。 +7. 选择允许同步的页面 → 确认 → 这些页面生成新的设计草稿;逐页预览、保存与发布。网站仍然需要重新构建、执行正式审批部署。 +8. 需要完全独立时,在属性栏点击“解除关联、保留当前内容”。 + +演示:[公共组件版本与同步的离线交互页](../examples/V8_25_公共组件_版本与同步演示.html)。该演示使用模拟数据,不连接 SiteForge 后台。 + +## 数据与接口 + +### 增量 Schema + +沿用 `reusable_components`,新增: + +`reusable_component_versions(component_id, version, block_json, snapshot_hash, created_at)`,主键 `(component_id, version)`。针对现存旧组件仅能为**当时当前版本**补快照,无法凭空还原过去没有保存的历史版本。 + +页面区块新增一个**可选、严格验证**的 `shared_ref`: + +```json +{"id":"source_component_id","version":2,"hash":"sha256_64_hex"} +``` + +引用元数据随安全区块数据一同保存,不产生运行时动态远程引用。指纹排除拷贝后重新生成的块 ID 和来源引用,比较实际区块内容。不能通过本功能执行任意 HTML/JS。 + +### API(所有接口要求登录/CSRF 和相应站点权限) + +| 方法 | 路径 | 权限 | 功能 | +|---|---|---|---| +| GET | `/api/sites/{site}/components` | Viewer | 本站组件与当前快照 SHA | +| POST | `/api/sites/{site}/components` | Editor | 新建组件,初始版本 v1 | +| PUT | `/api/sites/{site}/components/{id}` | Editor | 按 `expected_version` 乐观锁创建下一版本 | +| GET | `/api/sites/{site}/components/{id}/versions` | Viewer | 查询不可变版本列表 | +| GET | `/api/sites/{site}/components/{id}/versions/{version}` | Viewer | 读取已校验 SHA 的历史快照 | +| GET | `/api/sites/{site}/components/{id}/usage` | Viewer | 预检被引用页面、版本、冲突、`plan_token` | +| POST | `/api/sites/{site}/components/{id}/sync` | Editor | 按 `plan_token` 和页面 ID 列表同步到草稿 | +| DELETE | `/api/sites/{site}/components/{id}` | Editor | 无任何引用时允许删除 | + +同步请求样例: + +```json +{"plan_token":"64位预检SHA256","entry_ids":["页面ID1","页面ID2"]} +``` + +### 同步安全边界 + +- 源组件版本发生变化、预检结果不一致、被选页面出现本地修改或页面草稿乐观锁冲突 → 409 拒绝。 +- 所选页面最多 100 个;事务内重新核对完整页面哈希与草稿修订号。 +- `BEGIN IMMEDIATE` 的读/比较/写窗口和事务性快照日志;在 SQLite 下启用写锁,在 PostgreSQL 兼容层中使用事务顾问锁。 +- 事务任一页面失败会整体回滚。只有新草稿变化,发布的 `entries.meta_json` 不变。 +- 对于一个页面中的同一组件多个引用,同步所有满足条件的该组件实例;任何一个已在本地编辑都会拒绝整页,避免部分覆盖。 +- 原页面的 URL、SEO、正文等未更改,组件源只在设计层按明确操作应用。 + +## 验收与运行 + +```bash +python -m pytest -q tests/test_v825_shared_components.py +node --check app/static/editor.js +node --test tests_js/*.test.cjs +python scripts/http_end_to_end.py +python scripts/verify_release.py +python scripts/regression_v825.py --timeout 55 --group-size 2 +``` + +本轮已完成:23 批共 370 项 Python 回归;13 项 Node JavaScript 回归;HTTP + Worker E2E;隔离 Chromium HTML 演示的 PC 和 390px 手机布局。参见 [`V8_25_验收报告.html`](../reports/V8_25_验收报告.html)。 + +## 尚未完成 + +- 当前同步是**选择性草稿更新**,不是一个“所有页面实时引用同一可变组件”的无版本动态系统。设计成这样是为了防止意外批量改动已发布站点。 +- 全站页眉、页脚、导航仍由现有 `site_design_v87` 管理,尚未纳入本次公共组件源版本与跨页面同步模型。 +- 没有完成多人实时协同编辑、视觉差异对比、正式 Art Design Pro 官方工程编译或真实 HTTPS 已登录 Chromium 后台验收。 +- PostgreSQL/Redis 多 Worker、真实 S3/SFTP/Agent 发布、灾备恢复仍需独立生产化测试。 diff --git a/docs/V8_26_GLOBAL_DESIGN.md b/docs/V8_26_GLOBAL_DESIGN.md new file mode 100644 index 0000000..dd32c19 --- /dev/null +++ b/docs/V8_26_GLOBAL_DESIGN.md @@ -0,0 +1,32 @@ +# V8.26 全站设计管理 — 实现与验收 + +**基线:** SiteForge V8.25.0-dev.1。当前源码版本:V8.26.0-dev.1。 + +## 核心架构 + +已有 `site_design_drafts` 与 `site_design_publications` 保存全站草稿与发布快照。本轮**不改变数据库 Schema**,主要在 `app/site_design_v87.py` 增加审核差异、审核令牌、历史快照查询与安全恢复。前端主要在 `app/templates/editor.html`、`app/static/editor.js`、`app/static/editor.css`。 + +- 导航采用树形数据,层级不超过 3,总元素不超过 48、同层最多 18;仍执行原 URL 白名单校验。 +- `GET /api/sites/{site}/site-design/review` 将已发布配置与当前草稿逐字段比较,返回变更清单、影响范围及绑定 site_id、草稿版本、当前站点设置哈希的 `plan_token`。 +- `POST /api/sites/{site}/site-design/publish-reviewed` 仅 Owner 可调用;在同一数据库事务内校验草稿版本和 token 后发布。旧发布接口为兼容保留,但当前编辑器改用审核发布接口。 +- `GET /api/sites/{site}/site-design/publications/{id}` 返回所属站点历史版本及结构化差异。 +- `GET /api/sites/{site}/site-design/live-hash` 返回当前已发布站点设置哈希。 +- `POST /api/sites/{site}/site-design/publications/{id}/restore` 在单一事务中检查历史归属、当前正式配置哈希、预期草稿版本及目标快照是否合法,然后写入新的全站草稿。不会直接修改 `sites.settings_json`。 + +## 安全保证 + +1. **跨站点隔离**:历史记录必须属于当前 site_id,否则返回 404;鉴权由 `enterprise.require` 处理。 +2. **审核过期保护**:草稿版本或站点已发布 settings 变化,审核令牌失效;`publish-reviewed` 返回 409。 +3. **原子发布与恢复**:读/校验/更新使用 `BEGIN IMMEDIATE` 事务窗口,降低读写竞态。 +4. **原有发布安全不变**:全站设计发布只影响内容库和下一次静态构建,不会替换线上目录或跳过正式发布审批。 +5. **前端差异防 XSS**:所有用户输入展示均使用 `textContent`,不将差异数据当作 HTML 执行。 + +## 验收结果与限制 + +- 23 个隔离 Python 测试批次:376 项通过,0 失败、0 超时。 +- JavaScript:13 项通过;`node --check` 通过。 +- HTTP + Worker:健康检查、登录、CSRF、站点/页面创建、异步构建、ZIP 下载和预览通过。 +- Chromium:离线页面通过 `set_content` 隔离加载验证新增导航、子菜单、保存、审核与历史模拟(0 脚本错误);**没有完成真实登录后台的浏览器 E2E**。 +- **未执行**真实 PostgreSQL/Redis、远程正式部署与 Art Design Pro 官方工程编译。 + +**兼容提醒:** 历史发布快照恢复不会修改已经发布的网站;为了让恢复内容上线,必须在站点设计审核后重新发布、构建和部署。 diff --git a/docs/V8_27_USER_FRIENDLY_WORKSPACE.md b/docs/V8_27_USER_FRIENDLY_WORKSPACE.md new file mode 100644 index 0000000..41973c3 --- /dev/null +++ b/docs/V8_27_USER_FRIENDLY_WORKSPACE.md @@ -0,0 +1,73 @@ +# SiteForge Enterprise V8.27 — 易上手工作台与操作指引 + +## 本轮交付性质 + +V8.27.0-dev.1 是 V8.26 完整源码上的**增量集成版**,不替换原后台 API,也不改变原数据库结构和静态构建引擎。历史版本功能继续保留。 + +## 改动范围 + +| 位置 | 已实现的操作 | +|---|---| +| 网站创建弹窗 | 拆成三步:基本信息 → 选择行业风格 → 预览和确认;支持上一步、必填校验、避免重复提交 | +| 当前网站操作指引 | 根据已保存内容、构建状态、Worker 任务与远程发布历史生成步骤;逐项有“开始操作”跳转 | +| 网站概览 | 突出“下一步应该做什么”,常用操作缩减为内容、设计、生成与预览 | +| 术语说明 | 区分内容保存、静态构建、检查与审批、正式部署;不把下载 ZIP、发布设计误称为上线 | +| 数据状态 | 仅自动建立的示例首页不会使“内容准备”自动完成;用户主动修改初始首页或添加正式内容才计入 | +| 手机界面 | 创建设计向导与引导列表适配窄屏,侧栏默认关闭,不增加底部固定遮挡 | + +### 操作路径 + +1. 登录 → 工作台 → 创建网站。 +2. 分三步填写网站名称、模式、主题和可选域名。 +3. 系统创建项目,自动切换到“建站操作指引”。 +4. 根据引导准备内容(旧站模式自动跳转迁移入口),可进入可视化编辑器修改样式。 +5. 执行静态构建,进入构建页面查看任务、预览和质量报告。 +6. 人工检查后由审批人员批准,再发起正式环境发布;必须核查实际域名。 + +### 使用者可读的状态定义 + +- **已保存**:写入 SiteForge 内容数据库;访客网站可能尚未变化。 +- **已构建**:成功生成了一个静态版本;不能推断质量检查或发布已通过。 +- **正式发布记录**:有成功记录;仍需要在实际域名核实当前可用性。 +- **构建可能过期**:已保存内容/站点在最近完成构建之后变更,提示人工复核。 +- **设计**:始终视为可优化,不因为选择主题自动声明设计验收完成。 + +## 代码结构 + +- `app/templates/workspace.html`:三步创建表单、引导导航入口。 +- `app/static/workspace-guide.js`:纯函数 `SiteForgeJourney.plan`;无本地跨用户数据缓存、无额外业务接口。 +- `app/static/workspace.js`:向导控制、流程状态渲染、已有 API 调用。 +- `app/static/workspace.css`:清晰的步骤条、状态列表、移动端布局。 +- `tests_js/workspace_guide_v827.test.cjs`:引导状态单元测试。 +- `tests/test_v827_guided_workspace.py`:真实测试客户端页面/接口联通。 +- `scripts/browser_guide_v827.py`:实际工作台 JS 的 Chromium 隔离交互检查(模拟 API,不经过用户真实账号)。 +- `scripts/regression_v827.py`:原项目分批 pytest 入口。 + +## 本轮测试及证据 + +- 原项目 Python 测试模块合计 **379 条用例通过**(24 批运行,其中 22 批直接通过;第 10 批组合运行超时、两模块拆开后 7+7 通过;第 22 批原断言对老结构写死而失败,更新以新模块校验后重新运行 21 项通过)。**一键回归稳定性未通过**。 +- Node.js JavaScript 测试 **23 项通过**(原有 13 项 + 新增 10 项)。 +- 原项目 `scripts/http_end_to_end.py` 已通过真实 Web + Worker 隔离端到端链路。 +- `scripts/browser_guide_v827.py`:实际 V8.27 workspace 代码,模拟网络接口在 Chromium 隔离页测试,验证三步表单、空名称阻断、只在最后创建、创建后显示状态、手机不溢出、0 页面脚本错误。 +- `scripts/verify_release.py`、`python -m compileall -q app` 和 `node --check` 通过。 + +## 尚未完成/生产上线限制 + +- 正式 Art Design Pro 官方工程的 `pnpm build` 及统一 SSO 登录未验收。 +- 已登录真实服务器浏览器 E2E、真实手机测试尚未完成;Chromium 测试使用了模拟 API。 +- PostgreSQL/Redis 多 Worker 真实压力及灾备、远程发布/回滚尚未在真实生产环境完整验收。 +- 生产上线路径需要继续按原 P5 发布审批执行;本轮**不绕过**角色、审批或安全检查。 +- 因原回归执行器存在组合批次偶发停滞,**不得将本轮 Python 回归描述为一键全绿**。 + +## 推荐复核命令 + +```bash +python -m pytest -q tests/test_v827_guided_workspace.py tests/test_workspace_v812.py +node --test tests_js/*.test.cjs +python scripts/http_end_to_end.py +python scripts/browser_guide_v827.py +python scripts/verify_release.py +python scripts/regression_v827.py --group-size 2 --timeout 35 +``` + +> 最后一条命令的运行环境可能出现分组超时,查看 `reports/v827-regression/result.json` 与原始批次日志。正式发布前仍需要真实 Web/Art/PG/Redis/发布服务器的独立验收。 diff --git a/docs/V8_28_GUIDED_LAUNCH_CENTER.md b/docs/V8_28_GUIDED_LAUNCH_CENTER.md new file mode 100644 index 0000000..f070336 --- /dev/null +++ b/docs/V8_28_GUIDED_LAUNCH_CENTER.md @@ -0,0 +1,67 @@ +# SiteForge Enterprise V8.28 — 新手友好上线操作中心 + +**版本**:8.28.0-dev.1 +**交付类型**:V8.27 完整源码的增量集成版(开发验收,不是生产验收) +**设计原则**:用户只看到当前应执行的操作;用日常中文解释状态;不能把构建、审批或任务排队错误地称为“已上线”。 + +## 1. 打开方式 + +登录工作台 → 选择当前网站 → 左侧 **检查并上线**。也可从网站概览的快捷卡片、建站操作指引(审核并上线)进入。 + +## 2. 六个步骤 + +| 步骤 | 使用者要做的事 | 系统做的检查 | 常见问题 | +|---|---|---|---| +| 1. 选择网站版本 | 选择已完成的静态构建;如果没有则点击“开始构建” | 只列出 `status=complete` 的构建 | 网站保存成功不代表已构建 | +| 2. 预览并检查质量 | 打开预览、核对图片和 SEO;勾选本地检查框 | 人工确认只存在于当前页面会话,不是服务器审批 | 检查不同设备和关键链接 | +| 3. 提交审批 | 向另一位审核人提交申请 | 读取服务器审批状态;重复 pending/approved 不重新申请 | 自己不能审批自己提交的申请 | +| 4. 发布前检查 | 审批通过后点击“执行发布前检查” | 调用既有 `/api/production/sites/{site}/preflight/{build}` | 会重新校验构建、质量、迁移和审批 | +| 5. 提交部署 | 选择测试或正式环境,再提交 | 只有前述条件全部满足且目标已配置时才启用;服务器仍重新校验 | 未配置目标时联系运维配置 Agent/SFTP/S3 | +| 6. 真实网址核查 | 等待 Worker 完成,再到网站地址检查 | 读取发布记录,但**不**把发布记录视为外网验收成功 | 检查 DNS、TLS、CDN 缓存、主页、联系表单 | + +**请注意正确顺序**:先提交审批、由其他有权限的人员通过,再执行发布前检查。之前页面中“检查发布条件”放在“提交审批”之前,实际服务器会因为缺乏审批而拒绝,是本版修正的重要体验问题。 + +## 3. 安全边界及兼容性 + +- **没有新开任何发布后门**。申请、检查、部署都调用原有服务端端点,继续受登录、CSRF、站点角色、质量检查、独立审核、Worker 任务与安全出网限制。 +- 所有临时确认与发布前检查结果仅用于当前会话的按钮状态,不写入业务数据库;浏览器刷新后需重新操作。换站、换构建或换环境会清除相关确认,防止复用错误状态。 +- 发布前检查与部署存在时间差,服务端部署操作必须再次校验。客户端按钮仅用于简化引导,不能替代后端检查。 +- 读取审批状态失败时不宣称“未申请”或者“已批准”;读取目标配置失败时不宣称目标已经配置。 +- 只显示当前网站对应版本的审批/发布记录,跳过不属于所选站点的结果。 +- 已有“构建与交付”的专业管理功能继续保留在高级折叠区域,原有 API、数据库 Schema、URL、构建产物和发布审批策略均未改变。 +- 正式域名按钮只接受符合 HTTPS 格式的地址;在离线演示中使用 example.com 占位地址,不会访问生产环境。 + +## 4. 非技术使用者视角的改善 + +原流程需要在“建站指引、构建、审批中心、质量报告、部署记录”之间来回跳转,也容易把构建成功当作上线。现在正常日常操作可以在一个页面内完成,进阶操作仍可进入专业工具。 + +导航明确命名为 **“生成与预览”** 和 **“检查并上线”**,避免技术用户和普通用户混淆。移动端在 390px 宽度验证按钮、表单自适应,无横向溢出。 + +## 5. 模块与回归入口 + +- `app/static/workspace-launch.js`:可单独测试的发布流程状态模型。 +- `app/static/workspace.js`:上线操作中心 UI、API 操作、审批状态读取及站点切换保护。 +- `app/templates/workspace.html`、`app/static/workspace.css`:统一入口与响应式布局。 +- `tests_js/workspace_launch_v828.test.cjs`:上线流程前置条件、防跨站/跨版本、目标环境、是否真正上线等场景。 +- `tests/test_v828_launch_center.py`:页面/脚本/API 连接检查。 +- `scripts/browser_launch_v828.py`:使用真实工作台 JS 的隔离 Chromium 测试(模拟 API,不触碰生产)。 +- `scripts/regression_v828.py`:独立 pytest 批次回归执行器,保留原始结果。 +- `examples/V8_28_简洁上线操作中心_交互演示.html`:双击即可打开的模拟数据界面,可点击“模拟另一位审核人批准”。 + +### 本地检查命令 + +```bash +python -m pytest -q tests/test_v828_launch_center.py tests/test_v827_guided_workspace.py +node --test tests_js/*.test.cjs +python scripts/browser_launch_v828.py +python scripts/http_end_to_end.py +python scripts/verify_release.py +python scripts/regression_v828.py --group-size 2 --timeout 25 +``` + +## 6. 未关闭的正式交付门槛 + +- Chromium 本次模拟原始后台 Web/API,不能代替真实账号登录、真正不同账号审批、实际公网部署与回滚的端到端演练。 +- Art Design Pro 官方完整工程未随项目提供,官方 `pnpm build` 尚无实测证据。 +- PostgreSQL/Redis 多 Worker、多实例、真实 Agent/SFTP/S3 与备份恢复、CDN、公网 DNS/TLS 仍需独立验收。 +- 复杂 WordPress 站点的全量 URL/SEO/图片及插件迁移还不能直接宣称 1:1 全部完成。 diff --git a/examples/Studio_V8_22_画布级可视化编辑器_交互演示.html b/examples/Studio_V8_22_画布级可视化编辑器_交互演示.html new file mode 100644 index 0000000..0f92791 --- /dev/null +++ b/examples/Studio_V8_22_画布级可视化编辑器_交互演示.html @@ -0,0 +1,21 @@ +SiteForge V8.22 · 高级可视化编辑器(交互演示)
    我的网站 / 首页页面可视化编辑
    未保存修改
    ● 实时画布 / 首页点击区块直接编辑 · 拖动列宽
    这是本地演示数据 · 改动仅保留在当前打开的演示页面
    \ No newline at end of file diff --git a/examples/Studio_V8_23_嵌套组件编辑器_可交互预览.html b/examples/Studio_V8_23_嵌套组件编辑器_可交互预览.html new file mode 100644 index 0000000..51e0954 --- /dev/null +++ b/examples/Studio_V8_23_嵌套组件编辑器_可交互预览.html @@ -0,0 +1,13 @@ +SiteForge Studio V8.23 · 嵌套组件编辑 +
    ◈ SiteForge StudioV8.23 · 嵌套画布编辑演示演示草稿
    +
    ① 点击画布中的组件 → ② 直接编辑右侧内容或选择布局 → ③ 保存草稿
    +
    +
    ● 可视化预览 · 点击卡片直接编辑
    HOME VEHICLES ABOUT CONTACT ☰

    China Sourcing. Global Delivery.

    拖动布局、点击组件、修改文字,立即看到页面变化。

    画布修改只影响演示数据 · 不会连接、修改或发布正式网站
    +
    + diff --git a/examples/Studio_V8_24_深层嵌套可视化编辑器_交互演示.html b/examples/Studio_V8_24_深层嵌套可视化编辑器_交互演示.html new file mode 100644 index 0000000..06cd049 --- /dev/null +++ b/examples/Studio_V8_24_深层嵌套可视化编辑器_交互演示.html @@ -0,0 +1,54 @@ +SiteForge Studio V8.24 · 深层画布编辑 +
    ◈ SiteForge StudioV8.24 · 深层画布编辑演示演示草稿
    +
    ① 点击画布中的组件 → ② 直接编辑右侧内容或选择布局 → ③ 保存草稿
    +
    +
    ● 可视化预览 · 点击卡片直接编辑
    HOME VEHICLES ABOUT CONTACT ☰

    China Sourcing. Global Delivery.

    内外层布局、手机列数与媒体选择均可直接操作。

    画布修改只影响演示数据 · 不会连接、修改或发布正式网站
    +
    + diff --git a/examples/V8_25_公共组件_版本与同步演示.html b/examples/V8_25_公共组件_版本与同步演示.html new file mode 100644 index 0000000..55f0cd9 --- /dev/null +++ b/examples/V8_25_公共组件_版本与同步演示.html @@ -0,0 +1,14 @@ +SiteForge V8.25 · 公共组件管理演示 +
    ◈ SiteForge / Studio
    V8.25 · 交互演示(模拟数据)
    +
    全站设计系统 · 组件库

    公共组件,集中维护

    更新一个组件后,先确认受影响的页面,再选择同步到草稿。已发布页面不会自动更改。

    +
    当前选中组件

    当前版本
    ① 编辑组件→② 查看引用与冲突→③ 勾选页面同步草稿

    引用该组件的页面

    安全规则:本地修改和有冲突的页面无法被覆盖;同步后还需进入页面编辑器检查、保存并发布。
    这是无需服务器的操作演示,不会修改真实网站。

    + diff --git a/examples/V8_26_全站设计与导航_交互预览.html b/examples/V8_26_全站设计与导航_交互预览.html new file mode 100644 index 0000000..39c1633 --- /dev/null +++ b/examples/V8_26_全站设计与导航_交互预览.html @@ -0,0 +1,703 @@ +SiteForge V8.26 · 全站设计 +
    ◈ SiteForge V8.26可操作演示 · 不连接正式网站

    全站统一设计,更容易维护

    直观编辑菜单、页眉和页脚。变更先保存草稿,再查看差异并确认发布。历史版本可恢复成新草稿。

    +

    全站设计 · 页眉、导航、页脚与响应式

    +

    先保存独立草稿;预览只显示在编辑器内。发布后,所有页面的下次静态构建才会使用新设计。

    +
    读取中...
    +
    +
    页眉与导航 + + + + + + +
    +
    网站菜单直接编辑文字和链接,支持三级菜单
    + + +

    点击“添加子菜单”即可建立下拉菜单。使用 ↑ ↓ 排序;保存草稿前会校验路径。

    + +
    +
    +
    全站页脚 + + + + +
    +
    不同设备布局 + + + + + +
    +
    手机底部快捷导航 Tabs(可选) +

    默认关闭。需要时开启后添加 1–5 个按钮。它们只显示在手机上,平板和电脑不显示。

    + + +
    +
    + + + + + + +
    +
    +
    + +

    全站设计发布审核

    +

    本次变更将在下一次静态构建后影响本站所有页面,线上已发布网站不会立即改变。

    +
    +
    +
    +
    + +

    全站设计历史

    恢复历史版本只会生成新草稿,不修改已上线的网站。

    +
    + +
    +
    + \ No newline at end of file diff --git a/examples/V8_27_新手友好建站工作台_交互演示.html b/examples/V8_27_新手友好建站工作台_交互演示.html new file mode 100644 index 0000000..bb17b3a --- /dev/null +++ b/examples/V8_27_新手友好建站工作台_交互演示.html @@ -0,0 +1,404 @@ + + +SiteForge · 网站工作台 + + +
    + +
    +
    +
    +
    +
    +
    正在读取工作空间…
    +
    SiteForge · 让网站制作有清晰的下一步正式发布前请完成内容与 SEO 检查
    +
    +
    +
    + + +
    离线交互演示 · 不会保存到服务器,也不会修改真实网站
    + + + + diff --git a/examples/V8_28_简洁上线操作中心_交互演示.html b/examples/V8_28_简洁上线操作中心_交互演示.html new file mode 100644 index 0000000..217b185 --- /dev/null +++ b/examples/V8_28_简洁上线操作中心_交互演示.html @@ -0,0 +1,508 @@ + + +SiteForge V8.28 · 上线操作中心演示(模拟数据) + +
    V8.28 交互演示 · 使用模拟数据,不连接真实服务器
    +
    + +
    +
    +
    +
    +
    +
    正在读取工作空间…
    +
    SiteForge · 让网站制作有清晰的下一步正式发布前请完成内容与 SEO 检查
    +
    +
    +
    + + + + + + + diff --git a/examples/V8_29_主题与可视化编辑_离线操作演示.html b/examples/V8_29_主题与可视化编辑_离线操作演示.html new file mode 100644 index 0000000..42bb1fe --- /dev/null +++ b/examples/V8_29_主题与可视化编辑_离线操作演示.html @@ -0,0 +1,5 @@ +SiteForge V8.29 · 主题与可视化编辑交互演示
    ◈ SiteForge StudioV8.29 · 交互演示
    这是独立离线交互示例:内容、保存状态和样式只在当前页面演示,不连接正式网站或数据库。
    实时预览
    HESU / SITEFORGEHOME · PRODUCTS · ABOUT

    探索更多 ↗

    预览宽度可切换。切换风格只影响此演示,不会替换网站主题。

    比较四套主题

    选择风格即可返回演示页面查看,正式站点不受影响。

    diff --git a/examples/V8_30_四套主题_真实页面交互预览.html b/examples/V8_30_四套主题_真实页面交互预览.html new file mode 100644 index 0000000..497056e --- /dev/null +++ b/examples/V8_30_四套主题_真实页面交互预览.html @@ -0,0 +1,2 @@ +SiteForge V8.30 · 四套专业主题 × 六类真实页面
    SITEFORGE / THEME LAB / V8.30

    四套主题 · 六类真实页面布局

    不是静态效果图:下方页面来自原项目静态构建,含真实菜单、列表、详情与文章结构。

    提示:演示中的公司、车型及资料均为虚构数据;正式网站使用自己的真实内容。可切换主题、页面和设备宽度观察布局差异。

    所有内容是本地静态演示,不调用后台接口。返回上一级阅读 升级说明,也可直接打开四套主题目录中的页面。
    \ No newline at end of file diff --git a/examples/V8_31_1_汽车主题性能与语义化图标_离线演示.html b/examples/V8_31_1_汽车主题性能与语义化图标_离线演示.html new file mode 100644 index 0000000..c4f5c17 --- /dev/null +++ b/examples/V8_31_1_汽车主题性能与语义化图标_离线演示.html @@ -0,0 +1,622 @@ +首页跳转至正文 + + +
    AUTOMOTIVE SOURCING · GLOBAL DELIVERY探索更广阔的出行可能
    +
    + + +
    +
    +
    +
    GLOBAL VEHICLE SOURCING +

    Connecting You to the Right Vehicle

    +

    探索更广阔的出行可能

    + +
    FEATURED VEHICLENOVA MOBILITY添加车型主图即可显示真实产品
    CAR COLLECTION
    +
    +
    + +
    +
    WHO WE ARE

    NOVA MOBILITY

    探索更广阔的出行可能

    了解我们
    WHY WORK WITH US
    01Vehicle Sourcing车型与产品信息
    02Export Coordination沟通出口与物流需求
    03Local Support通过实际配置的渠道联系团队
    +
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们
    +
    + + + + \ No newline at end of file diff --git a/examples/V8_31_汽车主题_完整页面交互预览.html b/examples/V8_31_汽车主题_完整页面交互预览.html new file mode 100644 index 0000000..6fd4343 --- /dev/null +++ b/examples/V8_31_汽车主题_完整页面交互预览.html @@ -0,0 +1,4 @@ +SiteForge V8.31 · 汽车主题交互预览
    SITEFORGE 汽车主题 1.4.0 · 参考 Magic Bridge Auto

    本预览由 SiteForge 真实静态构建输出生成,使用虚构车型资料;图片未提供时显示占位图。页面跳转请使用上方选择框。

    \ No newline at end of file diff --git a/examples/v830-built-sites/BUILD_REPORT.json b/examples/v830-built-sites/BUILD_REPORT.json new file mode 100644 index 0000000..7abf1d5 --- /dev/null +++ b/examples/v830-built-sites/BUILD_REPORT.json @@ -0,0 +1,242 @@ +{ + "automotive": { + "page_count": 36, + "warnings": [], + "quality": { + "files": 38, + "errors": 0, + "warnings": 8, + "passed": true, + "issues": [ + { + "file": "cases/2/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "cases/1/index.html" + }, + { + "file": "cases/3/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "cases/2/index.html" + }, + { + "file": "categories/term-8d6647722ef3/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "categories/term-79e34764f8ce/index.html" + }, + { + "file": "categories/term-95acf900fafc/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "categories/term-8d6647722ef3/index.html" + }, + { + "file": "categories/term-a68a8656a4dc/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "categories/term-95acf900fafc/index.html" + }, + { + "file": "index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "404.html" + }, + { + "file": "news/2/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "news/1/index.html" + }, + { + "file": "news/3/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "news/2/index.html" + } + ] + } + }, + "industrial": { + "page_count": 36, + "warnings": [], + "quality": { + "files": 38, + "errors": 0, + "warnings": 8, + "passed": true, + "issues": [ + { + "file": "cases/2/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "cases/1/index.html" + }, + { + "file": "cases/3/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "cases/2/index.html" + }, + { + "file": "categories/term-8d6647722ef3/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "categories/term-79e34764f8ce/index.html" + }, + { + "file": "categories/term-95acf900fafc/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "categories/term-8d6647722ef3/index.html" + }, + { + "file": "categories/term-a68a8656a4dc/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "categories/term-95acf900fafc/index.html" + }, + { + "file": "index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "404.html" + }, + { + "file": "news/2/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "news/1/index.html" + }, + { + "file": "news/3/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "news/2/index.html" + } + ] + } + }, + "corporate": { + "page_count": 36, + "warnings": [], + "quality": { + "files": 38, + "errors": 0, + "warnings": 8, + "passed": true, + "issues": [ + { + "file": "cases/2/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "cases/1/index.html" + }, + { + "file": "cases/3/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "cases/2/index.html" + }, + { + "file": "categories/term-8d6647722ef3/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "categories/term-79e34764f8ce/index.html" + }, + { + "file": "categories/term-95acf900fafc/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "categories/term-8d6647722ef3/index.html" + }, + { + "file": "categories/term-a68a8656a4dc/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "categories/term-95acf900fafc/index.html" + }, + { + "file": "index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "404.html" + }, + { + "file": "news/2/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "news/1/index.html" + }, + { + "file": "news/3/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "news/2/index.html" + } + ] + } + }, + "minimal": { + "page_count": 36, + "warnings": [], + "quality": { + "files": 38, + "errors": 0, + "warnings": 8, + "passed": true, + "issues": [ + { + "file": "cases/2/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "cases/1/index.html" + }, + { + "file": "cases/3/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "cases/2/index.html" + }, + { + "file": "categories/term-8d6647722ef3/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "categories/term-79e34764f8ce/index.html" + }, + { + "file": "categories/term-95acf900fafc/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "categories/term-8d6647722ef3/index.html" + }, + { + "file": "categories/term-a68a8656a4dc/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "categories/term-95acf900fafc/index.html" + }, + { + "file": "index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "404.html" + }, + { + "file": "news/2/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "news/1/index.html" + }, + { + "file": "news/3/index.html", + "type": "duplicate_description", + "severity": "warning", + "other": "news/2/index.html" + } + ] + } + } +} \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/.htaccess b/examples/v830-built-sites/automotive/.htaccess new file mode 100644 index 0000000..1d4fcb4 --- /dev/null +++ b/examples/v830-built-sites/automotive/.htaccess @@ -0,0 +1,2 @@ +Options -MultiViews +RewriteEngine On diff --git a/examples/v830-built-sites/automotive/404.html b/examples/v830-built-sites/automotive/404.html new file mode 100644 index 0000000..b9d3658 --- /dev/null +++ b/examples/v830-built-sites/automotive/404.html @@ -0,0 +1,12 @@ +404 · 页面不存在跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    ERROR / 404

    404

    抱歉,你访问的页面不存在,或者已被移动。

    返回首页 ↗
    + +
    + +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/about/index.html b/examples/v830-built-sites/automotive/about/index.html new file mode 100644 index 0000000..a4d9f1d --- /dev/null +++ b/examples/v830-built-sites/automotive/about/index.html @@ -0,0 +1,47 @@ +关于我们跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/assets/blocks.css b/examples/v830-built-sites/automotive/assets/blocks.css new file mode 100644 index 0000000..9ce1279 --- /dev/null +++ b/examples/v830-built-sites/automotive/assets/blocks.css @@ -0,0 +1,29 @@ +/* Portable SiteForge blocks, loaded with every theme (all styles scoped to sf-). */ +.sf-section{background:var(--sf-bg,transparent);color:var(--sf-fg,inherit);padding:var(--sf-pad,82px) 0;margin:0}.sf-section:nth-of-type(even){background:var(--sf-bg,#f4f6f9)}.sf-container{max-width:1200px;margin:auto;padding:0 32px}.sf-section h1,.sf-section h2,.sf-section h3,.sf-section p{color:inherit;line-height:1.3}.sf-section h1{font-size:clamp(38px,5vw,76px);font-weight:790;letter-spacing:-.052em}.sf-section h2{font-size:clamp(27px,3.2vw,44px);font-weight:760;letter-spacing:-.037em}.sf-kicker{display:block;font-size:12px;letter-spacing:.17em;text-transform:uppercase;font-weight:740;color:var(--accent,#3569d3);margin-bottom:18px}.sf-hero-grid,.sf-image-text{display:grid;grid-template-columns:1.08fr .92fr;gap:68px;align-items:center}.sf-hero-copy p{font-size:18px;line-height:1.75;max-width:520px;opacity:.75}.sf-hero-img,.sf-image-side{overflow:hidden;border-radius:9px;min-height:380px;background:linear-gradient(130deg,#d5e1ee,#eef3f9);display:grid;place-items:center}.sf-hero-img img,.sf-image-side img{width:100%;height:100%;max-height:580px;object-fit:cover}.sf-hero-abstract{font-size:110px;color:#a7bdd4}.sf-button{display:inline-flex;align-items:center;justify-content:center;gap:28px;background:var(--accent,#315ee2);color:white!important;padding:16px 26px;border-radius:6px;font-size:14px;text-decoration:none;font-weight:720;margin-top:24px}.sf-section-head{display:flex;align-items:end;justify-content:space-between;margin-bottom:32px;gap:24px}.sf-section-head h2{margin:0}.sf-section-head>a,.sf-link{color:var(--accent,#3569d3);font-weight:700;text-decoration:none}.sf-prose{font-size:16px;line-height:1.85;max-width:930px}.sf-prose p{line-height:1.85}.sf-features,.sf-collection,.sf-stats{display:grid;gap:20px}.sf-features{grid-template-columns:repeat(3,minmax(0,1fr))}.sf-feature{border:1px solid #e0e6eb;padding:32px 28px;border-radius:8px;background:#fff;color:#253247}.sf-feature>span{font-size:12px;font-weight:800;color:var(--accent,#346add)}.sf-feature h3{font-size:22px;margin:30px 0 8px}.sf-feature p{font-size:14px;line-height:1.7;color:#647181}.sf-stats{grid-template-columns:repeat(4,1fr);padding:40px 0;border-top:1px solid #b7c0cd66;border-bottom:1px solid #b7c0cd66}.sf-stats>div{display:flex;flex-direction:column;gap:8px}.sf-stats strong{font-size:clamp(28px,4vw,53px);letter-spacing:-.04em}.sf-stats span{font-size:12px;opacity:.65;letter-spacing:.04em}.sf-collection{grid-template-columns:repeat(var(--sf-cols,3),minmax(0,1fr))}.sf-item{display:block;text-decoration:none;color:#233044;background:#fff;border:1px solid #e8edf1;border-radius:8px;overflow:hidden;transition:transform .2s,box-shadow .2s}.sf-item:hover{transform:translateY(-4px);box-shadow:0 18px 38px #344d7018}.sf-item-img{height:210px;overflow:hidden;background:#e4eaf0}.sf-item-img img{height:100%;width:100%;object-fit:cover}.sf-placeholder{display:grid;place-items:center;width:100%;height:100%;min-height:190px;background:linear-gradient(130deg,#e2eaf2,#c9d7e6);font-size:72px;color:#8399b2;font-weight:800}.sf-large{min-height:360px}.sf-item-copy{padding:25px}.sf-item-copy small{text-transform:uppercase;letter-spacing:.13em;color:var(--accent,#376edc)}.sf-item-copy h3{font-size:22px;margin:12px 0 7px}.sf-item-copy p{font-size:14px;line-height:1.6;color:#7a8796;min-height:42px}.sf-item-copy span{font-size:12px;color:var(--accent,#376edc);font-weight:800}.sf-image-text>div>p{font-size:17px;line-height:1.8;max-width:520px;opacity:.7}.sf-reverse>div:first-child{order:2}.sf-gallery{display:grid;grid-template-columns:repeat(3,1fr);gap:15px}.sf-gallery img{width:100%;height:230px;object-fit:cover;border-radius:6px}.sf-faq{max-width:920px}.sf-faq details{border-bottom:1px solid #dce3eb;padding:22px 0}.sf-faq summary{font-size:17px;cursor:pointer;font-weight:700}.sf-faq p{color:#647181;line-height:1.75}.sf-cta-wrap{display:flex;justify-content:space-between;align-items:center;gap:24px}.sf-cta-wrap h2{margin:0}.sf-cta-wrap p{font-size:16px;opacity:.75}.sf-section a{cursor:pointer}.sf-muted{opacity:.65} +@media(max-width:820px){.sf-container{padding:0 20px}.sf-section{padding:50px 0}.sf-hero-grid,.sf-image-text{grid-template-columns:1fr;gap:26px}.sf-reverse>div:first-child{order:initial}.sf-hero-img,.sf-image-side{min-height:250px}.sf-features,.sf-collection{grid-template-columns:repeat(2,minmax(0,1fr))}.sf-stats{grid-template-columns:repeat(2,1fr)}.sf-cta-wrap{align-items:flex-start;flex-direction:column}} +@media(max-width:540px){.sf-features,.sf-collection,.sf-gallery{grid-template-columns:1fr}.sf-section-head{display:block}.sf-section-head>a{display:block;margin-top:13px}.sf-item-img{height:220px}.sf-hero-grid{gap:22px}.sf-hero-copy p{font-size:16px}.sf-stats{gap:28px}} + +.sf-attributes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 32px;border-top:1px solid #e5eaf0}.sf-attribute{display:flex;justify-content:space-between;align-items:center;gap:18px;border-bottom:1px solid #e5eaf0;padding:19px 10px;font-size:14px}.sf-attribute span{color:#748497}.sf-attribute strong{font-weight:720;text-align:right}@media(max-width:640px){.sf-attributes{grid-template-columns:1fr}} + +/* SiteForge responsive no-code grid container */ +.sf-layout-grid{display:grid;grid-template-columns:var(--sf-layout-cols,1fr 1fr);gap:var(--sf-layout-gap,24px);align-items:stretch} +.sf-layout-column{min-width:0}.sf-layout-column>.sf-section{padding:0;margin:0 0 18px}.sf-layout-column .sf-container{width:100%;padding:0} +.sf-layout-column>.sf-section:last-child{margin-bottom:0} +@media(max-width:820px){.sf-layout-grid{grid-template-columns:repeat(2,minmax(0,1fr))!important}} +@media(max-width:540px){.sf-layout-grid{grid-template-columns:minmax(0,1fr)!important}} + +/* V8.6: accessible, script-free commercial design blocks */ +.sf-slides{display:flex;gap:18px;overflow-x:auto;scroll-snap-type:x mandatory;padding:6px 0 18px;scrollbar-width:thin} +.sf-slide{flex:0 0 min(78%,720px);min-width:220px;margin:0;scroll-snap-align:start} +.sf-slide img{width:100%;aspect-ratio:16/9;object-fit:cover;border-radius:10px} +.sf-slide figcaption{padding:10px 2px;opacity:.7;font-size:14px} +.sf-video{aspect-ratio:16/9;max-width:1000px;background:#ebf0f5;border-radius:10px;overflow:hidden} +.sf-video iframe{width:100%;height:100%;border:0} +.sf-tab{padding:19px 0;border-bottom:1px solid #dde4ec;max-width:960px} +.sf-tab summary{font-size:18px;font-weight:700;cursor:pointer}.sf-tab p{max-width:850px;line-height:1.8} +.sf-prices{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:18px} +.sf-price{padding:28px;background:#fff;border:1px solid #dee5ef;border-radius:10px;color:#29394b} +.sf-price strong{display:block;font-size:27px;margin:14px 0}.sf-price li{margin:11px 0}.sf-price ul{padding-left:19px} +.sf-map-address{font-style:normal;font-size:18px;white-space:pre-line;line-height:1.8} +@media (prefers-reduced-motion:reduce){.sf-slides{scroll-behavior:auto}.sf-item{transition:none}} +@media(max-width:540px){.sf-slide{flex-basis:92%}} diff --git a/examples/v830-built-sites/automotive/assets/commercial.css b/examples/v830-built-sites/automotive/assets/commercial.css new file mode 100644 index 0000000..353bee4 --- /dev/null +++ b/examples/v830-built-sites/automotive/assets/commercial.css @@ -0,0 +1,84 @@ +/* SiteForge commercial theme UX layer: accessibility, layout rhythm, media, responsive navigation. */ +:root{--sf-shadow:0 20px 55px rgba(17,33,55,.08);--sf-shadow-hover:0 26px 65px rgba(17,33,55,.15)} +html{scroll-padding-top:104px}body{font-feature-settings:"kern";text-rendering:optimizeLegibility} +a,button,input,select,textarea{-webkit-tap-highlight-color:transparent} +a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{outline:3px solid var(--pro-accent);outline-offset:4px} +.pro-wrap{width:100%;max-width:min(var(--pro-wide),100%)}.pro-header{isolation:isolate;box-shadow:0 1px 0 rgba(15,35,60,.035)}.pro-head-inner{gap:clamp(15px,2vw,29px)}.pro-logo{min-width:0;flex-shrink:0;gap:12px}.pro-brand-logo{max-width:155px;max-height:46px;width:auto;height:auto;object-fit:contain}.pro-logo-name{overflow-wrap:anywhere}.pro-navigation{gap:clamp(11px,1.6vw,24px)}.pro-header-cta{white-space:nowrap} +.pro-mobile-toggle,.pro-catalog-toggle,.pro-nav-disclose{border:0;background:transparent;color:inherit;line-height:1.2} +.pro-mobile-toggle{min-height:44px;min-width:44px;border:1px solid currentColor;border-radius:6px;font-size:19px}.pro-nav-group{position:relative;display:flex;align-items:center;gap:2px} +.pro-nav-disclose{padding:9px;font-size:13px}.pro-nav-children{position:absolute;top:100%;left:0;min-width:215px;max-width:330px;display:grid;gap:2px;padding:13px;box-shadow:var(--sf-shadow);border-radius:10px;z-index:45;background:var(--pro-background);border:1px solid var(--pro-border);color:var(--pro-text)} +.pro-nav-children[hidden],.pro-mega[hidden]{display:none!important}.pro-nav-children a{display:block;font-size:13px;white-space:normal;padding:10px;border-radius:5px}.pro-nav-children a:hover{background:var(--pro-surface)} +.pro-catalog-toggle{padding:11px 3px;white-space:nowrap;font-size:12px;font-weight:700}.pro-mega{position:absolute;top:100%;left:50%;transform:translateX(-50%);width:min(100%,var(--pro-wide));box-shadow:var(--sf-shadow);z-index:41;display:grid;grid-template-columns:215px 1fr;background:var(--pro-background);color:var(--pro-text);border:1px solid var(--pro-border);border-radius:0 0 15px 15px;padding:29px;align-items:start}.pro-mega>span{font-size:12px;letter-spacing:.06em}.pro-mega>div{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:9px 22px;overflow:visible}.pro-mega>div a{white-space:normal;padding:10px 5px;border-bottom:1px solid var(--pro-border)} +.pro-home-hero{overflow:hidden}.pro-home-hero .pro-home-grid{min-height:660px;gap:5%}.pro-home-hero .pro-hero-copy{position:relative;z-index:2}.pro-home-hero .pro-hero-copy h1{font-size:clamp(46px,5.7vw,92px);line-height:1.06;letter-spacing:-.064em;max-width:15ch}.pro-home-hero .pro-hero-copy h1 em{font-style:normal;display:block}.pro-home-hero .pro-hero-copy p{font-size:clamp(15px,1.3vw,19px);line-height:1.75;max-width:44ch}.pro-home-hero .pro-hero-art{min-width:0;min-height:425px;position:relative;isolation:isolate}.pro-home-hero .pro-hero-art>img{width:100%;height:100%;object-fit:cover;position:absolute;inset:0}.pro-hero-art:has(.pro-abstract-car),.pro-hero-art:has(.pro-technical),.pro-hero-art:has(.pro-corporate-shape){background-position:center;background-size:cover;background-repeat:no-repeat}.pro-abstract-car,.pro-technical,.pro-corporate-shape{position:relative;z-index:1;pointer-events:none} +.pro-hero-actions{display:flex;flex-wrap:wrap;align-items:center;gap:15px}.pro-button,.pro-header-cta,.pro-outline-button{min-height:48px;transition:transform .24s ease,box-shadow .24s ease,opacity .24s ease}.pro-button:hover,.pro-header-cta:hover,.pro-outline-button:hover{transform:translateY(-2px);box-shadow:0 10px 22px rgba(0,0,0,.10)} +.pro-section{padding-top:clamp(76px,7vw,112px)!important;padding-bottom:clamp(76px,7vw,112px)!important}.pro-section-head{gap:16px}.pro-section-head h2{font-size:clamp(32px,3.5vw,53px);max-width:22ch}.pro-section-head .pro-text-link{align-self:end} +.pro-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px}.pro-card{min-width:0;display:flex;flex-direction:column;transition:transform .28s ease,box-shadow .28s ease;border:1px solid var(--pro-border);background:var(--pro-background);overflow:hidden}.pro-card:hover{transform:translateY(-6px);box-shadow:var(--sf-shadow-hover)}.pro-card-cover{aspect-ratio:1.42;overflow:hidden;background:var(--pro-surface);position:relative}.pro-card-cover .pro-photo{width:100%;height:100%;object-fit:cover;transition:transform .45s ease}.pro-card:hover .pro-photo{transform:scale(1.045)}.pro-card-body{display:flex;flex-direction:column;flex:1}.pro-card-body h3{font-size:clamp(19px,1.6vw,24px);line-height:1.26}.pro-card-body p{font-size:14px}.pro-card-link{margin-top:auto;padding-top:14px;font-size:13px;font-weight:700} +.pro-art{min-height:100%;width:100%;position:relative;overflow:hidden;display:grid;place-items:center;isolation:isolate}.pro-art-ring{width:60%;aspect-ratio:1;border:1px solid currentColor;opacity:.13;border-radius:50%;transform:rotate(20deg);box-shadow:0 0 0 23px #ffffff10,0 0 0 57px #ffffff07}.pro-art-center{font-size:clamp(38px,5vw,80px);position:absolute;font-weight:800;letter-spacing:-.065em;opacity:.65}.pro-art-label{position:absolute;bottom:19px;left:22px;font-size:10px;letter-spacing:.22em;opacity:.7} +.pro-breadcrumb{display:flex;gap:11px;flex-wrap:wrap;font-size:12px;align-items:center}.pro-breadcrumb a{text-decoration:underline;text-underline-offset:4px}.pro-product-hero{align-items:start;gap:clamp(28px,5vw,80px)}.pro-product-media{aspect-ratio:1.12;background:var(--pro-surface);overflow:hidden}.pro-product-media>img,.pro-product-media>.pro-art{width:100%;height:100%;object-fit:contain}.pro-product-summary{padding:clamp(12px,3vw,50px) 0}.pro-product-summary h1{font-size:clamp(36px,4.3vw,72px)}.pro-detail-layout{border-top:1px solid var(--pro-border);padding-top:50px}.pro-specs>div{display:grid;grid-template-columns:minmax(100px,40%) 1fr;gap:10px;align-items:baseline;padding:15px 0;border-bottom:1px solid var(--pro-border)}.pro-specs strong{overflow-wrap:anywhere}.pro-gallery-thumbs button{flex-basis:96px;height:76px}.pro-gallery-lightbox{backdrop-filter:blur(6px)} +.pro-filter-panel{display:flex;align-items:end;flex-wrap:wrap;gap:16px;background:var(--pro-surface);border:1px solid var(--pro-border);padding:20px;margin-bottom:25px;border-radius:var(--pro-radius)}.pro-filter-panel label{display:grid;gap:7px;min-width:180px;flex:1}.pro-filter-panel input,.pro-filter-panel select{width:100%;background:var(--pro-background);border:1px solid var(--pro-border);padding:12px 14px;color:var(--pro-text);border-radius:6px}.pro-filter-count{white-space:nowrap;font-size:13px;padding:12px 0}.pro-card[hidden]{display:none!important}.pro-filter-empty{padding:38px;border:1px dashed var(--pro-border);text-align:center;grid-column:1/-1} +.pro-inquiry input,.pro-inquiry textarea{min-height:46px}.pro-inquiry textarea{min-height:150px}.pro-inquiry-wrap{gap:clamp(32px,7vw,110px)}.pro-inquiry .pro-button{border:0;justify-self:start}.pro-footer-links a{padding-block:5px;display:inline-block} +.pro-end-cta{overflow:hidden}.pro-end-cta h2{font-size:clamp(30px,4vw,64px)} +.pro-rich{line-height:1.85}.pro-rich img{border-radius:var(--pro-radius);margin-block:24px}.pro-rich table{width:100%;display:block;overflow:auto;border-collapse:collapse}.pro-rich td,.pro-rich th{border:1px solid var(--pro-border);padding:10px 14px}.pro-rich a{text-decoration:underline;text-underline-offset:3px} +@media(min-width:1025px){.pro-navigation>.pro-nav-group:hover .pro-nav-children:not([hidden]){visibility:visible}} +@media(max-width:1150px){.pro-head-inner{gap:15px}.pro-navigation{gap:12px}.pro-logo-name{font-size:15px}.pro-header-cta{padding:13px 16px}} +@media(max-width:1024px){.pro-head-inner{min-height:72px;flex-wrap:wrap}.pro-mobile-toggle{display:inline-flex;align-items:center;justify-content:center;margin-left:auto}.pro-navigation{display:none;width:100%;flex-basis:100%;flex-direction:column;align-items:stretch;gap:0;order:5;margin:0;padding:8px 0 20px;border-top:1px solid var(--pro-border)}.pro-navigation.is-open{display:flex}.pro-navigation>a,.pro-nav-group>a{padding:14px 8px;font-size:15px}.pro-nav-group{display:flex;flex-wrap:wrap;justify-content:space-between}.pro-nav-children{position:static;flex-basis:100%;max-width:none;width:100%;box-shadow:none;border-radius:0;border-left:2px solid var(--pro-accent);margin:0 0 12px 8px}.pro-nav-disclose{min-width:44px;min-height:44px}.pro-catalog-toggle{margin-left:auto}.pro-mega{top:100%;display:block;padding:20px}.pro-mega>div{grid-template-columns:repeat(2,minmax(0,1fr));margin-top:12px}.pro-home-hero .pro-home-grid{min-height:560px}.pro-home-hero .pro-hero-art{min-height:325px}.pro-grid{grid-template-columns:repeat(2,minmax(0,1fr))}} +@media(max-width:700px){.pro-wrap{padding-left:20px;padding-right:20px}.pro-utility{display:none}.pro-head-inner{min-height:66px}.pro-logo-name{max-width:140px;font-size:14px}.pro-brand-logo{max-width:125px}.pro-header-cta{display:none}.pro-catalog-toggle{font-size:11px;padding-inline:7px;margin-left:0}.pro-home-hero .pro-home-grid{display:flex;flex-direction:column;gap:36px;padding-top:48px;padding-bottom:48px}.pro-home-hero .pro-hero-copy h1{font-size:clamp(43px,10vw,68px)}.pro-home-hero .pro-hero-copy p{font-size:15px}.pro-home-hero .pro-hero-art{width:100%;min-height:290px}.pro-home-hero .pro-hero-bottom{display:none}.pro-section{padding-top:68px!important;padding-bottom:68px!important}.pro-section-head{align-items:flex-start}.pro-grid{grid-template-columns:1fr;gap:18px}.pro-card-cover{aspect-ratio:1.45}.pro-product-hero,.pro-detail-layout,.pro-info-grid,.pro-inquiry-wrap{display:grid;grid-template-columns:1fr;gap:30px}.pro-product-summary{padding:0}.pro-specs>div{grid-template-columns:1fr 1fr}.pro-mega{top:100%;max-height:65vh;overflow-y:auto}.pro-mega>div{grid-template-columns:1fr}.pro-filter-panel{display:grid;grid-template-columns:1fr;gap:12px}.pro-filter-panel label{min-width:0}.pro-footer-top{display:grid;grid-template-columns:1fr;gap:27px}.pro-footer-bottom{gap:12px;flex-wrap:wrap}} +@media(max-width:410px){.pro-logo-name{max-width:115px}.pro-logo-symbol{font-size:28px}.pro-catalog-toggle{font-size:10px}.pro-mobile-toggle{min-width:42px}} +@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,*:before,*:after{animation-duration:.01ms!important;transition-duration:.01ms!important;scroll-behavior:auto!important}} + +/* Accessible static catalogue pagination for large inventories. */ +.pro-pages-nav{display:flex;gap:1rem;justify-content:center;align-items:center;margin:2rem 0;flex-wrap:wrap} +.pro-pages-nav a{padding:.7rem 1.1rem;border:1px solid currentColor;border-radius:.4rem;text-decoration:none} +.pro-pages-nav a:focus-visible{outline:3px solid var(--accent,#2563eb);outline-offset:3px} +.pro-pages-nav span{font-size:.875rem} + +/* P6 international sites: small, keyboard-operable language switch. */ +.sf-language-switch{display:inline-flex;gap:6px;align-items:center;flex-wrap:wrap;margin:8px 12px;padding:4px;border:1px solid rgba(120,130,145,.22);border-radius:10px;background:rgba(255,255,255,.08)} +.sf-language-switch a{font:inherit;font-size:12px;line-height:1.5;padding:4px 7px;border-radius:6px;color:inherit;text-decoration:none} +.sf-language-switch a[aria-current="page"]{font-weight:700;text-decoration:underline;text-underline-offset:3px} +.sf-language-switch a:focus-visible{outline:2px solid #2563eb;outline-offset:3px} +@media(max-width:640px){.sf-language-switch{margin:6px 0;width:auto}} + +/* V8.21.3 — Four-theme unified mobile off-canvas navigation & optional tab bar. + Desktop remains unchanged. Phone / tablet use one accessible drawer. */ +.sf-mobile-tabs{display:none!important} +.sf-drawer-header,.sf-mobile-drawer-backdrop,.sf-drawer-extra{display:none} +@media(max-width:1024px){ + .pro-head-inner{flex-wrap:nowrap!important;gap:12px!important} + .pro-mobile-toggle{display:inline-flex;align-items:center;justify-content:center;margin-left:auto!important;flex:0 0 44px;min-width:44px;min-height:44px;position:relative;z-index:3} + .pro-catalog-toggle{display:none!important} + .pro-navigation,.pro-navigation.is-open{display:flex!important;position:fixed!important;inset:0 0 0 auto!important;width:min(88vw,360px)!important;height:100dvh!important;height:100vh;max-height:100dvh!important;flex:unset!important;flex-direction:column!important;align-items:stretch!important;order:unset!important;margin:0!important;padding:0 0 calc(20px + env(safe-area-inset-bottom,0px))!important;overflow-x:hidden;overflow-y:auto!important;background:var(--pro-background,#fff)!important;color:var(--pro-text,#19283c)!important;border:0!important;border-left:1px solid var(--pro-border,#ddd)!important;box-shadow:-15px 0 45px #0002!important;z-index:1201!important;transform:translateX(105%);visibility:hidden;pointer-events:none;transition:transform .24s ease,visibility .24s ease!important;overscroll-behavior:contain} + .pro-navigation.is-open{transform:translateX(0);visibility:visible;pointer-events:auto} + .sf-drawer-header{display:flex!important;align-items:center;justify-content:space-between;gap:12px;padding:20px 18px;border-bottom:1px solid var(--pro-border,#dde3e9);font-size:17px;font-weight:750;position:sticky;top:0;background:var(--pro-background,#fff);z-index:2} + .sf-drawer-close{min-width:44px;min-height:44px;border:1px solid var(--pro-border,#dde3e9);color:inherit;background:transparent;border-radius:10px;font-size:24px;cursor:pointer} + .sf-mobile-drawer-backdrop{display:block;position:fixed;inset:0;z-index:1200;background:#0b1b31a3;opacity:0;visibility:hidden;pointer-events:none;transition:opacity .24s ease,visibility .24s ease} + .sf-mobile-drawer-backdrop.is-open{opacity:1;visibility:visible;pointer-events:auto} + body.sf-drawer-open{overflow:hidden!important} + .pro-navigation>a,.pro-navigation .pro-nav-group>a,.pro-navigation .sf-drawer-extra>a{display:flex;align-items:center;min-height:50px;padding:13px 20px!important;font-size:15px!important;color:inherit!important;white-space:normal;border-bottom:1px solid var(--pro-border,#dde3e9)!important;text-decoration:none!important} + .pro-navigation .pro-nav-group{display:flex;position:relative;flex-wrap:wrap!important;width:100%;gap:0;align-items:center;justify-content:space-between} + .pro-navigation .pro-nav-group>a{flex:1;min-width:0} + .pro-navigation .pro-nav-disclose{margin-right:12px;min-width:44px;min-height:44px;border-radius:9px;background:var(--pro-surface,#f4f6f8)} + .pro-navigation .pro-nav-children{position:static!important;width:100%!important;max-width:100%!important;box-shadow:none!important;border-left:3px solid var(--pro-accent,#e77730);border-radius:0!important;margin:0 0 8px 14px!important;flex-basis:calc(100% - 14px)!important;background:var(--pro-surface,#f6f8fa)} + .pro-navigation .pro-nav-children a{padding:12px 16px!important;font-size:14px!important;color:inherit!important;min-height:44px} + .sf-drawer-extra{display:block;padding:12px 0 5px}.sf-drawer-extra strong{display:block;font-size:12px;letter-spacing:.06em;padding:12px 20px;opacity:.65}.sf-drawer-extra a{font-size:14px!important} + .sf-drawer-close:focus-visible,.pro-mobile-toggle:focus-visible,.pro-nav-disclose:focus-visible,.sf-mobile-tab:focus-visible{outline:3px solid var(--pro-accent,#ff8200);outline-offset:2px} +} +@media(max-width:767px){ + .pro-header-cta{display:none!important} + .pro-head-inner .pro-logo{min-width:0;max-width:calc(100% - 65px)} + .pro-logo-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap} + .pro-home-hero .pro-home-grid{min-height:0!important} + .pro-home-hero .pro-hero-art{min-height:230px} + .pro-card,.pro-card-cover,.pro-product-media{max-width:100%;min-width:0} + .pro-rich img,.pro-content img,.sf-canvas img{max-width:100%;height:auto} + .pro-rich table{max-width:100%;overflow:auto} + .pro-grid,.pro-footer-top{min-width:0} + .sf-mobile-tabs{display:grid!important;position:fixed;z-index:1100;bottom:0;left:0;right:0;grid-template-columns:repeat(var(--sf-mobile-tab-count,4),minmax(0,1fr));align-items:stretch;padding:5px 6px calc(5px + env(safe-area-inset-bottom,0px));min-height:63px;background:var(--pro-background,#fff);color:var(--pro-text,#263446);border-top:1px solid var(--pro-border,#dfe4eb);box-shadow:0 -6px 24px #13223914} + .sf-mobile-tab{appearance:none;border:0!important;background:transparent!important;color:inherit!important;text-decoration:none!important;padding:6px 2px;min-height:50px;min-width:0;display:flex;flex-direction:column;justify-content:center;align-items:center;gap:2px;border-radius:9px;cursor:pointer;font-family:inherit} + .sf-tab-icon{font-size:23px;line-height:1.15;font-weight:500} + .sf-tab-label{font-size:11px;font-weight:600;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} + .sf-mobile-tab[aria-current=page]{color:var(--pro-accent,#e47730)!important;background:var(--pro-surface,#f5f6f8)!important} + body:has(> .sf-mobile-tabs){padding-bottom:calc(76px + env(safe-area-inset-bottom,0px))!important} +} +@media(min-width:768px){.sf-mobile-tabs{display:none!important}} +@media(prefers-reduced-motion:reduce){.pro-navigation,.sf-mobile-drawer-backdrop{transition:none!important}} diff --git a/examples/v830-built-sites/automotive/assets/custom.css b/examples/v830-built-sites/automotive/assets/custom.css new file mode 100644 index 0000000..f197c0a --- /dev/null +++ b/examples/v830-built-sites/automotive/assets/custom.css @@ -0,0 +1 @@ +:root{--accent:#315f92;--sf-font:system-ui,-apple-system,sans-serif;--sf-radius:12px;--sf-space:72px;--sf-width:1200px;--sf-heading-scale:1.0;}body{font-family:var(--sf-font)} .sf-canvas .sf-section,.sf-canvas .section{padding-block:var(--sf-space)}.container,.sf-container{max-width:var(--sf-width)}.btn,.primary,.request,.button,.nav-btn{background-color:#315f92;border-radius:12px}body .sf-canvas h1{font-size:clamp(2.5rem,5vw,calc(4.8rem * var(--sf-heading-scale)))}body .pro-utility[hidden]{display:none!important}@media(max-width:1023px){.sf-canvas .sf-section{padding-block:64px}}@media(max-width:767px){.sf-canvas .sf-section{padding-block:40px}.pro-wrap,.sf-container{padding-left:20px;padding-right:20px}body .pro-utility{display:none!important}} \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/assets/factory.css b/examples/v830-built-sites/automotive/assets/factory.css new file mode 100644 index 0000000..154ffb3 --- /dev/null +++ b/examples/v830-built-sites/automotive/assets/factory.css @@ -0,0 +1,27 @@ +/* SiteForge trusted global shell. Site themes remain visually independent. */ +:root{--sf-shell:#12243d;--sf-shell-accent:#dcae71;--sf-shell-soft:#edf2f8;--sf-shell-fg:#173049} +html{scroll-behavior:smooth}body{overflow-x:hidden}body>.header,body>.utility,body>.top,body>header,body>footer{display:none!important} +.sf-theme-industrial{--sf-shell:#114e79;--sf-shell-accent:#92d5ed;--sf-shell-soft:#ebf6fa;--sf-shell-fg:#0c4267} +.sf-theme-corporate{--sf-shell:#232d62;--sf-shell-accent:#b8bdff;--sf-shell-soft:#f3f3fa;--sf-shell-fg:#333468} +.sf-theme-minimal{--sf-shell:#1e1e1c;--sf-shell-accent:#ded6c5;--sf-shell-soft:#f6f4ef;--sf-shell-fg:#252520} +.sf-site-head{position:relative;z-index:25;background:var(--sf-shell);color:#fff;font-family:system-ui,-apple-system,sans-serif} +.sf-head-inner{max-width:1240px;margin:0 auto;min-height:78px;padding:0 28px;display:flex;align-items:center;gap:28px} +.sf-logo{display:flex;align-items:center;gap:11px;font-size:18px;text-decoration:none!important;color:#fff!important;white-space:nowrap} +.sf-logo-mark{width:36px;height:36px;display:grid;place-items:center;background:var(--sf-shell-accent);color:var(--sf-shell);font-size:22px;font-weight:900;border-radius:9px} +.sf-primary-links{display:flex;gap:23px;margin-left:auto;align-items:center} +.sf-primary-links a,.sf-mega a{color:#fff!important;text-decoration:none!important;font-size:13px;font-weight:650;white-space:nowrap} +.sf-primary-links a:hover{color:var(--sf-shell-accent)!important} +.sf-head-cta{font-size:13px;font-weight:750;text-decoration:none;background:var(--sf-shell-accent);color:var(--sf-shell)!important;padding:13px 18px;border-radius:4px;white-space:nowrap} +.sf-menu-toggle{display:none;margin-left:auto;color:white;border:1px solid #ffffff55;background:none;border-radius:4px;padding:8px 12px;font-size:19px;cursor:pointer} +.sf-mega{display:flex;gap:18px;max-width:1240px;margin:auto;padding:0 28px 9px;overflow-x:auto} +.sf-mega a{display:block;min-width:120px;border-top:1px solid #ffffff2e;padding:12px 8px}.sf-mega small{display:block;color:#ffffff99;max-width:160px;overflow:hidden;text-overflow:ellipsis;font-size:10px;margin-top:6px} +.sf-site-foot{background:var(--sf-shell);color:white!important;font:14px/1.7 system-ui,-apple-system,sans-serif;padding:72px 28px 26px} +.sf-foot-grid{max-width:1200px;margin:auto;display:grid;grid-template-columns:2fr 1fr 1fr;gap:70px}.sf-foot-grid h2{font-size:25px;color:white;margin:0 0 17px}.sf-foot-grid h4{font-size:13px;color:var(--sf-shell-accent);letter-spacing:.07em;margin:0 0 17px}.sf-foot-grid p{color:#ffffffae;max-width:380px}.sf-foot-grid a{display:block;width:fit-content;color:#fff!important;text-decoration:none;margin-bottom:8px}.sf-foot-lower{border-top:1px solid #ffffff33;max-width:1200px;margin:45px auto 0;padding-top:20px;display:flex;justify-content:space-between;color:#ffffff9e;font-size:12px} +.sf-filters{display:flex;align-items:center;flex-wrap:wrap;gap:12px;margin:0 0 30px}.sf-filters input,.sf-filters select{padding:11px 13px;border-radius:6px;border:1px solid #cfd9e4;background:#fff;color:#263a51;max-width:280px}.sf-filter-empty{padding:22px;color:#778598} +.sf-search-page{min-height:76vh;max-width:1060px;padding:90px 24px;margin:auto;font-family:system-ui,sans-serif;color:var(--sf-shell-fg)}.sf-search-page h1{font-size:clamp(35px,5vw,62px);margin:20px 0}.sf-search-page>label{display:block;margin:18px 0 8px}.sf-search-page input{display:block;width:100%;padding:17px;font-size:18px;border:1px solid #b7c6d7;border-radius:8px}.sf-search-page #sf-search-count{margin:22px 0;color:#607589}.sf-search-result{padding:22px 0;border-bottom:1px solid #dae1ea}.sf-search-result a{color:var(--sf-shell-fg);font-size:21px;font-weight:750;text-decoration:none}.sf-search-result small{display:block;color:#7992a7}.sf-search-result p{margin:7px 0;color:#657487} +@media(max-width:1050px){.sf-head-inner{gap:13px}.sf-primary-links{gap:12px}.sf-primary-links a{font-size:12px}.sf-head-cta{padding:10px}} +@media(max-width:850px){.sf-head-inner{min-height:68px}.sf-menu-toggle{display:block}.sf-head-cta{display:none}.sf-primary-links{display:none;position:absolute;top:68px;left:0;right:0;margin:0;background:var(--sf-shell);padding:20px 28px;flex-direction:column;align-items:stretch;box-shadow:0 20px 24px #0002}.sf-primary-links.is-open{display:flex}.sf-mega{display:none}.sf-foot-grid{grid-template-columns:1fr 1fr;gap:35px}} +@media(max-width:560px){.sf-foot-grid{grid-template-columns:1fr}.sf-foot-lower{display:block}.sf-site-foot{padding-top:48px}.sf-head-inner{padding:0 16px}} + +.sf-page-intro{padding:80px 28px;background:var(--sf-shell-soft);color:var(--sf-shell-fg);font-family:system-ui,sans-serif}.sf-page-intro>div{max-width:1200px;margin:auto}.sf-page-intro p{font-size:11px;font-weight:850;letter-spacing:.19em;text-transform:uppercase;color:var(--sf-shell-fg);opacity:.58}.sf-page-intro h1{font-size:clamp(38px,5vw,67px);letter-spacing:-.04em;line-height:1.08;margin:13px 0}.sf-page-intro span{font-size:16px;opacity:.72} +.sf-item[hidden]{display:none!important} diff --git a/examples/v830-built-sites/automotive/assets/pro-base.css b/examples/v830-built-sites/automotive/assets/pro-base.css new file mode 100644 index 0000000..c2c4f61 --- /dev/null +++ b/examples/v830-built-sites/automotive/assets/pro-base.css @@ -0,0 +1,21 @@ +/* SiteForge V3 professional theme primitives. Each commercial theme adds its own art direction. */ +:root{--pro-text:#19283a;--pro-muted:#687587;--pro-border:#dfe5ea;--pro-background:#fff;--pro-surface:#f5f7fa;--pro-accent:#365cb7;--pro-hero:#15263d;--pro-hero-fg:#fff;--pro-radius:12px;--pro-headings:system-ui,-apple-system,sans-serif;--pro-font:system-ui,-apple-system,sans-serif;--pro-wide:1270px} +*,*:before,*:after{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:var(--pro-background);color:var(--pro-text);font-family:var(--pro-font);-webkit-font-smoothing:antialiased;overflow-x:hidden}button,input,select{font:inherit}button,a{touch-action:manipulation}button{cursor:pointer}a{text-decoration:none;color:inherit}a:hover{color:var(--pro-accent)}img{max-width:100%;display:block}h1,h2,h3,h4,p{margin-top:0}h1,h2,h3{font-family:var(--pro-headings);line-height:1.09}h1{letter-spacing:-.052em}h2{letter-spacing:-.042em}h3{letter-spacing:-.028em}p{line-height:1.72}.pro-wrap{max-width:var(--pro-wide);margin:0 auto;padding-left:32px;padding-right:32px}.pro-skip{position:absolute;left:-9999px;z-index:90;background:#fff;color:#000;padding:12px}.pro-skip:focus{left:10px;top:10px}.pro-eyebrow{font-weight:750;font-size:11px;letter-spacing:.17em;text-transform:uppercase;display:block;line-height:1.6;color:var(--pro-accent)}.pro-muted{opacity:.7}.pro-utility{min-height:30px;background:var(--pro-hero);color:#c5d2db;font-size:10px;letter-spacing:.16em}.pro-utility .pro-wrap{display:flex;justify-content:space-between;padding-block:8px}.pro-utility i{font-style:normal;color:var(--pro-accent)}.pro-header{background:var(--pro-background);color:var(--pro-text);border-bottom:1px solid var(--pro-border);position:relative;z-index:35}.pro-head-inner{min-height:84px;display:flex;align-items:center;gap:28px}.pro-logo{display:flex;align-items:center;gap:12px;min-width:170px}.pro-logo-symbol{font-size:32px;line-height:1;font-weight:800;letter-spacing:-.07em;color:var(--pro-accent)}.pro-logo-name{max-width:220px;font-weight:820;font-size:17px;line-height:1.1;letter-spacing:-.035em}.pro-logo-name small{display:block;font-weight:650;font-size:9px;letter-spacing:.19em;margin-top:7px;color:var(--pro-muted)}.pro-navigation{display:flex;align-items:center;gap:24px;margin-left:auto}.pro-navigation a{font-size:13px;font-weight:650;white-space:nowrap;transition:opacity .2s}.pro-navigation a:hover{opacity:.6}.pro-header-cta,.pro-button{display:inline-flex;align-items:center;justify-content:center;gap:22px;background:var(--pro-accent);color:#fff!important;border-radius:var(--pro-radius);font-size:13px;letter-spacing:.01em;font-weight:750;padding:16px 24px;white-space:nowrap;transition:transform .2s,background .2s}.pro-header-cta:hover,.pro-button:hover{transform:translateY(-2px)}.pro-mobile-toggle{display:none}.pro-mega{display:flex;align-items:center;gap:22px;min-height:37px;border-top:1px solid var(--pro-border);padding-block:10px;font-size:11px}.pro-mega>span{font-weight:750;color:var(--pro-muted);white-space:nowrap}.pro-mega>div{display:flex;gap:16px;overflow:auto;scrollbar-width:none}.pro-mega a{white-space:nowrap;font-weight:650}.pro-search-link{font-size:19px!important}.pro-home-hero{position:relative;overflow:hidden}.pro-home-grid{display:grid;grid-template-columns:1.02fr .98fr;align-items:center;gap:5%;min-height:580px;padding-top:85px;padding-bottom:85px}.pro-hero-copy{position:relative;z-index:2}.pro-hero-copy h1{font-size:clamp(48px,6.2vw,91px);line-height:1.03;margin:20px 0 25px;max-width:730px}.pro-hero-copy h1 em{font-style:normal;display:block;color:var(--pro-accent)}.pro-hero-copy p{font-size:17px;max-width:495px;color:var(--pro-muted)}.pro-hero-actions{display:flex;align-items:center;flex-wrap:wrap;gap:25px;margin-top:34px}.pro-outline-button{font-weight:700;border-bottom:1px solid currentColor;padding:12px 0}.pro-hero-art{width:100%;height:435px;position:relative;overflow:hidden;border-radius:var(--pro-radius)}.pro-hero-art>img{width:100%;height:100%;object-fit:cover}.pro-hero-bottom{display:flex;justify-content:space-between;font-size:10px;letter-spacing:.18em;padding-block:22px;border-top:1px solid #ffffff32}.pro-section{padding:106px 0}.pro-section-head{display:flex;align-items:end;justify-content:space-between;gap:25px;margin-bottom:34px}.pro-section-head h2{font-size:clamp(36px,4vw,57px);margin:12px 0 0}.pro-text-link{font-size:13px;font-weight:750;display:inline-flex;gap:18px;align-items:center;border-bottom:1px solid;padding-bottom:7px;color:var(--pro-accent)}.pro-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:22px}.pro-card{display:block;min-width:0;background:var(--pro-background);color:var(--pro-text);border:1px solid var(--pro-border);overflow:hidden;border-radius:var(--pro-radius);transition:transform .25s,box-shadow .25s}.pro-card:hover{transform:translateY(-6px);box-shadow:0 24px 45px #0f25431b}.pro-card-cover{width:100%;height:244px;overflow:hidden;background:var(--pro-surface)}.pro-photo{width:100%;height:100%;object-fit:cover;transition:transform .5s}.pro-card:hover .pro-photo{transform:scale(1.045)}.pro-art{width:100%;height:100%;overflow:hidden;display:grid;place-items:center;position:relative;background:linear-gradient(130deg,#d8e1ed,#f3f6f9)}.pro-art-ring{width:55%;aspect-ratio:1;border:28px solid #ffffff5f;border-radius:50%;box-shadow:0 0 0 42px #ffffff30;transform:rotate(-25deg)}.pro-art-center{position:absolute;font-family:var(--pro-headings);font-weight:800;font-size:76px;letter-spacing:-.08em;color:#45647d90}.pro-art-label{position:absolute;bottom:16px;left:18px;letter-spacing:.16em;font-size:9px;color:#435773}.pro-card-body{padding:25px 25px 28px}.pro-card-meta{display:flex;justify-content:space-between;gap:20px;font-size:10px;font-weight:750;letter-spacing:.1em;text-transform:uppercase;color:var(--pro-accent)}.pro-card h3{font-size:23px;margin:14px 0 9px}.pro-card p{font-size:13px;color:var(--pro-muted);margin-bottom:24px;min-height:44px}.pro-card-link{font-size:12px;font-weight:800;display:flex;justify-content:space-between;color:var(--pro-text);padding-top:14px;border-top:1px solid var(--pro-border)}.pro-empty{grid-column:1/-1;padding:45px;border:1px dashed var(--pro-border);background:var(--pro-surface);color:var(--pro-muted)}.pro-statement{background:var(--pro-surface)}.pro-statement-layout{display:grid;grid-template-columns:1fr 2fr;gap:60px}.pro-statement h2{font-size:clamp(36px,4.5vw,63px);max-width:760px}.pro-statement p{max-width:520px;color:var(--pro-muted)}.pro-brand-pills{display:flex;flex-wrap:wrap;gap:12px}.pro-brand-pills a{padding:18px 28px;border:1px solid var(--pro-border);border-radius:var(--pro-radius);font-weight:750}.pro-brand-pills a:hover{border-color:var(--pro-accent)}.pro-inner-hero{background:var(--pro-surface);padding:92px 0 65px;position:relative;overflow:hidden}.pro-inner-hero h1{max-width:870px;font-size:clamp(43px,6vw,85px);margin:18px 0}.pro-inner-hero p{max-width:650px;color:var(--pro-muted);font-size:17px}.pro-breadcrumb{font-size:12px;color:var(--pro-muted);margin-top:25px;display:flex;gap:12px;align-items:center;flex-wrap:wrap}.pro-breadcrumb strong{color:var(--pro-text)}.pro-list-section{padding:65px 0 110px}.pro-filter-panel{display:grid;grid-template-columns:minmax(220px,2fr) 1fr 1fr auto;align-items:end;gap:14px;margin-bottom:35px}.pro-filter-panel label>span{display:block;font-size:11px;margin-bottom:8px;color:var(--pro-muted);font-weight:750}.pro-filter-panel input,.pro-filter-panel select{display:block;width:100%;padding:14px 15px;border-radius:var(--pro-radius);border:1px solid var(--pro-border);background:var(--pro-background);color:var(--pro-text);outline-offset:2px}.pro-filter-count{font-size:12px;padding-bottom:17px;color:var(--pro-muted)}.pro-filter-scope .pro-card[hidden]{display:none}.pro-product-layout{padding-top:38px}.pro-product-layout .pro-breadcrumb{margin-bottom:38px}.pro-product-hero{display:grid;grid-template-columns:1.18fr .82fr;gap:6%;align-items:center}.pro-product-media{height:460px;overflow:hidden;background:var(--pro-surface);border-radius:var(--pro-radius)}.pro-product-media .pro-photo{height:100%}.pro-product-summary h1{font-size:clamp(45px,5vw,72px);margin:16px 0}.pro-product-summary p{font-size:16px;color:var(--pro-muted)}.pro-product-brand{font-weight:700;color:var(--pro-text)!important}.pro-detail-layout{border-top:1px solid var(--pro-border);display:grid;grid-template-columns:1fr 1fr;gap:8%;margin-top:80px;padding-top:55px}.pro-detail-layout h2{font-size:32px;margin-top:13px}.pro-specs{margin-top:25px}.pro-specs>div{display:grid;grid-template-columns:1fr 1fr;gap:22px;padding:16px 0;border-bottom:1px solid var(--pro-border)}.pro-specs span{color:var(--pro-muted)}.pro-rich{line-height:1.85;font-size:16px;overflow-wrap:anywhere}.pro-rich img{border-radius:var(--pro-radius);margin:25px 0}.pro-rich a{text-decoration:underline}.pro-rich h2{margin-top:30px}.pro-lead{font-size:20px;color:var(--pro-muted)}.pro-brand-hero-grid{display:grid;grid-template-columns:1.1fr .9fr;gap:7%;align-items:center}.pro-brand-media{height:300px;overflow:hidden;border-radius:var(--pro-radius)}.pro-article-hero{text-align:center;padding:110px 0 75px;background:var(--pro-surface)}.pro-article-width{max-width:900px}.pro-article-hero h1{font-size:clamp(40px,5vw,75px);margin:15px 0 25px}.pro-article-hero p{color:var(--pro-muted);font-size:18px}.pro-article-hero time{font-size:12px;color:var(--pro-muted)}.pro-article-content{max-width:930px;padding-top:70px;padding-bottom:90px}.pro-article-cover{width:100%;max-height:530px;object-fit:cover;margin-bottom:40px;border-radius:var(--pro-radius)}.pro-article-content>.pro-text-link{margin-top:35px}.pro-case-detail{max-width:1020px}.pro-case-detail>img{width:100%;max-height:620px;object-fit:cover}.pro-case-meta{display:flex;gap:35px;margin:35px 0;color:var(--pro-muted);font-size:13px}.pro-case-meta strong{display:block;color:var(--pro-text);font-size:18px;margin-top:7px}.pro-info-grid{display:grid;grid-template-columns:.8fr 1.2fr;gap:12%}.pro-info-grid h2{font-size:clamp(31px,4.5vw,54px);margin-top:15px}.pro-contact-email{font-size:20px;color:var(--pro-accent);font-weight:750;word-break:break-word}.pro-info-photo{max-height:450px;object-fit:cover;margin-top:35px;border-radius:var(--pro-radius)}.pro-custom-content .sf-section{background:transparent}.pro-custom-content .sf-section:nth-of-type(even){background:var(--pro-surface)}.pro-end-cta{padding:76px 0;background:var(--pro-hero);color:#fff}.pro-end-cta .pro-wrap{display:flex;align-items:center;justify-content:space-between;gap:40px}.pro-end-cta h2{font-size:clamp(32px,4vw,53px);margin:13px 0}.pro-end-cta p{color:#c5c9d1}.pro-end-cta a{background:var(--pro-accent);color:#fff;font-weight:800;padding:19px 30px;border-radius:var(--pro-radius);white-space:nowrap}.pro-404{text-align:center;padding-block:125px}.pro-404>span{font-size:12px;letter-spacing:.3em}.pro-404 h1{font-size:clamp(150px,20vw,320px);margin:10px 0;letter-spacing:-.08em}.pro-404 p{font-size:18px;color:var(--pro-muted)}.pro-404 a{margin-top:22px}.pro-footer{background:#15212d;color:#fff;padding:75px 0 22px}.pro-footer-top{display:grid;grid-template-columns:1.45fr 1fr 1fr;gap:55px}.pro-footer h2{font-size:32px;margin:12px 0}.pro-footer p{max-width:350px;font-size:13px;color:#afbbc8}.pro-footer .pro-eyebrow{color:#b6c3d2}.pro-footer-links ul{margin:0;padding:0;list-style:none;display:grid;grid-template-columns:1fr 1fr;gap:15px}.pro-footer-links a{font-size:13px;color:#d6e0e8}.pro-footer-bottom{border-top:1px solid #ffffff29;margin-top:60px;padding-top:20px;font-size:10px;letter-spacing:.12em;color:#adb9c3;display:flex;justify-content:space-between}.pro-anchor{display:block;height:0}.pro-category-tiles{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}.pro-category-tiles a{padding:35px 28px;min-height:155px;background:var(--pro-surface);display:flex;flex-direction:column;justify-content:space-between}.pro-category-tiles span{font-size:11px;color:var(--pro-muted)}.pro-category-tiles strong{font-size:24px}.pro-category-tiles b{align-self:end}.sf-site-head .sf-head-inner,.sf-site-head .sf-primary-links{display:none} +@media(max-width:1100px){.pro-head-inner{gap:17px}.pro-navigation{gap:14px}.pro-navigation a{font-size:12px}.pro-home-grid{min-height:500px}.pro-hero-copy h1{font-size:60px}.pro-hero-art{height:350px}} +@media(max-width:860px){.pro-wrap{padding-left:22px;padding-right:22px}.pro-utility{display:none}.pro-head-inner{min-height:70px;flex-wrap:wrap;gap:12px}.pro-mobile-toggle{display:block;margin-left:auto;border:1px solid var(--pro-border);padding:8px 12px;background:transparent;color:var(--pro-text);border-radius:5px}.pro-navigation{display:none;order:10;width:100%;flex-direction:column;align-items:stretch;gap:0;padding-bottom:12px}.pro-navigation.is-open{display:flex}.pro-navigation a{padding:11px 2px;border-bottom:1px solid var(--pro-border)}.pro-header-cta{display:none}.pro-mega{display:none}.pro-home-grid{grid-template-columns:1fr;gap:35px;padding-top:60px;padding-bottom:60px}.pro-hero-art{height:350px}.pro-hero-copy h1{font-size:clamp(45px,9vw,73px)}.pro-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.pro-product-hero,.pro-detail-layout,.pro-info-grid,.pro-brand-hero-grid{grid-template-columns:1fr;gap:35px}.pro-product-media{height:380px}.pro-filter-panel{grid-template-columns:1fr 1fr}.pro-filter-panel label:first-child{grid-column:1/-1}.pro-end-cta .pro-wrap{align-items:start;flex-direction:column}.pro-section{padding:72px 0}.pro-footer-top{grid-template-columns:1fr 1fr}.pro-footer-top>div:first-child{grid-column:1/-1}.pro-category-tiles{grid-template-columns:repeat(2,1fr)}} +@media(max-width:560px){.pro-wrap{padding-left:18px;padding-right:18px}.pro-logo-name{font-size:15px}.pro-hero-copy h1{font-size:43px}.pro-hero-art{height:255px}.pro-hero-bottom{display:none}.pro-home-grid{min-height:0}.pro-grid{grid-template-columns:1fr}.pro-section-head{align-items:start;flex-direction:column}.pro-section-head h2{font-size:37px}.pro-card-cover{height:230px}.pro-filter-panel{grid-template-columns:1fr}.pro-filter-panel label:first-child{grid-column:auto}.pro-filter-count{padding-bottom:4px}.pro-statement-layout,.pro-footer-top{grid-template-columns:1fr;gap:25px}.pro-footer-top>div:first-child{grid-column:auto}.pro-footer-bottom{flex-direction:column;gap:8px}.pro-inner-hero{padding:60px 0}.pro-product-media{height:270px}.pro-product-summary h1{font-size:43px}.pro-category-tiles{grid-template-columns:1fr}.pro-end-cta h2{font-size:38px}.pro-minimal-meta{display:block!important}} + +/* V2 compatibility stylesheet hides direct headers/footers; full themes restore their own. */ +body>header.sf-site-head.pro-header,body>footer.sf-site-foot.pro-footer{display:block!important} + +/* Accessible desktop mega-navigation and mobile disclosure */ +.pro-catalog-toggle{font-size:12px;font-weight:750;border:1px solid var(--pro-border);background:transparent;color:inherit;border-radius:var(--pro-radius);padding:10px 14px;white-space:nowrap} +.pro-mega[hidden]{display:none!important}.pro-mega.is-open{display:flex}.pro-mega>div{padding-block:3px} +@media(max-width:1060px){.pro-catalog-toggle{display:none}} +@media(max-width:860px){.pro-mega.is-open{display:block!important}.pro-mega.is-open>div{display:flex;flex-wrap:wrap;gap:14px;padding:12px 0}.pro-mega>span{white-space:normal}} + +/* V4: responsive nested navigation, gallery and opt-in inquiry integration */ +.pro-nav-group{position:relative;display:flex;align-items:center;gap:3px}.pro-nav-disclose{border:0;background:none;color:inherit;font-size:12px;padding:8px}.pro-nav-children[hidden]{display:none!important}.pro-nav-children{position:absolute;left:0;top:100%;z-index:45;min-width:230px;max-width:360px;padding:10px;background:var(--pro-background);border:1px solid var(--pro-border);box-shadow:0 18px 35px #0002;border-radius:var(--pro-radius);display:flex;flex-direction:column}.pro-nav-children a{padding:10px 12px;white-space:nowrap}.pro-nav-children .pro-nav-leaf{padding-left:28px;color:var(--pro-muted)} +.pro-product-gallery{min-width:0}.pro-gallery-thumbs{display:flex;gap:8px;margin-top:12px;overflow:auto;scrollbar-width:thin;padding-bottom:5px}.pro-gallery-thumbs button{flex:0 0 86px;height:67px;border:2px solid transparent;padding:3px;border-radius:8px;background:var(--pro-surface)}.pro-gallery-thumbs button:focus-visible,.pro-gallery-thumbs button[aria-pressed=true]{border-color:var(--pro-accent)}.pro-gallery-thumbs img{width:100%;height:100%;object-fit:cover;border-radius:4px}.pro-gallery-lightbox{position:fixed;inset:0;background:rgba(10,16,30,.92);z-index:1000;display:grid;place-items:center;padding:6vw}.pro-gallery-lightbox[hidden]{display:none}.pro-gallery-lightbox img{max-width:92vw;max-height:80vh;object-fit:contain}.pro-gallery-lightbox button{position:absolute;right:25px;top:25px;border:1px solid #fff8;background:#222;color:#fff;padding:10px 15px;border-radius:5px} +.pro-inquiry-wrap{display:grid;grid-template-columns:1fr 1fr;gap:70px}.pro-inquiry{display:grid;gap:17px}.pro-inquiry label{display:grid;gap:7px;font-weight:650}.pro-inquiry input,.pro-inquiry textarea{padding:13px;border:1px solid var(--pro-border);border-radius:var(--pro-radius);background:var(--pro-background);color:var(--pro-text);width:100%}.pro-inquiry textarea{min-height:140px}.pro-inquiry .pro-honeypot{position:absolute;left:-10000px;width:1px;height:1px}.pro-inquiry p{font-size:12px;color:var(--pro-muted)} +@media(max-width:860px){.pro-nav-group{display:block}.pro-nav-children{position:static;max-width:none;width:100%;box-shadow:none;border:0;border-left:2px solid var(--pro-accent);padding-left:8px}.pro-nav-group>a{display:inline-block}.pro-inquiry-wrap{grid-template-columns:1fr;gap:20px}} diff --git a/examples/v830-built-sites/automotive/assets/pro.css b/examples/v830-built-sites/automotive/assets/pro.css new file mode 100644 index 0000000..9deff66 --- /dev/null +++ b/examples/v830-built-sites/automotive/assets/pro.css @@ -0,0 +1,92 @@ +:root{--pro-text:#1c2a3b;--pro-muted:#718094;--pro-border:#e2e8ef;--pro-background:#fff;--pro-surface:#f2f5f9;--pro-accent:#bb8d50;--pro-hero:#0c1b2e;--pro-radius:5px;--pro-headings:'Arial Narrow',Arial,sans-serif;--pro-wide:1320px} +.pro-header{background:#0e1e30;color:#fff;border-color:#26374b}.pro-logo-symbol{color:#e0ae6c}.pro-logo-symbol span{color:#fff}.pro-logo-name small{color:#b3bfcf}.pro-header-cta{background:#c59b63;color:#0f1a26!important}.pro-navigation a:hover{color:#dfb97d}.pro-mega{background:#13263b;border-color:#2a4058;color:#c2d0de}.pro-mega>span{color:#d5aa72}.pro-mobile-toggle{color:#fff} +.pro-auto-hero{background:radial-gradient(circle at 68% 50%,#243b54 0%,#112539 34%,#081728 100%);color:#fff}.pro-auto-hero .pro-eyebrow{color:#d5a366}.pro-auto-hero .pro-hero-copy h1 em{color:#d2a16b}.pro-auto-hero .pro-hero-copy p{color:#b9c7d6}.pro-auto-hero .pro-button{color:#0d1b2d!important;background:#d8ad72}.pro-link-light{color:#d8e4ec;font-size:13px;font-weight:750}.pro-auto-hero .pro-hero-art{background:linear-gradient(160deg,#243e59,#0f2033);border:1px solid #ffffff25;box-shadow:0 50px 80px #0005;border-radius:3px;overflow:visible}.pro-abstract-car{position:absolute;inset:0;overflow:hidden;background:radial-gradient(ellipse at 50% 80%,#45648599,transparent 63%)}.pro-abstract-car:before{content:'';position:absolute;left:10%;right:9%;bottom:29%;height:29%;border:3px solid #d3dfefad;border-radius:53% 49% 10% 12%;transform:skewX(-9deg);box-shadow:0 23px 15px #05121f88,0 0 0 3px #182c41 inset}.pro-abstract-car:after{content:'';position:absolute;left:23%;right:23%;bottom:56%;height:17%;border:3px solid #d3dfef72;border-radius:85% 85% 0 0;transform:skewX(-20deg)}.pro-abstract-car>span{position:absolute;top:26px;right:22px;font-size:10px;letter-spacing:.2em;color:#ccd9e5}.auto-wheel{position:absolute;bottom:18%;width:16%;aspect-ratio:1;border-radius:50%;border:11px solid #6f8499;background:#111e2c;box-shadow:0 0 0 4px #111a25}.auto-wheel.a{left:19%}.auto-wheel.b{right:17%}.pro-hero-art>b{position:absolute;bottom:-31px;right:0;font-size:11px;letter-spacing:.2em;color:#bdcde0}.pro-featured{background:#f4f6f8}.pro-featured .pro-card{border:0;box-shadow:0 7px 30px #0f2e4710}.pro-featured .pro-card-cover{background:#d9e2eb}.pro-featured .pro-art{background:linear-gradient(140deg,#dce5ed,#a9baca)}.pro-featured .pro-art-ring{border-color:#eef3f8bb}.pro-statement{background:#12243b;color:#fff}.pro-statement .pro-eyebrow{color:#d3a975}.pro-statement p{color:#aebfd3}.pro-statement h2{font-size:clamp(42px,5vw,70px);max-width:700px}.pro-statement .pro-text-link{color:#dfba83}.pro-brand-section{background:white}.pro-brand-pills a{min-width:150px;text-align:center;background:#f5f7fa}.pro-inner-hero{background:linear-gradient(120deg,#101e31,#273b51);color:#fff}.pro-inner-hero .pro-eyebrow{color:#d0a46b}.pro-inner-hero p,.pro-inner-hero .pro-breadcrumb{color:#c9d1df}.pro-inner-hero .pro-breadcrumb strong{color:#fff}.pro-article-hero{background:#14243a;color:#fff}.pro-article-hero p{color:#bed0df}.pro-footer{background:#071421}.pro-footer-bottom{color:#98aebf}.pro-end-cta{background:#1a324b}.pro-end-cta a{background:#d4a56d;color:#132339!important}.pro-404 h1{color:#b8905c} + +/* SiteForge V5 commercial signature */ +.pro-auto-hero .pro-hero-art{background-image:url("./visual/hero.svg")!important;background-position:center;background-size:cover;} + +.pro-auto-hero{background:linear-gradient(117deg,#081729 0%,#102a43 100%)}.pro-auto-hero .pro-hero-art{border:1px solid #52667a55;border-radius:3px;box-shadow:0 30px 90px #0004;transform:translateX(0)}.pro-auto-hero .pro-hero-art .pro-abstract-car{opacity:0}.pro-hero-bottom{border-top:1px solid #ffffff1c}.pro-brand-pills a{transition:background .2s}.pro-brand-pills a:hover{background:#d6a974;color:#10233a}.pro-card{border-color:#e0e6ee;border-radius:5px}.pro-card-cover{background:linear-gradient(135deg,#edf1f6,#dbe4eb)}.pro-art{background:linear-gradient(130deg,#e0e8ee,#c4d0dc);color:#37536b}.pro-featured{background:#f8fafc}.pro-statement{background:#0d2134;color:white}.pro-statement p{color:#c6d0dd}.pro-statement .pro-text-link{color:#f0b870}.pro-section-head h2{font-weight:800}.pro-footer{background:#08182a;color:#e5e9ed} + +/* V8.29 presentation refinement: automotive. Preserve per-theme design language. */ +body.pro-automotive{--pro-studio-ring:rgba(209,161,99,.28);--pro-focus-color:#d1a163;--pro-interact-radius:6px} +body.pro-automotive .pro-wrap{max-width:100%;min-width:0} +body.pro-automotive .pro-hero-copy,body.pro-automotive .pro-card-body,body.pro-automotive .pro-card-copy{min-width:0;overflow-wrap:anywhere} +body.pro-automotive .pro-hero-copy h1{font-size:clamp(2.45rem,5.15vw,5.6rem);line-height:1.08;max-width:18ch;text-wrap:balance} +body.pro-automotive .pro-section-head h2{font-size:clamp(1.85rem,3vw,3.25rem);text-wrap:balance} +body.pro-automotive .pro-card,body.pro-automotive .pro-product-card{transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease} +@media(hover:hover){body.pro-automotive .pro-card:hover,body.pro-automotive .pro-product-card:hover{transform:translateY(-3px);box-shadow:0 14px 36px var(--pro-studio-ring)}} +body.pro-automotive :where(button,a,input,select,textarea):focus-visible{outline:3px solid var(--pro-focus-color);outline-offset:3px} +body.pro-automotive img{max-width:100%;height:auto} +body.pro-automotive .pro-card-cover img,body.pro-automotive .pro-gallery-main img{object-fit:cover;max-height:100%} +body.pro-automotive .pro-mobile-toggle,body.pro-automotive .pro-nav-disclose{min-height:44px;min-width:44px} +@media(max-width:860px){body.pro-automotive .pro-home-grid,body.pro-automotive .pro-product-layout,body.pro-automotive .pro-inquiry-wrap{min-width:0}body.pro-automotive .pro-card-grid,body.pro-automotive .pro-grid{gap:clamp(12px,3vw,23px)}} +@media(max-width:560px){body.pro-automotive .pro-wrap{padding-left:max(16px,env(safe-area-inset-left));padding-right:max(16px,env(safe-area-inset-right))}body.pro-automotive .pro-hero-copy h1{font-size:clamp(2rem,9vw,3.2rem)}body.pro-automotive .pro-section-head h2{font-size:clamp(1.75rem,7vw,2.5rem)}body.pro-automotive .pro-section{padding-block:clamp(34px,9vw,60px)}body.pro-automotive .pro-card-cover{height:auto;aspect-ratio:4/3}body.pro-automotive .pro-card-cover img{width:100%;height:100%;object-fit:cover}} +@media(prefers-reduced-motion:reduce){body.pro-automotive .pro-card,body.pro-automotive .pro-product-card{transition:none!important;transform:none!important}} + + +/* V8.30 REAL PAGE COMPOSITION. Built-in theme version 1.3.0 only. + Content-driven sections do not invent client names, certifications or KPIs. */ +.pro-v30-page{--v30-ink:var(--pro-text);--v30-secondary:var(--pro-muted);--v30-line:var(--pro-border);--v30-panel:var(--pro-surface);--v30-max:1180px;color:var(--v30-ink);overflow:clip} +.pro-v30-page .pro-wrap{max-width:var(--v30-max);min-width:0} +.pro-v30-page h1,.pro-v30-page h2{overflow-wrap:anywhere;text-wrap:balance;line-height:1.11} +.pro-v30-page h1{font-size:clamp(2.55rem,5.2vw,5.6rem);margin:18px 0 22px;letter-spacing:-.035em} +.pro-v30-page h2{font-size:clamp(1.8rem,3.3vw,3rem);margin:16px 0 26px;letter-spacing:-.02em} +.pro-v30-page p{line-height:1.75;overflow-wrap:anywhere} +.pro-v30-page img{max-width:100%} +.pro-v30-intro-layout{display:grid;grid-template-columns:minmax(0,1fr) 190px;gap:8vw;align-items:end} +.pro-v30-page-intro{padding:clamp(68px,10vw,128px) 0 clamp(55px,8vw,94px);background:var(--v30-panel)} +.pro-v30-intro-main>p{max-width:610px;font-size:clamp(16px,2vw,21px);color:var(--v30-secondary)} +.pro-v30-intro-aside{border-left:1px solid var(--v30-line);padding-left:27px;display:grid;gap:8px;align-content:end;min-height:120px} +.pro-v30-overline,.pro-v30-caption{font-size:11px;letter-spacing:.12em;color:var(--v30-secondary)} +.pro-v30-index-number{font-size:64px;line-height:1;font-weight:650;letter-spacing:-.08em} +.pro-v30-index-toolbar{display:flex;justify-content:space-between;align-items:end;gap:22px;margin-bottom:28px} +.pro-v30-index-body{background:var(--pro-background)} +.pro-v30-index-body .pro-section-head,.pro-v30-index-toolbar h2{margin:8px 0} +.pro-v30-subtle-link,.pro-v30-text-action{display:inline-flex;gap:10px;text-decoration:none;font-weight:750;font-size:13px;align-items:center;min-height:44px} +.pro-v30-subtle-link:hover,.pro-v30-text-action:hover{text-decoration:underline} +.pro-v30-results{margin-top:clamp(28px,5vw,54px)} +.pro-v30-product-top{padding:26px 0 clamp(60px,8vw,110px);background:var(--v30-panel)} +.pro-v30-crumb{display:flex;flex-wrap:wrap;gap:11px;align-items:center;font-size:12px;color:var(--v30-secondary);margin:8px 0 46px} +.pro-v30-crumb a{text-decoration:underline;text-underline-offset:4px} +.pro-v30-product-head{display:grid;grid-template-columns:minmax(290px,.78fr) minmax(0,1.22fr);align-items:center;gap:clamp(30px,6vw,90px)} +.pro-v30-product-intro>p{font-size:clamp(16px,2vw,19px);color:var(--v30-secondary);max-width:48ch} +.pro-v30-tags{display:flex;gap:8px;flex-wrap:wrap;margin:24px 0 30px}.pro-v30-tags span{padding:8px 13px;border:1px solid var(--v30-line);font-size:12px;border-radius:2px} +.pro-v30-action{display:inline-flex;align-items:center;justify-content:center;min-height:48px} +.pro-v30-main-media{background:var(--pro-surface);aspect-ratio:4/3;overflow:hidden;display:grid;place-items:center;border-radius:var(--pro-radius)} +.pro-v30-main-media .pro-photo{width:100%;height:100%;object-fit:contain} +.pro-v30-product-details{display:grid;grid-template-columns:minmax(0,1.3fr) minmax(270px,.7fr);gap:clamp(30px,7vw,104px)} +.pro-v30-details-main .pro-rich{max-width:760px}.pro-v30-details-side{align-self:start;border-top:3px solid var(--pro-accent);padding-top:25px} +.pro-v30-details-side .pro-specs>div{grid-template-columns:minmax(0,1fr) minmax(0,1.1fr);gap:16px}.pro-v30-details-side .pro-specs strong{overflow-wrap:anywhere} +.pro-v30-reading-head{padding:clamp(50px,8vw,100px) 0 clamp(60px,8vw,100px);background:var(--v30-panel)} +.pro-v30-reading-title{max-width:940px;margin:auto}.pro-v30-reading-title>p{font-size:clamp(16px,2.1vw,22px);max-width:65ch;color:var(--v30-secondary)} +.pro-v30-reading-title time{display:block;margin-top:24px;font-size:13px;color:var(--v30-secondary)} +.pro-v30-reading-layout{display:grid;grid-template-columns:180px minmax(0,750px);gap:clamp(35px,7vw,110px);padding-block:clamp(55px,8vw,110px)} +.pro-v30-reading-aside{display:flex;flex-direction:column;gap:18px;align-self:start;position:sticky;top:30px;font-size:13px} +.pro-v30-reading-rule{height:1px;background:var(--v30-line)} +.pro-v30-reading-content{min-width:0}.pro-v30-reading-content figure{margin:0 0 45px}.pro-v30-reading-content figure img{display:block;width:100%;height:auto;max-height:550px;object-fit:cover} +.pro-v30-reading-content .pro-rich{line-height:1.9;font-size:clamp(16px,1.75vw,18px)}.pro-v30-reading-content .pro-rich>*+*{margin-top:1.3em} +.pro-v30-about-opening{padding:clamp(75px,10vw,130px) 0;background:var(--v30-panel)} +.pro-v30-about-heading{display:grid;grid-template-columns:1.3fr .7fr;gap:9%;align-items:end}.pro-v30-about-heading>p{font-size:clamp(17px,2vw,23px);color:var(--v30-secondary);padding-bottom:12px} +.pro-v30-about-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(36px,8vw,120px);align-items:center} +.pro-v30-about-media{min-height:360px;aspect-ratio:5/4;background:var(--v30-panel);overflow:hidden}.pro-v30-about-media img{width:100%;height:100%;object-fit:cover} +.pro-v30-media-placeholder{height:100%;min-height:360px;display:grid;place-items:center;color:var(--v30-secondary);letter-spacing:.18em;font-size:12px;border:1px solid var(--v30-line)} +.pro-v30-about-copy .pro-rich{max-width:620px}.pro-v30-about-cases{background:var(--v30-panel)} +.pro-v30-contact-header{background:var(--v30-panel);padding:clamp(75px,10vw,135px) 0}.pro-v30-contact-header p{font-size:clamp(17px,2vw,21px);max-width:58ch;color:var(--v30-secondary)} +.pro-v30-contact-layout{display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);gap:clamp(40px,8vw,120px)} +.pro-v30-contact-channel{display:grid;gap:10px;margin-top:45px;border-top:1px solid var(--v30-line);padding-top:25px}.pro-v30-contact-channel span{font-size:12px;color:var(--v30-secondary)}.pro-v30-contact-channel a{font-size:clamp(15px,2vw,24px);overflow-wrap:anywhere;font-weight:650} +.pro-v30-contact-form-wrap{padding:clamp(22px,4vw,48px);background:var(--v30-panel);min-width:0} +.pro-v30-contact-form-wrap .pro-inquiry{margin-top:22px}.pro-v30-contact-form-wrap .pro-inquiry input,.pro-v30-contact-form-wrap textarea{background:var(--pro-background)} +.pro-v30-contact-note{display:grid;align-content:space-between;min-height:270px;gap:24px}.pro-v30-decorative-number{font-size:90px;line-height:1;justify-self:end;color:var(--pro-accent)} +.pro-v30-home-editorial{background:var(--pro-surface)} +.pro-v30-page :where(a,button,input,textarea,select):focus-visible{outline:3px solid var(--pro-accent);outline-offset:3px} +@media(max-width:950px){.pro-v30-product-head,.pro-v30-product-details,.pro-v30-about-grid,.pro-v30-contact-layout{grid-template-columns:1fr;gap:38px}.pro-v30-product-visual{order:-1}.pro-v30-about-heading{grid-template-columns:1fr;gap:4px}.pro-v30-about-media{max-height:430px}.pro-v30-reading-layout{grid-template-columns:1fr;gap:24px}.pro-v30-reading-aside{position:static;flex-direction:row;align-items:center;flex-wrap:wrap}.pro-v30-reading-rule{display:none}} +@media(max-width:600px){.pro-v30-page .pro-wrap{padding-inline:max(18px,env(safe-area-inset-left));}.pro-v30-page h1{font-size:clamp(2.2rem,9.2vw,3.4rem)}.pro-v30-intro-layout{grid-template-columns:1fr;gap:18px}.pro-v30-intro-aside{display:none}.pro-v30-index-toolbar{align-items:start;flex-direction:column;gap:0}.pro-v30-crumb{margin-bottom:24px}.pro-v30-product-top{padding-bottom:42px}.pro-v30-main-media{aspect-ratio:5/4}.pro-v30-product-details{gap:45px}.pro-v30-reading-title{margin:0}.pro-v30-reading-content figure{margin-bottom:22px}.pro-v30-about-media,.pro-v30-media-placeholder{min-height:220px}.pro-v30-contact-form-wrap{padding:20px}.pro-v30-contact-layout{gap:30px}} +@media(prefers-reduced-motion:reduce){.pro-v30-page *{scroll-behavior:auto!important}} + +/* Theme-specific editorial composition */ + .pro-v30-product-automotive .pro-v30-main-media{background:linear-gradient(155deg,#eaf0f5,#d8e4ed)}.pro-v30-product-automotive .pro-v30-product-head{grid-template-columns:.7fr 1.3fr}.pro-v30-article-automotive .pro-v30-reading-head{background:linear-gradient(145deg,#0d2339,#213a55);color:#fff}.pro-v30-article-automotive .pro-v30-reading-title>p,.pro-v30-article-automotive .pro-v30-crumb{color:#d9e4ed}.pro-v30-vehicle-index .pro-v30-page-intro{background:#11283d;color:#f7f9fb}.pro-v30-vehicle-index .pro-v30-intro-main>p,.pro-v30-vehicle-index .pro-v30-intro-aside{color:#cbd6e0}.pro-v30-vehicle-index .pro-v30-intro-aside{border-color:#ffffff39}.pro-v30-vehicle-index .pro-eyebrow{color:#e2b47b}.pro-v30-product-automotive .pro-v30-product-intro h1{letter-spacing:-.055em} + +@media(max-width:950px){.pro-v30-product-automotive .pro-v30-product-head{grid-template-columns:1fr}} + +/* Retain existing gallery runtime behavior with re-composed product layout. */ +.pro-v30-page .pro-product-media{height:auto;min-height:0} diff --git a/examples/v830-built-sites/automotive/assets/pro.js b/examples/v830-built-sites/automotive/assets/pro.js new file mode 100644 index 0000000..9cf100d --- /dev/null +++ b/examples/v830-built-sites/automotive/assets/pro.js @@ -0,0 +1,72 @@ +'use strict';(()=>{ + const menu=document.querySelector('[data-pro-menu]'); const nav=document.querySelector('#pro-navigation'); + if(menu&&nav){menu.addEventListener('click',()=>{const open=menu.getAttribute('aria-expanded')!=='true';menu.setAttribute('aria-expanded',String(open));nav.classList.toggle('is-open',open);menu.setAttribute('aria-label',open?'关闭导航':'打开导航');});} + // Drawer navigation. The same markup is used across the four professional themes. + const mobileNav=document.querySelector('#pro-navigation'); + let drawerBackdrop=null,drawerClose=null,returnFocus=null; + if(menu&&mobileNav){ + const originalParent=mobileNav.parentNode,originalNext=mobileNav.nextSibling; + const heading=document.createElement('div');heading.className='sf-drawer-header'; + const title=document.createElement('strong');title.textContent='网站导航'; + drawerClose=document.createElement('button');drawerClose.type='button';drawerClose.className='sf-drawer-close';drawerClose.textContent='×';drawerClose.setAttribute('aria-label','关闭网站导航'); + heading.append(title,drawerClose);mobileNav.prepend(heading); + drawerBackdrop=document.createElement('div');drawerBackdrop.className='sf-mobile-drawer-backdrop';drawerBackdrop.hidden=false;document.body.append(drawerBackdrop); + function setDrawer(open,focusBack=true){ + const isMobile=window.matchMedia('(max-width:1024px)').matches; + open=Boolean(open&&isMobile); + if(open){returnFocus=document.activeElement;document.body.append(mobileNav);} + else if(mobileNav.parentNode!==originalParent){if(originalNext&&originalNext.parentNode===originalParent)originalParent.insertBefore(mobileNav,originalNext);else originalParent.append(mobileNav);} + mobileNav.classList.toggle('is-open',open);drawerBackdrop.classList.toggle('is-open',open); + document.body.classList.toggle('sf-drawer-open',open); + menu.setAttribute('aria-expanded',String(open));menu.setAttribute('aria-label',open?'关闭导航':'打开导航'); + mobileNav.setAttribute('aria-hidden',String(!open&&isMobile)); + if('inert' in mobileNav)mobileNav.inert=!open&&isMobile; + if(open)drawerClose.focus(); + else if(focusBack&&returnFocus instanceof HTMLElement){returnFocus.focus();returnFocus=null;} + } + // Replace the old inline-expansion listener: use capture to stop the old listener. + menu.addEventListener('click',e=>{if(!window.matchMedia('(max-width:1024px)').matches)return;e.stopImmediatePropagation();setDrawer(!mobileNav.classList.contains('is-open'));},true); + drawerClose.addEventListener('click',()=>setDrawer(false)); + drawerBackdrop.addEventListener('click',()=>setDrawer(false)); + document.querySelectorAll('[data-mobile-open-menu]').forEach(b=>b.addEventListener('click',()=>setDrawer(true))); + mobileNav.addEventListener('click',e=>{if(e.target.closest('a'))setDrawer(false,false)}); + document.addEventListener('keydown',e=>{ + if(e.key==='Escape'&&mobileNav.classList.contains('is-open')){e.preventDefault();setDrawer(false);} + if(e.key!=='Tab'||!mobileNav.classList.contains('is-open'))return; + const els=[...mobileNav.querySelectorAll('button:not([disabled]),a[href]')].filter(el=>el.getClientRects().length&&!el.closest('[hidden]')); + if(!els.length)return;const first=els[0],last=els[els.length-1]; + if(e.shiftKey&&document.activeElement===first){e.preventDefault();last.focus();} + else if(!e.shiftKey&&document.activeElement===last){e.preventDefault();first.focus();} + }); + window.matchMedia('(max-width:1024px)').addEventListener('change',()=>setDrawer(false,false)); + if('inert' in mobileNav&&window.matchMedia('(max-width:1024px)').matches)mobileNav.inert=true; + // Do not strand catalogue links when the old mobile mega-button is hidden. + const megaLinks=document.querySelectorAll('[data-pro-mega] a'); + if(megaLinks.length){const wrap=document.createElement('div');wrap.className='sf-drawer-extra';const h=document.createElement('strong');h.textContent='更多分类与系列';wrap.append(h); + [...megaLinks].slice(0,20).forEach(a=>{const clone=a.cloneNode(true);wrap.append(clone);});mobileNav.append(wrap);} + } + const tabbar=document.querySelector('[data-mobile-tabs]'); + if(tabbar){tabbar.style.setProperty('--sf-mobile-tab-count',String(tabbar.children.length));} + const megaButton=document.querySelector('[data-pro-catalog]'), mega=document.querySelector('[data-pro-mega]'); + if(megaButton&&mega){function setMega(open){mega.hidden=!open;mega.classList.toggle('is-open',open);megaButton.setAttribute('aria-expanded',String(open));} + megaButton.addEventListener('click',()=>setMega(mega.hidden)); + document.addEventListener('keydown',e=>{if(e.key==='Escape')setMega(false);}); + document.addEventListener('click',e=>{if(!mega.hidden&&!mega.contains(e.target)&&!megaButton.contains(e.target))setMega(false);}); + } + document.querySelectorAll('.pro-nav-disclose').forEach(button=>{button.addEventListener('click',()=>{let panel=button.parentElement.querySelector('.pro-nav-children');let visible=button.getAttribute('aria-expanded')==='true';button.setAttribute('aria-expanded',String(!visible));panel.hidden=visible;});}); + document.querySelectorAll('.pro-gallery-thumbs').forEach(container=>{const main=container.parentElement.querySelector('.pro-product-media img');const buttons=[...container.querySelectorAll('[data-gallery-image]')]; + buttons.forEach(b=>{b.addEventListener('click',()=>{buttons.forEach(x=>x.setAttribute('aria-pressed',String(x===b)));if(main){main.src=b.dataset.galleryImage;main.alt=b.querySelector('img')?.alt||'';}});}); + if(!main)return;main.tabIndex=0;main.style.cursor='zoom-in';const open=()=>{const pane=document.createElement('div');pane.className='pro-gallery-lightbox';pane.setAttribute('role','dialog');pane.setAttribute('aria-label','产品大图预览');let img=document.createElement('img');img.src=main.src;img.alt=main.alt;const close=document.createElement('button');close.type='button';close.textContent='关闭 ×';pane.append(img,close);document.body.append(pane);const done=()=>{pane.remove();document.removeEventListener('keydown',esc);main.focus();};const esc=e=>{if(e.key==='Escape')done();};document.addEventListener('keydown',esc);close.addEventListener('click',done);pane.addEventListener('click',e=>{if(e.target===pane)done();});close.focus();};main.addEventListener('click',open);main.addEventListener('keydown',e=>{if(e.key==='Enter')open();}); + }); + document.querySelectorAll('.pro-filter-scope').forEach(scope=>{ + const panel=scope.previousElementSibling;if(!panel||!panel.classList.contains('pro-filter-panel'))return; + const cards=Array.from(scope.querySelectorAll('.pro-card')); + const blank=document.createElement('div');blank.className='pro-filter-empty';blank.hidden=true;blank.textContent='没有找到符合条件的内容,请调整关键词或筛选条件。';scope.append(blank); + const q=panel.querySelector('[data-pro-filter-search]'),b=panel.querySelector('[data-pro-filter-brand]'),c=panel.querySelector('[data-pro-filter-category]'),count=panel.querySelector('[data-pro-filter-count]'); + function options(sel,key){const vals=[...new Set(cards.map(x=>x.dataset[key]||'').filter(Boolean))].sort();vals.forEach(x=>sel.add(new Option(x,x)));if(!vals.length)sel.closest('label').hidden=true;} + options(b,'brand');options(c,'category'); + function run(){const str=q.value.trim().toLocaleLowerCase();let visible=0; + cards.forEach(el=>{const hit=el.textContent.toLocaleLowerCase().includes(str)&&(!b.value||el.dataset.brand===b.value)&&(!c.value||el.dataset.category===c.value);el.hidden=!hit;visible+=Number(hit);});count.textContent=`共 ${visible} 条`;blank.hidden=visible!==0;} + [q,b,c].forEach(x=>x.addEventListener(x===q?'input':'change',run));run(); + }); +})(); diff --git a/examples/v830-built-sites/automotive/assets/site-runtime.js b/examples/v830-built-sites/automotive/assets/site-runtime.js new file mode 100644 index 0000000..e4715e8 --- /dev/null +++ b/examples/v830-built-sites/automotive/assets/site-runtime.js @@ -0,0 +1,31 @@ +'use strict'; +(()=>{ + const $=s=>document.querySelector(s), $$=s=>[...document.querySelectorAll(s)]; + const menu=$('.sf-menu-toggle');if(menu){menu.addEventListener('click',()=>{let open=menu.getAttribute('aria-expanded')!=='true';menu.setAttribute('aria-expanded',String(open));$('#sf-primary-links')?.classList.toggle('is-open',open);});} + // Filter actual static content cards, no API is needed at runtime. + $$('.sf-collection').forEach(grid=>{ + const cards=$$('.sf-item',grid); + if(cards.length<2)return; + const toolbar=document.createElement('div');toolbar.className='sf-filters'; + const search=document.createElement('input');search.type='search';search.placeholder='筛选当前列表';search.setAttribute('aria-label','筛选当前列表'); + const status=document.createElement('span');status.setAttribute('aria-live','polite');status.style.fontSize='12px'; + const brand=document.createElement('select');brand.setAttribute('aria-label','按品牌筛选'); + const category=document.createElement('select');category.setAttribute('aria-label','按分类筛选'); + function fill(el,field,all){el.append(new Option(all,''));const vals=[...new Set(cards.map(x=>x.dataset[field]||'').filter(Boolean))].sort();vals.forEach(v=>el.append(new Option(v,v)));if(!vals.length)el.hidden=true;} + fill(brand,'brand','全部品牌');fill(category,'category','全部分类'); + toolbar.append(search,brand,category,status);grid.parentNode.insertBefore(toolbar,grid); + function apply(){let val=search.value.trim().toLocaleLowerCase();let visible=0;cards.forEach(card=>{let hit=card.textContent.toLocaleLowerCase().includes(val)&&(!brand.value||card.dataset.brand===brand.value)&&(!category.value||card.dataset.category===category.value);card.hidden=!hit;if(hit)visible++;});status.textContent=`共 ${visible} 项`;} + search.addEventListener('input',apply);brand.addEventListener('change',apply);category.addEventListener('change',apply);apply(); + }); + const input=$('#sf-search'),root=$('#sf-search-results'),count=$('#sf-search-count'); + if(input&&root){ + let data=[];const params=new URLSearchParams(location.search);input.value=params.get('q')||''; + let debounce=null; + const render=()=>{let q=input.value.trim().toLocaleLowerCase();let found=q?data.filter(d=>`${d.title} ${d.summary} ${d.brand} ${d.type}`.toLocaleLowerCase().includes(q)).slice(0,100):data.slice(0,30); + root.replaceChildren();count.textContent=`${found.length} 条结果${!q?'(显示前30条)':''}`; + found.forEach(d=>{let article=document.createElement('article'),a=document.createElement('a'),small=document.createElement('small'),p=document.createElement('p');article.className='sf-search-result';a.textContent=d.title;a.href=d.url.replace(/^\//,'');small.textContent=d.type;p.textContent=d.summary;article.append(a,small,p);root.append(article);}); + };const base=document.querySelector('base')?.href||location.href; + fetch(new URL('search-index.json',base)).then(r=>{if(!r.ok)throw Error('index unavailable');return r.json();}).then(v=>{data=v;render()}).catch(()=>{count.textContent='搜索索引加载失败,请检查站点文件部署路径';}); + input.addEventListener('input',()=>{clearTimeout(debounce);debounce=setTimeout(render,100)}); + } +})(); diff --git a/examples/v830-built-sites/automotive/assets/theme.css b/examples/v830-built-sites/automotive/assets/theme.css new file mode 100644 index 0000000..709f906 --- /dev/null +++ b/examples/v830-built-sites/automotive/assets/theme.css @@ -0,0 +1,4 @@ +:root{--accent:#ecb75c;--ink:#f6f7fa;--body:#101318}*{box-sizing:border-box}body{margin:0;background:#f7f7f7;color:#1b232c;font:16px/1.65 Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}a{text-decoration:none;color:inherit}img{max-width:100%;object-fit:cover}.utility{height:32px;display:flex;justify-content:space-between;align-items:center;background:#090d13;color:#919da8;padding:0 5%;font-size:10px;letter-spacing:2px}.header{height:90px;background:#121922;color:#fff;display:flex;align-items:center;justify-content:space-between;padding:0 5%;gap:24px}.brand{font-size:22px;font-weight:780;display:flex;align-items:center;gap:14px;line-height:1.15}.brand small{display:block;font-size:9px;color:#9ba4b4;letter-spacing:2.5px;margin-top:5px}.mark{background:var(--accent);border-radius:3px;color:#111;padding:10px;font-size:19px}.header nav{display:flex;flex-wrap:wrap;gap:26px;font-size:12px;letter-spacing:1px}.header nav a:hover{color:var(--accent)}.nav-cta{border:1px solid #505a62;padding:12px 17px;color:#e6c893;font-size:11px;letter-spacing:1px}.hero{background:radial-gradient(circle at 80% 55%,#2d4359 0%,#141e2c 34%,#0b121b 75%);color:white;min-height:580px}.hero-inner{max-width:1450px;margin:auto;padding:70px 5% 50px;display:grid;grid-template-columns:51% 49%;align-items:center;min-height:520px}.eyebrow{font-size:11px;letter-spacing:3px;font-weight:700;color:#e9b962}.glow{display:inline-block;width:8px;height:8px;background:#efbf6e;border-radius:100%;margin-right:12px;box-shadow:0 0 16px #edc36d}.hero h1{font-size:clamp(54px,7.2vw,116px);font-weight:850;letter-spacing:-6px;line-height:.95;margin:29px 0}.hero p{font-size:17px;color:#b6c4d1;max-width:470px}.hero-actions{display:flex;align-items:center;gap:30px;margin-top:34px}.btn{display:inline-flex;align-items:center;justify-content:space-between;gap:32px;padding:17px 23px;background:#d5a962;color:#12181d;font-size:12px;font-weight:850;letter-spacing:.8px}.hero-hint{color:#89929b;font-size:12px}.hero-visual{height:330px;position:relative;display:flex;align-items:center;justify-content:center}.hero-visual img{max-height:360px;width:100%;object-fit:contain;filter:drop-shadow(0 16px 23px #0008)}.hero-no{position:absolute;right:0;bottom:-70px;color:#fff6;font-size:10px;letter-spacing:3px}.car-shape{height:220px;width:100%;position:relative;filter:drop-shadow(0 28px 16px #0007)}.car-body{position:absolute;inset:45px 0 24px;border-radius:90px 130px 36px 35px;background:linear-gradient(170deg,#c7d0d9,#60788a 37%,#142433 48%,#202d3d 70%);clip-path:polygon(0 70%,13% 47%,31% 38%,47% 6%,75% 6%,88% 39%,100% 56%,98% 95%,3% 95%)}.wheel{position:absolute;width:80px;height:80px;bottom:0;border-radius:100%;background:radial-gradient(circle,#71808b 0 25%,#101722 28% 50%,#354355 54% 61%,#0a0d13 64%)}.wheel-one{left:19%}.wheel-two{right:13%}.hero-bottom{border-top:1px solid #344052;padding:18px 5%;display:flex;justify-content:space-between;color:#9fa9b5;font-size:10px;letter-spacing:2px}.inner-hero{background:linear-gradient(110deg,#0d1925,#2a3f50);color:white;padding:100px 6% 90px}.inner-hero h1{font-size:clamp(40px,6vw,84px);line-height:1.1;letter-spacing:-2px;margin:16px 0}.inner-hero p{color:#c0ccd7}.container{max-width:1220px;margin:auto;padding:0 24px}.main{padding:75px 0 110px}.section-title{display:flex;align-items:end;gap:20px;justify-content:space-between;margin:30px 0 28px}.section-title span{font-size:11px;letter-spacing:2px;color:#9f7844}.section-title h2{font-size:37px;letter-spacing:-1.5px;flex:1;margin:0}.section-title a{font-size:12px;font-weight:700}.card-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:24px}.model-card{background:#fff;transition:transform .2s,box-shadow .2s;min-width:0}.model-card:hover{transform:translateY(-4px);box-shadow:0 14px 35px #15273822}.card-visual{height:210px;background:linear-gradient(120deg,#dae2e8,#abbcc7);display:flex;align-items:center;justify-content:center;overflow:hidden}.card-visual img{height:100%;width:100%;object-fit:contain}.card-monogram{font-size:75px;font-weight:900;letter-spacing:-8px;color:#ffffff77}.card-copy{padding:24px}.card-copy span{color:#ae854c;font-size:10px;letter-spacing:2px}.card-copy h3{font-size:24px;margin:8px 0}.card-copy p{font-size:13px;color:#73808b}.card-copy b{font-size:11px;letter-spacing:1px;color:#a6793f}.detail-media{margin:40px auto;text-align:center;max-height:600px}.detail-media img{max-height:600px}.rich-content{margin-bottom:55px}.prose{max-width:860px}.rich-content p{color:#596574}.section{padding:45px 0}.section-heading h2{font-size:38px}.block-hero{padding:60px 0}.block-hero h1{font-size:52px}.feature-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}.feature{padding:26px;background:white}.feature-mark{color:#b08756;font-size:12px}.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:20px}.stat strong{display:block;font-size:35px}.stat span{color:#71808c}.cta{background:#19283a;color:white;padding:55px}.cta p{color:#b8c8d6}footer{background:#0d151f;color:white;padding:70px 5% 25px}.footer-brand{font-size:25px;font-weight:750}.footer-brand span{font-size:11px;font-weight:400;color:#aeb8c2}footer p{color:#8593a2}.footer-bottom{border-top:1px solid #30404c;padding-top:25px;margin-top:65px;display:flex;justify-content:space-between;font-size:10px;letter-spacing:1px;color:#8995a3}@media(max-width:860px){.utility{font-size:8px}.header{height:auto;padding:18px 5%;align-items:flex-start;flex-wrap:wrap}.header nav{order:3;width:100%;gap:18px}.nav-cta{display:none}.hero-inner{grid-template-columns:1fr;padding-top:55px}.hero h1{letter-spacing:-3px}.hero-visual{height:210px}.hero-no{bottom:0}.card-grid,.feature-grid{grid-template-columns:repeat(2,1fr)}}@media(max-width:560px){.card-grid,.feature-grid,.stats{grid-template-columns:1fr}.hero h1{font-size:56px}.hero-actions{flex-wrap:wrap}.section-title{align-items:start;flex-direction:column}.inner-hero{padding:75px 6%}.hero-bottom{font-size:8px}} + +/* V8.29 baseline: accessible touch/focus and reduced motion */ +:where(a,button,input,select,textarea):focus-visible{outline:3px solid currentColor;outline-offset:3px}@media(max-width:560px){img{max-width:100%;height:auto}body{overflow-wrap:anywhere}}@media(prefers-reduced-motion:reduce){*,*:before,*:after{scroll-behavior:auto!important;transition:none!important;animation-duration:.01ms!important}} diff --git a/examples/v830-built-sites/automotive/assets/visual/hero.svg b/examples/v830-built-sites/automotive/assets/visual/hero.svg new file mode 100644 index 0000000..4ba145a --- /dev/null +++ b/examples/v830-built-sites/automotive/assets/visual/hero.svg @@ -0,0 +1 @@ +CONCEPT / MOBILITY diff --git a/examples/v830-built-sites/automotive/brand/index.html b/examples/v830-built-sites/automotive/brand/index.html new file mode 100644 index 0000000..dd721f1 --- /dev/null +++ b/examples/v830-built-sites/automotive/brand/index.html @@ -0,0 +1,41 @@ +品牌展示跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    +
    VEHICLE COLLECTION / INDEX

    品牌展示

    Explore our brand

    BROWSE / EXPLORE03本页展示内容
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/brands/arc/index.html b/examples/v830-built-sites/automotive/brands/arc/index.html new file mode 100644 index 0000000..e4bf63a --- /dev/null +++ b/examples/v830-built-sites/automotive/brands/arc/index.html @@ -0,0 +1,38 @@ +ARC跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    BRAND PROFILE / PARTNERS

    ARC

    ARC 品牌产品与应用。

    +
    ARBRAND
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/brands/index.html b/examples/v830-built-sites/automotive/brands/index.html new file mode 100644 index 0000000..02691a6 --- /dev/null +++ b/examples/v830-built-sites/automotive/brands/index.html @@ -0,0 +1,41 @@ +品牌中心跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    +
    VEHICLE COLLECTION / INDEX

    品牌中心

    探索与产品相关的品牌。

    BROWSE / EXPLORE03本页展示内容
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/brands/mono/index.html b/examples/v830-built-sites/automotive/brands/mono/index.html new file mode 100644 index 0000000..8ef1461 --- /dev/null +++ b/examples/v830-built-sites/automotive/brands/mono/index.html @@ -0,0 +1,30 @@ +MONO跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    BRAND PROFILE / PARTNERS

    MONO

    MONO 品牌产品与应用。

    +
    MOBRAND
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/brands/nova/index.html b/examples/v830-built-sites/automotive/brands/nova/index.html new file mode 100644 index 0000000..e47effa --- /dev/null +++ b/examples/v830-built-sites/automotive/brands/nova/index.html @@ -0,0 +1,38 @@ +NOVA跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    BRAND PROFILE / PARTNERS

    NOVA

    NOVA 品牌产品与应用。

    +
    NOBRAND
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/case/index.html b/examples/v830-built-sites/automotive/case/index.html new file mode 100644 index 0000000..ad78e5c --- /dev/null +++ b/examples/v830-built-sites/automotive/case/index.html @@ -0,0 +1,41 @@ +案例展示跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/cases/1/index.html b/examples/v830-built-sites/automotive/cases/1/index.html new file mode 100644 index 0000000..b2ce8b0 --- /dev/null +++ b/examples/v830-built-sites/automotive/cases/1/index.html @@ -0,0 +1,12 @@ +精选项目 · 01跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    SELECTED WORK / PROJECT

    精选项目 · 01

    展示项目背景、过程与成果。

    项目地点
    Demo location
    所属行业
    Demo industry

    本页仅为项目结构示例,并非实际完成的工程项目。

    浏览更多案例 →
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/cases/2/index.html b/examples/v830-built-sites/automotive/cases/2/index.html new file mode 100644 index 0000000..0c9eb90 --- /dev/null +++ b/examples/v830-built-sites/automotive/cases/2/index.html @@ -0,0 +1,12 @@ +精选项目 · 02跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    SELECTED WORK / PROJECT

    精选项目 · 02

    展示项目背景、过程与成果。

    项目地点
    Demo location
    所属行业
    Demo industry

    本页仅为项目结构示例,并非实际完成的工程项目。

    浏览更多案例 →
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/cases/3/index.html b/examples/v830-built-sites/automotive/cases/3/index.html new file mode 100644 index 0000000..29e137f --- /dev/null +++ b/examples/v830-built-sites/automotive/cases/3/index.html @@ -0,0 +1,12 @@ +精选项目 · 03跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    SELECTED WORK / PROJECT

    精选项目 · 03

    展示项目背景、过程与成果。

    项目地点
    Demo location
    所属行业
    Demo industry

    本页仅为项目结构示例,并非实际完成的工程项目。

    浏览更多案例 →
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/cases/index.html b/examples/v830-built-sites/automotive/cases/index.html new file mode 100644 index 0000000..9d604e1 --- /dev/null +++ b/examples/v830-built-sites/automotive/cases/index.html @@ -0,0 +1,41 @@ +项目案例跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/categories/term-79e34764f8ce/index.html b/examples/v830-built-sites/automotive/categories/term-79e34764f8ce/index.html new file mode 100644 index 0000000..35ba9c5 --- /dev/null +++ b/examples/v830-built-sites/automotive/categories/term-79e34764f8ce/index.html @@ -0,0 +1,29 @@ +旗舰系列跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    DISCOVER / CATEGORY

    旗舰系列

    分类产品与相关信息

    首页/旗舰系列
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/categories/term-8d6647722ef3/index.html b/examples/v830-built-sites/automotive/categories/term-8d6647722ef3/index.html new file mode 100644 index 0000000..d94362c --- /dev/null +++ b/examples/v830-built-sites/automotive/categories/term-8d6647722ef3/index.html @@ -0,0 +1,29 @@ +专业系列跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    DISCOVER / CATEGORY

    专业系列

    分类产品与相关信息

    首页/专业系列
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/categories/term-95acf900fafc/index.html b/examples/v830-built-sites/automotive/categories/term-95acf900fafc/index.html new file mode 100644 index 0000000..40bfbb2 --- /dev/null +++ b/examples/v830-built-sites/automotive/categories/term-95acf900fafc/index.html @@ -0,0 +1,29 @@ +畅销系列跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    DISCOVER / CATEGORY

    畅销系列

    分类产品与相关信息

    首页/畅销系列
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/categories/term-a68a8656a4dc/index.html b/examples/v830-built-sites/automotive/categories/term-a68a8656a4dc/index.html new file mode 100644 index 0000000..c95ab99 --- /dev/null +++ b/examples/v830-built-sites/automotive/categories/term-a68a8656a4dc/index.html @@ -0,0 +1,29 @@ +定制系列跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    DISCOVER / CATEGORY

    定制系列

    分类产品与相关信息

    首页/定制系列
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/commercial-readiness.json b/examples/v830-built-sites/automotive/commercial-readiness.json new file mode 100644 index 0000000..7f79e5b --- /dev/null +++ b/examples/v830-built-sites/automotive/commercial-readiness.json @@ -0,0 +1,34 @@ +{ + "ready_for_review": true, + "commercially_certified": false, + "blockers": [], + "warnings": [ + { + "code": "brand_logo", + "message": "尚未替换成企业正式 Logo" + }, + { + "code": "placeholder_images", + "count": 75, + "message": "部分页面仍使用示意图,正式发布前请替换为真实且有使用权的图片" + }, + { + "code": "demo_content", + "message": "检测到演示或默认文案,正式发布前请逐页核对" + }, + { + "code": "form_not_configured", + "message": "尚未配置 HTTPS 询盘接收服务;目前仅提供邮件联系" + }, + { + "code": "legal_pages", + "message": "请根据目标国家/地区法律审查是否需要隐私政策与 Cookie 声明" + } + ], + "metrics": { + "html_pages": 38, + "artwork_fallbacks": 75, + "pages_with_body": 18 + }, + "note": "仅为本地结构化交付清单,不等于合法合规、内容准确、无障碍、性能或生产上线认证" +} \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/contact/index.html b/examples/v830-built-sites/automotive/contact/index.html new file mode 100644 index 0000000..55b25ee --- /dev/null +++ b/examples/v830-built-sites/automotive/contact/index.html @@ -0,0 +1,16 @@ +联系我们跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    CONNECT / CONTACT

    联系我们

    欢迎通过邮件与我们的演示团队取得联系。

    +
    LET'S START A CONVERSATION

    咨询与合作

    本页为演示内容。您可以在网站工厂中直接修改和替换。

    + + +
    HOW TO REACH US

    您可以通过本页提供的联系渠道咨询产品、项目或合作事项。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/faq/index.html b/examples/v830-built-sites/automotive/faq/index.html new file mode 100644 index 0000000..ad5cfe9 --- /dev/null +++ b/examples/v830-built-sites/automotive/faq/index.html @@ -0,0 +1,13 @@ +常见问题跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    EXPLORE

    常见问题

    更多问题可以联系我们。

    +
    ABOUT / DISCOVER

    常见问题

    本页为演示内容。您可以在网站工厂中直接修改和替换。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/index.html b/examples/v830-built-sites/automotive/index.html new file mode 100644 index 0000000..689bc8d --- /dev/null +++ b/examples/v830-built-sites/automotive/index.html @@ -0,0 +1,89 @@ +首页跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    01 / THE WORLD IN MOTION

    NOVA MOBILITY MOVE BEYOND.

    探索更广阔的出行可能

    THE NEXT CHAPTER
    DRIVE / 01
    DESIGN / TRUST / DELIVERYSCROLL TO DISCOVER ↓
    + +
    THE COMPANY

    把产品带向更广阔的市场。

    探索更广阔的出行可能

    认识我们 ↗
    +
    03 / BRANDS

    品牌与合作伙伴

    浏览全部 ↗
    + +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/news/1/index.html b/examples/v830-built-sites/automotive/news/1/index.html new file mode 100644 index 0000000..e4aa8f6 --- /dev/null +++ b/examples/v830-built-sites/automotive/news/1/index.html @@ -0,0 +1,13 @@ +企业动态 · 01跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    IDEAS / JOURNAL

    企业动态 · 01

    在这里发布新闻资讯与品牌动态。

    +

    这是可替换的新闻正文内容,可包含图片、表格和链接。

    ← 返回资讯
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/news/2/index.html b/examples/v830-built-sites/automotive/news/2/index.html new file mode 100644 index 0000000..15efb59 --- /dev/null +++ b/examples/v830-built-sites/automotive/news/2/index.html @@ -0,0 +1,13 @@ +企业动态 · 02跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    IDEAS / JOURNAL

    企业动态 · 02

    在这里发布新闻资讯与品牌动态。

    +

    这是可替换的新闻正文内容,可包含图片、表格和链接。

    ← 返回资讯
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/news/3/index.html b/examples/v830-built-sites/automotive/news/3/index.html new file mode 100644 index 0000000..996613e --- /dev/null +++ b/examples/v830-built-sites/automotive/news/3/index.html @@ -0,0 +1,13 @@ +企业动态 · 03跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    IDEAS / JOURNAL

    企业动态 · 03

    在这里发布新闻资讯与品牌动态。

    +

    这是可替换的新闻正文内容,可包含图片、表格和链接。

    ← 返回资讯
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/news/index.html b/examples/v830-built-sites/automotive/news/index.html new file mode 100644 index 0000000..00316cd --- /dev/null +++ b/examples/v830-built-sites/automotive/news/index.html @@ -0,0 +1,41 @@ +新闻资讯跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/nginx-snippet.conf b/examples/v830-built-sites/automotive/nginx-snippet.conf new file mode 100644 index 0000000..5156189 --- /dev/null +++ b/examples/v830-built-sites/automotive/nginx-snippet.conf @@ -0,0 +1,4 @@ +# SiteForge 生成:将本文件内容合并到 Nginx server {} 内 +index index.html; +error_page 404 /404.html; +location / { try_files $uri $uri/ =404; } diff --git a/examples/v830-built-sites/automotive/post/index.html b/examples/v830-built-sites/automotive/post/index.html new file mode 100644 index 0000000..377a737 --- /dev/null +++ b/examples/v830-built-sites/automotive/post/index.html @@ -0,0 +1,41 @@ +新闻展示跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/product/index.html b/examples/v830-built-sites/automotive/product/index.html new file mode 100644 index 0000000..82e53e3 --- /dev/null +++ b/examples/v830-built-sites/automotive/product/index.html @@ -0,0 +1,81 @@ +产品展示跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/products/1/index.html b/examples/v830-built-sites/automotive/products/1/index.html new file mode 100644 index 0000000..3b1b609 --- /dev/null +++ b/examples/v830-built-sites/automotive/products/1/index.html @@ -0,0 +1,17 @@ +Cars Alpha跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    +
    VEHICLE COLLECTION / DETAILS

    Cars Alpha

    Cars Alpha — 针对多样应用的演示产品。

    NOVA旗舰系列
    咨询相关信息 ↗
    +
    +
    CaPRODUCT
    +
    +
    OVERVIEW / 车型概览

    车型概览

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/products/2/index.html b/examples/v830-built-sites/automotive/products/2/index.html new file mode 100644 index 0000000..a4687b3 --- /dev/null +++ b/examples/v830-built-sites/automotive/products/2/index.html @@ -0,0 +1,17 @@ +Cars Beta跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    +
    VEHICLE COLLECTION / DETAILS

    Cars Beta

    Cars Beta — 针对多样应用的演示产品。

    NOVA旗舰系列
    咨询相关信息 ↗
    +
    +
    CaPRODUCT
    +
    +
    OVERVIEW / 车型概览

    车型概览

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/products/3/index.html b/examples/v830-built-sites/automotive/products/3/index.html new file mode 100644 index 0000000..c4408f5 --- /dev/null +++ b/examples/v830-built-sites/automotive/products/3/index.html @@ -0,0 +1,17 @@ +Cars Gamma跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    +
    VEHICLE COLLECTION / DETAILS

    Cars Gamma

    Cars Gamma — 针对多样应用的演示产品。

    ARC畅销系列
    咨询相关信息 ↗
    +
    +
    CaPRODUCT
    +
    +
    OVERVIEW / 车型概览

    车型概览

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/products/4/index.html b/examples/v830-built-sites/automotive/products/4/index.html new file mode 100644 index 0000000..6b4c94d --- /dev/null +++ b/examples/v830-built-sites/automotive/products/4/index.html @@ -0,0 +1,17 @@ +Cars Delta跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    +
    VEHICLE COLLECTION / DETAILS

    Cars Delta

    Cars Delta — 针对多样应用的演示产品。

    ARC畅销系列
    咨询相关信息 ↗
    +
    +
    CaPRODUCT
    +
    +
    OVERVIEW / 车型概览

    车型概览

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/products/5/index.html b/examples/v830-built-sites/automotive/products/5/index.html new file mode 100644 index 0000000..5dce780 --- /dev/null +++ b/examples/v830-built-sites/automotive/products/5/index.html @@ -0,0 +1,17 @@ +Cars Epsilon跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    +
    VEHICLE COLLECTION / DETAILS

    Cars Epsilon

    Cars Epsilon — 针对多样应用的演示产品。

    MONO定制系列
    咨询相关信息 ↗
    +
    +
    CaPRODUCT
    +
    +
    OVERVIEW / 车型概览

    车型概览

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/products/6/index.html b/examples/v830-built-sites/automotive/products/6/index.html new file mode 100644 index 0000000..b66d47b --- /dev/null +++ b/examples/v830-built-sites/automotive/products/6/index.html @@ -0,0 +1,17 @@ +Cars Zeta跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    +
    VEHICLE COLLECTION / DETAILS

    Cars Zeta

    Cars Zeta — 针对多样应用的演示产品。

    MONO定制系列
    咨询相关信息 ↗
    +
    +
    CaPRODUCT
    +
    +
    OVERVIEW / 车型概览

    车型概览

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/products/7/index.html b/examples/v830-built-sites/automotive/products/7/index.html new file mode 100644 index 0000000..58284f8 --- /dev/null +++ b/examples/v830-built-sites/automotive/products/7/index.html @@ -0,0 +1,17 @@ +Cars Eta跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    +
    VEHICLE COLLECTION / DETAILS

    Cars Eta

    Cars Eta — 针对多样应用的演示产品。

    NOVA专业系列
    咨询相关信息 ↗
    +
    +
    CaPRODUCT
    +
    +
    OVERVIEW / 车型概览

    车型概览

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/products/8/index.html b/examples/v830-built-sites/automotive/products/8/index.html new file mode 100644 index 0000000..2053746 --- /dev/null +++ b/examples/v830-built-sites/automotive/products/8/index.html @@ -0,0 +1,17 @@ +Cars Theta跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    +
    VEHICLE COLLECTION / DETAILS

    Cars Theta

    Cars Theta — 针对多样应用的演示产品。

    ARC专业系列
    咨询相关信息 ↗
    +
    +
    CaPRODUCT
    +
    +
    OVERVIEW / 车型概览

    车型概览

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/products/index.html b/examples/v830-built-sites/automotive/products/index.html new file mode 100644 index 0000000..28fd247 --- /dev/null +++ b/examples/v830-built-sites/automotive/products/index.html @@ -0,0 +1,81 @@ +产品中心跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/robots.txt b/examples/v830-built-sites/automotive/robots.txt new file mode 100644 index 0000000..0413435 --- /dev/null +++ b/examples/v830-built-sites/automotive/robots.txt @@ -0,0 +1,3 @@ +User-agent: * +Allow: / +Sitemap: https://automotive.example.test/sitemap.xml diff --git a/examples/v830-built-sites/automotive/search-index.json b/examples/v830-built-sites/automotive/search-index.json new file mode 100644 index 0000000..406f9fd --- /dev/null +++ b/examples/v830-built-sites/automotive/search-index.json @@ -0,0 +1 @@ +[{"title": "ARC", "url": "/brands/arc/", "summary": "ARC 品牌产品与应用。", "type": "brand", "brand": ""}, {"title": "MONO", "url": "/brands/mono/", "summary": "MONO 品牌产品与应用。", "type": "brand", "brand": ""}, {"title": "NOVA", "url": "/brands/nova/", "summary": "NOVA 品牌产品与应用。", "type": "brand", "brand": ""}, {"title": "精选项目 · 01", "url": "/cases/1/", "summary": "展示项目背景、过程与成果。", "type": "case", "brand": ""}, {"title": "精选项目 · 02", "url": "/cases/2/", "summary": "展示项目背景、过程与成果。", "type": "case", "brand": ""}, {"title": "精选项目 · 03", "url": "/cases/3/", "summary": "展示项目背景、过程与成果。", "type": "case", "brand": ""}, {"title": "产品中心", "url": "/products/", "summary": "查看系列、类别及产品资料。", "type": "page", "brand": ""}, {"title": "关于我们", "url": "/about/", "summary": "企业介绍、发展理念、合作能力与团队故事。", "type": "page", "brand": ""}, {"title": "品牌中心", "url": "/brands/", "summary": "探索与产品相关的品牌。", "type": "page", "brand": ""}, {"title": "常见问题", "url": "/faq/", "summary": "更多问题可以联系我们。", "type": "page", "brand": ""}, {"title": "新闻资讯", "url": "/news/", "summary": "了解最新消息与团队动态。", "type": "page", "brand": ""}, {"title": "服务与解决方案", "url": "/services/", "summary": "从咨询到交付的全链路服务。", "type": "page", "brand": ""}, {"title": "联系我们", "url": "/contact/", "summary": "欢迎通过邮件与我们的演示团队取得联系。", "type": "page", "brand": ""}, {"title": "项目案例", "url": "/cases/", "summary": "精选项目展示。", "type": "page", "brand": ""}, {"title": "企业动态 · 01", "url": "/news/1/", "summary": "在这里发布新闻资讯与品牌动态。", "type": "post", "brand": ""}, {"title": "企业动态 · 02", "url": "/news/2/", "summary": "在这里发布新闻资讯与品牌动态。", "type": "post", "brand": ""}, {"title": "企业动态 · 03", "url": "/news/3/", "summary": "在这里发布新闻资讯与品牌动态。", "type": "post", "brand": ""}, {"title": "Cars Alpha", "url": "/products/1/", "summary": "Cars Alpha — 针对多样应用的演示产品。", "type": "product", "brand": "NOVA"}, {"title": "Cars Beta", "url": "/products/2/", "summary": "Cars Beta — 针对多样应用的演示产品。", "type": "product", "brand": "NOVA"}, {"title": "Cars Delta", "url": "/products/4/", "summary": "Cars Delta — 针对多样应用的演示产品。", "type": "product", "brand": "ARC"}, {"title": "Cars Epsilon", "url": "/products/5/", "summary": "Cars Epsilon — 针对多样应用的演示产品。", "type": "product", "brand": "MONO"}, {"title": "Cars Eta", "url": "/products/7/", "summary": "Cars Eta — 针对多样应用的演示产品。", "type": "product", "brand": "NOVA"}, {"title": "Cars Gamma", "url": "/products/3/", "summary": "Cars Gamma — 针对多样应用的演示产品。", "type": "product", "brand": "ARC"}, {"title": "Cars Theta", "url": "/products/8/", "summary": "Cars Theta — 针对多样应用的演示产品。", "type": "product", "brand": "ARC"}, {"title": "Cars Zeta", "url": "/products/6/", "summary": "Cars Zeta — 针对多样应用的演示产品。", "type": "product", "brand": "MONO"}, {"title": "供应与交付方案", "url": "/services/solution/", "summary": "灵活、可配置的供应交付服务。", "type": "service", "brand": ""}] \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/search/index.html b/examples/v830-built-sites/automotive/search/index.html new file mode 100644 index 0000000..a7848c1 --- /dev/null +++ b/examples/v830-built-sites/automotive/search/index.html @@ -0,0 +1,13 @@ +站内搜索跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    SEARCH / CONTENT

    站内搜索

    搜索本网站的产品、品牌、新闻和案例。

    +
    + +
    + +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/service/index.html b/examples/v830-built-sites/automotive/service/index.html new file mode 100644 index 0000000..a3282e1 --- /dev/null +++ b/examples/v830-built-sites/automotive/service/index.html @@ -0,0 +1,25 @@ +服务展示跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    +
    VEHICLE COLLECTION / INDEX

    服务展示

    Explore our service

    BROWSE / EXPLORE01本页展示内容
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/services/index.html b/examples/v830-built-sites/automotive/services/index.html new file mode 100644 index 0000000..471e7e4 --- /dev/null +++ b/examples/v830-built-sites/automotive/services/index.html @@ -0,0 +1,13 @@ +服务与解决方案跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    EXPLORE

    服务与解决方案

    从咨询到交付的全链路服务。

    +
    ABOUT / DISCOVER

    服务与解决方案

    本页为演示内容。您可以在网站工厂中直接修改和替换。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/services/solution/index.html b/examples/v830-built-sites/automotive/services/solution/index.html new file mode 100644 index 0000000..7900e6c --- /dev/null +++ b/examples/v830-built-sites/automotive/services/solution/index.html @@ -0,0 +1,13 @@ +供应与交付方案跳转至正文 + +
    GLOBAL MOBILITY / CURATED SUPPLYDRIVEN BY WHAT'S NEXT ✦
    +
    +
    EXPLORE

    供应与交付方案

    灵活、可配置的供应交付服务。

    +
    ABOUT / DISCOVER

    供应与交付方案

    灵活、可配置的供应交付服务。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    探索更广阔的出行可能

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/siteforge-report.json b/examples/v830-built-sites/automotive/siteforge-report.json new file mode 100644 index 0000000..ac6d291 --- /dev/null +++ b/examples/v830-built-sites/automotive/siteforge-report.json @@ -0,0 +1,27 @@ +{ + "site": "NOVA MOBILITY", + "locale": "zh-CN", + "alternate_pages": 0, + "version": "cffe582043e7", + "pages": 36, + "theme": "automotive", + "theme_version": "1.3.0", + "warnings": [], + "errors": [], + "external_assets": [], + "missing_local_images": [], + "broken_links": [], + "legacy_links": [], + "canonical_mismatches": [], + "slashless_routes": [], + "redirects": 0, + "mirrored_images": 0, + "quality_status": "passed", + "blueprint_blocks": 0, + "commercial_readiness": { + "ready_for_review": true, + "commercially_certified": false, + "blockers": 0, + "warnings": 5 + } +} \ No newline at end of file diff --git a/examples/v830-built-sites/automotive/sitemap.xml b/examples/v830-built-sites/automotive/sitemap.xml new file mode 100644 index 0000000..922212b --- /dev/null +++ b/examples/v830-built-sites/automotive/sitemap.xml @@ -0,0 +1,37 @@ + +https://automotive.example.test/ +https://automotive.example.test/about/ +https://automotive.example.test/brand/ +https://automotive.example.test/brands/ +https://automotive.example.test/brands/arc/ +https://automotive.example.test/brands/mono/ +https://automotive.example.test/brands/nova/ +https://automotive.example.test/case/ +https://automotive.example.test/cases/ +https://automotive.example.test/cases/1/ +https://automotive.example.test/cases/2/ +https://automotive.example.test/cases/3/ +https://automotive.example.test/categories/term-79e34764f8ce/ +https://automotive.example.test/categories/term-8d6647722ef3/ +https://automotive.example.test/categories/term-95acf900fafc/ +https://automotive.example.test/categories/term-a68a8656a4dc/ +https://automotive.example.test/contact/ +https://automotive.example.test/faq/ +https://automotive.example.test/news/ +https://automotive.example.test/news/1/ +https://automotive.example.test/news/2/ +https://automotive.example.test/news/3/ +https://automotive.example.test/post/ +https://automotive.example.test/product/ +https://automotive.example.test/products/ +https://automotive.example.test/products/1/ +https://automotive.example.test/products/2/ +https://automotive.example.test/products/3/ +https://automotive.example.test/products/4/ +https://automotive.example.test/products/5/ +https://automotive.example.test/products/6/ +https://automotive.example.test/products/7/ +https://automotive.example.test/products/8/ +https://automotive.example.test/service/ +https://automotive.example.test/services/ +https://automotive.example.test/services/solution/ \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/.htaccess b/examples/v830-built-sites/corporate/.htaccess new file mode 100644 index 0000000..1d4fcb4 --- /dev/null +++ b/examples/v830-built-sites/corporate/.htaccess @@ -0,0 +1,2 @@ +Options -MultiViews +RewriteEngine On diff --git a/examples/v830-built-sites/corporate/404.html b/examples/v830-built-sites/corporate/404.html new file mode 100644 index 0000000..a60122b --- /dev/null +++ b/examples/v830-built-sites/corporate/404.html @@ -0,0 +1,12 @@ +404 · 页面不存在跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    ERROR / 404

    404

    抱歉,你访问的页面不存在,或者已被移动。

    返回首页 ↗
    + +
    + +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/about/index.html b/examples/v830-built-sites/corporate/about/index.html new file mode 100644 index 0000000..d346933 --- /dev/null +++ b/examples/v830-built-sites/corporate/about/index.html @@ -0,0 +1,47 @@ +关于我们跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/assets/blocks.css b/examples/v830-built-sites/corporate/assets/blocks.css new file mode 100644 index 0000000..9ce1279 --- /dev/null +++ b/examples/v830-built-sites/corporate/assets/blocks.css @@ -0,0 +1,29 @@ +/* Portable SiteForge blocks, loaded with every theme (all styles scoped to sf-). */ +.sf-section{background:var(--sf-bg,transparent);color:var(--sf-fg,inherit);padding:var(--sf-pad,82px) 0;margin:0}.sf-section:nth-of-type(even){background:var(--sf-bg,#f4f6f9)}.sf-container{max-width:1200px;margin:auto;padding:0 32px}.sf-section h1,.sf-section h2,.sf-section h3,.sf-section p{color:inherit;line-height:1.3}.sf-section h1{font-size:clamp(38px,5vw,76px);font-weight:790;letter-spacing:-.052em}.sf-section h2{font-size:clamp(27px,3.2vw,44px);font-weight:760;letter-spacing:-.037em}.sf-kicker{display:block;font-size:12px;letter-spacing:.17em;text-transform:uppercase;font-weight:740;color:var(--accent,#3569d3);margin-bottom:18px}.sf-hero-grid,.sf-image-text{display:grid;grid-template-columns:1.08fr .92fr;gap:68px;align-items:center}.sf-hero-copy p{font-size:18px;line-height:1.75;max-width:520px;opacity:.75}.sf-hero-img,.sf-image-side{overflow:hidden;border-radius:9px;min-height:380px;background:linear-gradient(130deg,#d5e1ee,#eef3f9);display:grid;place-items:center}.sf-hero-img img,.sf-image-side img{width:100%;height:100%;max-height:580px;object-fit:cover}.sf-hero-abstract{font-size:110px;color:#a7bdd4}.sf-button{display:inline-flex;align-items:center;justify-content:center;gap:28px;background:var(--accent,#315ee2);color:white!important;padding:16px 26px;border-radius:6px;font-size:14px;text-decoration:none;font-weight:720;margin-top:24px}.sf-section-head{display:flex;align-items:end;justify-content:space-between;margin-bottom:32px;gap:24px}.sf-section-head h2{margin:0}.sf-section-head>a,.sf-link{color:var(--accent,#3569d3);font-weight:700;text-decoration:none}.sf-prose{font-size:16px;line-height:1.85;max-width:930px}.sf-prose p{line-height:1.85}.sf-features,.sf-collection,.sf-stats{display:grid;gap:20px}.sf-features{grid-template-columns:repeat(3,minmax(0,1fr))}.sf-feature{border:1px solid #e0e6eb;padding:32px 28px;border-radius:8px;background:#fff;color:#253247}.sf-feature>span{font-size:12px;font-weight:800;color:var(--accent,#346add)}.sf-feature h3{font-size:22px;margin:30px 0 8px}.sf-feature p{font-size:14px;line-height:1.7;color:#647181}.sf-stats{grid-template-columns:repeat(4,1fr);padding:40px 0;border-top:1px solid #b7c0cd66;border-bottom:1px solid #b7c0cd66}.sf-stats>div{display:flex;flex-direction:column;gap:8px}.sf-stats strong{font-size:clamp(28px,4vw,53px);letter-spacing:-.04em}.sf-stats span{font-size:12px;opacity:.65;letter-spacing:.04em}.sf-collection{grid-template-columns:repeat(var(--sf-cols,3),minmax(0,1fr))}.sf-item{display:block;text-decoration:none;color:#233044;background:#fff;border:1px solid #e8edf1;border-radius:8px;overflow:hidden;transition:transform .2s,box-shadow .2s}.sf-item:hover{transform:translateY(-4px);box-shadow:0 18px 38px #344d7018}.sf-item-img{height:210px;overflow:hidden;background:#e4eaf0}.sf-item-img img{height:100%;width:100%;object-fit:cover}.sf-placeholder{display:grid;place-items:center;width:100%;height:100%;min-height:190px;background:linear-gradient(130deg,#e2eaf2,#c9d7e6);font-size:72px;color:#8399b2;font-weight:800}.sf-large{min-height:360px}.sf-item-copy{padding:25px}.sf-item-copy small{text-transform:uppercase;letter-spacing:.13em;color:var(--accent,#376edc)}.sf-item-copy h3{font-size:22px;margin:12px 0 7px}.sf-item-copy p{font-size:14px;line-height:1.6;color:#7a8796;min-height:42px}.sf-item-copy span{font-size:12px;color:var(--accent,#376edc);font-weight:800}.sf-image-text>div>p{font-size:17px;line-height:1.8;max-width:520px;opacity:.7}.sf-reverse>div:first-child{order:2}.sf-gallery{display:grid;grid-template-columns:repeat(3,1fr);gap:15px}.sf-gallery img{width:100%;height:230px;object-fit:cover;border-radius:6px}.sf-faq{max-width:920px}.sf-faq details{border-bottom:1px solid #dce3eb;padding:22px 0}.sf-faq summary{font-size:17px;cursor:pointer;font-weight:700}.sf-faq p{color:#647181;line-height:1.75}.sf-cta-wrap{display:flex;justify-content:space-between;align-items:center;gap:24px}.sf-cta-wrap h2{margin:0}.sf-cta-wrap p{font-size:16px;opacity:.75}.sf-section a{cursor:pointer}.sf-muted{opacity:.65} +@media(max-width:820px){.sf-container{padding:0 20px}.sf-section{padding:50px 0}.sf-hero-grid,.sf-image-text{grid-template-columns:1fr;gap:26px}.sf-reverse>div:first-child{order:initial}.sf-hero-img,.sf-image-side{min-height:250px}.sf-features,.sf-collection{grid-template-columns:repeat(2,minmax(0,1fr))}.sf-stats{grid-template-columns:repeat(2,1fr)}.sf-cta-wrap{align-items:flex-start;flex-direction:column}} +@media(max-width:540px){.sf-features,.sf-collection,.sf-gallery{grid-template-columns:1fr}.sf-section-head{display:block}.sf-section-head>a{display:block;margin-top:13px}.sf-item-img{height:220px}.sf-hero-grid{gap:22px}.sf-hero-copy p{font-size:16px}.sf-stats{gap:28px}} + +.sf-attributes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 32px;border-top:1px solid #e5eaf0}.sf-attribute{display:flex;justify-content:space-between;align-items:center;gap:18px;border-bottom:1px solid #e5eaf0;padding:19px 10px;font-size:14px}.sf-attribute span{color:#748497}.sf-attribute strong{font-weight:720;text-align:right}@media(max-width:640px){.sf-attributes{grid-template-columns:1fr}} + +/* SiteForge responsive no-code grid container */ +.sf-layout-grid{display:grid;grid-template-columns:var(--sf-layout-cols,1fr 1fr);gap:var(--sf-layout-gap,24px);align-items:stretch} +.sf-layout-column{min-width:0}.sf-layout-column>.sf-section{padding:0;margin:0 0 18px}.sf-layout-column .sf-container{width:100%;padding:0} +.sf-layout-column>.sf-section:last-child{margin-bottom:0} +@media(max-width:820px){.sf-layout-grid{grid-template-columns:repeat(2,minmax(0,1fr))!important}} +@media(max-width:540px){.sf-layout-grid{grid-template-columns:minmax(0,1fr)!important}} + +/* V8.6: accessible, script-free commercial design blocks */ +.sf-slides{display:flex;gap:18px;overflow-x:auto;scroll-snap-type:x mandatory;padding:6px 0 18px;scrollbar-width:thin} +.sf-slide{flex:0 0 min(78%,720px);min-width:220px;margin:0;scroll-snap-align:start} +.sf-slide img{width:100%;aspect-ratio:16/9;object-fit:cover;border-radius:10px} +.sf-slide figcaption{padding:10px 2px;opacity:.7;font-size:14px} +.sf-video{aspect-ratio:16/9;max-width:1000px;background:#ebf0f5;border-radius:10px;overflow:hidden} +.sf-video iframe{width:100%;height:100%;border:0} +.sf-tab{padding:19px 0;border-bottom:1px solid #dde4ec;max-width:960px} +.sf-tab summary{font-size:18px;font-weight:700;cursor:pointer}.sf-tab p{max-width:850px;line-height:1.8} +.sf-prices{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:18px} +.sf-price{padding:28px;background:#fff;border:1px solid #dee5ef;border-radius:10px;color:#29394b} +.sf-price strong{display:block;font-size:27px;margin:14px 0}.sf-price li{margin:11px 0}.sf-price ul{padding-left:19px} +.sf-map-address{font-style:normal;font-size:18px;white-space:pre-line;line-height:1.8} +@media (prefers-reduced-motion:reduce){.sf-slides{scroll-behavior:auto}.sf-item{transition:none}} +@media(max-width:540px){.sf-slide{flex-basis:92%}} diff --git a/examples/v830-built-sites/corporate/assets/commercial.css b/examples/v830-built-sites/corporate/assets/commercial.css new file mode 100644 index 0000000..353bee4 --- /dev/null +++ b/examples/v830-built-sites/corporate/assets/commercial.css @@ -0,0 +1,84 @@ +/* SiteForge commercial theme UX layer: accessibility, layout rhythm, media, responsive navigation. */ +:root{--sf-shadow:0 20px 55px rgba(17,33,55,.08);--sf-shadow-hover:0 26px 65px rgba(17,33,55,.15)} +html{scroll-padding-top:104px}body{font-feature-settings:"kern";text-rendering:optimizeLegibility} +a,button,input,select,textarea{-webkit-tap-highlight-color:transparent} +a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{outline:3px solid var(--pro-accent);outline-offset:4px} +.pro-wrap{width:100%;max-width:min(var(--pro-wide),100%)}.pro-header{isolation:isolate;box-shadow:0 1px 0 rgba(15,35,60,.035)}.pro-head-inner{gap:clamp(15px,2vw,29px)}.pro-logo{min-width:0;flex-shrink:0;gap:12px}.pro-brand-logo{max-width:155px;max-height:46px;width:auto;height:auto;object-fit:contain}.pro-logo-name{overflow-wrap:anywhere}.pro-navigation{gap:clamp(11px,1.6vw,24px)}.pro-header-cta{white-space:nowrap} +.pro-mobile-toggle,.pro-catalog-toggle,.pro-nav-disclose{border:0;background:transparent;color:inherit;line-height:1.2} +.pro-mobile-toggle{min-height:44px;min-width:44px;border:1px solid currentColor;border-radius:6px;font-size:19px}.pro-nav-group{position:relative;display:flex;align-items:center;gap:2px} +.pro-nav-disclose{padding:9px;font-size:13px}.pro-nav-children{position:absolute;top:100%;left:0;min-width:215px;max-width:330px;display:grid;gap:2px;padding:13px;box-shadow:var(--sf-shadow);border-radius:10px;z-index:45;background:var(--pro-background);border:1px solid var(--pro-border);color:var(--pro-text)} +.pro-nav-children[hidden],.pro-mega[hidden]{display:none!important}.pro-nav-children a{display:block;font-size:13px;white-space:normal;padding:10px;border-radius:5px}.pro-nav-children a:hover{background:var(--pro-surface)} +.pro-catalog-toggle{padding:11px 3px;white-space:nowrap;font-size:12px;font-weight:700}.pro-mega{position:absolute;top:100%;left:50%;transform:translateX(-50%);width:min(100%,var(--pro-wide));box-shadow:var(--sf-shadow);z-index:41;display:grid;grid-template-columns:215px 1fr;background:var(--pro-background);color:var(--pro-text);border:1px solid var(--pro-border);border-radius:0 0 15px 15px;padding:29px;align-items:start}.pro-mega>span{font-size:12px;letter-spacing:.06em}.pro-mega>div{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:9px 22px;overflow:visible}.pro-mega>div a{white-space:normal;padding:10px 5px;border-bottom:1px solid var(--pro-border)} +.pro-home-hero{overflow:hidden}.pro-home-hero .pro-home-grid{min-height:660px;gap:5%}.pro-home-hero .pro-hero-copy{position:relative;z-index:2}.pro-home-hero .pro-hero-copy h1{font-size:clamp(46px,5.7vw,92px);line-height:1.06;letter-spacing:-.064em;max-width:15ch}.pro-home-hero .pro-hero-copy h1 em{font-style:normal;display:block}.pro-home-hero .pro-hero-copy p{font-size:clamp(15px,1.3vw,19px);line-height:1.75;max-width:44ch}.pro-home-hero .pro-hero-art{min-width:0;min-height:425px;position:relative;isolation:isolate}.pro-home-hero .pro-hero-art>img{width:100%;height:100%;object-fit:cover;position:absolute;inset:0}.pro-hero-art:has(.pro-abstract-car),.pro-hero-art:has(.pro-technical),.pro-hero-art:has(.pro-corporate-shape){background-position:center;background-size:cover;background-repeat:no-repeat}.pro-abstract-car,.pro-technical,.pro-corporate-shape{position:relative;z-index:1;pointer-events:none} +.pro-hero-actions{display:flex;flex-wrap:wrap;align-items:center;gap:15px}.pro-button,.pro-header-cta,.pro-outline-button{min-height:48px;transition:transform .24s ease,box-shadow .24s ease,opacity .24s ease}.pro-button:hover,.pro-header-cta:hover,.pro-outline-button:hover{transform:translateY(-2px);box-shadow:0 10px 22px rgba(0,0,0,.10)} +.pro-section{padding-top:clamp(76px,7vw,112px)!important;padding-bottom:clamp(76px,7vw,112px)!important}.pro-section-head{gap:16px}.pro-section-head h2{font-size:clamp(32px,3.5vw,53px);max-width:22ch}.pro-section-head .pro-text-link{align-self:end} +.pro-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px}.pro-card{min-width:0;display:flex;flex-direction:column;transition:transform .28s ease,box-shadow .28s ease;border:1px solid var(--pro-border);background:var(--pro-background);overflow:hidden}.pro-card:hover{transform:translateY(-6px);box-shadow:var(--sf-shadow-hover)}.pro-card-cover{aspect-ratio:1.42;overflow:hidden;background:var(--pro-surface);position:relative}.pro-card-cover .pro-photo{width:100%;height:100%;object-fit:cover;transition:transform .45s ease}.pro-card:hover .pro-photo{transform:scale(1.045)}.pro-card-body{display:flex;flex-direction:column;flex:1}.pro-card-body h3{font-size:clamp(19px,1.6vw,24px);line-height:1.26}.pro-card-body p{font-size:14px}.pro-card-link{margin-top:auto;padding-top:14px;font-size:13px;font-weight:700} +.pro-art{min-height:100%;width:100%;position:relative;overflow:hidden;display:grid;place-items:center;isolation:isolate}.pro-art-ring{width:60%;aspect-ratio:1;border:1px solid currentColor;opacity:.13;border-radius:50%;transform:rotate(20deg);box-shadow:0 0 0 23px #ffffff10,0 0 0 57px #ffffff07}.pro-art-center{font-size:clamp(38px,5vw,80px);position:absolute;font-weight:800;letter-spacing:-.065em;opacity:.65}.pro-art-label{position:absolute;bottom:19px;left:22px;font-size:10px;letter-spacing:.22em;opacity:.7} +.pro-breadcrumb{display:flex;gap:11px;flex-wrap:wrap;font-size:12px;align-items:center}.pro-breadcrumb a{text-decoration:underline;text-underline-offset:4px}.pro-product-hero{align-items:start;gap:clamp(28px,5vw,80px)}.pro-product-media{aspect-ratio:1.12;background:var(--pro-surface);overflow:hidden}.pro-product-media>img,.pro-product-media>.pro-art{width:100%;height:100%;object-fit:contain}.pro-product-summary{padding:clamp(12px,3vw,50px) 0}.pro-product-summary h1{font-size:clamp(36px,4.3vw,72px)}.pro-detail-layout{border-top:1px solid var(--pro-border);padding-top:50px}.pro-specs>div{display:grid;grid-template-columns:minmax(100px,40%) 1fr;gap:10px;align-items:baseline;padding:15px 0;border-bottom:1px solid var(--pro-border)}.pro-specs strong{overflow-wrap:anywhere}.pro-gallery-thumbs button{flex-basis:96px;height:76px}.pro-gallery-lightbox{backdrop-filter:blur(6px)} +.pro-filter-panel{display:flex;align-items:end;flex-wrap:wrap;gap:16px;background:var(--pro-surface);border:1px solid var(--pro-border);padding:20px;margin-bottom:25px;border-radius:var(--pro-radius)}.pro-filter-panel label{display:grid;gap:7px;min-width:180px;flex:1}.pro-filter-panel input,.pro-filter-panel select{width:100%;background:var(--pro-background);border:1px solid var(--pro-border);padding:12px 14px;color:var(--pro-text);border-radius:6px}.pro-filter-count{white-space:nowrap;font-size:13px;padding:12px 0}.pro-card[hidden]{display:none!important}.pro-filter-empty{padding:38px;border:1px dashed var(--pro-border);text-align:center;grid-column:1/-1} +.pro-inquiry input,.pro-inquiry textarea{min-height:46px}.pro-inquiry textarea{min-height:150px}.pro-inquiry-wrap{gap:clamp(32px,7vw,110px)}.pro-inquiry .pro-button{border:0;justify-self:start}.pro-footer-links a{padding-block:5px;display:inline-block} +.pro-end-cta{overflow:hidden}.pro-end-cta h2{font-size:clamp(30px,4vw,64px)} +.pro-rich{line-height:1.85}.pro-rich img{border-radius:var(--pro-radius);margin-block:24px}.pro-rich table{width:100%;display:block;overflow:auto;border-collapse:collapse}.pro-rich td,.pro-rich th{border:1px solid var(--pro-border);padding:10px 14px}.pro-rich a{text-decoration:underline;text-underline-offset:3px} +@media(min-width:1025px){.pro-navigation>.pro-nav-group:hover .pro-nav-children:not([hidden]){visibility:visible}} +@media(max-width:1150px){.pro-head-inner{gap:15px}.pro-navigation{gap:12px}.pro-logo-name{font-size:15px}.pro-header-cta{padding:13px 16px}} +@media(max-width:1024px){.pro-head-inner{min-height:72px;flex-wrap:wrap}.pro-mobile-toggle{display:inline-flex;align-items:center;justify-content:center;margin-left:auto}.pro-navigation{display:none;width:100%;flex-basis:100%;flex-direction:column;align-items:stretch;gap:0;order:5;margin:0;padding:8px 0 20px;border-top:1px solid var(--pro-border)}.pro-navigation.is-open{display:flex}.pro-navigation>a,.pro-nav-group>a{padding:14px 8px;font-size:15px}.pro-nav-group{display:flex;flex-wrap:wrap;justify-content:space-between}.pro-nav-children{position:static;flex-basis:100%;max-width:none;width:100%;box-shadow:none;border-radius:0;border-left:2px solid var(--pro-accent);margin:0 0 12px 8px}.pro-nav-disclose{min-width:44px;min-height:44px}.pro-catalog-toggle{margin-left:auto}.pro-mega{top:100%;display:block;padding:20px}.pro-mega>div{grid-template-columns:repeat(2,minmax(0,1fr));margin-top:12px}.pro-home-hero .pro-home-grid{min-height:560px}.pro-home-hero .pro-hero-art{min-height:325px}.pro-grid{grid-template-columns:repeat(2,minmax(0,1fr))}} +@media(max-width:700px){.pro-wrap{padding-left:20px;padding-right:20px}.pro-utility{display:none}.pro-head-inner{min-height:66px}.pro-logo-name{max-width:140px;font-size:14px}.pro-brand-logo{max-width:125px}.pro-header-cta{display:none}.pro-catalog-toggle{font-size:11px;padding-inline:7px;margin-left:0}.pro-home-hero .pro-home-grid{display:flex;flex-direction:column;gap:36px;padding-top:48px;padding-bottom:48px}.pro-home-hero .pro-hero-copy h1{font-size:clamp(43px,10vw,68px)}.pro-home-hero .pro-hero-copy p{font-size:15px}.pro-home-hero .pro-hero-art{width:100%;min-height:290px}.pro-home-hero .pro-hero-bottom{display:none}.pro-section{padding-top:68px!important;padding-bottom:68px!important}.pro-section-head{align-items:flex-start}.pro-grid{grid-template-columns:1fr;gap:18px}.pro-card-cover{aspect-ratio:1.45}.pro-product-hero,.pro-detail-layout,.pro-info-grid,.pro-inquiry-wrap{display:grid;grid-template-columns:1fr;gap:30px}.pro-product-summary{padding:0}.pro-specs>div{grid-template-columns:1fr 1fr}.pro-mega{top:100%;max-height:65vh;overflow-y:auto}.pro-mega>div{grid-template-columns:1fr}.pro-filter-panel{display:grid;grid-template-columns:1fr;gap:12px}.pro-filter-panel label{min-width:0}.pro-footer-top{display:grid;grid-template-columns:1fr;gap:27px}.pro-footer-bottom{gap:12px;flex-wrap:wrap}} +@media(max-width:410px){.pro-logo-name{max-width:115px}.pro-logo-symbol{font-size:28px}.pro-catalog-toggle{font-size:10px}.pro-mobile-toggle{min-width:42px}} +@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,*:before,*:after{animation-duration:.01ms!important;transition-duration:.01ms!important;scroll-behavior:auto!important}} + +/* Accessible static catalogue pagination for large inventories. */ +.pro-pages-nav{display:flex;gap:1rem;justify-content:center;align-items:center;margin:2rem 0;flex-wrap:wrap} +.pro-pages-nav a{padding:.7rem 1.1rem;border:1px solid currentColor;border-radius:.4rem;text-decoration:none} +.pro-pages-nav a:focus-visible{outline:3px solid var(--accent,#2563eb);outline-offset:3px} +.pro-pages-nav span{font-size:.875rem} + +/* P6 international sites: small, keyboard-operable language switch. */ +.sf-language-switch{display:inline-flex;gap:6px;align-items:center;flex-wrap:wrap;margin:8px 12px;padding:4px;border:1px solid rgba(120,130,145,.22);border-radius:10px;background:rgba(255,255,255,.08)} +.sf-language-switch a{font:inherit;font-size:12px;line-height:1.5;padding:4px 7px;border-radius:6px;color:inherit;text-decoration:none} +.sf-language-switch a[aria-current="page"]{font-weight:700;text-decoration:underline;text-underline-offset:3px} +.sf-language-switch a:focus-visible{outline:2px solid #2563eb;outline-offset:3px} +@media(max-width:640px){.sf-language-switch{margin:6px 0;width:auto}} + +/* V8.21.3 — Four-theme unified mobile off-canvas navigation & optional tab bar. + Desktop remains unchanged. Phone / tablet use one accessible drawer. */ +.sf-mobile-tabs{display:none!important} +.sf-drawer-header,.sf-mobile-drawer-backdrop,.sf-drawer-extra{display:none} +@media(max-width:1024px){ + .pro-head-inner{flex-wrap:nowrap!important;gap:12px!important} + .pro-mobile-toggle{display:inline-flex;align-items:center;justify-content:center;margin-left:auto!important;flex:0 0 44px;min-width:44px;min-height:44px;position:relative;z-index:3} + .pro-catalog-toggle{display:none!important} + .pro-navigation,.pro-navigation.is-open{display:flex!important;position:fixed!important;inset:0 0 0 auto!important;width:min(88vw,360px)!important;height:100dvh!important;height:100vh;max-height:100dvh!important;flex:unset!important;flex-direction:column!important;align-items:stretch!important;order:unset!important;margin:0!important;padding:0 0 calc(20px + env(safe-area-inset-bottom,0px))!important;overflow-x:hidden;overflow-y:auto!important;background:var(--pro-background,#fff)!important;color:var(--pro-text,#19283c)!important;border:0!important;border-left:1px solid var(--pro-border,#ddd)!important;box-shadow:-15px 0 45px #0002!important;z-index:1201!important;transform:translateX(105%);visibility:hidden;pointer-events:none;transition:transform .24s ease,visibility .24s ease!important;overscroll-behavior:contain} + .pro-navigation.is-open{transform:translateX(0);visibility:visible;pointer-events:auto} + .sf-drawer-header{display:flex!important;align-items:center;justify-content:space-between;gap:12px;padding:20px 18px;border-bottom:1px solid var(--pro-border,#dde3e9);font-size:17px;font-weight:750;position:sticky;top:0;background:var(--pro-background,#fff);z-index:2} + .sf-drawer-close{min-width:44px;min-height:44px;border:1px solid var(--pro-border,#dde3e9);color:inherit;background:transparent;border-radius:10px;font-size:24px;cursor:pointer} + .sf-mobile-drawer-backdrop{display:block;position:fixed;inset:0;z-index:1200;background:#0b1b31a3;opacity:0;visibility:hidden;pointer-events:none;transition:opacity .24s ease,visibility .24s ease} + .sf-mobile-drawer-backdrop.is-open{opacity:1;visibility:visible;pointer-events:auto} + body.sf-drawer-open{overflow:hidden!important} + .pro-navigation>a,.pro-navigation .pro-nav-group>a,.pro-navigation .sf-drawer-extra>a{display:flex;align-items:center;min-height:50px;padding:13px 20px!important;font-size:15px!important;color:inherit!important;white-space:normal;border-bottom:1px solid var(--pro-border,#dde3e9)!important;text-decoration:none!important} + .pro-navigation .pro-nav-group{display:flex;position:relative;flex-wrap:wrap!important;width:100%;gap:0;align-items:center;justify-content:space-between} + .pro-navigation .pro-nav-group>a{flex:1;min-width:0} + .pro-navigation .pro-nav-disclose{margin-right:12px;min-width:44px;min-height:44px;border-radius:9px;background:var(--pro-surface,#f4f6f8)} + .pro-navigation .pro-nav-children{position:static!important;width:100%!important;max-width:100%!important;box-shadow:none!important;border-left:3px solid var(--pro-accent,#e77730);border-radius:0!important;margin:0 0 8px 14px!important;flex-basis:calc(100% - 14px)!important;background:var(--pro-surface,#f6f8fa)} + .pro-navigation .pro-nav-children a{padding:12px 16px!important;font-size:14px!important;color:inherit!important;min-height:44px} + .sf-drawer-extra{display:block;padding:12px 0 5px}.sf-drawer-extra strong{display:block;font-size:12px;letter-spacing:.06em;padding:12px 20px;opacity:.65}.sf-drawer-extra a{font-size:14px!important} + .sf-drawer-close:focus-visible,.pro-mobile-toggle:focus-visible,.pro-nav-disclose:focus-visible,.sf-mobile-tab:focus-visible{outline:3px solid var(--pro-accent,#ff8200);outline-offset:2px} +} +@media(max-width:767px){ + .pro-header-cta{display:none!important} + .pro-head-inner .pro-logo{min-width:0;max-width:calc(100% - 65px)} + .pro-logo-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap} + .pro-home-hero .pro-home-grid{min-height:0!important} + .pro-home-hero .pro-hero-art{min-height:230px} + .pro-card,.pro-card-cover,.pro-product-media{max-width:100%;min-width:0} + .pro-rich img,.pro-content img,.sf-canvas img{max-width:100%;height:auto} + .pro-rich table{max-width:100%;overflow:auto} + .pro-grid,.pro-footer-top{min-width:0} + .sf-mobile-tabs{display:grid!important;position:fixed;z-index:1100;bottom:0;left:0;right:0;grid-template-columns:repeat(var(--sf-mobile-tab-count,4),minmax(0,1fr));align-items:stretch;padding:5px 6px calc(5px + env(safe-area-inset-bottom,0px));min-height:63px;background:var(--pro-background,#fff);color:var(--pro-text,#263446);border-top:1px solid var(--pro-border,#dfe4eb);box-shadow:0 -6px 24px #13223914} + .sf-mobile-tab{appearance:none;border:0!important;background:transparent!important;color:inherit!important;text-decoration:none!important;padding:6px 2px;min-height:50px;min-width:0;display:flex;flex-direction:column;justify-content:center;align-items:center;gap:2px;border-radius:9px;cursor:pointer;font-family:inherit} + .sf-tab-icon{font-size:23px;line-height:1.15;font-weight:500} + .sf-tab-label{font-size:11px;font-weight:600;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} + .sf-mobile-tab[aria-current=page]{color:var(--pro-accent,#e47730)!important;background:var(--pro-surface,#f5f6f8)!important} + body:has(> .sf-mobile-tabs){padding-bottom:calc(76px + env(safe-area-inset-bottom,0px))!important} +} +@media(min-width:768px){.sf-mobile-tabs{display:none!important}} +@media(prefers-reduced-motion:reduce){.pro-navigation,.sf-mobile-drawer-backdrop{transition:none!important}} diff --git a/examples/v830-built-sites/corporate/assets/custom.css b/examples/v830-built-sites/corporate/assets/custom.css new file mode 100644 index 0000000..f197c0a --- /dev/null +++ b/examples/v830-built-sites/corporate/assets/custom.css @@ -0,0 +1 @@ +:root{--accent:#315f92;--sf-font:system-ui,-apple-system,sans-serif;--sf-radius:12px;--sf-space:72px;--sf-width:1200px;--sf-heading-scale:1.0;}body{font-family:var(--sf-font)} .sf-canvas .sf-section,.sf-canvas .section{padding-block:var(--sf-space)}.container,.sf-container{max-width:var(--sf-width)}.btn,.primary,.request,.button,.nav-btn{background-color:#315f92;border-radius:12px}body .sf-canvas h1{font-size:clamp(2.5rem,5vw,calc(4.8rem * var(--sf-heading-scale)))}body .pro-utility[hidden]{display:none!important}@media(max-width:1023px){.sf-canvas .sf-section{padding-block:64px}}@media(max-width:767px){.sf-canvas .sf-section{padding-block:40px}.pro-wrap,.sf-container{padding-left:20px;padding-right:20px}body .pro-utility{display:none!important}} \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/assets/factory.css b/examples/v830-built-sites/corporate/assets/factory.css new file mode 100644 index 0000000..154ffb3 --- /dev/null +++ b/examples/v830-built-sites/corporate/assets/factory.css @@ -0,0 +1,27 @@ +/* SiteForge trusted global shell. Site themes remain visually independent. */ +:root{--sf-shell:#12243d;--sf-shell-accent:#dcae71;--sf-shell-soft:#edf2f8;--sf-shell-fg:#173049} +html{scroll-behavior:smooth}body{overflow-x:hidden}body>.header,body>.utility,body>.top,body>header,body>footer{display:none!important} +.sf-theme-industrial{--sf-shell:#114e79;--sf-shell-accent:#92d5ed;--sf-shell-soft:#ebf6fa;--sf-shell-fg:#0c4267} +.sf-theme-corporate{--sf-shell:#232d62;--sf-shell-accent:#b8bdff;--sf-shell-soft:#f3f3fa;--sf-shell-fg:#333468} +.sf-theme-minimal{--sf-shell:#1e1e1c;--sf-shell-accent:#ded6c5;--sf-shell-soft:#f6f4ef;--sf-shell-fg:#252520} +.sf-site-head{position:relative;z-index:25;background:var(--sf-shell);color:#fff;font-family:system-ui,-apple-system,sans-serif} +.sf-head-inner{max-width:1240px;margin:0 auto;min-height:78px;padding:0 28px;display:flex;align-items:center;gap:28px} +.sf-logo{display:flex;align-items:center;gap:11px;font-size:18px;text-decoration:none!important;color:#fff!important;white-space:nowrap} +.sf-logo-mark{width:36px;height:36px;display:grid;place-items:center;background:var(--sf-shell-accent);color:var(--sf-shell);font-size:22px;font-weight:900;border-radius:9px} +.sf-primary-links{display:flex;gap:23px;margin-left:auto;align-items:center} +.sf-primary-links a,.sf-mega a{color:#fff!important;text-decoration:none!important;font-size:13px;font-weight:650;white-space:nowrap} +.sf-primary-links a:hover{color:var(--sf-shell-accent)!important} +.sf-head-cta{font-size:13px;font-weight:750;text-decoration:none;background:var(--sf-shell-accent);color:var(--sf-shell)!important;padding:13px 18px;border-radius:4px;white-space:nowrap} +.sf-menu-toggle{display:none;margin-left:auto;color:white;border:1px solid #ffffff55;background:none;border-radius:4px;padding:8px 12px;font-size:19px;cursor:pointer} +.sf-mega{display:flex;gap:18px;max-width:1240px;margin:auto;padding:0 28px 9px;overflow-x:auto} +.sf-mega a{display:block;min-width:120px;border-top:1px solid #ffffff2e;padding:12px 8px}.sf-mega small{display:block;color:#ffffff99;max-width:160px;overflow:hidden;text-overflow:ellipsis;font-size:10px;margin-top:6px} +.sf-site-foot{background:var(--sf-shell);color:white!important;font:14px/1.7 system-ui,-apple-system,sans-serif;padding:72px 28px 26px} +.sf-foot-grid{max-width:1200px;margin:auto;display:grid;grid-template-columns:2fr 1fr 1fr;gap:70px}.sf-foot-grid h2{font-size:25px;color:white;margin:0 0 17px}.sf-foot-grid h4{font-size:13px;color:var(--sf-shell-accent);letter-spacing:.07em;margin:0 0 17px}.sf-foot-grid p{color:#ffffffae;max-width:380px}.sf-foot-grid a{display:block;width:fit-content;color:#fff!important;text-decoration:none;margin-bottom:8px}.sf-foot-lower{border-top:1px solid #ffffff33;max-width:1200px;margin:45px auto 0;padding-top:20px;display:flex;justify-content:space-between;color:#ffffff9e;font-size:12px} +.sf-filters{display:flex;align-items:center;flex-wrap:wrap;gap:12px;margin:0 0 30px}.sf-filters input,.sf-filters select{padding:11px 13px;border-radius:6px;border:1px solid #cfd9e4;background:#fff;color:#263a51;max-width:280px}.sf-filter-empty{padding:22px;color:#778598} +.sf-search-page{min-height:76vh;max-width:1060px;padding:90px 24px;margin:auto;font-family:system-ui,sans-serif;color:var(--sf-shell-fg)}.sf-search-page h1{font-size:clamp(35px,5vw,62px);margin:20px 0}.sf-search-page>label{display:block;margin:18px 0 8px}.sf-search-page input{display:block;width:100%;padding:17px;font-size:18px;border:1px solid #b7c6d7;border-radius:8px}.sf-search-page #sf-search-count{margin:22px 0;color:#607589}.sf-search-result{padding:22px 0;border-bottom:1px solid #dae1ea}.sf-search-result a{color:var(--sf-shell-fg);font-size:21px;font-weight:750;text-decoration:none}.sf-search-result small{display:block;color:#7992a7}.sf-search-result p{margin:7px 0;color:#657487} +@media(max-width:1050px){.sf-head-inner{gap:13px}.sf-primary-links{gap:12px}.sf-primary-links a{font-size:12px}.sf-head-cta{padding:10px}} +@media(max-width:850px){.sf-head-inner{min-height:68px}.sf-menu-toggle{display:block}.sf-head-cta{display:none}.sf-primary-links{display:none;position:absolute;top:68px;left:0;right:0;margin:0;background:var(--sf-shell);padding:20px 28px;flex-direction:column;align-items:stretch;box-shadow:0 20px 24px #0002}.sf-primary-links.is-open{display:flex}.sf-mega{display:none}.sf-foot-grid{grid-template-columns:1fr 1fr;gap:35px}} +@media(max-width:560px){.sf-foot-grid{grid-template-columns:1fr}.sf-foot-lower{display:block}.sf-site-foot{padding-top:48px}.sf-head-inner{padding:0 16px}} + +.sf-page-intro{padding:80px 28px;background:var(--sf-shell-soft);color:var(--sf-shell-fg);font-family:system-ui,sans-serif}.sf-page-intro>div{max-width:1200px;margin:auto}.sf-page-intro p{font-size:11px;font-weight:850;letter-spacing:.19em;text-transform:uppercase;color:var(--sf-shell-fg);opacity:.58}.sf-page-intro h1{font-size:clamp(38px,5vw,67px);letter-spacing:-.04em;line-height:1.08;margin:13px 0}.sf-page-intro span{font-size:16px;opacity:.72} +.sf-item[hidden]{display:none!important} diff --git a/examples/v830-built-sites/corporate/assets/pro-base.css b/examples/v830-built-sites/corporate/assets/pro-base.css new file mode 100644 index 0000000..c2c4f61 --- /dev/null +++ b/examples/v830-built-sites/corporate/assets/pro-base.css @@ -0,0 +1,21 @@ +/* SiteForge V3 professional theme primitives. Each commercial theme adds its own art direction. */ +:root{--pro-text:#19283a;--pro-muted:#687587;--pro-border:#dfe5ea;--pro-background:#fff;--pro-surface:#f5f7fa;--pro-accent:#365cb7;--pro-hero:#15263d;--pro-hero-fg:#fff;--pro-radius:12px;--pro-headings:system-ui,-apple-system,sans-serif;--pro-font:system-ui,-apple-system,sans-serif;--pro-wide:1270px} +*,*:before,*:after{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:var(--pro-background);color:var(--pro-text);font-family:var(--pro-font);-webkit-font-smoothing:antialiased;overflow-x:hidden}button,input,select{font:inherit}button,a{touch-action:manipulation}button{cursor:pointer}a{text-decoration:none;color:inherit}a:hover{color:var(--pro-accent)}img{max-width:100%;display:block}h1,h2,h3,h4,p{margin-top:0}h1,h2,h3{font-family:var(--pro-headings);line-height:1.09}h1{letter-spacing:-.052em}h2{letter-spacing:-.042em}h3{letter-spacing:-.028em}p{line-height:1.72}.pro-wrap{max-width:var(--pro-wide);margin:0 auto;padding-left:32px;padding-right:32px}.pro-skip{position:absolute;left:-9999px;z-index:90;background:#fff;color:#000;padding:12px}.pro-skip:focus{left:10px;top:10px}.pro-eyebrow{font-weight:750;font-size:11px;letter-spacing:.17em;text-transform:uppercase;display:block;line-height:1.6;color:var(--pro-accent)}.pro-muted{opacity:.7}.pro-utility{min-height:30px;background:var(--pro-hero);color:#c5d2db;font-size:10px;letter-spacing:.16em}.pro-utility .pro-wrap{display:flex;justify-content:space-between;padding-block:8px}.pro-utility i{font-style:normal;color:var(--pro-accent)}.pro-header{background:var(--pro-background);color:var(--pro-text);border-bottom:1px solid var(--pro-border);position:relative;z-index:35}.pro-head-inner{min-height:84px;display:flex;align-items:center;gap:28px}.pro-logo{display:flex;align-items:center;gap:12px;min-width:170px}.pro-logo-symbol{font-size:32px;line-height:1;font-weight:800;letter-spacing:-.07em;color:var(--pro-accent)}.pro-logo-name{max-width:220px;font-weight:820;font-size:17px;line-height:1.1;letter-spacing:-.035em}.pro-logo-name small{display:block;font-weight:650;font-size:9px;letter-spacing:.19em;margin-top:7px;color:var(--pro-muted)}.pro-navigation{display:flex;align-items:center;gap:24px;margin-left:auto}.pro-navigation a{font-size:13px;font-weight:650;white-space:nowrap;transition:opacity .2s}.pro-navigation a:hover{opacity:.6}.pro-header-cta,.pro-button{display:inline-flex;align-items:center;justify-content:center;gap:22px;background:var(--pro-accent);color:#fff!important;border-radius:var(--pro-radius);font-size:13px;letter-spacing:.01em;font-weight:750;padding:16px 24px;white-space:nowrap;transition:transform .2s,background .2s}.pro-header-cta:hover,.pro-button:hover{transform:translateY(-2px)}.pro-mobile-toggle{display:none}.pro-mega{display:flex;align-items:center;gap:22px;min-height:37px;border-top:1px solid var(--pro-border);padding-block:10px;font-size:11px}.pro-mega>span{font-weight:750;color:var(--pro-muted);white-space:nowrap}.pro-mega>div{display:flex;gap:16px;overflow:auto;scrollbar-width:none}.pro-mega a{white-space:nowrap;font-weight:650}.pro-search-link{font-size:19px!important}.pro-home-hero{position:relative;overflow:hidden}.pro-home-grid{display:grid;grid-template-columns:1.02fr .98fr;align-items:center;gap:5%;min-height:580px;padding-top:85px;padding-bottom:85px}.pro-hero-copy{position:relative;z-index:2}.pro-hero-copy h1{font-size:clamp(48px,6.2vw,91px);line-height:1.03;margin:20px 0 25px;max-width:730px}.pro-hero-copy h1 em{font-style:normal;display:block;color:var(--pro-accent)}.pro-hero-copy p{font-size:17px;max-width:495px;color:var(--pro-muted)}.pro-hero-actions{display:flex;align-items:center;flex-wrap:wrap;gap:25px;margin-top:34px}.pro-outline-button{font-weight:700;border-bottom:1px solid currentColor;padding:12px 0}.pro-hero-art{width:100%;height:435px;position:relative;overflow:hidden;border-radius:var(--pro-radius)}.pro-hero-art>img{width:100%;height:100%;object-fit:cover}.pro-hero-bottom{display:flex;justify-content:space-between;font-size:10px;letter-spacing:.18em;padding-block:22px;border-top:1px solid #ffffff32}.pro-section{padding:106px 0}.pro-section-head{display:flex;align-items:end;justify-content:space-between;gap:25px;margin-bottom:34px}.pro-section-head h2{font-size:clamp(36px,4vw,57px);margin:12px 0 0}.pro-text-link{font-size:13px;font-weight:750;display:inline-flex;gap:18px;align-items:center;border-bottom:1px solid;padding-bottom:7px;color:var(--pro-accent)}.pro-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:22px}.pro-card{display:block;min-width:0;background:var(--pro-background);color:var(--pro-text);border:1px solid var(--pro-border);overflow:hidden;border-radius:var(--pro-radius);transition:transform .25s,box-shadow .25s}.pro-card:hover{transform:translateY(-6px);box-shadow:0 24px 45px #0f25431b}.pro-card-cover{width:100%;height:244px;overflow:hidden;background:var(--pro-surface)}.pro-photo{width:100%;height:100%;object-fit:cover;transition:transform .5s}.pro-card:hover .pro-photo{transform:scale(1.045)}.pro-art{width:100%;height:100%;overflow:hidden;display:grid;place-items:center;position:relative;background:linear-gradient(130deg,#d8e1ed,#f3f6f9)}.pro-art-ring{width:55%;aspect-ratio:1;border:28px solid #ffffff5f;border-radius:50%;box-shadow:0 0 0 42px #ffffff30;transform:rotate(-25deg)}.pro-art-center{position:absolute;font-family:var(--pro-headings);font-weight:800;font-size:76px;letter-spacing:-.08em;color:#45647d90}.pro-art-label{position:absolute;bottom:16px;left:18px;letter-spacing:.16em;font-size:9px;color:#435773}.pro-card-body{padding:25px 25px 28px}.pro-card-meta{display:flex;justify-content:space-between;gap:20px;font-size:10px;font-weight:750;letter-spacing:.1em;text-transform:uppercase;color:var(--pro-accent)}.pro-card h3{font-size:23px;margin:14px 0 9px}.pro-card p{font-size:13px;color:var(--pro-muted);margin-bottom:24px;min-height:44px}.pro-card-link{font-size:12px;font-weight:800;display:flex;justify-content:space-between;color:var(--pro-text);padding-top:14px;border-top:1px solid var(--pro-border)}.pro-empty{grid-column:1/-1;padding:45px;border:1px dashed var(--pro-border);background:var(--pro-surface);color:var(--pro-muted)}.pro-statement{background:var(--pro-surface)}.pro-statement-layout{display:grid;grid-template-columns:1fr 2fr;gap:60px}.pro-statement h2{font-size:clamp(36px,4.5vw,63px);max-width:760px}.pro-statement p{max-width:520px;color:var(--pro-muted)}.pro-brand-pills{display:flex;flex-wrap:wrap;gap:12px}.pro-brand-pills a{padding:18px 28px;border:1px solid var(--pro-border);border-radius:var(--pro-radius);font-weight:750}.pro-brand-pills a:hover{border-color:var(--pro-accent)}.pro-inner-hero{background:var(--pro-surface);padding:92px 0 65px;position:relative;overflow:hidden}.pro-inner-hero h1{max-width:870px;font-size:clamp(43px,6vw,85px);margin:18px 0}.pro-inner-hero p{max-width:650px;color:var(--pro-muted);font-size:17px}.pro-breadcrumb{font-size:12px;color:var(--pro-muted);margin-top:25px;display:flex;gap:12px;align-items:center;flex-wrap:wrap}.pro-breadcrumb strong{color:var(--pro-text)}.pro-list-section{padding:65px 0 110px}.pro-filter-panel{display:grid;grid-template-columns:minmax(220px,2fr) 1fr 1fr auto;align-items:end;gap:14px;margin-bottom:35px}.pro-filter-panel label>span{display:block;font-size:11px;margin-bottom:8px;color:var(--pro-muted);font-weight:750}.pro-filter-panel input,.pro-filter-panel select{display:block;width:100%;padding:14px 15px;border-radius:var(--pro-radius);border:1px solid var(--pro-border);background:var(--pro-background);color:var(--pro-text);outline-offset:2px}.pro-filter-count{font-size:12px;padding-bottom:17px;color:var(--pro-muted)}.pro-filter-scope .pro-card[hidden]{display:none}.pro-product-layout{padding-top:38px}.pro-product-layout .pro-breadcrumb{margin-bottom:38px}.pro-product-hero{display:grid;grid-template-columns:1.18fr .82fr;gap:6%;align-items:center}.pro-product-media{height:460px;overflow:hidden;background:var(--pro-surface);border-radius:var(--pro-radius)}.pro-product-media .pro-photo{height:100%}.pro-product-summary h1{font-size:clamp(45px,5vw,72px);margin:16px 0}.pro-product-summary p{font-size:16px;color:var(--pro-muted)}.pro-product-brand{font-weight:700;color:var(--pro-text)!important}.pro-detail-layout{border-top:1px solid var(--pro-border);display:grid;grid-template-columns:1fr 1fr;gap:8%;margin-top:80px;padding-top:55px}.pro-detail-layout h2{font-size:32px;margin-top:13px}.pro-specs{margin-top:25px}.pro-specs>div{display:grid;grid-template-columns:1fr 1fr;gap:22px;padding:16px 0;border-bottom:1px solid var(--pro-border)}.pro-specs span{color:var(--pro-muted)}.pro-rich{line-height:1.85;font-size:16px;overflow-wrap:anywhere}.pro-rich img{border-radius:var(--pro-radius);margin:25px 0}.pro-rich a{text-decoration:underline}.pro-rich h2{margin-top:30px}.pro-lead{font-size:20px;color:var(--pro-muted)}.pro-brand-hero-grid{display:grid;grid-template-columns:1.1fr .9fr;gap:7%;align-items:center}.pro-brand-media{height:300px;overflow:hidden;border-radius:var(--pro-radius)}.pro-article-hero{text-align:center;padding:110px 0 75px;background:var(--pro-surface)}.pro-article-width{max-width:900px}.pro-article-hero h1{font-size:clamp(40px,5vw,75px);margin:15px 0 25px}.pro-article-hero p{color:var(--pro-muted);font-size:18px}.pro-article-hero time{font-size:12px;color:var(--pro-muted)}.pro-article-content{max-width:930px;padding-top:70px;padding-bottom:90px}.pro-article-cover{width:100%;max-height:530px;object-fit:cover;margin-bottom:40px;border-radius:var(--pro-radius)}.pro-article-content>.pro-text-link{margin-top:35px}.pro-case-detail{max-width:1020px}.pro-case-detail>img{width:100%;max-height:620px;object-fit:cover}.pro-case-meta{display:flex;gap:35px;margin:35px 0;color:var(--pro-muted);font-size:13px}.pro-case-meta strong{display:block;color:var(--pro-text);font-size:18px;margin-top:7px}.pro-info-grid{display:grid;grid-template-columns:.8fr 1.2fr;gap:12%}.pro-info-grid h2{font-size:clamp(31px,4.5vw,54px);margin-top:15px}.pro-contact-email{font-size:20px;color:var(--pro-accent);font-weight:750;word-break:break-word}.pro-info-photo{max-height:450px;object-fit:cover;margin-top:35px;border-radius:var(--pro-radius)}.pro-custom-content .sf-section{background:transparent}.pro-custom-content .sf-section:nth-of-type(even){background:var(--pro-surface)}.pro-end-cta{padding:76px 0;background:var(--pro-hero);color:#fff}.pro-end-cta .pro-wrap{display:flex;align-items:center;justify-content:space-between;gap:40px}.pro-end-cta h2{font-size:clamp(32px,4vw,53px);margin:13px 0}.pro-end-cta p{color:#c5c9d1}.pro-end-cta a{background:var(--pro-accent);color:#fff;font-weight:800;padding:19px 30px;border-radius:var(--pro-radius);white-space:nowrap}.pro-404{text-align:center;padding-block:125px}.pro-404>span{font-size:12px;letter-spacing:.3em}.pro-404 h1{font-size:clamp(150px,20vw,320px);margin:10px 0;letter-spacing:-.08em}.pro-404 p{font-size:18px;color:var(--pro-muted)}.pro-404 a{margin-top:22px}.pro-footer{background:#15212d;color:#fff;padding:75px 0 22px}.pro-footer-top{display:grid;grid-template-columns:1.45fr 1fr 1fr;gap:55px}.pro-footer h2{font-size:32px;margin:12px 0}.pro-footer p{max-width:350px;font-size:13px;color:#afbbc8}.pro-footer .pro-eyebrow{color:#b6c3d2}.pro-footer-links ul{margin:0;padding:0;list-style:none;display:grid;grid-template-columns:1fr 1fr;gap:15px}.pro-footer-links a{font-size:13px;color:#d6e0e8}.pro-footer-bottom{border-top:1px solid #ffffff29;margin-top:60px;padding-top:20px;font-size:10px;letter-spacing:.12em;color:#adb9c3;display:flex;justify-content:space-between}.pro-anchor{display:block;height:0}.pro-category-tiles{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}.pro-category-tiles a{padding:35px 28px;min-height:155px;background:var(--pro-surface);display:flex;flex-direction:column;justify-content:space-between}.pro-category-tiles span{font-size:11px;color:var(--pro-muted)}.pro-category-tiles strong{font-size:24px}.pro-category-tiles b{align-self:end}.sf-site-head .sf-head-inner,.sf-site-head .sf-primary-links{display:none} +@media(max-width:1100px){.pro-head-inner{gap:17px}.pro-navigation{gap:14px}.pro-navigation a{font-size:12px}.pro-home-grid{min-height:500px}.pro-hero-copy h1{font-size:60px}.pro-hero-art{height:350px}} +@media(max-width:860px){.pro-wrap{padding-left:22px;padding-right:22px}.pro-utility{display:none}.pro-head-inner{min-height:70px;flex-wrap:wrap;gap:12px}.pro-mobile-toggle{display:block;margin-left:auto;border:1px solid var(--pro-border);padding:8px 12px;background:transparent;color:var(--pro-text);border-radius:5px}.pro-navigation{display:none;order:10;width:100%;flex-direction:column;align-items:stretch;gap:0;padding-bottom:12px}.pro-navigation.is-open{display:flex}.pro-navigation a{padding:11px 2px;border-bottom:1px solid var(--pro-border)}.pro-header-cta{display:none}.pro-mega{display:none}.pro-home-grid{grid-template-columns:1fr;gap:35px;padding-top:60px;padding-bottom:60px}.pro-hero-art{height:350px}.pro-hero-copy h1{font-size:clamp(45px,9vw,73px)}.pro-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.pro-product-hero,.pro-detail-layout,.pro-info-grid,.pro-brand-hero-grid{grid-template-columns:1fr;gap:35px}.pro-product-media{height:380px}.pro-filter-panel{grid-template-columns:1fr 1fr}.pro-filter-panel label:first-child{grid-column:1/-1}.pro-end-cta .pro-wrap{align-items:start;flex-direction:column}.pro-section{padding:72px 0}.pro-footer-top{grid-template-columns:1fr 1fr}.pro-footer-top>div:first-child{grid-column:1/-1}.pro-category-tiles{grid-template-columns:repeat(2,1fr)}} +@media(max-width:560px){.pro-wrap{padding-left:18px;padding-right:18px}.pro-logo-name{font-size:15px}.pro-hero-copy h1{font-size:43px}.pro-hero-art{height:255px}.pro-hero-bottom{display:none}.pro-home-grid{min-height:0}.pro-grid{grid-template-columns:1fr}.pro-section-head{align-items:start;flex-direction:column}.pro-section-head h2{font-size:37px}.pro-card-cover{height:230px}.pro-filter-panel{grid-template-columns:1fr}.pro-filter-panel label:first-child{grid-column:auto}.pro-filter-count{padding-bottom:4px}.pro-statement-layout,.pro-footer-top{grid-template-columns:1fr;gap:25px}.pro-footer-top>div:first-child{grid-column:auto}.pro-footer-bottom{flex-direction:column;gap:8px}.pro-inner-hero{padding:60px 0}.pro-product-media{height:270px}.pro-product-summary h1{font-size:43px}.pro-category-tiles{grid-template-columns:1fr}.pro-end-cta h2{font-size:38px}.pro-minimal-meta{display:block!important}} + +/* V2 compatibility stylesheet hides direct headers/footers; full themes restore their own. */ +body>header.sf-site-head.pro-header,body>footer.sf-site-foot.pro-footer{display:block!important} + +/* Accessible desktop mega-navigation and mobile disclosure */ +.pro-catalog-toggle{font-size:12px;font-weight:750;border:1px solid var(--pro-border);background:transparent;color:inherit;border-radius:var(--pro-radius);padding:10px 14px;white-space:nowrap} +.pro-mega[hidden]{display:none!important}.pro-mega.is-open{display:flex}.pro-mega>div{padding-block:3px} +@media(max-width:1060px){.pro-catalog-toggle{display:none}} +@media(max-width:860px){.pro-mega.is-open{display:block!important}.pro-mega.is-open>div{display:flex;flex-wrap:wrap;gap:14px;padding:12px 0}.pro-mega>span{white-space:normal}} + +/* V4: responsive nested navigation, gallery and opt-in inquiry integration */ +.pro-nav-group{position:relative;display:flex;align-items:center;gap:3px}.pro-nav-disclose{border:0;background:none;color:inherit;font-size:12px;padding:8px}.pro-nav-children[hidden]{display:none!important}.pro-nav-children{position:absolute;left:0;top:100%;z-index:45;min-width:230px;max-width:360px;padding:10px;background:var(--pro-background);border:1px solid var(--pro-border);box-shadow:0 18px 35px #0002;border-radius:var(--pro-radius);display:flex;flex-direction:column}.pro-nav-children a{padding:10px 12px;white-space:nowrap}.pro-nav-children .pro-nav-leaf{padding-left:28px;color:var(--pro-muted)} +.pro-product-gallery{min-width:0}.pro-gallery-thumbs{display:flex;gap:8px;margin-top:12px;overflow:auto;scrollbar-width:thin;padding-bottom:5px}.pro-gallery-thumbs button{flex:0 0 86px;height:67px;border:2px solid transparent;padding:3px;border-radius:8px;background:var(--pro-surface)}.pro-gallery-thumbs button:focus-visible,.pro-gallery-thumbs button[aria-pressed=true]{border-color:var(--pro-accent)}.pro-gallery-thumbs img{width:100%;height:100%;object-fit:cover;border-radius:4px}.pro-gallery-lightbox{position:fixed;inset:0;background:rgba(10,16,30,.92);z-index:1000;display:grid;place-items:center;padding:6vw}.pro-gallery-lightbox[hidden]{display:none}.pro-gallery-lightbox img{max-width:92vw;max-height:80vh;object-fit:contain}.pro-gallery-lightbox button{position:absolute;right:25px;top:25px;border:1px solid #fff8;background:#222;color:#fff;padding:10px 15px;border-radius:5px} +.pro-inquiry-wrap{display:grid;grid-template-columns:1fr 1fr;gap:70px}.pro-inquiry{display:grid;gap:17px}.pro-inquiry label{display:grid;gap:7px;font-weight:650}.pro-inquiry input,.pro-inquiry textarea{padding:13px;border:1px solid var(--pro-border);border-radius:var(--pro-radius);background:var(--pro-background);color:var(--pro-text);width:100%}.pro-inquiry textarea{min-height:140px}.pro-inquiry .pro-honeypot{position:absolute;left:-10000px;width:1px;height:1px}.pro-inquiry p{font-size:12px;color:var(--pro-muted)} +@media(max-width:860px){.pro-nav-group{display:block}.pro-nav-children{position:static;max-width:none;width:100%;box-shadow:none;border:0;border-left:2px solid var(--pro-accent);padding-left:8px}.pro-nav-group>a{display:inline-block}.pro-inquiry-wrap{grid-template-columns:1fr;gap:20px}} diff --git a/examples/v830-built-sites/corporate/assets/pro.css b/examples/v830-built-sites/corporate/assets/pro.css new file mode 100644 index 0000000..bdf8348 --- /dev/null +++ b/examples/v830-built-sites/corporate/assets/pro.css @@ -0,0 +1,89 @@ +:root{--pro-text:#292d50;--pro-muted:#737793;--pro-border:#e1e2ed;--pro-background:#fff;--pro-surface:#f3f3f9;--pro-accent:#6054c5;--pro-hero:#272b61;--pro-radius:18px;--pro-headings:system-ui,Arial,sans-serif;--pro-wide:1250px} +.pro-utility{background:#343771;color:#f6f6ff}.pro-header{background:#fff}.pro-logo-symbol{color:#655dc0;font-size:35px}.pro-logo-name{letter-spacing:-.07em}.pro-navigation a{font-weight:600}.pro-header-cta{background:#4e4aa4;border-radius:999px}.pro-corporate-hero{background:linear-gradient(135deg,#fafafe 0%,#f0f0fc 55%,#e9e8fa 100%)}.pro-corporate-hero .pro-home-grid{min-height:630px}.pro-corporate-hero .pro-hero-copy h1{font-weight:810}.pro-corporate-hero .pro-hero-copy h1 em{color:#6763c3}.pro-corporate-hero .pro-hero-art{border-radius:25px 160px 25px 160px;background:#dad9f7;box-shadow:25px 35px 0 #c3bde655}.pro-corporate-shape{position:absolute;inset:0;display:grid;place-items:center;background:radial-gradient(circle at 70% 40%,#8079dc 0%,#4d4aab 55%,#333576 100%)}.pro-corporate-shape:before{content:'';position:absolute;width:62%;aspect-ratio:1;border:65px solid #a19dfb77;border-radius:50%;left:-15%;top:-27%}.pro-corporate-shape:after{content:'';position:absolute;width:53%;aspect-ratio:1;border:50px solid #9994e955;border-radius:50%;right:-16%;bottom:-33%}.pro-corporate-shape span{z-index:1;color:#fff;font-size:clamp(26px,3vw,42px);font-weight:850;text-align:center;line-height:1.15;letter-spacing:-.06em}.pro-featured{background:#fff}.pro-featured .pro-card{border-color:#e6e5f0;box-shadow:0 18px 35px #30327a0e}.pro-card-cover{background:#e9eaf7}.pro-art-service{background:linear-gradient(120deg,#d5d2f8,#e9e8fa)}.pro-art-center{color:#716eb69c}.pro-statement{background:#f3f2fa;color:#2a2d50}.pro-statement h2{max-width:820px}.pro-statement .pro-text-link{color:#5e56bc}.pro-case-section{background:#f9f9fc}.pro-inner-hero{background:linear-gradient(140deg,#f3f3fc,#dfdff5)}.pro-inner-hero:after{content:'';position:absolute;right:-5%;bottom:-55%;width:400px;aspect-ratio:1;border:80px solid #8780e41a;border-radius:50%}.pro-article-hero{background:#eeedfa}.pro-footer{background:#242750}.pro-end-cta{background:#34366e}.pro-end-cta a{background:#fff;color:#383776!important}.pro-404 h1{color:#8a84d9} + +/* SiteForge V5 commercial signature */ +.pro-corporate-hero .pro-hero-art{background-image:url("./visual/hero.svg")!important;background-position:center;background-size:cover;} + +.pro-corporate-hero .pro-hero-art{background-color:#f5f4ff;border-radius:38px 120px 40px 120px;overflow:hidden;box-shadow:30px 35px 70px #565baa21}.pro-corporate-hero .pro-hero-art .pro-corporate-shape{opacity:0}.pro-card{border:1px solid #e5e2f2;border-radius:20px;box-shadow:0 10px 40px #3d3b8110}.pro-card-cover{border-radius:20px 20px 0 0;background:#edeafa}.pro-art{background:radial-gradient(circle at 75% 32%,#dad5f7,#eceafa 74%);color:#7772c1}.pro-featured{background:#fff}.pro-statement{background:linear-gradient(120deg,#f2f1fc,#e9e7fb)}.pro-brand-section{background:#f6f5fb}.pro-footer{background:#232658;color:#fff}.pro-header-cta{border-radius:100px}.pro-section-head h2{font-weight:760} + +/* V8.29 presentation refinement: corporate. Preserve per-theme design language. */ +body.pro-corporate{--pro-studio-ring:rgba(96,84,197,.16);--pro-focus-color:#6559ba;--pro-interact-radius:16px} +body.pro-corporate .pro-wrap{max-width:100%;min-width:0} +body.pro-corporate .pro-hero-copy,body.pro-corporate .pro-card-body,body.pro-corporate .pro-card-copy{min-width:0;overflow-wrap:anywhere} +body.pro-corporate .pro-hero-copy h1{font-size:clamp(2.45rem,5.15vw,5.6rem);line-height:1.08;max-width:18ch;text-wrap:balance} +body.pro-corporate .pro-section-head h2{font-size:clamp(1.85rem,3vw,3.25rem);text-wrap:balance} +body.pro-corporate .pro-card,body.pro-corporate .pro-product-card{transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease} +@media(hover:hover){body.pro-corporate .pro-card:hover,body.pro-corporate .pro-product-card:hover{transform:translateY(-3px);box-shadow:0 14px 36px var(--pro-studio-ring)}} +body.pro-corporate :where(button,a,input,select,textarea):focus-visible{outline:3px solid var(--pro-focus-color);outline-offset:3px} +body.pro-corporate img{max-width:100%;height:auto} +body.pro-corporate .pro-card-cover img,body.pro-corporate .pro-gallery-main img{object-fit:cover;max-height:100%} +body.pro-corporate .pro-mobile-toggle,body.pro-corporate .pro-nav-disclose{min-height:44px;min-width:44px} +@media(max-width:860px){body.pro-corporate .pro-home-grid,body.pro-corporate .pro-product-layout,body.pro-corporate .pro-inquiry-wrap{min-width:0}body.pro-corporate .pro-card-grid,body.pro-corporate .pro-grid{gap:clamp(12px,3vw,23px)}} +@media(max-width:560px){body.pro-corporate .pro-wrap{padding-left:max(16px,env(safe-area-inset-left));padding-right:max(16px,env(safe-area-inset-right))}body.pro-corporate .pro-hero-copy h1{font-size:clamp(2rem,9vw,3.2rem)}body.pro-corporate .pro-section-head h2{font-size:clamp(1.75rem,7vw,2.5rem)}body.pro-corporate .pro-section{padding-block:clamp(34px,9vw,60px)}body.pro-corporate .pro-card-cover{height:auto;aspect-ratio:4/3}body.pro-corporate .pro-card-cover img{width:100%;height:100%;object-fit:cover}} +@media(prefers-reduced-motion:reduce){body.pro-corporate .pro-card,body.pro-corporate .pro-product-card{transition:none!important;transform:none!important}} + + +/* V8.30 REAL PAGE COMPOSITION. Built-in theme version 1.3.0 only. + Content-driven sections do not invent client names, certifications or KPIs. */ +.pro-v30-page{--v30-ink:var(--pro-text);--v30-secondary:var(--pro-muted);--v30-line:var(--pro-border);--v30-panel:var(--pro-surface);--v30-max:1180px;color:var(--v30-ink);overflow:clip} +.pro-v30-page .pro-wrap{max-width:var(--v30-max);min-width:0} +.pro-v30-page h1,.pro-v30-page h2{overflow-wrap:anywhere;text-wrap:balance;line-height:1.11} +.pro-v30-page h1{font-size:clamp(2.55rem,5.2vw,5.6rem);margin:18px 0 22px;letter-spacing:-.035em} +.pro-v30-page h2{font-size:clamp(1.8rem,3.3vw,3rem);margin:16px 0 26px;letter-spacing:-.02em} +.pro-v30-page p{line-height:1.75;overflow-wrap:anywhere} +.pro-v30-page img{max-width:100%} +.pro-v30-intro-layout{display:grid;grid-template-columns:minmax(0,1fr) 190px;gap:8vw;align-items:end} +.pro-v30-page-intro{padding:clamp(68px,10vw,128px) 0 clamp(55px,8vw,94px);background:var(--v30-panel)} +.pro-v30-intro-main>p{max-width:610px;font-size:clamp(16px,2vw,21px);color:var(--v30-secondary)} +.pro-v30-intro-aside{border-left:1px solid var(--v30-line);padding-left:27px;display:grid;gap:8px;align-content:end;min-height:120px} +.pro-v30-overline,.pro-v30-caption{font-size:11px;letter-spacing:.12em;color:var(--v30-secondary)} +.pro-v30-index-number{font-size:64px;line-height:1;font-weight:650;letter-spacing:-.08em} +.pro-v30-index-toolbar{display:flex;justify-content:space-between;align-items:end;gap:22px;margin-bottom:28px} +.pro-v30-index-body{background:var(--pro-background)} +.pro-v30-index-body .pro-section-head,.pro-v30-index-toolbar h2{margin:8px 0} +.pro-v30-subtle-link,.pro-v30-text-action{display:inline-flex;gap:10px;text-decoration:none;font-weight:750;font-size:13px;align-items:center;min-height:44px} +.pro-v30-subtle-link:hover,.pro-v30-text-action:hover{text-decoration:underline} +.pro-v30-results{margin-top:clamp(28px,5vw,54px)} +.pro-v30-product-top{padding:26px 0 clamp(60px,8vw,110px);background:var(--v30-panel)} +.pro-v30-crumb{display:flex;flex-wrap:wrap;gap:11px;align-items:center;font-size:12px;color:var(--v30-secondary);margin:8px 0 46px} +.pro-v30-crumb a{text-decoration:underline;text-underline-offset:4px} +.pro-v30-product-head{display:grid;grid-template-columns:minmax(290px,.78fr) minmax(0,1.22fr);align-items:center;gap:clamp(30px,6vw,90px)} +.pro-v30-product-intro>p{font-size:clamp(16px,2vw,19px);color:var(--v30-secondary);max-width:48ch} +.pro-v30-tags{display:flex;gap:8px;flex-wrap:wrap;margin:24px 0 30px}.pro-v30-tags span{padding:8px 13px;border:1px solid var(--v30-line);font-size:12px;border-radius:2px} +.pro-v30-action{display:inline-flex;align-items:center;justify-content:center;min-height:48px} +.pro-v30-main-media{background:var(--pro-surface);aspect-ratio:4/3;overflow:hidden;display:grid;place-items:center;border-radius:var(--pro-radius)} +.pro-v30-main-media .pro-photo{width:100%;height:100%;object-fit:contain} +.pro-v30-product-details{display:grid;grid-template-columns:minmax(0,1.3fr) minmax(270px,.7fr);gap:clamp(30px,7vw,104px)} +.pro-v30-details-main .pro-rich{max-width:760px}.pro-v30-details-side{align-self:start;border-top:3px solid var(--pro-accent);padding-top:25px} +.pro-v30-details-side .pro-specs>div{grid-template-columns:minmax(0,1fr) minmax(0,1.1fr);gap:16px}.pro-v30-details-side .pro-specs strong{overflow-wrap:anywhere} +.pro-v30-reading-head{padding:clamp(50px,8vw,100px) 0 clamp(60px,8vw,100px);background:var(--v30-panel)} +.pro-v30-reading-title{max-width:940px;margin:auto}.pro-v30-reading-title>p{font-size:clamp(16px,2.1vw,22px);max-width:65ch;color:var(--v30-secondary)} +.pro-v30-reading-title time{display:block;margin-top:24px;font-size:13px;color:var(--v30-secondary)} +.pro-v30-reading-layout{display:grid;grid-template-columns:180px minmax(0,750px);gap:clamp(35px,7vw,110px);padding-block:clamp(55px,8vw,110px)} +.pro-v30-reading-aside{display:flex;flex-direction:column;gap:18px;align-self:start;position:sticky;top:30px;font-size:13px} +.pro-v30-reading-rule{height:1px;background:var(--v30-line)} +.pro-v30-reading-content{min-width:0}.pro-v30-reading-content figure{margin:0 0 45px}.pro-v30-reading-content figure img{display:block;width:100%;height:auto;max-height:550px;object-fit:cover} +.pro-v30-reading-content .pro-rich{line-height:1.9;font-size:clamp(16px,1.75vw,18px)}.pro-v30-reading-content .pro-rich>*+*{margin-top:1.3em} +.pro-v30-about-opening{padding:clamp(75px,10vw,130px) 0;background:var(--v30-panel)} +.pro-v30-about-heading{display:grid;grid-template-columns:1.3fr .7fr;gap:9%;align-items:end}.pro-v30-about-heading>p{font-size:clamp(17px,2vw,23px);color:var(--v30-secondary);padding-bottom:12px} +.pro-v30-about-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(36px,8vw,120px);align-items:center} +.pro-v30-about-media{min-height:360px;aspect-ratio:5/4;background:var(--v30-panel);overflow:hidden}.pro-v30-about-media img{width:100%;height:100%;object-fit:cover} +.pro-v30-media-placeholder{height:100%;min-height:360px;display:grid;place-items:center;color:var(--v30-secondary);letter-spacing:.18em;font-size:12px;border:1px solid var(--v30-line)} +.pro-v30-about-copy .pro-rich{max-width:620px}.pro-v30-about-cases{background:var(--v30-panel)} +.pro-v30-contact-header{background:var(--v30-panel);padding:clamp(75px,10vw,135px) 0}.pro-v30-contact-header p{font-size:clamp(17px,2vw,21px);max-width:58ch;color:var(--v30-secondary)} +.pro-v30-contact-layout{display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);gap:clamp(40px,8vw,120px)} +.pro-v30-contact-channel{display:grid;gap:10px;margin-top:45px;border-top:1px solid var(--v30-line);padding-top:25px}.pro-v30-contact-channel span{font-size:12px;color:var(--v30-secondary)}.pro-v30-contact-channel a{font-size:clamp(15px,2vw,24px);overflow-wrap:anywhere;font-weight:650} +.pro-v30-contact-form-wrap{padding:clamp(22px,4vw,48px);background:var(--v30-panel);min-width:0} +.pro-v30-contact-form-wrap .pro-inquiry{margin-top:22px}.pro-v30-contact-form-wrap .pro-inquiry input,.pro-v30-contact-form-wrap textarea{background:var(--pro-background)} +.pro-v30-contact-note{display:grid;align-content:space-between;min-height:270px;gap:24px}.pro-v30-decorative-number{font-size:90px;line-height:1;justify-self:end;color:var(--pro-accent)} +.pro-v30-home-editorial{background:var(--pro-surface)} +.pro-v30-page :where(a,button,input,textarea,select):focus-visible{outline:3px solid var(--pro-accent);outline-offset:3px} +@media(max-width:950px){.pro-v30-product-head,.pro-v30-product-details,.pro-v30-about-grid,.pro-v30-contact-layout{grid-template-columns:1fr;gap:38px}.pro-v30-product-visual{order:-1}.pro-v30-about-heading{grid-template-columns:1fr;gap:4px}.pro-v30-about-media{max-height:430px}.pro-v30-reading-layout{grid-template-columns:1fr;gap:24px}.pro-v30-reading-aside{position:static;flex-direction:row;align-items:center;flex-wrap:wrap}.pro-v30-reading-rule{display:none}} +@media(max-width:600px){.pro-v30-page .pro-wrap{padding-inline:max(18px,env(safe-area-inset-left));}.pro-v30-page h1{font-size:clamp(2.2rem,9.2vw,3.4rem)}.pro-v30-intro-layout{grid-template-columns:1fr;gap:18px}.pro-v30-intro-aside{display:none}.pro-v30-index-toolbar{align-items:start;flex-direction:column;gap:0}.pro-v30-crumb{margin-bottom:24px}.pro-v30-product-top{padding-bottom:42px}.pro-v30-main-media{aspect-ratio:5/4}.pro-v30-product-details{gap:45px}.pro-v30-reading-title{margin:0}.pro-v30-reading-content figure{margin-bottom:22px}.pro-v30-about-media,.pro-v30-media-placeholder{min-height:220px}.pro-v30-contact-form-wrap{padding:20px}.pro-v30-contact-layout{gap:30px}} +@media(prefers-reduced-motion:reduce){.pro-v30-page *{scroll-behavior:auto!important}} + +/* Theme-specific editorial composition */ + .pro-v30-business-index .pro-v30-page-intro{background:linear-gradient(116deg,#edf3fa,#f7f9fc)}.pro-v30-business-index .pro-v30-intro-aside{border-left-color:#9bb3ce}.pro-v30-product-corporate .pro-v30-product-top{background:#f4f7fb}.pro-v30-product-corporate .pro-v30-main-media{border-radius:20px}.pro-v30-product-corporate .pro-v30-details-side{border-top:4px solid #316eb1}.pro-v30-article-corporate .pro-v30-reading-title{max-width:840px}.pro-v30-about-corporate .pro-v30-about-heading{max-width:1080px}.pro-v30-about-corporate .pro-v30-about-media{border-radius:18px}.pro-v30-contact-corporate .pro-v30-contact-form-wrap{border-radius:18px} + +/* Retain existing gallery runtime behavior with re-composed product layout. */ +.pro-v30-page .pro-product-media{height:auto;min-height:0} diff --git a/examples/v830-built-sites/corporate/assets/pro.js b/examples/v830-built-sites/corporate/assets/pro.js new file mode 100644 index 0000000..9cf100d --- /dev/null +++ b/examples/v830-built-sites/corporate/assets/pro.js @@ -0,0 +1,72 @@ +'use strict';(()=>{ + const menu=document.querySelector('[data-pro-menu]'); const nav=document.querySelector('#pro-navigation'); + if(menu&&nav){menu.addEventListener('click',()=>{const open=menu.getAttribute('aria-expanded')!=='true';menu.setAttribute('aria-expanded',String(open));nav.classList.toggle('is-open',open);menu.setAttribute('aria-label',open?'关闭导航':'打开导航');});} + // Drawer navigation. The same markup is used across the four professional themes. + const mobileNav=document.querySelector('#pro-navigation'); + let drawerBackdrop=null,drawerClose=null,returnFocus=null; + if(menu&&mobileNav){ + const originalParent=mobileNav.parentNode,originalNext=mobileNav.nextSibling; + const heading=document.createElement('div');heading.className='sf-drawer-header'; + const title=document.createElement('strong');title.textContent='网站导航'; + drawerClose=document.createElement('button');drawerClose.type='button';drawerClose.className='sf-drawer-close';drawerClose.textContent='×';drawerClose.setAttribute('aria-label','关闭网站导航'); + heading.append(title,drawerClose);mobileNav.prepend(heading); + drawerBackdrop=document.createElement('div');drawerBackdrop.className='sf-mobile-drawer-backdrop';drawerBackdrop.hidden=false;document.body.append(drawerBackdrop); + function setDrawer(open,focusBack=true){ + const isMobile=window.matchMedia('(max-width:1024px)').matches; + open=Boolean(open&&isMobile); + if(open){returnFocus=document.activeElement;document.body.append(mobileNav);} + else if(mobileNav.parentNode!==originalParent){if(originalNext&&originalNext.parentNode===originalParent)originalParent.insertBefore(mobileNav,originalNext);else originalParent.append(mobileNav);} + mobileNav.classList.toggle('is-open',open);drawerBackdrop.classList.toggle('is-open',open); + document.body.classList.toggle('sf-drawer-open',open); + menu.setAttribute('aria-expanded',String(open));menu.setAttribute('aria-label',open?'关闭导航':'打开导航'); + mobileNav.setAttribute('aria-hidden',String(!open&&isMobile)); + if('inert' in mobileNav)mobileNav.inert=!open&&isMobile; + if(open)drawerClose.focus(); + else if(focusBack&&returnFocus instanceof HTMLElement){returnFocus.focus();returnFocus=null;} + } + // Replace the old inline-expansion listener: use capture to stop the old listener. + menu.addEventListener('click',e=>{if(!window.matchMedia('(max-width:1024px)').matches)return;e.stopImmediatePropagation();setDrawer(!mobileNav.classList.contains('is-open'));},true); + drawerClose.addEventListener('click',()=>setDrawer(false)); + drawerBackdrop.addEventListener('click',()=>setDrawer(false)); + document.querySelectorAll('[data-mobile-open-menu]').forEach(b=>b.addEventListener('click',()=>setDrawer(true))); + mobileNav.addEventListener('click',e=>{if(e.target.closest('a'))setDrawer(false,false)}); + document.addEventListener('keydown',e=>{ + if(e.key==='Escape'&&mobileNav.classList.contains('is-open')){e.preventDefault();setDrawer(false);} + if(e.key!=='Tab'||!mobileNav.classList.contains('is-open'))return; + const els=[...mobileNav.querySelectorAll('button:not([disabled]),a[href]')].filter(el=>el.getClientRects().length&&!el.closest('[hidden]')); + if(!els.length)return;const first=els[0],last=els[els.length-1]; + if(e.shiftKey&&document.activeElement===first){e.preventDefault();last.focus();} + else if(!e.shiftKey&&document.activeElement===last){e.preventDefault();first.focus();} + }); + window.matchMedia('(max-width:1024px)').addEventListener('change',()=>setDrawer(false,false)); + if('inert' in mobileNav&&window.matchMedia('(max-width:1024px)').matches)mobileNav.inert=true; + // Do not strand catalogue links when the old mobile mega-button is hidden. + const megaLinks=document.querySelectorAll('[data-pro-mega] a'); + if(megaLinks.length){const wrap=document.createElement('div');wrap.className='sf-drawer-extra';const h=document.createElement('strong');h.textContent='更多分类与系列';wrap.append(h); + [...megaLinks].slice(0,20).forEach(a=>{const clone=a.cloneNode(true);wrap.append(clone);});mobileNav.append(wrap);} + } + const tabbar=document.querySelector('[data-mobile-tabs]'); + if(tabbar){tabbar.style.setProperty('--sf-mobile-tab-count',String(tabbar.children.length));} + const megaButton=document.querySelector('[data-pro-catalog]'), mega=document.querySelector('[data-pro-mega]'); + if(megaButton&&mega){function setMega(open){mega.hidden=!open;mega.classList.toggle('is-open',open);megaButton.setAttribute('aria-expanded',String(open));} + megaButton.addEventListener('click',()=>setMega(mega.hidden)); + document.addEventListener('keydown',e=>{if(e.key==='Escape')setMega(false);}); + document.addEventListener('click',e=>{if(!mega.hidden&&!mega.contains(e.target)&&!megaButton.contains(e.target))setMega(false);}); + } + document.querySelectorAll('.pro-nav-disclose').forEach(button=>{button.addEventListener('click',()=>{let panel=button.parentElement.querySelector('.pro-nav-children');let visible=button.getAttribute('aria-expanded')==='true';button.setAttribute('aria-expanded',String(!visible));panel.hidden=visible;});}); + document.querySelectorAll('.pro-gallery-thumbs').forEach(container=>{const main=container.parentElement.querySelector('.pro-product-media img');const buttons=[...container.querySelectorAll('[data-gallery-image]')]; + buttons.forEach(b=>{b.addEventListener('click',()=>{buttons.forEach(x=>x.setAttribute('aria-pressed',String(x===b)));if(main){main.src=b.dataset.galleryImage;main.alt=b.querySelector('img')?.alt||'';}});}); + if(!main)return;main.tabIndex=0;main.style.cursor='zoom-in';const open=()=>{const pane=document.createElement('div');pane.className='pro-gallery-lightbox';pane.setAttribute('role','dialog');pane.setAttribute('aria-label','产品大图预览');let img=document.createElement('img');img.src=main.src;img.alt=main.alt;const close=document.createElement('button');close.type='button';close.textContent='关闭 ×';pane.append(img,close);document.body.append(pane);const done=()=>{pane.remove();document.removeEventListener('keydown',esc);main.focus();};const esc=e=>{if(e.key==='Escape')done();};document.addEventListener('keydown',esc);close.addEventListener('click',done);pane.addEventListener('click',e=>{if(e.target===pane)done();});close.focus();};main.addEventListener('click',open);main.addEventListener('keydown',e=>{if(e.key==='Enter')open();}); + }); + document.querySelectorAll('.pro-filter-scope').forEach(scope=>{ + const panel=scope.previousElementSibling;if(!panel||!panel.classList.contains('pro-filter-panel'))return; + const cards=Array.from(scope.querySelectorAll('.pro-card')); + const blank=document.createElement('div');blank.className='pro-filter-empty';blank.hidden=true;blank.textContent='没有找到符合条件的内容,请调整关键词或筛选条件。';scope.append(blank); + const q=panel.querySelector('[data-pro-filter-search]'),b=panel.querySelector('[data-pro-filter-brand]'),c=panel.querySelector('[data-pro-filter-category]'),count=panel.querySelector('[data-pro-filter-count]'); + function options(sel,key){const vals=[...new Set(cards.map(x=>x.dataset[key]||'').filter(Boolean))].sort();vals.forEach(x=>sel.add(new Option(x,x)));if(!vals.length)sel.closest('label').hidden=true;} + options(b,'brand');options(c,'category'); + function run(){const str=q.value.trim().toLocaleLowerCase();let visible=0; + cards.forEach(el=>{const hit=el.textContent.toLocaleLowerCase().includes(str)&&(!b.value||el.dataset.brand===b.value)&&(!c.value||el.dataset.category===c.value);el.hidden=!hit;visible+=Number(hit);});count.textContent=`共 ${visible} 条`;blank.hidden=visible!==0;} + [q,b,c].forEach(x=>x.addEventListener(x===q?'input':'change',run));run(); + }); +})(); diff --git a/examples/v830-built-sites/corporate/assets/site-runtime.js b/examples/v830-built-sites/corporate/assets/site-runtime.js new file mode 100644 index 0000000..e4715e8 --- /dev/null +++ b/examples/v830-built-sites/corporate/assets/site-runtime.js @@ -0,0 +1,31 @@ +'use strict'; +(()=>{ + const $=s=>document.querySelector(s), $$=s=>[...document.querySelectorAll(s)]; + const menu=$('.sf-menu-toggle');if(menu){menu.addEventListener('click',()=>{let open=menu.getAttribute('aria-expanded')!=='true';menu.setAttribute('aria-expanded',String(open));$('#sf-primary-links')?.classList.toggle('is-open',open);});} + // Filter actual static content cards, no API is needed at runtime. + $$('.sf-collection').forEach(grid=>{ + const cards=$$('.sf-item',grid); + if(cards.length<2)return; + const toolbar=document.createElement('div');toolbar.className='sf-filters'; + const search=document.createElement('input');search.type='search';search.placeholder='筛选当前列表';search.setAttribute('aria-label','筛选当前列表'); + const status=document.createElement('span');status.setAttribute('aria-live','polite');status.style.fontSize='12px'; + const brand=document.createElement('select');brand.setAttribute('aria-label','按品牌筛选'); + const category=document.createElement('select');category.setAttribute('aria-label','按分类筛选'); + function fill(el,field,all){el.append(new Option(all,''));const vals=[...new Set(cards.map(x=>x.dataset[field]||'').filter(Boolean))].sort();vals.forEach(v=>el.append(new Option(v,v)));if(!vals.length)el.hidden=true;} + fill(brand,'brand','全部品牌');fill(category,'category','全部分类'); + toolbar.append(search,brand,category,status);grid.parentNode.insertBefore(toolbar,grid); + function apply(){let val=search.value.trim().toLocaleLowerCase();let visible=0;cards.forEach(card=>{let hit=card.textContent.toLocaleLowerCase().includes(val)&&(!brand.value||card.dataset.brand===brand.value)&&(!category.value||card.dataset.category===category.value);card.hidden=!hit;if(hit)visible++;});status.textContent=`共 ${visible} 项`;} + search.addEventListener('input',apply);brand.addEventListener('change',apply);category.addEventListener('change',apply);apply(); + }); + const input=$('#sf-search'),root=$('#sf-search-results'),count=$('#sf-search-count'); + if(input&&root){ + let data=[];const params=new URLSearchParams(location.search);input.value=params.get('q')||''; + let debounce=null; + const render=()=>{let q=input.value.trim().toLocaleLowerCase();let found=q?data.filter(d=>`${d.title} ${d.summary} ${d.brand} ${d.type}`.toLocaleLowerCase().includes(q)).slice(0,100):data.slice(0,30); + root.replaceChildren();count.textContent=`${found.length} 条结果${!q?'(显示前30条)':''}`; + found.forEach(d=>{let article=document.createElement('article'),a=document.createElement('a'),small=document.createElement('small'),p=document.createElement('p');article.className='sf-search-result';a.textContent=d.title;a.href=d.url.replace(/^\//,'');small.textContent=d.type;p.textContent=d.summary;article.append(a,small,p);root.append(article);}); + };const base=document.querySelector('base')?.href||location.href; + fetch(new URL('search-index.json',base)).then(r=>{if(!r.ok)throw Error('index unavailable');return r.json();}).then(v=>{data=v;render()}).catch(()=>{count.textContent='搜索索引加载失败,请检查站点文件部署路径';}); + input.addEventListener('input',()=>{clearTimeout(debounce);debounce=setTimeout(render,100)}); + } +})(); diff --git a/examples/v830-built-sites/corporate/assets/theme.css b/examples/v830-built-sites/corporate/assets/theme.css new file mode 100644 index 0000000..7e9702a --- /dev/null +++ b/examples/v830-built-sites/corporate/assets/theme.css @@ -0,0 +1,4 @@ +:root{--ink:#152040;--blue:#283d8c;--purple:#6558b9;--light:#f6f7fb}*{box-sizing:border-box}body{margin:0;background:white;color:#172347;font-family:Inter,"Segoe UI",Arial,sans-serif;line-height:1.65}a{color:inherit;text-decoration:none}img{max-width:100%}.shell{width:min(1200px,89%);margin:auto}.announcement{height:35px;background:#262d70;color:white;display:flex;justify-content:center;align-items:center;gap:12px;font-size:10px;letter-spacing:1.3px}.announcement span{color:#b8d6fd}.header{height:94px;display:flex;align-items:center;justify-content:space-between;gap:20px}.logo{font-size:23px;font-weight:850;letter-spacing:-1px;display:flex;align-items:center;gap:12px}.logo-box{display:grid;place-items:center;width:43px;height:43px;color:#fff;font-size:25px;background:linear-gradient(135deg,#5b6ce0,#7c4dc3);border-radius:13px}.header nav{display:flex;gap:28px;font-size:13px;font-weight:600;flex-wrap:wrap}.header nav a:hover{color:#585cca}.nav-btn{background:#243475;color:#fff;padding:13px 20px;border-radius:8px;font-size:12px;font-weight:700}.nav-btn span{margin-left:18px}.hero{background:linear-gradient(120deg,#f5f7ff,#ebeeff 45%,#f8f6fc);overflow:hidden}.hero-grid{min-height:580px;display:grid;grid-template-columns:53% 47%;align-items:center}.hero-text{padding:70px 0}.pill{font-size:10px;letter-spacing:1.5px;color:#5549ac;background:#e5e5fa;border-radius:50px;display:inline-block;padding:8px 15px;font-weight:750}.hero h1{font-size:clamp(52px,6.2vw,87px);line-height:1.06;letter-spacing:-4px;margin:32px 0 20px;max-width:620px;color:#19265e}.hero p{font-size:18px;line-height:1.8;color:#69718f;max-width:520px}.actions{display:flex;gap:14px;flex-wrap:wrap;margin-top:34px}.primary,.secondary{padding:14px 24px;border-radius:8px;font-size:13px;font-weight:750}.primary{background:#38489e;color:#fff}.secondary{background:white;border:1px solid #d2d7ed}.trusted{font-size:10px;color:#9b9db6;letter-spacing:2px;margin-top:77px}.trusted span{padding:0 9px}.abstract-art{position:relative;height:100%;min-height:440px;display:grid;place-items:center}.abstract-art img{max-height:510px;object-fit:contain;filter:drop-shadow(0 25px 30px #33376620)}.orb{position:absolute;border-radius:50%;filter:drop-shadow(18px 15px 25px #5b69b125)}.orb-main{width:350px;height:350px;background:radial-gradient(circle at 30% 25%,#d9ddff,#8493e4 40%,#3d539e 70%,#1c3079);transform:rotate(-20deg)}.orb-inner{width:250px;height:250px;background:radial-gradient(circle at 30% 35%,#fff9,#a1aff366 38%,#5c68aa9c 65%);border:1px solid #ffffffc4;transform:translate(80px,60px)}.orb-small{width:93px;height:93px;background:linear-gradient(125deg,#c59fff,#6851a6);transform:translate(-155px,-155px)}.art-caption{position:relative;z-index:3;color:#fff;font-size:15px;line-height:1.4;letter-spacing:3px;text-align:center;font-weight:800;transform:translate(5px,20px)}.inner-hero{padding:85px 0;background:#f0f2ff}.inner-hero h1{font-size:clamp(40px,6vw,70px);letter-spacing:-2px;line-height:1.1;margin:20px 0}.inner-hero p{color:#69748c}.content{padding:60px 0 100px}.nudge{color:#6b6c95;font-size:10px;letter-spacing:2px;font-weight:750}.nudge span{color:#7b58d0;margin-right:7px}.section-header{margin:62px 0 25px;display:flex;justify-content:space-between;align-items:end}.section-header h2{font-size:40px;letter-spacing:-1.5px;margin:7px 0}.section-header>span{font-size:12px;color:#858eaa}.kicker{font-size:11px;color:#685dba;letter-spacing:2px}.tiles{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}.tile{border:1px solid #eceef8;border-radius:15px;overflow:hidden;transition:box-shadow .2s,transform .2s}.tile:hover{box-shadow:0 18px 32px #323c7c18;transform:translateY(-4px)}.tile-image{height:195px;background:linear-gradient(130deg,#cbd3f5,#929de0);display:grid;place-items:center}.tile-image img{width:100%;height:100%;object-fit:contain}.tile-image>span{font-size:85px;color:#ffffffa8}.tile-info{padding:25px}.tile-info>span{font-size:10px;color:#7d6eba;letter-spacing:1.5px}.tile-info h3{font-size:23px;margin:9px 0}.tile-info p{font-size:13px;color:#7c859b;min-height:40px}.tile-info b{font-size:12px;color:#4e51a3}.rich-content{margin:30px 0}.section{padding:40px 0}.feature-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:15px}.feature{padding:27px;background:#f5f6fd;border-radius:10px}.feature-mark{color:#6e68c7}.stat strong{display:block;font-size:38px}.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:20px}.cta{padding:50px;background:#252d73;color:white;border-radius:18px}.cta p{color:#c2c6ec}.big-cta{background:#293788;color:white;border-radius:20px;padding:60px;margin-top:90px;position:relative;overflow:hidden}.big-cta:after{content:'✦';position:absolute;right:-15px;top:-110px;font-size:410px;opacity:.10}.big-cta span{font-size:10px;letter-spacing:2px}.big-cta h2{font-size:45px;line-height:1.2;letter-spacing:-2px}.big-cta a{display:inline-block;background:white;color:#313e9a;padding:14px 20px;border-radius:9px;font-size:12px;font-weight:800}.detail-image{text-align:center;margin:30px 0}.detail-image img{max-height:520px}footer{background:#151c3c;color:white;padding:70px 0 30px}.footer-upper{display:flex;align-items:center;justify-content:space-between}.footer-upper h2{font-size:30px}.footer-upper p{color:#a6acce}.footer-line{border-top:1px solid #424866;padding-top:28px;margin-top:60px;display:flex;justify-content:space-between;color:#a7aed4;font-size:10px;letter-spacing:1.4px}@media(max-width:900px){.header{height:auto;padding:20px 0;flex-wrap:wrap}.header nav{order:3;width:100%}.hero-grid{grid-template-columns:1fr}.abstract-art{min-height:340px}.trusted{margin-top:40px}.tiles{grid-template-columns:repeat(2,1fr)}}@media(max-width:560px){.tiles,.feature-grid,.stats{grid-template-columns:1fr}.hero h1{font-size:54px}.footer-upper,.footer-line,.section-header{align-items:start;flex-direction:column}.announcement{padding:0 8px;font-size:8px}.big-cta h2{font-size:34px}} + +/* V8.29 baseline: accessible touch/focus and reduced motion */ +:where(a,button,input,select,textarea):focus-visible{outline:3px solid currentColor;outline-offset:3px}@media(max-width:560px){img{max-width:100%;height:auto}body{overflow-wrap:anywhere}}@media(prefers-reduced-motion:reduce){*,*:before,*:after{scroll-behavior:auto!important;transition:none!important;animation-duration:.01ms!important}} diff --git a/examples/v830-built-sites/corporate/assets/visual/hero.svg b/examples/v830-built-sites/corporate/assets/visual/hero.svg new file mode 100644 index 0000000..f89e148 --- /dev/null +++ b/examples/v830-built-sites/corporate/assets/visual/hero.svg @@ -0,0 +1 @@ +IDEAS / PROGRESS diff --git a/examples/v830-built-sites/corporate/brand/index.html b/examples/v830-built-sites/corporate/brand/index.html new file mode 100644 index 0000000..7360c9b --- /dev/null +++ b/examples/v830-built-sites/corporate/brand/index.html @@ -0,0 +1,41 @@ +品牌展示跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    +
    SOLUTIONS & WORK / INDEX

    品牌展示

    Explore our brand

    BROWSE / EXPLORE03本页展示内容
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/brands/arc/index.html b/examples/v830-built-sites/corporate/brands/arc/index.html new file mode 100644 index 0000000..ebe6bf2 --- /dev/null +++ b/examples/v830-built-sites/corporate/brands/arc/index.html @@ -0,0 +1,38 @@ +ARC跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    BRAND PROFILE / PARTNERS

    ARC

    ARC 品牌产品与应用。

    +
    ARBRAND
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/brands/index.html b/examples/v830-built-sites/corporate/brands/index.html new file mode 100644 index 0000000..2a0f89a --- /dev/null +++ b/examples/v830-built-sites/corporate/brands/index.html @@ -0,0 +1,41 @@ +品牌中心跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    +
    SOLUTIONS & WORK / INDEX

    品牌中心

    探索与产品相关的品牌。

    BROWSE / EXPLORE03本页展示内容
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/brands/mono/index.html b/examples/v830-built-sites/corporate/brands/mono/index.html new file mode 100644 index 0000000..e0d913f --- /dev/null +++ b/examples/v830-built-sites/corporate/brands/mono/index.html @@ -0,0 +1,30 @@ +MONO跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    BRAND PROFILE / PARTNERS

    MONO

    MONO 品牌产品与应用。

    +
    MOBRAND
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/brands/nova/index.html b/examples/v830-built-sites/corporate/brands/nova/index.html new file mode 100644 index 0000000..52bdbca --- /dev/null +++ b/examples/v830-built-sites/corporate/brands/nova/index.html @@ -0,0 +1,38 @@ +NOVA跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    BRAND PROFILE / PARTNERS

    NOVA

    NOVA 品牌产品与应用。

    +
    NOBRAND
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/case/index.html b/examples/v830-built-sites/corporate/case/index.html new file mode 100644 index 0000000..ebd08b1 --- /dev/null +++ b/examples/v830-built-sites/corporate/case/index.html @@ -0,0 +1,41 @@ +案例展示跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/cases/1/index.html b/examples/v830-built-sites/corporate/cases/1/index.html new file mode 100644 index 0000000..0269836 --- /dev/null +++ b/examples/v830-built-sites/corporate/cases/1/index.html @@ -0,0 +1,12 @@ +精选项目 · 01跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    SELECTED WORK / PROJECT

    精选项目 · 01

    展示项目背景、过程与成果。

    项目地点
    Demo location
    所属行业
    Demo industry

    本页仅为项目结构示例,并非实际完成的工程项目。

    浏览更多案例 →
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/cases/2/index.html b/examples/v830-built-sites/corporate/cases/2/index.html new file mode 100644 index 0000000..b016bbc --- /dev/null +++ b/examples/v830-built-sites/corporate/cases/2/index.html @@ -0,0 +1,12 @@ +精选项目 · 02跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    SELECTED WORK / PROJECT

    精选项目 · 02

    展示项目背景、过程与成果。

    项目地点
    Demo location
    所属行业
    Demo industry

    本页仅为项目结构示例,并非实际完成的工程项目。

    浏览更多案例 →
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/cases/3/index.html b/examples/v830-built-sites/corporate/cases/3/index.html new file mode 100644 index 0000000..5a8e39f --- /dev/null +++ b/examples/v830-built-sites/corporate/cases/3/index.html @@ -0,0 +1,12 @@ +精选项目 · 03跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    SELECTED WORK / PROJECT

    精选项目 · 03

    展示项目背景、过程与成果。

    项目地点
    Demo location
    所属行业
    Demo industry

    本页仅为项目结构示例,并非实际完成的工程项目。

    浏览更多案例 →
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/cases/index.html b/examples/v830-built-sites/corporate/cases/index.html new file mode 100644 index 0000000..acb5ade --- /dev/null +++ b/examples/v830-built-sites/corporate/cases/index.html @@ -0,0 +1,41 @@ +项目案例跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/categories/term-79e34764f8ce/index.html b/examples/v830-built-sites/corporate/categories/term-79e34764f8ce/index.html new file mode 100644 index 0000000..b718b62 --- /dev/null +++ b/examples/v830-built-sites/corporate/categories/term-79e34764f8ce/index.html @@ -0,0 +1,29 @@ +旗舰系列跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    DISCOVER / CATEGORY

    旗舰系列

    分类产品与相关信息

    首页/旗舰系列
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/categories/term-8d6647722ef3/index.html b/examples/v830-built-sites/corporate/categories/term-8d6647722ef3/index.html new file mode 100644 index 0000000..a380ca0 --- /dev/null +++ b/examples/v830-built-sites/corporate/categories/term-8d6647722ef3/index.html @@ -0,0 +1,29 @@ +专业系列跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    DISCOVER / CATEGORY

    专业系列

    分类产品与相关信息

    首页/专业系列
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/categories/term-95acf900fafc/index.html b/examples/v830-built-sites/corporate/categories/term-95acf900fafc/index.html new file mode 100644 index 0000000..1369200 --- /dev/null +++ b/examples/v830-built-sites/corporate/categories/term-95acf900fafc/index.html @@ -0,0 +1,29 @@ +畅销系列跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    DISCOVER / CATEGORY

    畅销系列

    分类产品与相关信息

    首页/畅销系列
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/categories/term-a68a8656a4dc/index.html b/examples/v830-built-sites/corporate/categories/term-a68a8656a4dc/index.html new file mode 100644 index 0000000..5b57ecc --- /dev/null +++ b/examples/v830-built-sites/corporate/categories/term-a68a8656a4dc/index.html @@ -0,0 +1,29 @@ +定制系列跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    DISCOVER / CATEGORY

    定制系列

    分类产品与相关信息

    首页/定制系列
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/commercial-readiness.json b/examples/v830-built-sites/corporate/commercial-readiness.json new file mode 100644 index 0000000..bc941c0 --- /dev/null +++ b/examples/v830-built-sites/corporate/commercial-readiness.json @@ -0,0 +1,34 @@ +{ + "ready_for_review": true, + "commercially_certified": false, + "blockers": [], + "warnings": [ + { + "code": "brand_logo", + "message": "尚未替换成企业正式 Logo" + }, + { + "code": "placeholder_images", + "count": 73, + "message": "部分页面仍使用示意图,正式发布前请替换为真实且有使用权的图片" + }, + { + "code": "demo_content", + "message": "检测到演示或默认文案,正式发布前请逐页核对" + }, + { + "code": "form_not_configured", + "message": "尚未配置 HTTPS 询盘接收服务;目前仅提供邮件联系" + }, + { + "code": "legal_pages", + "message": "请根据目标国家/地区法律审查是否需要隐私政策与 Cookie 声明" + } + ], + "metrics": { + "html_pages": 38, + "artwork_fallbacks": 73, + "pages_with_body": 18 + }, + "note": "仅为本地结构化交付清单,不等于合法合规、内容准确、无障碍、性能或生产上线认证" +} \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/contact/index.html b/examples/v830-built-sites/corporate/contact/index.html new file mode 100644 index 0000000..8e44a42 --- /dev/null +++ b/examples/v830-built-sites/corporate/contact/index.html @@ -0,0 +1,16 @@ +联系我们跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    CONNECT / CONTACT

    联系我们

    欢迎通过邮件与我们的演示团队取得联系。

    +
    LET'S START A CONVERSATION

    建立联系

    本页为演示内容。您可以在网站工厂中直接修改和替换。

    + + +
    HOW TO REACH US

    您可以通过本页提供的联系渠道咨询产品、项目或合作事项。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/faq/index.html b/examples/v830-built-sites/corporate/faq/index.html new file mode 100644 index 0000000..c6730eb --- /dev/null +++ b/examples/v830-built-sites/corporate/faq/index.html @@ -0,0 +1,13 @@ +常见问题跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    EXPLORE

    常见问题

    更多问题可以联系我们。

    +
    ABOUT / DISCOVER

    常见问题

    本页为演示内容。您可以在网站工厂中直接修改和替换。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/index.html b/examples/v830-built-sites/corporate/index.html new file mode 100644 index 0000000..e6e860d --- /dev/null +++ b/examples/v830-built-sites/corporate/index.html @@ -0,0 +1,73 @@ +首页跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    STRATEGY · PARTNERSHIP · DELIVERY

    NORTHLINE GROUP IDEAS INTO IMPACT.

    以专业的服务连接企业与未来

    BRINGING
    IDEAS TO LIFE
    + +
    ABOUT THE COMPANY

    以专业连接价值,以合作创造可能。

    以专业的服务连接企业与未来

    了解我们 ↗
    +
    + +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/news/1/index.html b/examples/v830-built-sites/corporate/news/1/index.html new file mode 100644 index 0000000..47be80e --- /dev/null +++ b/examples/v830-built-sites/corporate/news/1/index.html @@ -0,0 +1,13 @@ +企业动态 · 01跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    IDEAS / JOURNAL

    企业动态 · 01

    在这里发布新闻资讯与品牌动态。

    +

    这是可替换的新闻正文内容,可包含图片、表格和链接。

    ← 返回新闻
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/news/2/index.html b/examples/v830-built-sites/corporate/news/2/index.html new file mode 100644 index 0000000..43172de --- /dev/null +++ b/examples/v830-built-sites/corporate/news/2/index.html @@ -0,0 +1,13 @@ +企业动态 · 02跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    IDEAS / JOURNAL

    企业动态 · 02

    在这里发布新闻资讯与品牌动态。

    +

    这是可替换的新闻正文内容,可包含图片、表格和链接。

    ← 返回新闻
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/news/3/index.html b/examples/v830-built-sites/corporate/news/3/index.html new file mode 100644 index 0000000..05b0099 --- /dev/null +++ b/examples/v830-built-sites/corporate/news/3/index.html @@ -0,0 +1,13 @@ +企业动态 · 03跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    IDEAS / JOURNAL

    企业动态 · 03

    在这里发布新闻资讯与品牌动态。

    +

    这是可替换的新闻正文内容,可包含图片、表格和链接。

    ← 返回新闻
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/news/index.html b/examples/v830-built-sites/corporate/news/index.html new file mode 100644 index 0000000..b881a55 --- /dev/null +++ b/examples/v830-built-sites/corporate/news/index.html @@ -0,0 +1,41 @@ +新闻资讯跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/nginx-snippet.conf b/examples/v830-built-sites/corporate/nginx-snippet.conf new file mode 100644 index 0000000..5156189 --- /dev/null +++ b/examples/v830-built-sites/corporate/nginx-snippet.conf @@ -0,0 +1,4 @@ +# SiteForge 生成:将本文件内容合并到 Nginx server {} 内 +index index.html; +error_page 404 /404.html; +location / { try_files $uri $uri/ =404; } diff --git a/examples/v830-built-sites/corporate/post/index.html b/examples/v830-built-sites/corporate/post/index.html new file mode 100644 index 0000000..e50974b --- /dev/null +++ b/examples/v830-built-sites/corporate/post/index.html @@ -0,0 +1,41 @@ +新闻展示跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/product/index.html b/examples/v830-built-sites/corporate/product/index.html new file mode 100644 index 0000000..816f883 --- /dev/null +++ b/examples/v830-built-sites/corporate/product/index.html @@ -0,0 +1,81 @@ +产品展示跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/products/1/index.html b/examples/v830-built-sites/corporate/products/1/index.html new file mode 100644 index 0000000..455d6fe --- /dev/null +++ b/examples/v830-built-sites/corporate/products/1/index.html @@ -0,0 +1,17 @@ +Services Alpha跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    +
    SOLUTIONS & WORK / DETAILS

    Services Alpha

    Services Alpha — 针对多样应用的演示产品。

    NOVA旗舰系列
    咨询相关信息 ↗
    +
    +
    SePRODUCT
    +
    +
    OVERVIEW / 项目与产品介绍

    项目与产品介绍

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/products/2/index.html b/examples/v830-built-sites/corporate/products/2/index.html new file mode 100644 index 0000000..8b98e7a --- /dev/null +++ b/examples/v830-built-sites/corporate/products/2/index.html @@ -0,0 +1,17 @@ +Services Beta跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    +
    SOLUTIONS & WORK / DETAILS

    Services Beta

    Services Beta — 针对多样应用的演示产品。

    NOVA旗舰系列
    咨询相关信息 ↗
    +
    +
    SePRODUCT
    +
    +
    OVERVIEW / 项目与产品介绍

    项目与产品介绍

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/products/3/index.html b/examples/v830-built-sites/corporate/products/3/index.html new file mode 100644 index 0000000..2d1eb4f --- /dev/null +++ b/examples/v830-built-sites/corporate/products/3/index.html @@ -0,0 +1,17 @@ +Services Gamma跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    +
    SOLUTIONS & WORK / DETAILS

    Services Gamma

    Services Gamma — 针对多样应用的演示产品。

    ARC畅销系列
    咨询相关信息 ↗
    +
    +
    SePRODUCT
    +
    +
    OVERVIEW / 项目与产品介绍

    项目与产品介绍

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/products/4/index.html b/examples/v830-built-sites/corporate/products/4/index.html new file mode 100644 index 0000000..3d8429d --- /dev/null +++ b/examples/v830-built-sites/corporate/products/4/index.html @@ -0,0 +1,17 @@ +Services Delta跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    +
    SOLUTIONS & WORK / DETAILS

    Services Delta

    Services Delta — 针对多样应用的演示产品。

    ARC畅销系列
    咨询相关信息 ↗
    +
    +
    SePRODUCT
    +
    +
    OVERVIEW / 项目与产品介绍

    项目与产品介绍

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/products/5/index.html b/examples/v830-built-sites/corporate/products/5/index.html new file mode 100644 index 0000000..ec4ed64 --- /dev/null +++ b/examples/v830-built-sites/corporate/products/5/index.html @@ -0,0 +1,17 @@ +Services Epsilon跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    +
    SOLUTIONS & WORK / DETAILS

    Services Epsilon

    Services Epsilon — 针对多样应用的演示产品。

    MONO定制系列
    咨询相关信息 ↗
    +
    +
    SePRODUCT
    +
    +
    OVERVIEW / 项目与产品介绍

    项目与产品介绍

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/products/6/index.html b/examples/v830-built-sites/corporate/products/6/index.html new file mode 100644 index 0000000..f27ad4e --- /dev/null +++ b/examples/v830-built-sites/corporate/products/6/index.html @@ -0,0 +1,17 @@ +Services Zeta跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    +
    SOLUTIONS & WORK / DETAILS

    Services Zeta

    Services Zeta — 针对多样应用的演示产品。

    MONO定制系列
    咨询相关信息 ↗
    +
    +
    SePRODUCT
    +
    +
    OVERVIEW / 项目与产品介绍

    项目与产品介绍

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/products/7/index.html b/examples/v830-built-sites/corporate/products/7/index.html new file mode 100644 index 0000000..d583d1a --- /dev/null +++ b/examples/v830-built-sites/corporate/products/7/index.html @@ -0,0 +1,17 @@ +Services Eta跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    +
    SOLUTIONS & WORK / DETAILS

    Services Eta

    Services Eta — 针对多样应用的演示产品。

    NOVA专业系列
    咨询相关信息 ↗
    +
    +
    SePRODUCT
    +
    +
    OVERVIEW / 项目与产品介绍

    项目与产品介绍

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/products/8/index.html b/examples/v830-built-sites/corporate/products/8/index.html new file mode 100644 index 0000000..90c32d3 --- /dev/null +++ b/examples/v830-built-sites/corporate/products/8/index.html @@ -0,0 +1,17 @@ +Services Theta跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    +
    SOLUTIONS & WORK / DETAILS

    Services Theta

    Services Theta — 针对多样应用的演示产品。

    ARC专业系列
    咨询相关信息 ↗
    +
    +
    SePRODUCT
    +
    +
    OVERVIEW / 项目与产品介绍

    项目与产品介绍

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/products/index.html b/examples/v830-built-sites/corporate/products/index.html new file mode 100644 index 0000000..33a7249 --- /dev/null +++ b/examples/v830-built-sites/corporate/products/index.html @@ -0,0 +1,81 @@ +产品中心跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/robots.txt b/examples/v830-built-sites/corporate/robots.txt new file mode 100644 index 0000000..7f56dd2 --- /dev/null +++ b/examples/v830-built-sites/corporate/robots.txt @@ -0,0 +1,3 @@ +User-agent: * +Allow: / +Sitemap: https://corporate.example.test/sitemap.xml diff --git a/examples/v830-built-sites/corporate/search-index.json b/examples/v830-built-sites/corporate/search-index.json new file mode 100644 index 0000000..42b3469 --- /dev/null +++ b/examples/v830-built-sites/corporate/search-index.json @@ -0,0 +1 @@ +[{"title": "ARC", "url": "/brands/arc/", "summary": "ARC 品牌产品与应用。", "type": "brand", "brand": ""}, {"title": "MONO", "url": "/brands/mono/", "summary": "MONO 品牌产品与应用。", "type": "brand", "brand": ""}, {"title": "NOVA", "url": "/brands/nova/", "summary": "NOVA 品牌产品与应用。", "type": "brand", "brand": ""}, {"title": "精选项目 · 01", "url": "/cases/1/", "summary": "展示项目背景、过程与成果。", "type": "case", "brand": ""}, {"title": "精选项目 · 02", "url": "/cases/2/", "summary": "展示项目背景、过程与成果。", "type": "case", "brand": ""}, {"title": "精选项目 · 03", "url": "/cases/3/", "summary": "展示项目背景、过程与成果。", "type": "case", "brand": ""}, {"title": "产品中心", "url": "/products/", "summary": "查看系列、类别及产品资料。", "type": "page", "brand": ""}, {"title": "关于我们", "url": "/about/", "summary": "企业介绍、发展理念、合作能力与团队故事。", "type": "page", "brand": ""}, {"title": "品牌中心", "url": "/brands/", "summary": "探索与产品相关的品牌。", "type": "page", "brand": ""}, {"title": "常见问题", "url": "/faq/", "summary": "更多问题可以联系我们。", "type": "page", "brand": ""}, {"title": "新闻资讯", "url": "/news/", "summary": "了解最新消息与团队动态。", "type": "page", "brand": ""}, {"title": "服务与解决方案", "url": "/services/", "summary": "从咨询到交付的全链路服务。", "type": "page", "brand": ""}, {"title": "联系我们", "url": "/contact/", "summary": "欢迎通过邮件与我们的演示团队取得联系。", "type": "page", "brand": ""}, {"title": "项目案例", "url": "/cases/", "summary": "精选项目展示。", "type": "page", "brand": ""}, {"title": "企业动态 · 01", "url": "/news/1/", "summary": "在这里发布新闻资讯与品牌动态。", "type": "post", "brand": ""}, {"title": "企业动态 · 02", "url": "/news/2/", "summary": "在这里发布新闻资讯与品牌动态。", "type": "post", "brand": ""}, {"title": "企业动态 · 03", "url": "/news/3/", "summary": "在这里发布新闻资讯与品牌动态。", "type": "post", "brand": ""}, {"title": "Services Alpha", "url": "/products/1/", "summary": "Services Alpha — 针对多样应用的演示产品。", "type": "product", "brand": "NOVA"}, {"title": "Services Beta", "url": "/products/2/", "summary": "Services Beta — 针对多样应用的演示产品。", "type": "product", "brand": "NOVA"}, {"title": "Services Delta", "url": "/products/4/", "summary": "Services Delta — 针对多样应用的演示产品。", "type": "product", "brand": "ARC"}, {"title": "Services Epsilon", "url": "/products/5/", "summary": "Services Epsilon — 针对多样应用的演示产品。", "type": "product", "brand": "MONO"}, {"title": "Services Eta", "url": "/products/7/", "summary": "Services Eta — 针对多样应用的演示产品。", "type": "product", "brand": "NOVA"}, {"title": "Services Gamma", "url": "/products/3/", "summary": "Services Gamma — 针对多样应用的演示产品。", "type": "product", "brand": "ARC"}, {"title": "Services Theta", "url": "/products/8/", "summary": "Services Theta — 针对多样应用的演示产品。", "type": "product", "brand": "ARC"}, {"title": "Services Zeta", "url": "/products/6/", "summary": "Services Zeta — 针对多样应用的演示产品。", "type": "product", "brand": "MONO"}, {"title": "供应与交付方案", "url": "/services/solution/", "summary": "灵活、可配置的供应交付服务。", "type": "service", "brand": ""}] \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/search/index.html b/examples/v830-built-sites/corporate/search/index.html new file mode 100644 index 0000000..6ad6911 --- /dev/null +++ b/examples/v830-built-sites/corporate/search/index.html @@ -0,0 +1,13 @@ +站内搜索跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    SEARCH / CONTENT

    站内搜索

    搜索本网站的产品、品牌、新闻和案例。

    +
    + +
    + +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/service/index.html b/examples/v830-built-sites/corporate/service/index.html new file mode 100644 index 0000000..b6e1a11 --- /dev/null +++ b/examples/v830-built-sites/corporate/service/index.html @@ -0,0 +1,25 @@ +服务展示跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    +
    SOLUTIONS & WORK / INDEX

    服务展示

    Explore our service

    BROWSE / EXPLORE01本页展示内容
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/services/index.html b/examples/v830-built-sites/corporate/services/index.html new file mode 100644 index 0000000..ae7facf --- /dev/null +++ b/examples/v830-built-sites/corporate/services/index.html @@ -0,0 +1,13 @@ +服务与解决方案跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    EXPLORE

    服务与解决方案

    从咨询到交付的全链路服务。

    +
    ABOUT / DISCOVER

    服务与解决方案

    本页为演示内容。您可以在网站工厂中直接修改和替换。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/services/solution/index.html b/examples/v830-built-sites/corporate/services/solution/index.html new file mode 100644 index 0000000..9a13afe --- /dev/null +++ b/examples/v830-built-sites/corporate/services/solution/index.html @@ -0,0 +1,13 @@ +供应与交付方案跳转至正文 + +
    IDEAS INTO IMPACTBUSINESS / PEOPLE / PROGRESS
    +
    +
    EXPLORE

    供应与交付方案

    灵活、可配置的供应交付服务。

    +
    ABOUT / DISCOVER

    供应与交付方案

    灵活、可配置的供应交付服务。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    以专业的服务连接企业与未来

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/siteforge-report.json b/examples/v830-built-sites/corporate/siteforge-report.json new file mode 100644 index 0000000..d081898 --- /dev/null +++ b/examples/v830-built-sites/corporate/siteforge-report.json @@ -0,0 +1,27 @@ +{ + "site": "NORTHLINE GROUP", + "locale": "zh-CN", + "alternate_pages": 0, + "version": "b61fd00880d7", + "pages": 36, + "theme": "corporate", + "theme_version": "1.3.0", + "warnings": [], + "errors": [], + "external_assets": [], + "missing_local_images": [], + "broken_links": [], + "legacy_links": [], + "canonical_mismatches": [], + "slashless_routes": [], + "redirects": 0, + "mirrored_images": 0, + "quality_status": "passed", + "blueprint_blocks": 0, + "commercial_readiness": { + "ready_for_review": true, + "commercially_certified": false, + "blockers": 0, + "warnings": 5 + } +} \ No newline at end of file diff --git a/examples/v830-built-sites/corporate/sitemap.xml b/examples/v830-built-sites/corporate/sitemap.xml new file mode 100644 index 0000000..c2572f5 --- /dev/null +++ b/examples/v830-built-sites/corporate/sitemap.xml @@ -0,0 +1,37 @@ + +https://corporate.example.test/ +https://corporate.example.test/about/ +https://corporate.example.test/brand/ +https://corporate.example.test/brands/ +https://corporate.example.test/brands/arc/ +https://corporate.example.test/brands/mono/ +https://corporate.example.test/brands/nova/ +https://corporate.example.test/case/ +https://corporate.example.test/cases/ +https://corporate.example.test/cases/1/ +https://corporate.example.test/cases/2/ +https://corporate.example.test/cases/3/ +https://corporate.example.test/categories/term-79e34764f8ce/ +https://corporate.example.test/categories/term-8d6647722ef3/ +https://corporate.example.test/categories/term-95acf900fafc/ +https://corporate.example.test/categories/term-a68a8656a4dc/ +https://corporate.example.test/contact/ +https://corporate.example.test/faq/ +https://corporate.example.test/news/ +https://corporate.example.test/news/1/ +https://corporate.example.test/news/2/ +https://corporate.example.test/news/3/ +https://corporate.example.test/post/ +https://corporate.example.test/product/ +https://corporate.example.test/products/ +https://corporate.example.test/products/1/ +https://corporate.example.test/products/2/ +https://corporate.example.test/products/3/ +https://corporate.example.test/products/4/ +https://corporate.example.test/products/5/ +https://corporate.example.test/products/6/ +https://corporate.example.test/products/7/ +https://corporate.example.test/products/8/ +https://corporate.example.test/service/ +https://corporate.example.test/services/ +https://corporate.example.test/services/solution/ \ No newline at end of file diff --git a/examples/v830-built-sites/index.html b/examples/v830-built-sites/index.html new file mode 100644 index 0000000..4ea8d67 --- /dev/null +++ b/examples/v830-built-sites/index.html @@ -0,0 +1,2 @@ +SiteForge V8.30 · 四套专业主题 × 六类真实页面
    SITEFORGE / THEME LAB / V8.30

    四套主题 · 六类真实页面布局

    不是静态效果图:下方页面来自原项目静态构建,含真实菜单、列表、详情与文章结构。

    提示:演示中的公司、车型及资料均为虚构数据;正式网站使用自己的真实内容。可切换主题、页面和设备宽度观察布局差异。

    所有内容是本地静态演示,不调用后台接口。返回上一级阅读 升级说明,也可直接打开四套主题目录中的页面。
    \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/.htaccess b/examples/v830-built-sites/industrial/.htaccess new file mode 100644 index 0000000..1d4fcb4 --- /dev/null +++ b/examples/v830-built-sites/industrial/.htaccess @@ -0,0 +1,2 @@ +Options -MultiViews +RewriteEngine On diff --git a/examples/v830-built-sites/industrial/404.html b/examples/v830-built-sites/industrial/404.html new file mode 100644 index 0000000..6683da3 --- /dev/null +++ b/examples/v830-built-sites/industrial/404.html @@ -0,0 +1,12 @@ +404 · 页面不存在跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    ERROR / 404

    404

    抱歉,你访问的页面不存在,或者已被移动。

    返回首页 ↗
    + +
    + +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/about/index.html b/examples/v830-built-sites/industrial/about/index.html new file mode 100644 index 0000000..21aad53 --- /dev/null +++ b/examples/v830-built-sites/industrial/about/index.html @@ -0,0 +1,47 @@ +关于我们跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/assets/blocks.css b/examples/v830-built-sites/industrial/assets/blocks.css new file mode 100644 index 0000000..9ce1279 --- /dev/null +++ b/examples/v830-built-sites/industrial/assets/blocks.css @@ -0,0 +1,29 @@ +/* Portable SiteForge blocks, loaded with every theme (all styles scoped to sf-). */ +.sf-section{background:var(--sf-bg,transparent);color:var(--sf-fg,inherit);padding:var(--sf-pad,82px) 0;margin:0}.sf-section:nth-of-type(even){background:var(--sf-bg,#f4f6f9)}.sf-container{max-width:1200px;margin:auto;padding:0 32px}.sf-section h1,.sf-section h2,.sf-section h3,.sf-section p{color:inherit;line-height:1.3}.sf-section h1{font-size:clamp(38px,5vw,76px);font-weight:790;letter-spacing:-.052em}.sf-section h2{font-size:clamp(27px,3.2vw,44px);font-weight:760;letter-spacing:-.037em}.sf-kicker{display:block;font-size:12px;letter-spacing:.17em;text-transform:uppercase;font-weight:740;color:var(--accent,#3569d3);margin-bottom:18px}.sf-hero-grid,.sf-image-text{display:grid;grid-template-columns:1.08fr .92fr;gap:68px;align-items:center}.sf-hero-copy p{font-size:18px;line-height:1.75;max-width:520px;opacity:.75}.sf-hero-img,.sf-image-side{overflow:hidden;border-radius:9px;min-height:380px;background:linear-gradient(130deg,#d5e1ee,#eef3f9);display:grid;place-items:center}.sf-hero-img img,.sf-image-side img{width:100%;height:100%;max-height:580px;object-fit:cover}.sf-hero-abstract{font-size:110px;color:#a7bdd4}.sf-button{display:inline-flex;align-items:center;justify-content:center;gap:28px;background:var(--accent,#315ee2);color:white!important;padding:16px 26px;border-radius:6px;font-size:14px;text-decoration:none;font-weight:720;margin-top:24px}.sf-section-head{display:flex;align-items:end;justify-content:space-between;margin-bottom:32px;gap:24px}.sf-section-head h2{margin:0}.sf-section-head>a,.sf-link{color:var(--accent,#3569d3);font-weight:700;text-decoration:none}.sf-prose{font-size:16px;line-height:1.85;max-width:930px}.sf-prose p{line-height:1.85}.sf-features,.sf-collection,.sf-stats{display:grid;gap:20px}.sf-features{grid-template-columns:repeat(3,minmax(0,1fr))}.sf-feature{border:1px solid #e0e6eb;padding:32px 28px;border-radius:8px;background:#fff;color:#253247}.sf-feature>span{font-size:12px;font-weight:800;color:var(--accent,#346add)}.sf-feature h3{font-size:22px;margin:30px 0 8px}.sf-feature p{font-size:14px;line-height:1.7;color:#647181}.sf-stats{grid-template-columns:repeat(4,1fr);padding:40px 0;border-top:1px solid #b7c0cd66;border-bottom:1px solid #b7c0cd66}.sf-stats>div{display:flex;flex-direction:column;gap:8px}.sf-stats strong{font-size:clamp(28px,4vw,53px);letter-spacing:-.04em}.sf-stats span{font-size:12px;opacity:.65;letter-spacing:.04em}.sf-collection{grid-template-columns:repeat(var(--sf-cols,3),minmax(0,1fr))}.sf-item{display:block;text-decoration:none;color:#233044;background:#fff;border:1px solid #e8edf1;border-radius:8px;overflow:hidden;transition:transform .2s,box-shadow .2s}.sf-item:hover{transform:translateY(-4px);box-shadow:0 18px 38px #344d7018}.sf-item-img{height:210px;overflow:hidden;background:#e4eaf0}.sf-item-img img{height:100%;width:100%;object-fit:cover}.sf-placeholder{display:grid;place-items:center;width:100%;height:100%;min-height:190px;background:linear-gradient(130deg,#e2eaf2,#c9d7e6);font-size:72px;color:#8399b2;font-weight:800}.sf-large{min-height:360px}.sf-item-copy{padding:25px}.sf-item-copy small{text-transform:uppercase;letter-spacing:.13em;color:var(--accent,#376edc)}.sf-item-copy h3{font-size:22px;margin:12px 0 7px}.sf-item-copy p{font-size:14px;line-height:1.6;color:#7a8796;min-height:42px}.sf-item-copy span{font-size:12px;color:var(--accent,#376edc);font-weight:800}.sf-image-text>div>p{font-size:17px;line-height:1.8;max-width:520px;opacity:.7}.sf-reverse>div:first-child{order:2}.sf-gallery{display:grid;grid-template-columns:repeat(3,1fr);gap:15px}.sf-gallery img{width:100%;height:230px;object-fit:cover;border-radius:6px}.sf-faq{max-width:920px}.sf-faq details{border-bottom:1px solid #dce3eb;padding:22px 0}.sf-faq summary{font-size:17px;cursor:pointer;font-weight:700}.sf-faq p{color:#647181;line-height:1.75}.sf-cta-wrap{display:flex;justify-content:space-between;align-items:center;gap:24px}.sf-cta-wrap h2{margin:0}.sf-cta-wrap p{font-size:16px;opacity:.75}.sf-section a{cursor:pointer}.sf-muted{opacity:.65} +@media(max-width:820px){.sf-container{padding:0 20px}.sf-section{padding:50px 0}.sf-hero-grid,.sf-image-text{grid-template-columns:1fr;gap:26px}.sf-reverse>div:first-child{order:initial}.sf-hero-img,.sf-image-side{min-height:250px}.sf-features,.sf-collection{grid-template-columns:repeat(2,minmax(0,1fr))}.sf-stats{grid-template-columns:repeat(2,1fr)}.sf-cta-wrap{align-items:flex-start;flex-direction:column}} +@media(max-width:540px){.sf-features,.sf-collection,.sf-gallery{grid-template-columns:1fr}.sf-section-head{display:block}.sf-section-head>a{display:block;margin-top:13px}.sf-item-img{height:220px}.sf-hero-grid{gap:22px}.sf-hero-copy p{font-size:16px}.sf-stats{gap:28px}} + +.sf-attributes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 32px;border-top:1px solid #e5eaf0}.sf-attribute{display:flex;justify-content:space-between;align-items:center;gap:18px;border-bottom:1px solid #e5eaf0;padding:19px 10px;font-size:14px}.sf-attribute span{color:#748497}.sf-attribute strong{font-weight:720;text-align:right}@media(max-width:640px){.sf-attributes{grid-template-columns:1fr}} + +/* SiteForge responsive no-code grid container */ +.sf-layout-grid{display:grid;grid-template-columns:var(--sf-layout-cols,1fr 1fr);gap:var(--sf-layout-gap,24px);align-items:stretch} +.sf-layout-column{min-width:0}.sf-layout-column>.sf-section{padding:0;margin:0 0 18px}.sf-layout-column .sf-container{width:100%;padding:0} +.sf-layout-column>.sf-section:last-child{margin-bottom:0} +@media(max-width:820px){.sf-layout-grid{grid-template-columns:repeat(2,minmax(0,1fr))!important}} +@media(max-width:540px){.sf-layout-grid{grid-template-columns:minmax(0,1fr)!important}} + +/* V8.6: accessible, script-free commercial design blocks */ +.sf-slides{display:flex;gap:18px;overflow-x:auto;scroll-snap-type:x mandatory;padding:6px 0 18px;scrollbar-width:thin} +.sf-slide{flex:0 0 min(78%,720px);min-width:220px;margin:0;scroll-snap-align:start} +.sf-slide img{width:100%;aspect-ratio:16/9;object-fit:cover;border-radius:10px} +.sf-slide figcaption{padding:10px 2px;opacity:.7;font-size:14px} +.sf-video{aspect-ratio:16/9;max-width:1000px;background:#ebf0f5;border-radius:10px;overflow:hidden} +.sf-video iframe{width:100%;height:100%;border:0} +.sf-tab{padding:19px 0;border-bottom:1px solid #dde4ec;max-width:960px} +.sf-tab summary{font-size:18px;font-weight:700;cursor:pointer}.sf-tab p{max-width:850px;line-height:1.8} +.sf-prices{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:18px} +.sf-price{padding:28px;background:#fff;border:1px solid #dee5ef;border-radius:10px;color:#29394b} +.sf-price strong{display:block;font-size:27px;margin:14px 0}.sf-price li{margin:11px 0}.sf-price ul{padding-left:19px} +.sf-map-address{font-style:normal;font-size:18px;white-space:pre-line;line-height:1.8} +@media (prefers-reduced-motion:reduce){.sf-slides{scroll-behavior:auto}.sf-item{transition:none}} +@media(max-width:540px){.sf-slide{flex-basis:92%}} diff --git a/examples/v830-built-sites/industrial/assets/commercial.css b/examples/v830-built-sites/industrial/assets/commercial.css new file mode 100644 index 0000000..353bee4 --- /dev/null +++ b/examples/v830-built-sites/industrial/assets/commercial.css @@ -0,0 +1,84 @@ +/* SiteForge commercial theme UX layer: accessibility, layout rhythm, media, responsive navigation. */ +:root{--sf-shadow:0 20px 55px rgba(17,33,55,.08);--sf-shadow-hover:0 26px 65px rgba(17,33,55,.15)} +html{scroll-padding-top:104px}body{font-feature-settings:"kern";text-rendering:optimizeLegibility} +a,button,input,select,textarea{-webkit-tap-highlight-color:transparent} +a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{outline:3px solid var(--pro-accent);outline-offset:4px} +.pro-wrap{width:100%;max-width:min(var(--pro-wide),100%)}.pro-header{isolation:isolate;box-shadow:0 1px 0 rgba(15,35,60,.035)}.pro-head-inner{gap:clamp(15px,2vw,29px)}.pro-logo{min-width:0;flex-shrink:0;gap:12px}.pro-brand-logo{max-width:155px;max-height:46px;width:auto;height:auto;object-fit:contain}.pro-logo-name{overflow-wrap:anywhere}.pro-navigation{gap:clamp(11px,1.6vw,24px)}.pro-header-cta{white-space:nowrap} +.pro-mobile-toggle,.pro-catalog-toggle,.pro-nav-disclose{border:0;background:transparent;color:inherit;line-height:1.2} +.pro-mobile-toggle{min-height:44px;min-width:44px;border:1px solid currentColor;border-radius:6px;font-size:19px}.pro-nav-group{position:relative;display:flex;align-items:center;gap:2px} +.pro-nav-disclose{padding:9px;font-size:13px}.pro-nav-children{position:absolute;top:100%;left:0;min-width:215px;max-width:330px;display:grid;gap:2px;padding:13px;box-shadow:var(--sf-shadow);border-radius:10px;z-index:45;background:var(--pro-background);border:1px solid var(--pro-border);color:var(--pro-text)} +.pro-nav-children[hidden],.pro-mega[hidden]{display:none!important}.pro-nav-children a{display:block;font-size:13px;white-space:normal;padding:10px;border-radius:5px}.pro-nav-children a:hover{background:var(--pro-surface)} +.pro-catalog-toggle{padding:11px 3px;white-space:nowrap;font-size:12px;font-weight:700}.pro-mega{position:absolute;top:100%;left:50%;transform:translateX(-50%);width:min(100%,var(--pro-wide));box-shadow:var(--sf-shadow);z-index:41;display:grid;grid-template-columns:215px 1fr;background:var(--pro-background);color:var(--pro-text);border:1px solid var(--pro-border);border-radius:0 0 15px 15px;padding:29px;align-items:start}.pro-mega>span{font-size:12px;letter-spacing:.06em}.pro-mega>div{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:9px 22px;overflow:visible}.pro-mega>div a{white-space:normal;padding:10px 5px;border-bottom:1px solid var(--pro-border)} +.pro-home-hero{overflow:hidden}.pro-home-hero .pro-home-grid{min-height:660px;gap:5%}.pro-home-hero .pro-hero-copy{position:relative;z-index:2}.pro-home-hero .pro-hero-copy h1{font-size:clamp(46px,5.7vw,92px);line-height:1.06;letter-spacing:-.064em;max-width:15ch}.pro-home-hero .pro-hero-copy h1 em{font-style:normal;display:block}.pro-home-hero .pro-hero-copy p{font-size:clamp(15px,1.3vw,19px);line-height:1.75;max-width:44ch}.pro-home-hero .pro-hero-art{min-width:0;min-height:425px;position:relative;isolation:isolate}.pro-home-hero .pro-hero-art>img{width:100%;height:100%;object-fit:cover;position:absolute;inset:0}.pro-hero-art:has(.pro-abstract-car),.pro-hero-art:has(.pro-technical),.pro-hero-art:has(.pro-corporate-shape){background-position:center;background-size:cover;background-repeat:no-repeat}.pro-abstract-car,.pro-technical,.pro-corporate-shape{position:relative;z-index:1;pointer-events:none} +.pro-hero-actions{display:flex;flex-wrap:wrap;align-items:center;gap:15px}.pro-button,.pro-header-cta,.pro-outline-button{min-height:48px;transition:transform .24s ease,box-shadow .24s ease,opacity .24s ease}.pro-button:hover,.pro-header-cta:hover,.pro-outline-button:hover{transform:translateY(-2px);box-shadow:0 10px 22px rgba(0,0,0,.10)} +.pro-section{padding-top:clamp(76px,7vw,112px)!important;padding-bottom:clamp(76px,7vw,112px)!important}.pro-section-head{gap:16px}.pro-section-head h2{font-size:clamp(32px,3.5vw,53px);max-width:22ch}.pro-section-head .pro-text-link{align-self:end} +.pro-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px}.pro-card{min-width:0;display:flex;flex-direction:column;transition:transform .28s ease,box-shadow .28s ease;border:1px solid var(--pro-border);background:var(--pro-background);overflow:hidden}.pro-card:hover{transform:translateY(-6px);box-shadow:var(--sf-shadow-hover)}.pro-card-cover{aspect-ratio:1.42;overflow:hidden;background:var(--pro-surface);position:relative}.pro-card-cover .pro-photo{width:100%;height:100%;object-fit:cover;transition:transform .45s ease}.pro-card:hover .pro-photo{transform:scale(1.045)}.pro-card-body{display:flex;flex-direction:column;flex:1}.pro-card-body h3{font-size:clamp(19px,1.6vw,24px);line-height:1.26}.pro-card-body p{font-size:14px}.pro-card-link{margin-top:auto;padding-top:14px;font-size:13px;font-weight:700} +.pro-art{min-height:100%;width:100%;position:relative;overflow:hidden;display:grid;place-items:center;isolation:isolate}.pro-art-ring{width:60%;aspect-ratio:1;border:1px solid currentColor;opacity:.13;border-radius:50%;transform:rotate(20deg);box-shadow:0 0 0 23px #ffffff10,0 0 0 57px #ffffff07}.pro-art-center{font-size:clamp(38px,5vw,80px);position:absolute;font-weight:800;letter-spacing:-.065em;opacity:.65}.pro-art-label{position:absolute;bottom:19px;left:22px;font-size:10px;letter-spacing:.22em;opacity:.7} +.pro-breadcrumb{display:flex;gap:11px;flex-wrap:wrap;font-size:12px;align-items:center}.pro-breadcrumb a{text-decoration:underline;text-underline-offset:4px}.pro-product-hero{align-items:start;gap:clamp(28px,5vw,80px)}.pro-product-media{aspect-ratio:1.12;background:var(--pro-surface);overflow:hidden}.pro-product-media>img,.pro-product-media>.pro-art{width:100%;height:100%;object-fit:contain}.pro-product-summary{padding:clamp(12px,3vw,50px) 0}.pro-product-summary h1{font-size:clamp(36px,4.3vw,72px)}.pro-detail-layout{border-top:1px solid var(--pro-border);padding-top:50px}.pro-specs>div{display:grid;grid-template-columns:minmax(100px,40%) 1fr;gap:10px;align-items:baseline;padding:15px 0;border-bottom:1px solid var(--pro-border)}.pro-specs strong{overflow-wrap:anywhere}.pro-gallery-thumbs button{flex-basis:96px;height:76px}.pro-gallery-lightbox{backdrop-filter:blur(6px)} +.pro-filter-panel{display:flex;align-items:end;flex-wrap:wrap;gap:16px;background:var(--pro-surface);border:1px solid var(--pro-border);padding:20px;margin-bottom:25px;border-radius:var(--pro-radius)}.pro-filter-panel label{display:grid;gap:7px;min-width:180px;flex:1}.pro-filter-panel input,.pro-filter-panel select{width:100%;background:var(--pro-background);border:1px solid var(--pro-border);padding:12px 14px;color:var(--pro-text);border-radius:6px}.pro-filter-count{white-space:nowrap;font-size:13px;padding:12px 0}.pro-card[hidden]{display:none!important}.pro-filter-empty{padding:38px;border:1px dashed var(--pro-border);text-align:center;grid-column:1/-1} +.pro-inquiry input,.pro-inquiry textarea{min-height:46px}.pro-inquiry textarea{min-height:150px}.pro-inquiry-wrap{gap:clamp(32px,7vw,110px)}.pro-inquiry .pro-button{border:0;justify-self:start}.pro-footer-links a{padding-block:5px;display:inline-block} +.pro-end-cta{overflow:hidden}.pro-end-cta h2{font-size:clamp(30px,4vw,64px)} +.pro-rich{line-height:1.85}.pro-rich img{border-radius:var(--pro-radius);margin-block:24px}.pro-rich table{width:100%;display:block;overflow:auto;border-collapse:collapse}.pro-rich td,.pro-rich th{border:1px solid var(--pro-border);padding:10px 14px}.pro-rich a{text-decoration:underline;text-underline-offset:3px} +@media(min-width:1025px){.pro-navigation>.pro-nav-group:hover .pro-nav-children:not([hidden]){visibility:visible}} +@media(max-width:1150px){.pro-head-inner{gap:15px}.pro-navigation{gap:12px}.pro-logo-name{font-size:15px}.pro-header-cta{padding:13px 16px}} +@media(max-width:1024px){.pro-head-inner{min-height:72px;flex-wrap:wrap}.pro-mobile-toggle{display:inline-flex;align-items:center;justify-content:center;margin-left:auto}.pro-navigation{display:none;width:100%;flex-basis:100%;flex-direction:column;align-items:stretch;gap:0;order:5;margin:0;padding:8px 0 20px;border-top:1px solid var(--pro-border)}.pro-navigation.is-open{display:flex}.pro-navigation>a,.pro-nav-group>a{padding:14px 8px;font-size:15px}.pro-nav-group{display:flex;flex-wrap:wrap;justify-content:space-between}.pro-nav-children{position:static;flex-basis:100%;max-width:none;width:100%;box-shadow:none;border-radius:0;border-left:2px solid var(--pro-accent);margin:0 0 12px 8px}.pro-nav-disclose{min-width:44px;min-height:44px}.pro-catalog-toggle{margin-left:auto}.pro-mega{top:100%;display:block;padding:20px}.pro-mega>div{grid-template-columns:repeat(2,minmax(0,1fr));margin-top:12px}.pro-home-hero .pro-home-grid{min-height:560px}.pro-home-hero .pro-hero-art{min-height:325px}.pro-grid{grid-template-columns:repeat(2,minmax(0,1fr))}} +@media(max-width:700px){.pro-wrap{padding-left:20px;padding-right:20px}.pro-utility{display:none}.pro-head-inner{min-height:66px}.pro-logo-name{max-width:140px;font-size:14px}.pro-brand-logo{max-width:125px}.pro-header-cta{display:none}.pro-catalog-toggle{font-size:11px;padding-inline:7px;margin-left:0}.pro-home-hero .pro-home-grid{display:flex;flex-direction:column;gap:36px;padding-top:48px;padding-bottom:48px}.pro-home-hero .pro-hero-copy h1{font-size:clamp(43px,10vw,68px)}.pro-home-hero .pro-hero-copy p{font-size:15px}.pro-home-hero .pro-hero-art{width:100%;min-height:290px}.pro-home-hero .pro-hero-bottom{display:none}.pro-section{padding-top:68px!important;padding-bottom:68px!important}.pro-section-head{align-items:flex-start}.pro-grid{grid-template-columns:1fr;gap:18px}.pro-card-cover{aspect-ratio:1.45}.pro-product-hero,.pro-detail-layout,.pro-info-grid,.pro-inquiry-wrap{display:grid;grid-template-columns:1fr;gap:30px}.pro-product-summary{padding:0}.pro-specs>div{grid-template-columns:1fr 1fr}.pro-mega{top:100%;max-height:65vh;overflow-y:auto}.pro-mega>div{grid-template-columns:1fr}.pro-filter-panel{display:grid;grid-template-columns:1fr;gap:12px}.pro-filter-panel label{min-width:0}.pro-footer-top{display:grid;grid-template-columns:1fr;gap:27px}.pro-footer-bottom{gap:12px;flex-wrap:wrap}} +@media(max-width:410px){.pro-logo-name{max-width:115px}.pro-logo-symbol{font-size:28px}.pro-catalog-toggle{font-size:10px}.pro-mobile-toggle{min-width:42px}} +@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,*:before,*:after{animation-duration:.01ms!important;transition-duration:.01ms!important;scroll-behavior:auto!important}} + +/* Accessible static catalogue pagination for large inventories. */ +.pro-pages-nav{display:flex;gap:1rem;justify-content:center;align-items:center;margin:2rem 0;flex-wrap:wrap} +.pro-pages-nav a{padding:.7rem 1.1rem;border:1px solid currentColor;border-radius:.4rem;text-decoration:none} +.pro-pages-nav a:focus-visible{outline:3px solid var(--accent,#2563eb);outline-offset:3px} +.pro-pages-nav span{font-size:.875rem} + +/* P6 international sites: small, keyboard-operable language switch. */ +.sf-language-switch{display:inline-flex;gap:6px;align-items:center;flex-wrap:wrap;margin:8px 12px;padding:4px;border:1px solid rgba(120,130,145,.22);border-radius:10px;background:rgba(255,255,255,.08)} +.sf-language-switch a{font:inherit;font-size:12px;line-height:1.5;padding:4px 7px;border-radius:6px;color:inherit;text-decoration:none} +.sf-language-switch a[aria-current="page"]{font-weight:700;text-decoration:underline;text-underline-offset:3px} +.sf-language-switch a:focus-visible{outline:2px solid #2563eb;outline-offset:3px} +@media(max-width:640px){.sf-language-switch{margin:6px 0;width:auto}} + +/* V8.21.3 — Four-theme unified mobile off-canvas navigation & optional tab bar. + Desktop remains unchanged. Phone / tablet use one accessible drawer. */ +.sf-mobile-tabs{display:none!important} +.sf-drawer-header,.sf-mobile-drawer-backdrop,.sf-drawer-extra{display:none} +@media(max-width:1024px){ + .pro-head-inner{flex-wrap:nowrap!important;gap:12px!important} + .pro-mobile-toggle{display:inline-flex;align-items:center;justify-content:center;margin-left:auto!important;flex:0 0 44px;min-width:44px;min-height:44px;position:relative;z-index:3} + .pro-catalog-toggle{display:none!important} + .pro-navigation,.pro-navigation.is-open{display:flex!important;position:fixed!important;inset:0 0 0 auto!important;width:min(88vw,360px)!important;height:100dvh!important;height:100vh;max-height:100dvh!important;flex:unset!important;flex-direction:column!important;align-items:stretch!important;order:unset!important;margin:0!important;padding:0 0 calc(20px + env(safe-area-inset-bottom,0px))!important;overflow-x:hidden;overflow-y:auto!important;background:var(--pro-background,#fff)!important;color:var(--pro-text,#19283c)!important;border:0!important;border-left:1px solid var(--pro-border,#ddd)!important;box-shadow:-15px 0 45px #0002!important;z-index:1201!important;transform:translateX(105%);visibility:hidden;pointer-events:none;transition:transform .24s ease,visibility .24s ease!important;overscroll-behavior:contain} + .pro-navigation.is-open{transform:translateX(0);visibility:visible;pointer-events:auto} + .sf-drawer-header{display:flex!important;align-items:center;justify-content:space-between;gap:12px;padding:20px 18px;border-bottom:1px solid var(--pro-border,#dde3e9);font-size:17px;font-weight:750;position:sticky;top:0;background:var(--pro-background,#fff);z-index:2} + .sf-drawer-close{min-width:44px;min-height:44px;border:1px solid var(--pro-border,#dde3e9);color:inherit;background:transparent;border-radius:10px;font-size:24px;cursor:pointer} + .sf-mobile-drawer-backdrop{display:block;position:fixed;inset:0;z-index:1200;background:#0b1b31a3;opacity:0;visibility:hidden;pointer-events:none;transition:opacity .24s ease,visibility .24s ease} + .sf-mobile-drawer-backdrop.is-open{opacity:1;visibility:visible;pointer-events:auto} + body.sf-drawer-open{overflow:hidden!important} + .pro-navigation>a,.pro-navigation .pro-nav-group>a,.pro-navigation .sf-drawer-extra>a{display:flex;align-items:center;min-height:50px;padding:13px 20px!important;font-size:15px!important;color:inherit!important;white-space:normal;border-bottom:1px solid var(--pro-border,#dde3e9)!important;text-decoration:none!important} + .pro-navigation .pro-nav-group{display:flex;position:relative;flex-wrap:wrap!important;width:100%;gap:0;align-items:center;justify-content:space-between} + .pro-navigation .pro-nav-group>a{flex:1;min-width:0} + .pro-navigation .pro-nav-disclose{margin-right:12px;min-width:44px;min-height:44px;border-radius:9px;background:var(--pro-surface,#f4f6f8)} + .pro-navigation .pro-nav-children{position:static!important;width:100%!important;max-width:100%!important;box-shadow:none!important;border-left:3px solid var(--pro-accent,#e77730);border-radius:0!important;margin:0 0 8px 14px!important;flex-basis:calc(100% - 14px)!important;background:var(--pro-surface,#f6f8fa)} + .pro-navigation .pro-nav-children a{padding:12px 16px!important;font-size:14px!important;color:inherit!important;min-height:44px} + .sf-drawer-extra{display:block;padding:12px 0 5px}.sf-drawer-extra strong{display:block;font-size:12px;letter-spacing:.06em;padding:12px 20px;opacity:.65}.sf-drawer-extra a{font-size:14px!important} + .sf-drawer-close:focus-visible,.pro-mobile-toggle:focus-visible,.pro-nav-disclose:focus-visible,.sf-mobile-tab:focus-visible{outline:3px solid var(--pro-accent,#ff8200);outline-offset:2px} +} +@media(max-width:767px){ + .pro-header-cta{display:none!important} + .pro-head-inner .pro-logo{min-width:0;max-width:calc(100% - 65px)} + .pro-logo-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap} + .pro-home-hero .pro-home-grid{min-height:0!important} + .pro-home-hero .pro-hero-art{min-height:230px} + .pro-card,.pro-card-cover,.pro-product-media{max-width:100%;min-width:0} + .pro-rich img,.pro-content img,.sf-canvas img{max-width:100%;height:auto} + .pro-rich table{max-width:100%;overflow:auto} + .pro-grid,.pro-footer-top{min-width:0} + .sf-mobile-tabs{display:grid!important;position:fixed;z-index:1100;bottom:0;left:0;right:0;grid-template-columns:repeat(var(--sf-mobile-tab-count,4),minmax(0,1fr));align-items:stretch;padding:5px 6px calc(5px + env(safe-area-inset-bottom,0px));min-height:63px;background:var(--pro-background,#fff);color:var(--pro-text,#263446);border-top:1px solid var(--pro-border,#dfe4eb);box-shadow:0 -6px 24px #13223914} + .sf-mobile-tab{appearance:none;border:0!important;background:transparent!important;color:inherit!important;text-decoration:none!important;padding:6px 2px;min-height:50px;min-width:0;display:flex;flex-direction:column;justify-content:center;align-items:center;gap:2px;border-radius:9px;cursor:pointer;font-family:inherit} + .sf-tab-icon{font-size:23px;line-height:1.15;font-weight:500} + .sf-tab-label{font-size:11px;font-weight:600;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} + .sf-mobile-tab[aria-current=page]{color:var(--pro-accent,#e47730)!important;background:var(--pro-surface,#f5f6f8)!important} + body:has(> .sf-mobile-tabs){padding-bottom:calc(76px + env(safe-area-inset-bottom,0px))!important} +} +@media(min-width:768px){.sf-mobile-tabs{display:none!important}} +@media(prefers-reduced-motion:reduce){.pro-navigation,.sf-mobile-drawer-backdrop{transition:none!important}} diff --git a/examples/v830-built-sites/industrial/assets/custom.css b/examples/v830-built-sites/industrial/assets/custom.css new file mode 100644 index 0000000..f197c0a --- /dev/null +++ b/examples/v830-built-sites/industrial/assets/custom.css @@ -0,0 +1 @@ +:root{--accent:#315f92;--sf-font:system-ui,-apple-system,sans-serif;--sf-radius:12px;--sf-space:72px;--sf-width:1200px;--sf-heading-scale:1.0;}body{font-family:var(--sf-font)} .sf-canvas .sf-section,.sf-canvas .section{padding-block:var(--sf-space)}.container,.sf-container{max-width:var(--sf-width)}.btn,.primary,.request,.button,.nav-btn{background-color:#315f92;border-radius:12px}body .sf-canvas h1{font-size:clamp(2.5rem,5vw,calc(4.8rem * var(--sf-heading-scale)))}body .pro-utility[hidden]{display:none!important}@media(max-width:1023px){.sf-canvas .sf-section{padding-block:64px}}@media(max-width:767px){.sf-canvas .sf-section{padding-block:40px}.pro-wrap,.sf-container{padding-left:20px;padding-right:20px}body .pro-utility{display:none!important}} \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/assets/factory.css b/examples/v830-built-sites/industrial/assets/factory.css new file mode 100644 index 0000000..154ffb3 --- /dev/null +++ b/examples/v830-built-sites/industrial/assets/factory.css @@ -0,0 +1,27 @@ +/* SiteForge trusted global shell. Site themes remain visually independent. */ +:root{--sf-shell:#12243d;--sf-shell-accent:#dcae71;--sf-shell-soft:#edf2f8;--sf-shell-fg:#173049} +html{scroll-behavior:smooth}body{overflow-x:hidden}body>.header,body>.utility,body>.top,body>header,body>footer{display:none!important} +.sf-theme-industrial{--sf-shell:#114e79;--sf-shell-accent:#92d5ed;--sf-shell-soft:#ebf6fa;--sf-shell-fg:#0c4267} +.sf-theme-corporate{--sf-shell:#232d62;--sf-shell-accent:#b8bdff;--sf-shell-soft:#f3f3fa;--sf-shell-fg:#333468} +.sf-theme-minimal{--sf-shell:#1e1e1c;--sf-shell-accent:#ded6c5;--sf-shell-soft:#f6f4ef;--sf-shell-fg:#252520} +.sf-site-head{position:relative;z-index:25;background:var(--sf-shell);color:#fff;font-family:system-ui,-apple-system,sans-serif} +.sf-head-inner{max-width:1240px;margin:0 auto;min-height:78px;padding:0 28px;display:flex;align-items:center;gap:28px} +.sf-logo{display:flex;align-items:center;gap:11px;font-size:18px;text-decoration:none!important;color:#fff!important;white-space:nowrap} +.sf-logo-mark{width:36px;height:36px;display:grid;place-items:center;background:var(--sf-shell-accent);color:var(--sf-shell);font-size:22px;font-weight:900;border-radius:9px} +.sf-primary-links{display:flex;gap:23px;margin-left:auto;align-items:center} +.sf-primary-links a,.sf-mega a{color:#fff!important;text-decoration:none!important;font-size:13px;font-weight:650;white-space:nowrap} +.sf-primary-links a:hover{color:var(--sf-shell-accent)!important} +.sf-head-cta{font-size:13px;font-weight:750;text-decoration:none;background:var(--sf-shell-accent);color:var(--sf-shell)!important;padding:13px 18px;border-radius:4px;white-space:nowrap} +.sf-menu-toggle{display:none;margin-left:auto;color:white;border:1px solid #ffffff55;background:none;border-radius:4px;padding:8px 12px;font-size:19px;cursor:pointer} +.sf-mega{display:flex;gap:18px;max-width:1240px;margin:auto;padding:0 28px 9px;overflow-x:auto} +.sf-mega a{display:block;min-width:120px;border-top:1px solid #ffffff2e;padding:12px 8px}.sf-mega small{display:block;color:#ffffff99;max-width:160px;overflow:hidden;text-overflow:ellipsis;font-size:10px;margin-top:6px} +.sf-site-foot{background:var(--sf-shell);color:white!important;font:14px/1.7 system-ui,-apple-system,sans-serif;padding:72px 28px 26px} +.sf-foot-grid{max-width:1200px;margin:auto;display:grid;grid-template-columns:2fr 1fr 1fr;gap:70px}.sf-foot-grid h2{font-size:25px;color:white;margin:0 0 17px}.sf-foot-grid h4{font-size:13px;color:var(--sf-shell-accent);letter-spacing:.07em;margin:0 0 17px}.sf-foot-grid p{color:#ffffffae;max-width:380px}.sf-foot-grid a{display:block;width:fit-content;color:#fff!important;text-decoration:none;margin-bottom:8px}.sf-foot-lower{border-top:1px solid #ffffff33;max-width:1200px;margin:45px auto 0;padding-top:20px;display:flex;justify-content:space-between;color:#ffffff9e;font-size:12px} +.sf-filters{display:flex;align-items:center;flex-wrap:wrap;gap:12px;margin:0 0 30px}.sf-filters input,.sf-filters select{padding:11px 13px;border-radius:6px;border:1px solid #cfd9e4;background:#fff;color:#263a51;max-width:280px}.sf-filter-empty{padding:22px;color:#778598} +.sf-search-page{min-height:76vh;max-width:1060px;padding:90px 24px;margin:auto;font-family:system-ui,sans-serif;color:var(--sf-shell-fg)}.sf-search-page h1{font-size:clamp(35px,5vw,62px);margin:20px 0}.sf-search-page>label{display:block;margin:18px 0 8px}.sf-search-page input{display:block;width:100%;padding:17px;font-size:18px;border:1px solid #b7c6d7;border-radius:8px}.sf-search-page #sf-search-count{margin:22px 0;color:#607589}.sf-search-result{padding:22px 0;border-bottom:1px solid #dae1ea}.sf-search-result a{color:var(--sf-shell-fg);font-size:21px;font-weight:750;text-decoration:none}.sf-search-result small{display:block;color:#7992a7}.sf-search-result p{margin:7px 0;color:#657487} +@media(max-width:1050px){.sf-head-inner{gap:13px}.sf-primary-links{gap:12px}.sf-primary-links a{font-size:12px}.sf-head-cta{padding:10px}} +@media(max-width:850px){.sf-head-inner{min-height:68px}.sf-menu-toggle{display:block}.sf-head-cta{display:none}.sf-primary-links{display:none;position:absolute;top:68px;left:0;right:0;margin:0;background:var(--sf-shell);padding:20px 28px;flex-direction:column;align-items:stretch;box-shadow:0 20px 24px #0002}.sf-primary-links.is-open{display:flex}.sf-mega{display:none}.sf-foot-grid{grid-template-columns:1fr 1fr;gap:35px}} +@media(max-width:560px){.sf-foot-grid{grid-template-columns:1fr}.sf-foot-lower{display:block}.sf-site-foot{padding-top:48px}.sf-head-inner{padding:0 16px}} + +.sf-page-intro{padding:80px 28px;background:var(--sf-shell-soft);color:var(--sf-shell-fg);font-family:system-ui,sans-serif}.sf-page-intro>div{max-width:1200px;margin:auto}.sf-page-intro p{font-size:11px;font-weight:850;letter-spacing:.19em;text-transform:uppercase;color:var(--sf-shell-fg);opacity:.58}.sf-page-intro h1{font-size:clamp(38px,5vw,67px);letter-spacing:-.04em;line-height:1.08;margin:13px 0}.sf-page-intro span{font-size:16px;opacity:.72} +.sf-item[hidden]{display:none!important} diff --git a/examples/v830-built-sites/industrial/assets/pro-base.css b/examples/v830-built-sites/industrial/assets/pro-base.css new file mode 100644 index 0000000..c2c4f61 --- /dev/null +++ b/examples/v830-built-sites/industrial/assets/pro-base.css @@ -0,0 +1,21 @@ +/* SiteForge V3 professional theme primitives. Each commercial theme adds its own art direction. */ +:root{--pro-text:#19283a;--pro-muted:#687587;--pro-border:#dfe5ea;--pro-background:#fff;--pro-surface:#f5f7fa;--pro-accent:#365cb7;--pro-hero:#15263d;--pro-hero-fg:#fff;--pro-radius:12px;--pro-headings:system-ui,-apple-system,sans-serif;--pro-font:system-ui,-apple-system,sans-serif;--pro-wide:1270px} +*,*:before,*:after{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:var(--pro-background);color:var(--pro-text);font-family:var(--pro-font);-webkit-font-smoothing:antialiased;overflow-x:hidden}button,input,select{font:inherit}button,a{touch-action:manipulation}button{cursor:pointer}a{text-decoration:none;color:inherit}a:hover{color:var(--pro-accent)}img{max-width:100%;display:block}h1,h2,h3,h4,p{margin-top:0}h1,h2,h3{font-family:var(--pro-headings);line-height:1.09}h1{letter-spacing:-.052em}h2{letter-spacing:-.042em}h3{letter-spacing:-.028em}p{line-height:1.72}.pro-wrap{max-width:var(--pro-wide);margin:0 auto;padding-left:32px;padding-right:32px}.pro-skip{position:absolute;left:-9999px;z-index:90;background:#fff;color:#000;padding:12px}.pro-skip:focus{left:10px;top:10px}.pro-eyebrow{font-weight:750;font-size:11px;letter-spacing:.17em;text-transform:uppercase;display:block;line-height:1.6;color:var(--pro-accent)}.pro-muted{opacity:.7}.pro-utility{min-height:30px;background:var(--pro-hero);color:#c5d2db;font-size:10px;letter-spacing:.16em}.pro-utility .pro-wrap{display:flex;justify-content:space-between;padding-block:8px}.pro-utility i{font-style:normal;color:var(--pro-accent)}.pro-header{background:var(--pro-background);color:var(--pro-text);border-bottom:1px solid var(--pro-border);position:relative;z-index:35}.pro-head-inner{min-height:84px;display:flex;align-items:center;gap:28px}.pro-logo{display:flex;align-items:center;gap:12px;min-width:170px}.pro-logo-symbol{font-size:32px;line-height:1;font-weight:800;letter-spacing:-.07em;color:var(--pro-accent)}.pro-logo-name{max-width:220px;font-weight:820;font-size:17px;line-height:1.1;letter-spacing:-.035em}.pro-logo-name small{display:block;font-weight:650;font-size:9px;letter-spacing:.19em;margin-top:7px;color:var(--pro-muted)}.pro-navigation{display:flex;align-items:center;gap:24px;margin-left:auto}.pro-navigation a{font-size:13px;font-weight:650;white-space:nowrap;transition:opacity .2s}.pro-navigation a:hover{opacity:.6}.pro-header-cta,.pro-button{display:inline-flex;align-items:center;justify-content:center;gap:22px;background:var(--pro-accent);color:#fff!important;border-radius:var(--pro-radius);font-size:13px;letter-spacing:.01em;font-weight:750;padding:16px 24px;white-space:nowrap;transition:transform .2s,background .2s}.pro-header-cta:hover,.pro-button:hover{transform:translateY(-2px)}.pro-mobile-toggle{display:none}.pro-mega{display:flex;align-items:center;gap:22px;min-height:37px;border-top:1px solid var(--pro-border);padding-block:10px;font-size:11px}.pro-mega>span{font-weight:750;color:var(--pro-muted);white-space:nowrap}.pro-mega>div{display:flex;gap:16px;overflow:auto;scrollbar-width:none}.pro-mega a{white-space:nowrap;font-weight:650}.pro-search-link{font-size:19px!important}.pro-home-hero{position:relative;overflow:hidden}.pro-home-grid{display:grid;grid-template-columns:1.02fr .98fr;align-items:center;gap:5%;min-height:580px;padding-top:85px;padding-bottom:85px}.pro-hero-copy{position:relative;z-index:2}.pro-hero-copy h1{font-size:clamp(48px,6.2vw,91px);line-height:1.03;margin:20px 0 25px;max-width:730px}.pro-hero-copy h1 em{font-style:normal;display:block;color:var(--pro-accent)}.pro-hero-copy p{font-size:17px;max-width:495px;color:var(--pro-muted)}.pro-hero-actions{display:flex;align-items:center;flex-wrap:wrap;gap:25px;margin-top:34px}.pro-outline-button{font-weight:700;border-bottom:1px solid currentColor;padding:12px 0}.pro-hero-art{width:100%;height:435px;position:relative;overflow:hidden;border-radius:var(--pro-radius)}.pro-hero-art>img{width:100%;height:100%;object-fit:cover}.pro-hero-bottom{display:flex;justify-content:space-between;font-size:10px;letter-spacing:.18em;padding-block:22px;border-top:1px solid #ffffff32}.pro-section{padding:106px 0}.pro-section-head{display:flex;align-items:end;justify-content:space-between;gap:25px;margin-bottom:34px}.pro-section-head h2{font-size:clamp(36px,4vw,57px);margin:12px 0 0}.pro-text-link{font-size:13px;font-weight:750;display:inline-flex;gap:18px;align-items:center;border-bottom:1px solid;padding-bottom:7px;color:var(--pro-accent)}.pro-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:22px}.pro-card{display:block;min-width:0;background:var(--pro-background);color:var(--pro-text);border:1px solid var(--pro-border);overflow:hidden;border-radius:var(--pro-radius);transition:transform .25s,box-shadow .25s}.pro-card:hover{transform:translateY(-6px);box-shadow:0 24px 45px #0f25431b}.pro-card-cover{width:100%;height:244px;overflow:hidden;background:var(--pro-surface)}.pro-photo{width:100%;height:100%;object-fit:cover;transition:transform .5s}.pro-card:hover .pro-photo{transform:scale(1.045)}.pro-art{width:100%;height:100%;overflow:hidden;display:grid;place-items:center;position:relative;background:linear-gradient(130deg,#d8e1ed,#f3f6f9)}.pro-art-ring{width:55%;aspect-ratio:1;border:28px solid #ffffff5f;border-radius:50%;box-shadow:0 0 0 42px #ffffff30;transform:rotate(-25deg)}.pro-art-center{position:absolute;font-family:var(--pro-headings);font-weight:800;font-size:76px;letter-spacing:-.08em;color:#45647d90}.pro-art-label{position:absolute;bottom:16px;left:18px;letter-spacing:.16em;font-size:9px;color:#435773}.pro-card-body{padding:25px 25px 28px}.pro-card-meta{display:flex;justify-content:space-between;gap:20px;font-size:10px;font-weight:750;letter-spacing:.1em;text-transform:uppercase;color:var(--pro-accent)}.pro-card h3{font-size:23px;margin:14px 0 9px}.pro-card p{font-size:13px;color:var(--pro-muted);margin-bottom:24px;min-height:44px}.pro-card-link{font-size:12px;font-weight:800;display:flex;justify-content:space-between;color:var(--pro-text);padding-top:14px;border-top:1px solid var(--pro-border)}.pro-empty{grid-column:1/-1;padding:45px;border:1px dashed var(--pro-border);background:var(--pro-surface);color:var(--pro-muted)}.pro-statement{background:var(--pro-surface)}.pro-statement-layout{display:grid;grid-template-columns:1fr 2fr;gap:60px}.pro-statement h2{font-size:clamp(36px,4.5vw,63px);max-width:760px}.pro-statement p{max-width:520px;color:var(--pro-muted)}.pro-brand-pills{display:flex;flex-wrap:wrap;gap:12px}.pro-brand-pills a{padding:18px 28px;border:1px solid var(--pro-border);border-radius:var(--pro-radius);font-weight:750}.pro-brand-pills a:hover{border-color:var(--pro-accent)}.pro-inner-hero{background:var(--pro-surface);padding:92px 0 65px;position:relative;overflow:hidden}.pro-inner-hero h1{max-width:870px;font-size:clamp(43px,6vw,85px);margin:18px 0}.pro-inner-hero p{max-width:650px;color:var(--pro-muted);font-size:17px}.pro-breadcrumb{font-size:12px;color:var(--pro-muted);margin-top:25px;display:flex;gap:12px;align-items:center;flex-wrap:wrap}.pro-breadcrumb strong{color:var(--pro-text)}.pro-list-section{padding:65px 0 110px}.pro-filter-panel{display:grid;grid-template-columns:minmax(220px,2fr) 1fr 1fr auto;align-items:end;gap:14px;margin-bottom:35px}.pro-filter-panel label>span{display:block;font-size:11px;margin-bottom:8px;color:var(--pro-muted);font-weight:750}.pro-filter-panel input,.pro-filter-panel select{display:block;width:100%;padding:14px 15px;border-radius:var(--pro-radius);border:1px solid var(--pro-border);background:var(--pro-background);color:var(--pro-text);outline-offset:2px}.pro-filter-count{font-size:12px;padding-bottom:17px;color:var(--pro-muted)}.pro-filter-scope .pro-card[hidden]{display:none}.pro-product-layout{padding-top:38px}.pro-product-layout .pro-breadcrumb{margin-bottom:38px}.pro-product-hero{display:grid;grid-template-columns:1.18fr .82fr;gap:6%;align-items:center}.pro-product-media{height:460px;overflow:hidden;background:var(--pro-surface);border-radius:var(--pro-radius)}.pro-product-media .pro-photo{height:100%}.pro-product-summary h1{font-size:clamp(45px,5vw,72px);margin:16px 0}.pro-product-summary p{font-size:16px;color:var(--pro-muted)}.pro-product-brand{font-weight:700;color:var(--pro-text)!important}.pro-detail-layout{border-top:1px solid var(--pro-border);display:grid;grid-template-columns:1fr 1fr;gap:8%;margin-top:80px;padding-top:55px}.pro-detail-layout h2{font-size:32px;margin-top:13px}.pro-specs{margin-top:25px}.pro-specs>div{display:grid;grid-template-columns:1fr 1fr;gap:22px;padding:16px 0;border-bottom:1px solid var(--pro-border)}.pro-specs span{color:var(--pro-muted)}.pro-rich{line-height:1.85;font-size:16px;overflow-wrap:anywhere}.pro-rich img{border-radius:var(--pro-radius);margin:25px 0}.pro-rich a{text-decoration:underline}.pro-rich h2{margin-top:30px}.pro-lead{font-size:20px;color:var(--pro-muted)}.pro-brand-hero-grid{display:grid;grid-template-columns:1.1fr .9fr;gap:7%;align-items:center}.pro-brand-media{height:300px;overflow:hidden;border-radius:var(--pro-radius)}.pro-article-hero{text-align:center;padding:110px 0 75px;background:var(--pro-surface)}.pro-article-width{max-width:900px}.pro-article-hero h1{font-size:clamp(40px,5vw,75px);margin:15px 0 25px}.pro-article-hero p{color:var(--pro-muted);font-size:18px}.pro-article-hero time{font-size:12px;color:var(--pro-muted)}.pro-article-content{max-width:930px;padding-top:70px;padding-bottom:90px}.pro-article-cover{width:100%;max-height:530px;object-fit:cover;margin-bottom:40px;border-radius:var(--pro-radius)}.pro-article-content>.pro-text-link{margin-top:35px}.pro-case-detail{max-width:1020px}.pro-case-detail>img{width:100%;max-height:620px;object-fit:cover}.pro-case-meta{display:flex;gap:35px;margin:35px 0;color:var(--pro-muted);font-size:13px}.pro-case-meta strong{display:block;color:var(--pro-text);font-size:18px;margin-top:7px}.pro-info-grid{display:grid;grid-template-columns:.8fr 1.2fr;gap:12%}.pro-info-grid h2{font-size:clamp(31px,4.5vw,54px);margin-top:15px}.pro-contact-email{font-size:20px;color:var(--pro-accent);font-weight:750;word-break:break-word}.pro-info-photo{max-height:450px;object-fit:cover;margin-top:35px;border-radius:var(--pro-radius)}.pro-custom-content .sf-section{background:transparent}.pro-custom-content .sf-section:nth-of-type(even){background:var(--pro-surface)}.pro-end-cta{padding:76px 0;background:var(--pro-hero);color:#fff}.pro-end-cta .pro-wrap{display:flex;align-items:center;justify-content:space-between;gap:40px}.pro-end-cta h2{font-size:clamp(32px,4vw,53px);margin:13px 0}.pro-end-cta p{color:#c5c9d1}.pro-end-cta a{background:var(--pro-accent);color:#fff;font-weight:800;padding:19px 30px;border-radius:var(--pro-radius);white-space:nowrap}.pro-404{text-align:center;padding-block:125px}.pro-404>span{font-size:12px;letter-spacing:.3em}.pro-404 h1{font-size:clamp(150px,20vw,320px);margin:10px 0;letter-spacing:-.08em}.pro-404 p{font-size:18px;color:var(--pro-muted)}.pro-404 a{margin-top:22px}.pro-footer{background:#15212d;color:#fff;padding:75px 0 22px}.pro-footer-top{display:grid;grid-template-columns:1.45fr 1fr 1fr;gap:55px}.pro-footer h2{font-size:32px;margin:12px 0}.pro-footer p{max-width:350px;font-size:13px;color:#afbbc8}.pro-footer .pro-eyebrow{color:#b6c3d2}.pro-footer-links ul{margin:0;padding:0;list-style:none;display:grid;grid-template-columns:1fr 1fr;gap:15px}.pro-footer-links a{font-size:13px;color:#d6e0e8}.pro-footer-bottom{border-top:1px solid #ffffff29;margin-top:60px;padding-top:20px;font-size:10px;letter-spacing:.12em;color:#adb9c3;display:flex;justify-content:space-between}.pro-anchor{display:block;height:0}.pro-category-tiles{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}.pro-category-tiles a{padding:35px 28px;min-height:155px;background:var(--pro-surface);display:flex;flex-direction:column;justify-content:space-between}.pro-category-tiles span{font-size:11px;color:var(--pro-muted)}.pro-category-tiles strong{font-size:24px}.pro-category-tiles b{align-self:end}.sf-site-head .sf-head-inner,.sf-site-head .sf-primary-links{display:none} +@media(max-width:1100px){.pro-head-inner{gap:17px}.pro-navigation{gap:14px}.pro-navigation a{font-size:12px}.pro-home-grid{min-height:500px}.pro-hero-copy h1{font-size:60px}.pro-hero-art{height:350px}} +@media(max-width:860px){.pro-wrap{padding-left:22px;padding-right:22px}.pro-utility{display:none}.pro-head-inner{min-height:70px;flex-wrap:wrap;gap:12px}.pro-mobile-toggle{display:block;margin-left:auto;border:1px solid var(--pro-border);padding:8px 12px;background:transparent;color:var(--pro-text);border-radius:5px}.pro-navigation{display:none;order:10;width:100%;flex-direction:column;align-items:stretch;gap:0;padding-bottom:12px}.pro-navigation.is-open{display:flex}.pro-navigation a{padding:11px 2px;border-bottom:1px solid var(--pro-border)}.pro-header-cta{display:none}.pro-mega{display:none}.pro-home-grid{grid-template-columns:1fr;gap:35px;padding-top:60px;padding-bottom:60px}.pro-hero-art{height:350px}.pro-hero-copy h1{font-size:clamp(45px,9vw,73px)}.pro-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.pro-product-hero,.pro-detail-layout,.pro-info-grid,.pro-brand-hero-grid{grid-template-columns:1fr;gap:35px}.pro-product-media{height:380px}.pro-filter-panel{grid-template-columns:1fr 1fr}.pro-filter-panel label:first-child{grid-column:1/-1}.pro-end-cta .pro-wrap{align-items:start;flex-direction:column}.pro-section{padding:72px 0}.pro-footer-top{grid-template-columns:1fr 1fr}.pro-footer-top>div:first-child{grid-column:1/-1}.pro-category-tiles{grid-template-columns:repeat(2,1fr)}} +@media(max-width:560px){.pro-wrap{padding-left:18px;padding-right:18px}.pro-logo-name{font-size:15px}.pro-hero-copy h1{font-size:43px}.pro-hero-art{height:255px}.pro-hero-bottom{display:none}.pro-home-grid{min-height:0}.pro-grid{grid-template-columns:1fr}.pro-section-head{align-items:start;flex-direction:column}.pro-section-head h2{font-size:37px}.pro-card-cover{height:230px}.pro-filter-panel{grid-template-columns:1fr}.pro-filter-panel label:first-child{grid-column:auto}.pro-filter-count{padding-bottom:4px}.pro-statement-layout,.pro-footer-top{grid-template-columns:1fr;gap:25px}.pro-footer-top>div:first-child{grid-column:auto}.pro-footer-bottom{flex-direction:column;gap:8px}.pro-inner-hero{padding:60px 0}.pro-product-media{height:270px}.pro-product-summary h1{font-size:43px}.pro-category-tiles{grid-template-columns:1fr}.pro-end-cta h2{font-size:38px}.pro-minimal-meta{display:block!important}} + +/* V2 compatibility stylesheet hides direct headers/footers; full themes restore their own. */ +body>header.sf-site-head.pro-header,body>footer.sf-site-foot.pro-footer{display:block!important} + +/* Accessible desktop mega-navigation and mobile disclosure */ +.pro-catalog-toggle{font-size:12px;font-weight:750;border:1px solid var(--pro-border);background:transparent;color:inherit;border-radius:var(--pro-radius);padding:10px 14px;white-space:nowrap} +.pro-mega[hidden]{display:none!important}.pro-mega.is-open{display:flex}.pro-mega>div{padding-block:3px} +@media(max-width:1060px){.pro-catalog-toggle{display:none}} +@media(max-width:860px){.pro-mega.is-open{display:block!important}.pro-mega.is-open>div{display:flex;flex-wrap:wrap;gap:14px;padding:12px 0}.pro-mega>span{white-space:normal}} + +/* V4: responsive nested navigation, gallery and opt-in inquiry integration */ +.pro-nav-group{position:relative;display:flex;align-items:center;gap:3px}.pro-nav-disclose{border:0;background:none;color:inherit;font-size:12px;padding:8px}.pro-nav-children[hidden]{display:none!important}.pro-nav-children{position:absolute;left:0;top:100%;z-index:45;min-width:230px;max-width:360px;padding:10px;background:var(--pro-background);border:1px solid var(--pro-border);box-shadow:0 18px 35px #0002;border-radius:var(--pro-radius);display:flex;flex-direction:column}.pro-nav-children a{padding:10px 12px;white-space:nowrap}.pro-nav-children .pro-nav-leaf{padding-left:28px;color:var(--pro-muted)} +.pro-product-gallery{min-width:0}.pro-gallery-thumbs{display:flex;gap:8px;margin-top:12px;overflow:auto;scrollbar-width:thin;padding-bottom:5px}.pro-gallery-thumbs button{flex:0 0 86px;height:67px;border:2px solid transparent;padding:3px;border-radius:8px;background:var(--pro-surface)}.pro-gallery-thumbs button:focus-visible,.pro-gallery-thumbs button[aria-pressed=true]{border-color:var(--pro-accent)}.pro-gallery-thumbs img{width:100%;height:100%;object-fit:cover;border-radius:4px}.pro-gallery-lightbox{position:fixed;inset:0;background:rgba(10,16,30,.92);z-index:1000;display:grid;place-items:center;padding:6vw}.pro-gallery-lightbox[hidden]{display:none}.pro-gallery-lightbox img{max-width:92vw;max-height:80vh;object-fit:contain}.pro-gallery-lightbox button{position:absolute;right:25px;top:25px;border:1px solid #fff8;background:#222;color:#fff;padding:10px 15px;border-radius:5px} +.pro-inquiry-wrap{display:grid;grid-template-columns:1fr 1fr;gap:70px}.pro-inquiry{display:grid;gap:17px}.pro-inquiry label{display:grid;gap:7px;font-weight:650}.pro-inquiry input,.pro-inquiry textarea{padding:13px;border:1px solid var(--pro-border);border-radius:var(--pro-radius);background:var(--pro-background);color:var(--pro-text);width:100%}.pro-inquiry textarea{min-height:140px}.pro-inquiry .pro-honeypot{position:absolute;left:-10000px;width:1px;height:1px}.pro-inquiry p{font-size:12px;color:var(--pro-muted)} +@media(max-width:860px){.pro-nav-group{display:block}.pro-nav-children{position:static;max-width:none;width:100%;box-shadow:none;border:0;border-left:2px solid var(--pro-accent);padding-left:8px}.pro-nav-group>a{display:inline-block}.pro-inquiry-wrap{grid-template-columns:1fr;gap:20px}} diff --git a/examples/v830-built-sites/industrial/assets/pro.css b/examples/v830-built-sites/industrial/assets/pro.css new file mode 100644 index 0000000..aa946f1 --- /dev/null +++ b/examples/v830-built-sites/industrial/assets/pro.css @@ -0,0 +1,89 @@ +:root{--pro-text:#173a57;--pro-muted:#6b8191;--pro-border:#d8e3eb;--pro-background:#fff;--pro-surface:#edf3f7;--pro-accent:#16629a;--pro-hero:#0e3959;--pro-radius:2px;--pro-headings:Arial,sans-serif;--pro-wide:1290px} +.pro-header{background:#fff}.pro-logo-symbol{color:#14649b;font-size:38px}.pro-utility{background:#0d3a5a;color:#c6e2f1}.pro-header-cta{border-radius:2px;background:#0c5b94}.pro-industrial-hero{background:linear-gradient(90deg,#eff4f8 0%,#e6eef5 60%,#d7e5f0 100%);color:#123b59}.pro-industrial-hero .pro-hero-copy{padding-right:6%}.pro-industrial-hero .pro-hero-copy h1{font-size:clamp(45px,5.3vw,80px)}.pro-industrial-hero .pro-hero-copy h1 em{color:#186fa4}.pro-industrial-hero .pro-hero-art{border-radius:0;background:#0c466d}.pro-technical{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;gap:3%;overflow:hidden;background:repeating-linear-gradient(0deg,transparent,transparent 39px,#ffffff0b 40px),repeating-linear-gradient(90deg,transparent,transparent 39px,#ffffff0b 40px)}.pro-technical>div{width:21%;height:55%;border-radius:60px;border:27px solid #6ba6d4;transform:skewY(-13deg) rotate(-5deg);box-shadow:18px 17px 0 #14324a,0 0 0 9px #bde2fb inset,12px 22px 50px #081c30}.pro-technical>div:nth-child(2){height:72%;width:27%;border-width:34px}.pro-technical strong{position:absolute;bottom:24px;left:28px;color:#aed1e8;font-size:13px;letter-spacing:.17em}.pro-outline-button{color:#0f5988}.pro-category-band{background:#fff}.pro-category-tiles a{background:#eaf2f7;border-top:4px solid #2176aa;min-height:185px;transition:background .2s}.pro-category-tiles a:hover{background:#dce9f2}.pro-category-tiles strong{font-size:21px}.pro-featured{background:#edf3f7}.pro-card{background:#fff;border-radius:2px}.pro-card-cover{background:#d8e6ef}.pro-art-industrial,.pro-art-product{background:linear-gradient(135deg,#aecadf,#e1f1fb)}.pro-art-center{color:#45789b99}.pro-statement{background:#103e5e;color:#fff}.pro-statement .pro-eyebrow{color:#8dc8eb}.pro-statement p{color:#d3e1e9}.pro-statement .pro-text-link{color:#9cdaff}.pro-inner-hero{background:linear-gradient(115deg,#edf4f9 0%,#d9e9f4 100%)}.pro-inner-hero:after{content:'+';position:absolute;right:11%;top:6%;font-size:350px;font-weight:100;color:#15699b10;line-height:1}.pro-article-hero{background:#dceaf4}.pro-article-hero p{color:#537088}.pro-footer{background:#092c45}.pro-end-cta{background:#0a4772}.pro-end-cta a{background:#fff;color:#144b75!important}.pro-404 h1{color:#156d9d} + +/* SiteForge V5 commercial signature */ +.pro-industrial-hero .pro-hero-art{background-image:url("./visual/hero.svg")!important;background-position:center;background-size:cover;} + +.pro-industrial-hero .pro-hero-art{border-radius:0;box-shadow:25px 25px 0 #ffffff9c}.pro-industrial-hero .pro-hero-art .pro-technical{opacity:0}.pro-category-tiles a{transition:transform .2s,background .2s}.pro-category-tiles a:hover{transform:translateY(-4px);background:#ddeef9}.pro-card{border-radius:0;border:1px solid #cddfe9}.pro-card-cover{background:linear-gradient(145deg,#dceaf0,#c3d9e7)}.pro-art{background:repeating-linear-gradient(0deg,#e2edf4,#e2edf4 24px,#d6e7ef 25px);color:#20577e}.pro-featured{background:#f4f8fb}.pro-statement{background:#103b57;color:#fff}.pro-statement p{color:#d4e5ed}.pro-statement .pro-text-link{color:#a8d8ee}.pro-footer{background:#0e3046;color:#eff5f9} + +/* V8.29 presentation refinement: industrial. Preserve per-theme design language. */ +body.pro-industrial{--pro-studio-ring:rgba(24,101,145,.19);--pro-focus-color:#13709b;--pro-interact-radius:7px} +body.pro-industrial .pro-wrap{max-width:100%;min-width:0} +body.pro-industrial .pro-hero-copy,body.pro-industrial .pro-card-body,body.pro-industrial .pro-card-copy{min-width:0;overflow-wrap:anywhere} +body.pro-industrial .pro-hero-copy h1{font-size:clamp(2.45rem,5.15vw,5.6rem);line-height:1.08;max-width:18ch;text-wrap:balance} +body.pro-industrial .pro-section-head h2{font-size:clamp(1.85rem,3vw,3.25rem);text-wrap:balance} +body.pro-industrial .pro-card,body.pro-industrial .pro-product-card{transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease} +@media(hover:hover){body.pro-industrial .pro-card:hover,body.pro-industrial .pro-product-card:hover{transform:translateY(-3px);box-shadow:0 14px 36px var(--pro-studio-ring)}} +body.pro-industrial :where(button,a,input,select,textarea):focus-visible{outline:3px solid var(--pro-focus-color);outline-offset:3px} +body.pro-industrial img{max-width:100%;height:auto} +body.pro-industrial .pro-card-cover img,body.pro-industrial .pro-gallery-main img{object-fit:cover;max-height:100%} +body.pro-industrial .pro-mobile-toggle,body.pro-industrial .pro-nav-disclose{min-height:44px;min-width:44px} +@media(max-width:860px){body.pro-industrial .pro-home-grid,body.pro-industrial .pro-product-layout,body.pro-industrial .pro-inquiry-wrap{min-width:0}body.pro-industrial .pro-card-grid,body.pro-industrial .pro-grid{gap:clamp(12px,3vw,23px)}} +@media(max-width:560px){body.pro-industrial .pro-wrap{padding-left:max(16px,env(safe-area-inset-left));padding-right:max(16px,env(safe-area-inset-right))}body.pro-industrial .pro-hero-copy h1{font-size:clamp(2rem,9vw,3.2rem)}body.pro-industrial .pro-section-head h2{font-size:clamp(1.75rem,7vw,2.5rem)}body.pro-industrial .pro-section{padding-block:clamp(34px,9vw,60px)}body.pro-industrial .pro-card-cover{height:auto;aspect-ratio:4/3}body.pro-industrial .pro-card-cover img{width:100%;height:100%;object-fit:cover}} +@media(prefers-reduced-motion:reduce){body.pro-industrial .pro-card,body.pro-industrial .pro-product-card{transition:none!important;transform:none!important}} + + +/* V8.30 REAL PAGE COMPOSITION. Built-in theme version 1.3.0 only. + Content-driven sections do not invent client names, certifications or KPIs. */ +.pro-v30-page{--v30-ink:var(--pro-text);--v30-secondary:var(--pro-muted);--v30-line:var(--pro-border);--v30-panel:var(--pro-surface);--v30-max:1180px;color:var(--v30-ink);overflow:clip} +.pro-v30-page .pro-wrap{max-width:var(--v30-max);min-width:0} +.pro-v30-page h1,.pro-v30-page h2{overflow-wrap:anywhere;text-wrap:balance;line-height:1.11} +.pro-v30-page h1{font-size:clamp(2.55rem,5.2vw,5.6rem);margin:18px 0 22px;letter-spacing:-.035em} +.pro-v30-page h2{font-size:clamp(1.8rem,3.3vw,3rem);margin:16px 0 26px;letter-spacing:-.02em} +.pro-v30-page p{line-height:1.75;overflow-wrap:anywhere} +.pro-v30-page img{max-width:100%} +.pro-v30-intro-layout{display:grid;grid-template-columns:minmax(0,1fr) 190px;gap:8vw;align-items:end} +.pro-v30-page-intro{padding:clamp(68px,10vw,128px) 0 clamp(55px,8vw,94px);background:var(--v30-panel)} +.pro-v30-intro-main>p{max-width:610px;font-size:clamp(16px,2vw,21px);color:var(--v30-secondary)} +.pro-v30-intro-aside{border-left:1px solid var(--v30-line);padding-left:27px;display:grid;gap:8px;align-content:end;min-height:120px} +.pro-v30-overline,.pro-v30-caption{font-size:11px;letter-spacing:.12em;color:var(--v30-secondary)} +.pro-v30-index-number{font-size:64px;line-height:1;font-weight:650;letter-spacing:-.08em} +.pro-v30-index-toolbar{display:flex;justify-content:space-between;align-items:end;gap:22px;margin-bottom:28px} +.pro-v30-index-body{background:var(--pro-background)} +.pro-v30-index-body .pro-section-head,.pro-v30-index-toolbar h2{margin:8px 0} +.pro-v30-subtle-link,.pro-v30-text-action{display:inline-flex;gap:10px;text-decoration:none;font-weight:750;font-size:13px;align-items:center;min-height:44px} +.pro-v30-subtle-link:hover,.pro-v30-text-action:hover{text-decoration:underline} +.pro-v30-results{margin-top:clamp(28px,5vw,54px)} +.pro-v30-product-top{padding:26px 0 clamp(60px,8vw,110px);background:var(--v30-panel)} +.pro-v30-crumb{display:flex;flex-wrap:wrap;gap:11px;align-items:center;font-size:12px;color:var(--v30-secondary);margin:8px 0 46px} +.pro-v30-crumb a{text-decoration:underline;text-underline-offset:4px} +.pro-v30-product-head{display:grid;grid-template-columns:minmax(290px,.78fr) minmax(0,1.22fr);align-items:center;gap:clamp(30px,6vw,90px)} +.pro-v30-product-intro>p{font-size:clamp(16px,2vw,19px);color:var(--v30-secondary);max-width:48ch} +.pro-v30-tags{display:flex;gap:8px;flex-wrap:wrap;margin:24px 0 30px}.pro-v30-tags span{padding:8px 13px;border:1px solid var(--v30-line);font-size:12px;border-radius:2px} +.pro-v30-action{display:inline-flex;align-items:center;justify-content:center;min-height:48px} +.pro-v30-main-media{background:var(--pro-surface);aspect-ratio:4/3;overflow:hidden;display:grid;place-items:center;border-radius:var(--pro-radius)} +.pro-v30-main-media .pro-photo{width:100%;height:100%;object-fit:contain} +.pro-v30-product-details{display:grid;grid-template-columns:minmax(0,1.3fr) minmax(270px,.7fr);gap:clamp(30px,7vw,104px)} +.pro-v30-details-main .pro-rich{max-width:760px}.pro-v30-details-side{align-self:start;border-top:3px solid var(--pro-accent);padding-top:25px} +.pro-v30-details-side .pro-specs>div{grid-template-columns:minmax(0,1fr) minmax(0,1.1fr);gap:16px}.pro-v30-details-side .pro-specs strong{overflow-wrap:anywhere} +.pro-v30-reading-head{padding:clamp(50px,8vw,100px) 0 clamp(60px,8vw,100px);background:var(--v30-panel)} +.pro-v30-reading-title{max-width:940px;margin:auto}.pro-v30-reading-title>p{font-size:clamp(16px,2.1vw,22px);max-width:65ch;color:var(--v30-secondary)} +.pro-v30-reading-title time{display:block;margin-top:24px;font-size:13px;color:var(--v30-secondary)} +.pro-v30-reading-layout{display:grid;grid-template-columns:180px minmax(0,750px);gap:clamp(35px,7vw,110px);padding-block:clamp(55px,8vw,110px)} +.pro-v30-reading-aside{display:flex;flex-direction:column;gap:18px;align-self:start;position:sticky;top:30px;font-size:13px} +.pro-v30-reading-rule{height:1px;background:var(--v30-line)} +.pro-v30-reading-content{min-width:0}.pro-v30-reading-content figure{margin:0 0 45px}.pro-v30-reading-content figure img{display:block;width:100%;height:auto;max-height:550px;object-fit:cover} +.pro-v30-reading-content .pro-rich{line-height:1.9;font-size:clamp(16px,1.75vw,18px)}.pro-v30-reading-content .pro-rich>*+*{margin-top:1.3em} +.pro-v30-about-opening{padding:clamp(75px,10vw,130px) 0;background:var(--v30-panel)} +.pro-v30-about-heading{display:grid;grid-template-columns:1.3fr .7fr;gap:9%;align-items:end}.pro-v30-about-heading>p{font-size:clamp(17px,2vw,23px);color:var(--v30-secondary);padding-bottom:12px} +.pro-v30-about-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(36px,8vw,120px);align-items:center} +.pro-v30-about-media{min-height:360px;aspect-ratio:5/4;background:var(--v30-panel);overflow:hidden}.pro-v30-about-media img{width:100%;height:100%;object-fit:cover} +.pro-v30-media-placeholder{height:100%;min-height:360px;display:grid;place-items:center;color:var(--v30-secondary);letter-spacing:.18em;font-size:12px;border:1px solid var(--v30-line)} +.pro-v30-about-copy .pro-rich{max-width:620px}.pro-v30-about-cases{background:var(--v30-panel)} +.pro-v30-contact-header{background:var(--v30-panel);padding:clamp(75px,10vw,135px) 0}.pro-v30-contact-header p{font-size:clamp(17px,2vw,21px);max-width:58ch;color:var(--v30-secondary)} +.pro-v30-contact-layout{display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);gap:clamp(40px,8vw,120px)} +.pro-v30-contact-channel{display:grid;gap:10px;margin-top:45px;border-top:1px solid var(--v30-line);padding-top:25px}.pro-v30-contact-channel span{font-size:12px;color:var(--v30-secondary)}.pro-v30-contact-channel a{font-size:clamp(15px,2vw,24px);overflow-wrap:anywhere;font-weight:650} +.pro-v30-contact-form-wrap{padding:clamp(22px,4vw,48px);background:var(--v30-panel);min-width:0} +.pro-v30-contact-form-wrap .pro-inquiry{margin-top:22px}.pro-v30-contact-form-wrap .pro-inquiry input,.pro-v30-contact-form-wrap textarea{background:var(--pro-background)} +.pro-v30-contact-note{display:grid;align-content:space-between;min-height:270px;gap:24px}.pro-v30-decorative-number{font-size:90px;line-height:1;justify-self:end;color:var(--pro-accent)} +.pro-v30-home-editorial{background:var(--pro-surface)} +.pro-v30-page :where(a,button,input,textarea,select):focus-visible{outline:3px solid var(--pro-accent);outline-offset:3px} +@media(max-width:950px){.pro-v30-product-head,.pro-v30-product-details,.pro-v30-about-grid,.pro-v30-contact-layout{grid-template-columns:1fr;gap:38px}.pro-v30-product-visual{order:-1}.pro-v30-about-heading{grid-template-columns:1fr;gap:4px}.pro-v30-about-media{max-height:430px}.pro-v30-reading-layout{grid-template-columns:1fr;gap:24px}.pro-v30-reading-aside{position:static;flex-direction:row;align-items:center;flex-wrap:wrap}.pro-v30-reading-rule{display:none}} +@media(max-width:600px){.pro-v30-page .pro-wrap{padding-inline:max(18px,env(safe-area-inset-left));}.pro-v30-page h1{font-size:clamp(2.2rem,9.2vw,3.4rem)}.pro-v30-intro-layout{grid-template-columns:1fr;gap:18px}.pro-v30-intro-aside{display:none}.pro-v30-index-toolbar{align-items:start;flex-direction:column;gap:0}.pro-v30-crumb{margin-bottom:24px}.pro-v30-product-top{padding-bottom:42px}.pro-v30-main-media{aspect-ratio:5/4}.pro-v30-product-details{gap:45px}.pro-v30-reading-title{margin:0}.pro-v30-reading-content figure{margin-bottom:22px}.pro-v30-about-media,.pro-v30-media-placeholder{min-height:220px}.pro-v30-contact-form-wrap{padding:20px}.pro-v30-contact-layout{gap:30px}} +@media(prefers-reduced-motion:reduce){.pro-v30-page *{scroll-behavior:auto!important}} + +/* Theme-specific editorial composition */ + .pro-v30-technical-index .pro-v30-page-intro{background:#eaf2f4;border-bottom:5px solid #154c62}.pro-v30-product-industrial .pro-v30-product-top{background:#eef3f4}.pro-v30-product-industrial .pro-v30-main-media{background:#fff;border:1px solid #d4e0e4}.pro-v30-product-industrial .pro-v30-main-media .pro-photo{object-fit:contain;padding:clamp(8px,2vw,24px)}.pro-v30-product-industrial .pro-v30-details-side{background:#edf3f5;padding:27px;border:1px solid #d8e4e7;border-top:4px solid #24718e}.pro-v30-article-industrial .pro-v30-reading-head{border-left:solid clamp(6px,1vw,18px) #276780}.pro-v30-about-industrial .pro-v30-about-media{border-radius:4px}.pro-v30-contact-industrial .pro-v30-contact-form-wrap{background:#eef4f6} + +/* Retain existing gallery runtime behavior with re-composed product layout. */ +.pro-v30-page .pro-product-media{height:auto;min-height:0} diff --git a/examples/v830-built-sites/industrial/assets/pro.js b/examples/v830-built-sites/industrial/assets/pro.js new file mode 100644 index 0000000..9cf100d --- /dev/null +++ b/examples/v830-built-sites/industrial/assets/pro.js @@ -0,0 +1,72 @@ +'use strict';(()=>{ + const menu=document.querySelector('[data-pro-menu]'); const nav=document.querySelector('#pro-navigation'); + if(menu&&nav){menu.addEventListener('click',()=>{const open=menu.getAttribute('aria-expanded')!=='true';menu.setAttribute('aria-expanded',String(open));nav.classList.toggle('is-open',open);menu.setAttribute('aria-label',open?'关闭导航':'打开导航');});} + // Drawer navigation. The same markup is used across the four professional themes. + const mobileNav=document.querySelector('#pro-navigation'); + let drawerBackdrop=null,drawerClose=null,returnFocus=null; + if(menu&&mobileNav){ + const originalParent=mobileNav.parentNode,originalNext=mobileNav.nextSibling; + const heading=document.createElement('div');heading.className='sf-drawer-header'; + const title=document.createElement('strong');title.textContent='网站导航'; + drawerClose=document.createElement('button');drawerClose.type='button';drawerClose.className='sf-drawer-close';drawerClose.textContent='×';drawerClose.setAttribute('aria-label','关闭网站导航'); + heading.append(title,drawerClose);mobileNav.prepend(heading); + drawerBackdrop=document.createElement('div');drawerBackdrop.className='sf-mobile-drawer-backdrop';drawerBackdrop.hidden=false;document.body.append(drawerBackdrop); + function setDrawer(open,focusBack=true){ + const isMobile=window.matchMedia('(max-width:1024px)').matches; + open=Boolean(open&&isMobile); + if(open){returnFocus=document.activeElement;document.body.append(mobileNav);} + else if(mobileNav.parentNode!==originalParent){if(originalNext&&originalNext.parentNode===originalParent)originalParent.insertBefore(mobileNav,originalNext);else originalParent.append(mobileNav);} + mobileNav.classList.toggle('is-open',open);drawerBackdrop.classList.toggle('is-open',open); + document.body.classList.toggle('sf-drawer-open',open); + menu.setAttribute('aria-expanded',String(open));menu.setAttribute('aria-label',open?'关闭导航':'打开导航'); + mobileNav.setAttribute('aria-hidden',String(!open&&isMobile)); + if('inert' in mobileNav)mobileNav.inert=!open&&isMobile; + if(open)drawerClose.focus(); + else if(focusBack&&returnFocus instanceof HTMLElement){returnFocus.focus();returnFocus=null;} + } + // Replace the old inline-expansion listener: use capture to stop the old listener. + menu.addEventListener('click',e=>{if(!window.matchMedia('(max-width:1024px)').matches)return;e.stopImmediatePropagation();setDrawer(!mobileNav.classList.contains('is-open'));},true); + drawerClose.addEventListener('click',()=>setDrawer(false)); + drawerBackdrop.addEventListener('click',()=>setDrawer(false)); + document.querySelectorAll('[data-mobile-open-menu]').forEach(b=>b.addEventListener('click',()=>setDrawer(true))); + mobileNav.addEventListener('click',e=>{if(e.target.closest('a'))setDrawer(false,false)}); + document.addEventListener('keydown',e=>{ + if(e.key==='Escape'&&mobileNav.classList.contains('is-open')){e.preventDefault();setDrawer(false);} + if(e.key!=='Tab'||!mobileNav.classList.contains('is-open'))return; + const els=[...mobileNav.querySelectorAll('button:not([disabled]),a[href]')].filter(el=>el.getClientRects().length&&!el.closest('[hidden]')); + if(!els.length)return;const first=els[0],last=els[els.length-1]; + if(e.shiftKey&&document.activeElement===first){e.preventDefault();last.focus();} + else if(!e.shiftKey&&document.activeElement===last){e.preventDefault();first.focus();} + }); + window.matchMedia('(max-width:1024px)').addEventListener('change',()=>setDrawer(false,false)); + if('inert' in mobileNav&&window.matchMedia('(max-width:1024px)').matches)mobileNav.inert=true; + // Do not strand catalogue links when the old mobile mega-button is hidden. + const megaLinks=document.querySelectorAll('[data-pro-mega] a'); + if(megaLinks.length){const wrap=document.createElement('div');wrap.className='sf-drawer-extra';const h=document.createElement('strong');h.textContent='更多分类与系列';wrap.append(h); + [...megaLinks].slice(0,20).forEach(a=>{const clone=a.cloneNode(true);wrap.append(clone);});mobileNav.append(wrap);} + } + const tabbar=document.querySelector('[data-mobile-tabs]'); + if(tabbar){tabbar.style.setProperty('--sf-mobile-tab-count',String(tabbar.children.length));} + const megaButton=document.querySelector('[data-pro-catalog]'), mega=document.querySelector('[data-pro-mega]'); + if(megaButton&&mega){function setMega(open){mega.hidden=!open;mega.classList.toggle('is-open',open);megaButton.setAttribute('aria-expanded',String(open));} + megaButton.addEventListener('click',()=>setMega(mega.hidden)); + document.addEventListener('keydown',e=>{if(e.key==='Escape')setMega(false);}); + document.addEventListener('click',e=>{if(!mega.hidden&&!mega.contains(e.target)&&!megaButton.contains(e.target))setMega(false);}); + } + document.querySelectorAll('.pro-nav-disclose').forEach(button=>{button.addEventListener('click',()=>{let panel=button.parentElement.querySelector('.pro-nav-children');let visible=button.getAttribute('aria-expanded')==='true';button.setAttribute('aria-expanded',String(!visible));panel.hidden=visible;});}); + document.querySelectorAll('.pro-gallery-thumbs').forEach(container=>{const main=container.parentElement.querySelector('.pro-product-media img');const buttons=[...container.querySelectorAll('[data-gallery-image]')]; + buttons.forEach(b=>{b.addEventListener('click',()=>{buttons.forEach(x=>x.setAttribute('aria-pressed',String(x===b)));if(main){main.src=b.dataset.galleryImage;main.alt=b.querySelector('img')?.alt||'';}});}); + if(!main)return;main.tabIndex=0;main.style.cursor='zoom-in';const open=()=>{const pane=document.createElement('div');pane.className='pro-gallery-lightbox';pane.setAttribute('role','dialog');pane.setAttribute('aria-label','产品大图预览');let img=document.createElement('img');img.src=main.src;img.alt=main.alt;const close=document.createElement('button');close.type='button';close.textContent='关闭 ×';pane.append(img,close);document.body.append(pane);const done=()=>{pane.remove();document.removeEventListener('keydown',esc);main.focus();};const esc=e=>{if(e.key==='Escape')done();};document.addEventListener('keydown',esc);close.addEventListener('click',done);pane.addEventListener('click',e=>{if(e.target===pane)done();});close.focus();};main.addEventListener('click',open);main.addEventListener('keydown',e=>{if(e.key==='Enter')open();}); + }); + document.querySelectorAll('.pro-filter-scope').forEach(scope=>{ + const panel=scope.previousElementSibling;if(!panel||!panel.classList.contains('pro-filter-panel'))return; + const cards=Array.from(scope.querySelectorAll('.pro-card')); + const blank=document.createElement('div');blank.className='pro-filter-empty';blank.hidden=true;blank.textContent='没有找到符合条件的内容,请调整关键词或筛选条件。';scope.append(blank); + const q=panel.querySelector('[data-pro-filter-search]'),b=panel.querySelector('[data-pro-filter-brand]'),c=panel.querySelector('[data-pro-filter-category]'),count=panel.querySelector('[data-pro-filter-count]'); + function options(sel,key){const vals=[...new Set(cards.map(x=>x.dataset[key]||'').filter(Boolean))].sort();vals.forEach(x=>sel.add(new Option(x,x)));if(!vals.length)sel.closest('label').hidden=true;} + options(b,'brand');options(c,'category'); + function run(){const str=q.value.trim().toLocaleLowerCase();let visible=0; + cards.forEach(el=>{const hit=el.textContent.toLocaleLowerCase().includes(str)&&(!b.value||el.dataset.brand===b.value)&&(!c.value||el.dataset.category===c.value);el.hidden=!hit;visible+=Number(hit);});count.textContent=`共 ${visible} 条`;blank.hidden=visible!==0;} + [q,b,c].forEach(x=>x.addEventListener(x===q?'input':'change',run));run(); + }); +})(); diff --git a/examples/v830-built-sites/industrial/assets/site-runtime.js b/examples/v830-built-sites/industrial/assets/site-runtime.js new file mode 100644 index 0000000..e4715e8 --- /dev/null +++ b/examples/v830-built-sites/industrial/assets/site-runtime.js @@ -0,0 +1,31 @@ +'use strict'; +(()=>{ + const $=s=>document.querySelector(s), $$=s=>[...document.querySelectorAll(s)]; + const menu=$('.sf-menu-toggle');if(menu){menu.addEventListener('click',()=>{let open=menu.getAttribute('aria-expanded')!=='true';menu.setAttribute('aria-expanded',String(open));$('#sf-primary-links')?.classList.toggle('is-open',open);});} + // Filter actual static content cards, no API is needed at runtime. + $$('.sf-collection').forEach(grid=>{ + const cards=$$('.sf-item',grid); + if(cards.length<2)return; + const toolbar=document.createElement('div');toolbar.className='sf-filters'; + const search=document.createElement('input');search.type='search';search.placeholder='筛选当前列表';search.setAttribute('aria-label','筛选当前列表'); + const status=document.createElement('span');status.setAttribute('aria-live','polite');status.style.fontSize='12px'; + const brand=document.createElement('select');brand.setAttribute('aria-label','按品牌筛选'); + const category=document.createElement('select');category.setAttribute('aria-label','按分类筛选'); + function fill(el,field,all){el.append(new Option(all,''));const vals=[...new Set(cards.map(x=>x.dataset[field]||'').filter(Boolean))].sort();vals.forEach(v=>el.append(new Option(v,v)));if(!vals.length)el.hidden=true;} + fill(brand,'brand','全部品牌');fill(category,'category','全部分类'); + toolbar.append(search,brand,category,status);grid.parentNode.insertBefore(toolbar,grid); + function apply(){let val=search.value.trim().toLocaleLowerCase();let visible=0;cards.forEach(card=>{let hit=card.textContent.toLocaleLowerCase().includes(val)&&(!brand.value||card.dataset.brand===brand.value)&&(!category.value||card.dataset.category===category.value);card.hidden=!hit;if(hit)visible++;});status.textContent=`共 ${visible} 项`;} + search.addEventListener('input',apply);brand.addEventListener('change',apply);category.addEventListener('change',apply);apply(); + }); + const input=$('#sf-search'),root=$('#sf-search-results'),count=$('#sf-search-count'); + if(input&&root){ + let data=[];const params=new URLSearchParams(location.search);input.value=params.get('q')||''; + let debounce=null; + const render=()=>{let q=input.value.trim().toLocaleLowerCase();let found=q?data.filter(d=>`${d.title} ${d.summary} ${d.brand} ${d.type}`.toLocaleLowerCase().includes(q)).slice(0,100):data.slice(0,30); + root.replaceChildren();count.textContent=`${found.length} 条结果${!q?'(显示前30条)':''}`; + found.forEach(d=>{let article=document.createElement('article'),a=document.createElement('a'),small=document.createElement('small'),p=document.createElement('p');article.className='sf-search-result';a.textContent=d.title;a.href=d.url.replace(/^\//,'');small.textContent=d.type;p.textContent=d.summary;article.append(a,small,p);root.append(article);}); + };const base=document.querySelector('base')?.href||location.href; + fetch(new URL('search-index.json',base)).then(r=>{if(!r.ok)throw Error('index unavailable');return r.json();}).then(v=>{data=v;render()}).catch(()=>{count.textContent='搜索索引加载失败,请检查站点文件部署路径';}); + input.addEventListener('input',()=>{clearTimeout(debounce);debounce=setTimeout(render,100)}); + } +})(); diff --git a/examples/v830-built-sites/industrial/assets/theme.css b/examples/v830-built-sites/industrial/assets/theme.css new file mode 100644 index 0000000..50bf80e --- /dev/null +++ b/examples/v830-built-sites/industrial/assets/theme.css @@ -0,0 +1,4 @@ +:root{--blue:#0a3d5c;--sky:#daeaf2;--orange:#ef8f35;--text:#1d3441}*{box-sizing:border-box}body{margin:0;color:var(--text);background:#f8fafb;font-family:Inter,"Segoe UI",Arial,sans-serif;line-height:1.6}a{color:inherit;text-decoration:none}img{max-width:100%;object-fit:contain}.wrap{width:min(1300px,90%);margin:auto}.top{background:#153d56;color:#a7c5d5;font-size:10px;letter-spacing:2px}.top .wrap{display:flex;justify-content:space-between;padding:9px 0}header{background:white;border-bottom:1px solid #e0e8ea}.header-inner{min-height:94px;display:flex;justify-content:space-between;align-items:center;gap:20px}.brand{display:flex;align-items:center;gap:12px;font-size:21px;font-weight:800;letter-spacing:-.5px;line-height:1}.brand-icon{display:grid;place-items:center;width:43px;height:43px;background:var(--blue);color:white;font-size:26px}.brand small{display:block;font-size:10px;color:#718793;letter-spacing:2px;margin-top:9px;font-weight:500}nav{display:flex;gap:25px;font-size:13px;font-weight:650;flex-wrap:wrap}nav a:hover{color:#eb8725}.request{background:#e88c36;color:white;padding:15px 20px;font-size:11px;font-weight:800;white-space:nowrap;letter-spacing:.5px}.hero{background:linear-gradient(107deg,#073653 0%,#0e5270 51%,#14748c 100%);color:white;overflow:hidden}.hero-grid{display:grid;grid-template-columns:55% 45%;min-height:530px}.hero-text{padding:76px 25px 60px 0;position:relative;z-index:1}.kicker{font-size:11px;letter-spacing:2px;font-weight:750;color:#ce882e}.hero .kicker{color:#f5ac57}.kicker i{display:inline-block;width:22px;height:2px;background:#f5ac57;vertical-align:middle;margin-right:10px}.hero h1{font-size:clamp(48px,6vw,86px);letter-spacing:-3px;line-height:1.02;max-width:700px;margin:35px 0 26px}.hero p{max-width:470px;color:#c6e1e9;font-size:17px}.button{display:inline-flex;gap:55px;align-items:center;background:#ef9136;padding:18px 22px;font-size:12px;letter-spacing:1px;font-weight:800;margin-top:26px}.button b{font-size:18px}.hero-tags{display:flex;gap:22px;margin-top:60px;font-size:10px;color:#85bfcb;letter-spacing:1px}.hero-art{position:relative;display:grid;place-items:center;overflow:hidden;background:radial-gradient(circle at center,#2c94a6 2%,#11617b 45%,transparent 70%)}.hero-art:before,.hero-art:after{content:"";position:absolute;width:540px;height:540px;border:1px solid #ffffff25;transform:rotate(45deg)}.hero-art:after{width:380px;height:380px}.hero-art img{position:relative;z-index:3;width:100%;max-height:480px;filter:drop-shadow(0 20px 20px #002a3b55)}.hero-art>span{position:relative;z-index:3;color:#c6eaf0;font-size:25px;letter-spacing:8px;text-align:center;font-weight:300}.ring{position:absolute;width:430px;height:430px;border:28px solid #ffffff13;border-radius:50%;transform:rotateX(55deg) rotate(45deg)}.ring-2{width:290px;height:290px;border-color:#ffffff1d}.ring-3{width:150px;height:150px;border-color:#fba74b55}.subhero{padding:80px 0;background:linear-gradient(110deg,#073e5d,#0d6981);color:white}.subhero h1{font-size:clamp(40px,5.3vw,68px);line-height:1.1;margin:20px 0}.subhero p{color:#b8d6df}.main{padding:58px 0 100px}.metrics{display:grid;grid-template-columns:repeat(3,1fr);background:white;margin-top:-90px;position:relative;box-shadow:0 15px 45px #0b4f7515}.metrics>div{padding:25px 34px;display:flex;align-items:center;gap:18px;border-right:1px solid #eef3f5}.metrics strong{color:#dc7e2d;font-size:30px}.metrics span{letter-spacing:1px;font-size:11px;font-weight:800}.titlebar{margin:65px 0 28px;display:flex;justify-content:space-between;align-items:end}.titlebar h2{font-size:37px;margin:12px 0 0}.titlebar>a{color:#ba6d2f;font-size:12px;font-weight:800}.product-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:23px}.product{border:1px solid #e0e8ed;background:white}.product:hover{box-shadow:0 15px 35px #194b6518}.product-img{height:225px;display:flex;align-items:center;justify-content:center;background:linear-gradient(125deg,#e8f0f4,#cadce6);overflow:hidden}.product-img img{height:100%;width:100%;object-fit:contain}.technical-graphic{width:110px;height:110px;border:18px solid #96b8c8;border-radius:50%;position:relative;box-shadow:0 20px 0 #244d6120}.technical-graphic span{position:absolute;color:#e9fbff}.technical-graphic span:first-child{top:-56px;left:-50px}.technical-graphic span:nth-child(2){top:-56px;right:-50px}.technical-graphic span:nth-child(3){bottom:-55px;left:-45px}.technical-graphic span:nth-child(4){bottom:-55px;right:-45px}.product-info{padding:25px}.product-info>span{font-size:9px;color:#c17a38;letter-spacing:1.5px;font-weight:700}.product-info h3{font-size:21px;margin:8px 0}.product-info p{color:#6d8792;font-size:13px}.arrow{border-top:1px solid #e6eef1;margin-top:25px;padding-top:18px;display:flex;justify-content:space-between;font-size:11px;letter-spacing:1px;font-weight:800;color:#0c6788}.rich-content{margin:30px 0}.rich-content p{color:#617787}.section{padding:40px 0}.feature-grid,.stats{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}.feature{background:white;padding:25px;border-top:4px solid #f09c52}.stat strong{display:block;font-size:40px}.stat span{color:#78909c}.cta{padding:50px;background:#0e5675;color:white}.detail-image img{max-height:560px}footer{background:#0f334a;color:white;padding:65px 0 25px}.footer-cols{display:flex;justify-content:space-between;gap:40px}.footer-cols h2{font-size:26px}.footer-cols p{color:#96b1bf}.bottom{border-top:1px solid #36596d;margin-top:65px;padding-top:22px;display:flex;justify-content:space-between;letter-spacing:1px;font-size:10px;color:#9cb9c7}@media(max-width:940px){.header-inner{flex-wrap:wrap;padding:16px 0}nav{order:3;width:100%}.request{display:none}.hero-grid{grid-template-columns:1fr}.hero-text{padding-right:0}.hero-art{min-height:300px}.metrics{margin-top:0}}@media(max-width:660px){.product-grid,.metrics,.feature-grid,.stats{grid-template-columns:1fr}.hero h1{font-size:51px}.hero-tags{flex-wrap:wrap}.footer-cols,.bottom{flex-direction:column}.top span:last-child{display:none}.subhero{padding:60px 0}} + +/* V8.29 baseline: accessible touch/focus and reduced motion */ +:where(a,button,input,select,textarea):focus-visible{outline:3px solid currentColor;outline-offset:3px}@media(max-width:560px){img{max-width:100%;height:auto}body{overflow-wrap:anywhere}}@media(prefers-reduced-motion:reduce){*,*:before,*:after{scroll-behavior:auto!important;transition:none!important;animation-duration:.01ms!important}} diff --git a/examples/v830-built-sites/industrial/assets/visual/hero.svg b/examples/v830-built-sites/industrial/assets/visual/hero.svg new file mode 100644 index 0000000..5c363ca --- /dev/null +++ b/examples/v830-built-sites/industrial/assets/visual/hero.svg @@ -0,0 +1 @@ +MATERIAL SYSTEMS diff --git a/examples/v830-built-sites/industrial/brand/index.html b/examples/v830-built-sites/industrial/brand/index.html new file mode 100644 index 0000000..8cc47bf --- /dev/null +++ b/examples/v830-built-sites/industrial/brand/index.html @@ -0,0 +1,41 @@ +品牌展示跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    +
    ENGINEERING MATERIALS / INDEX

    品牌展示

    Explore our brand

    BROWSE / EXPLORE03本页展示内容
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/brands/arc/index.html b/examples/v830-built-sites/industrial/brands/arc/index.html new file mode 100644 index 0000000..91dd3f8 --- /dev/null +++ b/examples/v830-built-sites/industrial/brands/arc/index.html @@ -0,0 +1,38 @@ +ARC跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    BRAND PROFILE / PARTNERS

    ARC

    ARC 品牌产品与应用。

    +
    ARBRAND
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/brands/index.html b/examples/v830-built-sites/industrial/brands/index.html new file mode 100644 index 0000000..3a7cc5e --- /dev/null +++ b/examples/v830-built-sites/industrial/brands/index.html @@ -0,0 +1,41 @@ +品牌中心跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    +
    ENGINEERING MATERIALS / INDEX

    品牌中心

    探索与产品相关的品牌。

    BROWSE / EXPLORE03本页展示内容
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/brands/mono/index.html b/examples/v830-built-sites/industrial/brands/mono/index.html new file mode 100644 index 0000000..8bab665 --- /dev/null +++ b/examples/v830-built-sites/industrial/brands/mono/index.html @@ -0,0 +1,30 @@ +MONO跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    BRAND PROFILE / PARTNERS

    MONO

    MONO 品牌产品与应用。

    +
    MOBRAND
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/brands/nova/index.html b/examples/v830-built-sites/industrial/brands/nova/index.html new file mode 100644 index 0000000..d9817be --- /dev/null +++ b/examples/v830-built-sites/industrial/brands/nova/index.html @@ -0,0 +1,38 @@ +NOVA跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    BRAND PROFILE / PARTNERS

    NOVA

    NOVA 品牌产品与应用。

    +
    NOBRAND
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/case/index.html b/examples/v830-built-sites/industrial/case/index.html new file mode 100644 index 0000000..e25831e --- /dev/null +++ b/examples/v830-built-sites/industrial/case/index.html @@ -0,0 +1,41 @@ +案例展示跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/cases/1/index.html b/examples/v830-built-sites/industrial/cases/1/index.html new file mode 100644 index 0000000..9930490 --- /dev/null +++ b/examples/v830-built-sites/industrial/cases/1/index.html @@ -0,0 +1,12 @@ +精选项目 · 01跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    SELECTED WORK / PROJECT

    精选项目 · 01

    展示项目背景、过程与成果。

    项目地点
    Demo location
    所属行业
    Demo industry

    本页仅为项目结构示例,并非实际完成的工程项目。

    浏览更多案例 →
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/cases/2/index.html b/examples/v830-built-sites/industrial/cases/2/index.html new file mode 100644 index 0000000..a192334 --- /dev/null +++ b/examples/v830-built-sites/industrial/cases/2/index.html @@ -0,0 +1,12 @@ +精选项目 · 02跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    SELECTED WORK / PROJECT

    精选项目 · 02

    展示项目背景、过程与成果。

    项目地点
    Demo location
    所属行业
    Demo industry

    本页仅为项目结构示例,并非实际完成的工程项目。

    浏览更多案例 →
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/cases/3/index.html b/examples/v830-built-sites/industrial/cases/3/index.html new file mode 100644 index 0000000..b668ad0 --- /dev/null +++ b/examples/v830-built-sites/industrial/cases/3/index.html @@ -0,0 +1,12 @@ +精选项目 · 03跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    SELECTED WORK / PROJECT

    精选项目 · 03

    展示项目背景、过程与成果。

    项目地点
    Demo location
    所属行业
    Demo industry

    本页仅为项目结构示例,并非实际完成的工程项目。

    浏览更多案例 →
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/cases/index.html b/examples/v830-built-sites/industrial/cases/index.html new file mode 100644 index 0000000..c4cdd0c --- /dev/null +++ b/examples/v830-built-sites/industrial/cases/index.html @@ -0,0 +1,41 @@ +项目案例跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/categories/term-79e34764f8ce/index.html b/examples/v830-built-sites/industrial/categories/term-79e34764f8ce/index.html new file mode 100644 index 0000000..8b42397 --- /dev/null +++ b/examples/v830-built-sites/industrial/categories/term-79e34764f8ce/index.html @@ -0,0 +1,29 @@ +旗舰系列跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    DISCOVER / CATEGORY

    旗舰系列

    分类产品与相关信息

    首页/旗舰系列
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/categories/term-8d6647722ef3/index.html b/examples/v830-built-sites/industrial/categories/term-8d6647722ef3/index.html new file mode 100644 index 0000000..1ab7a23 --- /dev/null +++ b/examples/v830-built-sites/industrial/categories/term-8d6647722ef3/index.html @@ -0,0 +1,29 @@ +专业系列跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    DISCOVER / CATEGORY

    专业系列

    分类产品与相关信息

    首页/专业系列
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/categories/term-95acf900fafc/index.html b/examples/v830-built-sites/industrial/categories/term-95acf900fafc/index.html new file mode 100644 index 0000000..b220b32 --- /dev/null +++ b/examples/v830-built-sites/industrial/categories/term-95acf900fafc/index.html @@ -0,0 +1,29 @@ +畅销系列跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    DISCOVER / CATEGORY

    畅销系列

    分类产品与相关信息

    首页/畅销系列
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/categories/term-a68a8656a4dc/index.html b/examples/v830-built-sites/industrial/categories/term-a68a8656a4dc/index.html new file mode 100644 index 0000000..6681849 --- /dev/null +++ b/examples/v830-built-sites/industrial/categories/term-a68a8656a4dc/index.html @@ -0,0 +1,29 @@ +定制系列跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    DISCOVER / CATEGORY

    定制系列

    分类产品与相关信息

    首页/定制系列
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/commercial-readiness.json b/examples/v830-built-sites/industrial/commercial-readiness.json new file mode 100644 index 0000000..7f79e5b --- /dev/null +++ b/examples/v830-built-sites/industrial/commercial-readiness.json @@ -0,0 +1,34 @@ +{ + "ready_for_review": true, + "commercially_certified": false, + "blockers": [], + "warnings": [ + { + "code": "brand_logo", + "message": "尚未替换成企业正式 Logo" + }, + { + "code": "placeholder_images", + "count": 75, + "message": "部分页面仍使用示意图,正式发布前请替换为真实且有使用权的图片" + }, + { + "code": "demo_content", + "message": "检测到演示或默认文案,正式发布前请逐页核对" + }, + { + "code": "form_not_configured", + "message": "尚未配置 HTTPS 询盘接收服务;目前仅提供邮件联系" + }, + { + "code": "legal_pages", + "message": "请根据目标国家/地区法律审查是否需要隐私政策与 Cookie 声明" + } + ], + "metrics": { + "html_pages": 38, + "artwork_fallbacks": 75, + "pages_with_body": 18 + }, + "note": "仅为本地结构化交付清单,不等于合法合规、内容准确、无障碍、性能或生产上线认证" +} \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/contact/index.html b/examples/v830-built-sites/industrial/contact/index.html new file mode 100644 index 0000000..6aaf479 --- /dev/null +++ b/examples/v830-built-sites/industrial/contact/index.html @@ -0,0 +1,16 @@ +联系我们跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    CONNECT / CONTACT

    联系我们

    欢迎通过邮件与我们的演示团队取得联系。

    +
    LET'S START A CONVERSATION

    咨询工程材料

    本页为演示内容。您可以在网站工厂中直接修改和替换。

    + + +
    HOW TO REACH US

    您可以通过本页提供的联系渠道咨询产品、项目或合作事项。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/faq/index.html b/examples/v830-built-sites/industrial/faq/index.html new file mode 100644 index 0000000..baad0b6 --- /dev/null +++ b/examples/v830-built-sites/industrial/faq/index.html @@ -0,0 +1,13 @@ +常见问题跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    EXPLORE

    常见问题

    更多问题可以联系我们。

    +
    ABOUT / DISCOVER

    常见问题

    本页为演示内容。您可以在网站工厂中直接修改和替换。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/index.html b/examples/v830-built-sites/industrial/index.html new file mode 100644 index 0000000..1b531b1 --- /dev/null +++ b/examples/v830-built-sites/industrial/index.html @@ -0,0 +1,89 @@ +首页跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    ENGINEERED FOR WHAT'S NEXT / 001

    ARC INDUSTRIES BUILT TO PERFORM.

    面向现代工程的产品与服务

    FORM / FUNCTION
    +
    + +
    APPLICATIONS & SUPPORT

    专注可靠交付,服务多元项目。

    面向现代工程的产品与服务

    服务与解决方案 ↗
    + +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/news/1/index.html b/examples/v830-built-sites/industrial/news/1/index.html new file mode 100644 index 0000000..c6830d2 --- /dev/null +++ b/examples/v830-built-sites/industrial/news/1/index.html @@ -0,0 +1,13 @@ +企业动态 · 01跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    IDEAS / JOURNAL

    企业动态 · 01

    在这里发布新闻资讯与品牌动态。

    +

    这是可替换的新闻正文内容,可包含图片、表格和链接。

    ← 返回资讯
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/news/2/index.html b/examples/v830-built-sites/industrial/news/2/index.html new file mode 100644 index 0000000..bcdec4d --- /dev/null +++ b/examples/v830-built-sites/industrial/news/2/index.html @@ -0,0 +1,13 @@ +企业动态 · 02跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    IDEAS / JOURNAL

    企业动态 · 02

    在这里发布新闻资讯与品牌动态。

    +

    这是可替换的新闻正文内容,可包含图片、表格和链接。

    ← 返回资讯
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/news/3/index.html b/examples/v830-built-sites/industrial/news/3/index.html new file mode 100644 index 0000000..8b9274c --- /dev/null +++ b/examples/v830-built-sites/industrial/news/3/index.html @@ -0,0 +1,13 @@ +企业动态 · 03跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    IDEAS / JOURNAL

    企业动态 · 03

    在这里发布新闻资讯与品牌动态。

    +

    这是可替换的新闻正文内容,可包含图片、表格和链接。

    ← 返回资讯
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/news/index.html b/examples/v830-built-sites/industrial/news/index.html new file mode 100644 index 0000000..90bc080 --- /dev/null +++ b/examples/v830-built-sites/industrial/news/index.html @@ -0,0 +1,41 @@ +新闻资讯跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/nginx-snippet.conf b/examples/v830-built-sites/industrial/nginx-snippet.conf new file mode 100644 index 0000000..5156189 --- /dev/null +++ b/examples/v830-built-sites/industrial/nginx-snippet.conf @@ -0,0 +1,4 @@ +# SiteForge 生成:将本文件内容合并到 Nginx server {} 内 +index index.html; +error_page 404 /404.html; +location / { try_files $uri $uri/ =404; } diff --git a/examples/v830-built-sites/industrial/post/index.html b/examples/v830-built-sites/industrial/post/index.html new file mode 100644 index 0000000..3b72e1d --- /dev/null +++ b/examples/v830-built-sites/industrial/post/index.html @@ -0,0 +1,41 @@ +新闻展示跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/product/index.html b/examples/v830-built-sites/industrial/product/index.html new file mode 100644 index 0000000..c685da3 --- /dev/null +++ b/examples/v830-built-sites/industrial/product/index.html @@ -0,0 +1,81 @@ +产品展示跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/products/1/index.html b/examples/v830-built-sites/industrial/products/1/index.html new file mode 100644 index 0000000..c9229f1 --- /dev/null +++ b/examples/v830-built-sites/industrial/products/1/index.html @@ -0,0 +1,17 @@ +Materials Alpha跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    +
    ENGINEERING MATERIALS / DETAILS

    Materials Alpha

    Materials Alpha — 针对多样应用的演示产品。

    NOVA旗舰系列
    咨询相关信息 ↗
    +
    +
    MaPRODUCT
    +
    +
    OVERVIEW / 产品资料

    产品资料

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/products/2/index.html b/examples/v830-built-sites/industrial/products/2/index.html new file mode 100644 index 0000000..b3f5a4f --- /dev/null +++ b/examples/v830-built-sites/industrial/products/2/index.html @@ -0,0 +1,17 @@ +Materials Beta跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    +
    ENGINEERING MATERIALS / DETAILS

    Materials Beta

    Materials Beta — 针对多样应用的演示产品。

    NOVA旗舰系列
    咨询相关信息 ↗
    +
    +
    MaPRODUCT
    +
    +
    OVERVIEW / 产品资料

    产品资料

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/products/3/index.html b/examples/v830-built-sites/industrial/products/3/index.html new file mode 100644 index 0000000..724e69d --- /dev/null +++ b/examples/v830-built-sites/industrial/products/3/index.html @@ -0,0 +1,17 @@ +Materials Gamma跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    +
    ENGINEERING MATERIALS / DETAILS

    Materials Gamma

    Materials Gamma — 针对多样应用的演示产品。

    ARC畅销系列
    咨询相关信息 ↗
    +
    +
    MaPRODUCT
    +
    +
    OVERVIEW / 产品资料

    产品资料

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/products/4/index.html b/examples/v830-built-sites/industrial/products/4/index.html new file mode 100644 index 0000000..06a3987 --- /dev/null +++ b/examples/v830-built-sites/industrial/products/4/index.html @@ -0,0 +1,17 @@ +Materials Delta跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    +
    ENGINEERING MATERIALS / DETAILS

    Materials Delta

    Materials Delta — 针对多样应用的演示产品。

    ARC畅销系列
    咨询相关信息 ↗
    +
    +
    MaPRODUCT
    +
    +
    OVERVIEW / 产品资料

    产品资料

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/products/5/index.html b/examples/v830-built-sites/industrial/products/5/index.html new file mode 100644 index 0000000..aa67905 --- /dev/null +++ b/examples/v830-built-sites/industrial/products/5/index.html @@ -0,0 +1,17 @@ +Materials Epsilon跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    +
    ENGINEERING MATERIALS / DETAILS

    Materials Epsilon

    Materials Epsilon — 针对多样应用的演示产品。

    MONO定制系列
    咨询相关信息 ↗
    +
    +
    MaPRODUCT
    +
    +
    OVERVIEW / 产品资料

    产品资料

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/products/6/index.html b/examples/v830-built-sites/industrial/products/6/index.html new file mode 100644 index 0000000..c92e02f --- /dev/null +++ b/examples/v830-built-sites/industrial/products/6/index.html @@ -0,0 +1,17 @@ +Materials Zeta跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    +
    ENGINEERING MATERIALS / DETAILS

    Materials Zeta

    Materials Zeta — 针对多样应用的演示产品。

    MONO定制系列
    咨询相关信息 ↗
    +
    +
    MaPRODUCT
    +
    +
    OVERVIEW / 产品资料

    产品资料

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/products/7/index.html b/examples/v830-built-sites/industrial/products/7/index.html new file mode 100644 index 0000000..db16bf0 --- /dev/null +++ b/examples/v830-built-sites/industrial/products/7/index.html @@ -0,0 +1,17 @@ +Materials Eta跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    +
    ENGINEERING MATERIALS / DETAILS

    Materials Eta

    Materials Eta — 针对多样应用的演示产品。

    NOVA专业系列
    咨询相关信息 ↗
    +
    +
    MaPRODUCT
    +
    +
    OVERVIEW / 产品资料

    产品资料

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/products/8/index.html b/examples/v830-built-sites/industrial/products/8/index.html new file mode 100644 index 0000000..16b54fc --- /dev/null +++ b/examples/v830-built-sites/industrial/products/8/index.html @@ -0,0 +1,17 @@ +Materials Theta跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    +
    ENGINEERING MATERIALS / DETAILS

    Materials Theta

    Materials Theta — 针对多样应用的演示产品。

    ARC专业系列
    咨询相关信息 ↗
    +
    +
    MaPRODUCT
    +
    +
    OVERVIEW / 产品资料

    产品资料

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/products/index.html b/examples/v830-built-sites/industrial/products/index.html new file mode 100644 index 0000000..cd7f96b --- /dev/null +++ b/examples/v830-built-sites/industrial/products/index.html @@ -0,0 +1,81 @@ +产品中心跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/robots.txt b/examples/v830-built-sites/industrial/robots.txt new file mode 100644 index 0000000..c1f0d36 --- /dev/null +++ b/examples/v830-built-sites/industrial/robots.txt @@ -0,0 +1,3 @@ +User-agent: * +Allow: / +Sitemap: https://industrial.example.test/sitemap.xml diff --git a/examples/v830-built-sites/industrial/search-index.json b/examples/v830-built-sites/industrial/search-index.json new file mode 100644 index 0000000..10099e1 --- /dev/null +++ b/examples/v830-built-sites/industrial/search-index.json @@ -0,0 +1 @@ +[{"title": "ARC", "url": "/brands/arc/", "summary": "ARC 品牌产品与应用。", "type": "brand", "brand": ""}, {"title": "MONO", "url": "/brands/mono/", "summary": "MONO 品牌产品与应用。", "type": "brand", "brand": ""}, {"title": "NOVA", "url": "/brands/nova/", "summary": "NOVA 品牌产品与应用。", "type": "brand", "brand": ""}, {"title": "精选项目 · 01", "url": "/cases/1/", "summary": "展示项目背景、过程与成果。", "type": "case", "brand": ""}, {"title": "精选项目 · 02", "url": "/cases/2/", "summary": "展示项目背景、过程与成果。", "type": "case", "brand": ""}, {"title": "精选项目 · 03", "url": "/cases/3/", "summary": "展示项目背景、过程与成果。", "type": "case", "brand": ""}, {"title": "产品中心", "url": "/products/", "summary": "查看系列、类别及产品资料。", "type": "page", "brand": ""}, {"title": "关于我们", "url": "/about/", "summary": "企业介绍、发展理念、合作能力与团队故事。", "type": "page", "brand": ""}, {"title": "品牌中心", "url": "/brands/", "summary": "探索与产品相关的品牌。", "type": "page", "brand": ""}, {"title": "常见问题", "url": "/faq/", "summary": "更多问题可以联系我们。", "type": "page", "brand": ""}, {"title": "新闻资讯", "url": "/news/", "summary": "了解最新消息与团队动态。", "type": "page", "brand": ""}, {"title": "服务与解决方案", "url": "/services/", "summary": "从咨询到交付的全链路服务。", "type": "page", "brand": ""}, {"title": "联系我们", "url": "/contact/", "summary": "欢迎通过邮件与我们的演示团队取得联系。", "type": "page", "brand": ""}, {"title": "项目案例", "url": "/cases/", "summary": "精选项目展示。", "type": "page", "brand": ""}, {"title": "企业动态 · 01", "url": "/news/1/", "summary": "在这里发布新闻资讯与品牌动态。", "type": "post", "brand": ""}, {"title": "企业动态 · 02", "url": "/news/2/", "summary": "在这里发布新闻资讯与品牌动态。", "type": "post", "brand": ""}, {"title": "企业动态 · 03", "url": "/news/3/", "summary": "在这里发布新闻资讯与品牌动态。", "type": "post", "brand": ""}, {"title": "Materials Alpha", "url": "/products/1/", "summary": "Materials Alpha — 针对多样应用的演示产品。", "type": "product", "brand": "NOVA"}, {"title": "Materials Beta", "url": "/products/2/", "summary": "Materials Beta — 针对多样应用的演示产品。", "type": "product", "brand": "NOVA"}, {"title": "Materials Delta", "url": "/products/4/", "summary": "Materials Delta — 针对多样应用的演示产品。", "type": "product", "brand": "ARC"}, {"title": "Materials Epsilon", "url": "/products/5/", "summary": "Materials Epsilon — 针对多样应用的演示产品。", "type": "product", "brand": "MONO"}, {"title": "Materials Eta", "url": "/products/7/", "summary": "Materials Eta — 针对多样应用的演示产品。", "type": "product", "brand": "NOVA"}, {"title": "Materials Gamma", "url": "/products/3/", "summary": "Materials Gamma — 针对多样应用的演示产品。", "type": "product", "brand": "ARC"}, {"title": "Materials Theta", "url": "/products/8/", "summary": "Materials Theta — 针对多样应用的演示产品。", "type": "product", "brand": "ARC"}, {"title": "Materials Zeta", "url": "/products/6/", "summary": "Materials Zeta — 针对多样应用的演示产品。", "type": "product", "brand": "MONO"}, {"title": "供应与交付方案", "url": "/services/solution/", "summary": "灵活、可配置的供应交付服务。", "type": "service", "brand": ""}] \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/search/index.html b/examples/v830-built-sites/industrial/search/index.html new file mode 100644 index 0000000..c4cea98 --- /dev/null +++ b/examples/v830-built-sites/industrial/search/index.html @@ -0,0 +1,13 @@ +站内搜索跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    SEARCH / CONTENT

    站内搜索

    搜索本网站的产品、品牌、新闻和案例。

    +
    + +
    + +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/service/index.html b/examples/v830-built-sites/industrial/service/index.html new file mode 100644 index 0000000..7a6c41a --- /dev/null +++ b/examples/v830-built-sites/industrial/service/index.html @@ -0,0 +1,25 @@ +服务展示跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    +
    ENGINEERING MATERIALS / INDEX

    服务展示

    Explore our service

    BROWSE / EXPLORE01本页展示内容
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/services/index.html b/examples/v830-built-sites/industrial/services/index.html new file mode 100644 index 0000000..1f6aff0 --- /dev/null +++ b/examples/v830-built-sites/industrial/services/index.html @@ -0,0 +1,13 @@ +服务与解决方案跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    EXPLORE

    服务与解决方案

    从咨询到交付的全链路服务。

    +
    ABOUT / DISCOVER

    服务与解决方案

    本页为演示内容。您可以在网站工厂中直接修改和替换。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/services/solution/index.html b/examples/v830-built-sites/industrial/services/solution/index.html new file mode 100644 index 0000000..28394c7 --- /dev/null +++ b/examples/v830-built-sites/industrial/services/solution/index.html @@ -0,0 +1,13 @@ +供应与交付方案跳转至正文 + +
    ENGINEERING · MATERIALS · SUPPLYINDUSTRIAL SOLUTIONS
    +
    +
    EXPLORE

    供应与交付方案

    灵活、可配置的供应交付服务。

    +
    ABOUT / DISCOVER

    供应与交付方案

    灵活、可配置的供应交付服务。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    面向现代工程的产品与服务

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/siteforge-report.json b/examples/v830-built-sites/industrial/siteforge-report.json new file mode 100644 index 0000000..4df89f5 --- /dev/null +++ b/examples/v830-built-sites/industrial/siteforge-report.json @@ -0,0 +1,27 @@ +{ + "site": "ARC INDUSTRIES", + "locale": "zh-CN", + "alternate_pages": 0, + "version": "4b3630e1dc81", + "pages": 36, + "theme": "industrial", + "theme_version": "1.3.0", + "warnings": [], + "errors": [], + "external_assets": [], + "missing_local_images": [], + "broken_links": [], + "legacy_links": [], + "canonical_mismatches": [], + "slashless_routes": [], + "redirects": 0, + "mirrored_images": 0, + "quality_status": "passed", + "blueprint_blocks": 0, + "commercial_readiness": { + "ready_for_review": true, + "commercially_certified": false, + "blockers": 0, + "warnings": 5 + } +} \ No newline at end of file diff --git a/examples/v830-built-sites/industrial/sitemap.xml b/examples/v830-built-sites/industrial/sitemap.xml new file mode 100644 index 0000000..c3b6e52 --- /dev/null +++ b/examples/v830-built-sites/industrial/sitemap.xml @@ -0,0 +1,37 @@ + +https://industrial.example.test/ +https://industrial.example.test/about/ +https://industrial.example.test/brand/ +https://industrial.example.test/brands/ +https://industrial.example.test/brands/arc/ +https://industrial.example.test/brands/mono/ +https://industrial.example.test/brands/nova/ +https://industrial.example.test/case/ +https://industrial.example.test/cases/ +https://industrial.example.test/cases/1/ +https://industrial.example.test/cases/2/ +https://industrial.example.test/cases/3/ +https://industrial.example.test/categories/term-79e34764f8ce/ +https://industrial.example.test/categories/term-8d6647722ef3/ +https://industrial.example.test/categories/term-95acf900fafc/ +https://industrial.example.test/categories/term-a68a8656a4dc/ +https://industrial.example.test/contact/ +https://industrial.example.test/faq/ +https://industrial.example.test/news/ +https://industrial.example.test/news/1/ +https://industrial.example.test/news/2/ +https://industrial.example.test/news/3/ +https://industrial.example.test/post/ +https://industrial.example.test/product/ +https://industrial.example.test/products/ +https://industrial.example.test/products/1/ +https://industrial.example.test/products/2/ +https://industrial.example.test/products/3/ +https://industrial.example.test/products/4/ +https://industrial.example.test/products/5/ +https://industrial.example.test/products/6/ +https://industrial.example.test/products/7/ +https://industrial.example.test/products/8/ +https://industrial.example.test/service/ +https://industrial.example.test/services/ +https://industrial.example.test/services/solution/ \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/.htaccess b/examples/v830-built-sites/minimal/.htaccess new file mode 100644 index 0000000..1d4fcb4 --- /dev/null +++ b/examples/v830-built-sites/minimal/.htaccess @@ -0,0 +1,2 @@ +Options -MultiViews +RewriteEngine On diff --git a/examples/v830-built-sites/minimal/404.html b/examples/v830-built-sites/minimal/404.html new file mode 100644 index 0000000..aa51761 --- /dev/null +++ b/examples/v830-built-sites/minimal/404.html @@ -0,0 +1,12 @@ +404 · 页面不存在跳转至正文 + + +
    +
    ERROR / 404

    404

    抱歉,你访问的页面不存在,或者已被移动。

    返回首页 ↗
    + +
    + +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/about/index.html b/examples/v830-built-sites/minimal/about/index.html new file mode 100644 index 0000000..2aae478 --- /dev/null +++ b/examples/v830-built-sites/minimal/about/index.html @@ -0,0 +1,47 @@ +关于我们跳转至正文 + + +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/assets/blocks.css b/examples/v830-built-sites/minimal/assets/blocks.css new file mode 100644 index 0000000..9ce1279 --- /dev/null +++ b/examples/v830-built-sites/minimal/assets/blocks.css @@ -0,0 +1,29 @@ +/* Portable SiteForge blocks, loaded with every theme (all styles scoped to sf-). */ +.sf-section{background:var(--sf-bg,transparent);color:var(--sf-fg,inherit);padding:var(--sf-pad,82px) 0;margin:0}.sf-section:nth-of-type(even){background:var(--sf-bg,#f4f6f9)}.sf-container{max-width:1200px;margin:auto;padding:0 32px}.sf-section h1,.sf-section h2,.sf-section h3,.sf-section p{color:inherit;line-height:1.3}.sf-section h1{font-size:clamp(38px,5vw,76px);font-weight:790;letter-spacing:-.052em}.sf-section h2{font-size:clamp(27px,3.2vw,44px);font-weight:760;letter-spacing:-.037em}.sf-kicker{display:block;font-size:12px;letter-spacing:.17em;text-transform:uppercase;font-weight:740;color:var(--accent,#3569d3);margin-bottom:18px}.sf-hero-grid,.sf-image-text{display:grid;grid-template-columns:1.08fr .92fr;gap:68px;align-items:center}.sf-hero-copy p{font-size:18px;line-height:1.75;max-width:520px;opacity:.75}.sf-hero-img,.sf-image-side{overflow:hidden;border-radius:9px;min-height:380px;background:linear-gradient(130deg,#d5e1ee,#eef3f9);display:grid;place-items:center}.sf-hero-img img,.sf-image-side img{width:100%;height:100%;max-height:580px;object-fit:cover}.sf-hero-abstract{font-size:110px;color:#a7bdd4}.sf-button{display:inline-flex;align-items:center;justify-content:center;gap:28px;background:var(--accent,#315ee2);color:white!important;padding:16px 26px;border-radius:6px;font-size:14px;text-decoration:none;font-weight:720;margin-top:24px}.sf-section-head{display:flex;align-items:end;justify-content:space-between;margin-bottom:32px;gap:24px}.sf-section-head h2{margin:0}.sf-section-head>a,.sf-link{color:var(--accent,#3569d3);font-weight:700;text-decoration:none}.sf-prose{font-size:16px;line-height:1.85;max-width:930px}.sf-prose p{line-height:1.85}.sf-features,.sf-collection,.sf-stats{display:grid;gap:20px}.sf-features{grid-template-columns:repeat(3,minmax(0,1fr))}.sf-feature{border:1px solid #e0e6eb;padding:32px 28px;border-radius:8px;background:#fff;color:#253247}.sf-feature>span{font-size:12px;font-weight:800;color:var(--accent,#346add)}.sf-feature h3{font-size:22px;margin:30px 0 8px}.sf-feature p{font-size:14px;line-height:1.7;color:#647181}.sf-stats{grid-template-columns:repeat(4,1fr);padding:40px 0;border-top:1px solid #b7c0cd66;border-bottom:1px solid #b7c0cd66}.sf-stats>div{display:flex;flex-direction:column;gap:8px}.sf-stats strong{font-size:clamp(28px,4vw,53px);letter-spacing:-.04em}.sf-stats span{font-size:12px;opacity:.65;letter-spacing:.04em}.sf-collection{grid-template-columns:repeat(var(--sf-cols,3),minmax(0,1fr))}.sf-item{display:block;text-decoration:none;color:#233044;background:#fff;border:1px solid #e8edf1;border-radius:8px;overflow:hidden;transition:transform .2s,box-shadow .2s}.sf-item:hover{transform:translateY(-4px);box-shadow:0 18px 38px #344d7018}.sf-item-img{height:210px;overflow:hidden;background:#e4eaf0}.sf-item-img img{height:100%;width:100%;object-fit:cover}.sf-placeholder{display:grid;place-items:center;width:100%;height:100%;min-height:190px;background:linear-gradient(130deg,#e2eaf2,#c9d7e6);font-size:72px;color:#8399b2;font-weight:800}.sf-large{min-height:360px}.sf-item-copy{padding:25px}.sf-item-copy small{text-transform:uppercase;letter-spacing:.13em;color:var(--accent,#376edc)}.sf-item-copy h3{font-size:22px;margin:12px 0 7px}.sf-item-copy p{font-size:14px;line-height:1.6;color:#7a8796;min-height:42px}.sf-item-copy span{font-size:12px;color:var(--accent,#376edc);font-weight:800}.sf-image-text>div>p{font-size:17px;line-height:1.8;max-width:520px;opacity:.7}.sf-reverse>div:first-child{order:2}.sf-gallery{display:grid;grid-template-columns:repeat(3,1fr);gap:15px}.sf-gallery img{width:100%;height:230px;object-fit:cover;border-radius:6px}.sf-faq{max-width:920px}.sf-faq details{border-bottom:1px solid #dce3eb;padding:22px 0}.sf-faq summary{font-size:17px;cursor:pointer;font-weight:700}.sf-faq p{color:#647181;line-height:1.75}.sf-cta-wrap{display:flex;justify-content:space-between;align-items:center;gap:24px}.sf-cta-wrap h2{margin:0}.sf-cta-wrap p{font-size:16px;opacity:.75}.sf-section a{cursor:pointer}.sf-muted{opacity:.65} +@media(max-width:820px){.sf-container{padding:0 20px}.sf-section{padding:50px 0}.sf-hero-grid,.sf-image-text{grid-template-columns:1fr;gap:26px}.sf-reverse>div:first-child{order:initial}.sf-hero-img,.sf-image-side{min-height:250px}.sf-features,.sf-collection{grid-template-columns:repeat(2,minmax(0,1fr))}.sf-stats{grid-template-columns:repeat(2,1fr)}.sf-cta-wrap{align-items:flex-start;flex-direction:column}} +@media(max-width:540px){.sf-features,.sf-collection,.sf-gallery{grid-template-columns:1fr}.sf-section-head{display:block}.sf-section-head>a{display:block;margin-top:13px}.sf-item-img{height:220px}.sf-hero-grid{gap:22px}.sf-hero-copy p{font-size:16px}.sf-stats{gap:28px}} + +.sf-attributes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 32px;border-top:1px solid #e5eaf0}.sf-attribute{display:flex;justify-content:space-between;align-items:center;gap:18px;border-bottom:1px solid #e5eaf0;padding:19px 10px;font-size:14px}.sf-attribute span{color:#748497}.sf-attribute strong{font-weight:720;text-align:right}@media(max-width:640px){.sf-attributes{grid-template-columns:1fr}} + +/* SiteForge responsive no-code grid container */ +.sf-layout-grid{display:grid;grid-template-columns:var(--sf-layout-cols,1fr 1fr);gap:var(--sf-layout-gap,24px);align-items:stretch} +.sf-layout-column{min-width:0}.sf-layout-column>.sf-section{padding:0;margin:0 0 18px}.sf-layout-column .sf-container{width:100%;padding:0} +.sf-layout-column>.sf-section:last-child{margin-bottom:0} +@media(max-width:820px){.sf-layout-grid{grid-template-columns:repeat(2,minmax(0,1fr))!important}} +@media(max-width:540px){.sf-layout-grid{grid-template-columns:minmax(0,1fr)!important}} + +/* V8.6: accessible, script-free commercial design blocks */ +.sf-slides{display:flex;gap:18px;overflow-x:auto;scroll-snap-type:x mandatory;padding:6px 0 18px;scrollbar-width:thin} +.sf-slide{flex:0 0 min(78%,720px);min-width:220px;margin:0;scroll-snap-align:start} +.sf-slide img{width:100%;aspect-ratio:16/9;object-fit:cover;border-radius:10px} +.sf-slide figcaption{padding:10px 2px;opacity:.7;font-size:14px} +.sf-video{aspect-ratio:16/9;max-width:1000px;background:#ebf0f5;border-radius:10px;overflow:hidden} +.sf-video iframe{width:100%;height:100%;border:0} +.sf-tab{padding:19px 0;border-bottom:1px solid #dde4ec;max-width:960px} +.sf-tab summary{font-size:18px;font-weight:700;cursor:pointer}.sf-tab p{max-width:850px;line-height:1.8} +.sf-prices{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:18px} +.sf-price{padding:28px;background:#fff;border:1px solid #dee5ef;border-radius:10px;color:#29394b} +.sf-price strong{display:block;font-size:27px;margin:14px 0}.sf-price li{margin:11px 0}.sf-price ul{padding-left:19px} +.sf-map-address{font-style:normal;font-size:18px;white-space:pre-line;line-height:1.8} +@media (prefers-reduced-motion:reduce){.sf-slides{scroll-behavior:auto}.sf-item{transition:none}} +@media(max-width:540px){.sf-slide{flex-basis:92%}} diff --git a/examples/v830-built-sites/minimal/assets/commercial.css b/examples/v830-built-sites/minimal/assets/commercial.css new file mode 100644 index 0000000..353bee4 --- /dev/null +++ b/examples/v830-built-sites/minimal/assets/commercial.css @@ -0,0 +1,84 @@ +/* SiteForge commercial theme UX layer: accessibility, layout rhythm, media, responsive navigation. */ +:root{--sf-shadow:0 20px 55px rgba(17,33,55,.08);--sf-shadow-hover:0 26px 65px rgba(17,33,55,.15)} +html{scroll-padding-top:104px}body{font-feature-settings:"kern";text-rendering:optimizeLegibility} +a,button,input,select,textarea{-webkit-tap-highlight-color:transparent} +a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{outline:3px solid var(--pro-accent);outline-offset:4px} +.pro-wrap{width:100%;max-width:min(var(--pro-wide),100%)}.pro-header{isolation:isolate;box-shadow:0 1px 0 rgba(15,35,60,.035)}.pro-head-inner{gap:clamp(15px,2vw,29px)}.pro-logo{min-width:0;flex-shrink:0;gap:12px}.pro-brand-logo{max-width:155px;max-height:46px;width:auto;height:auto;object-fit:contain}.pro-logo-name{overflow-wrap:anywhere}.pro-navigation{gap:clamp(11px,1.6vw,24px)}.pro-header-cta{white-space:nowrap} +.pro-mobile-toggle,.pro-catalog-toggle,.pro-nav-disclose{border:0;background:transparent;color:inherit;line-height:1.2} +.pro-mobile-toggle{min-height:44px;min-width:44px;border:1px solid currentColor;border-radius:6px;font-size:19px}.pro-nav-group{position:relative;display:flex;align-items:center;gap:2px} +.pro-nav-disclose{padding:9px;font-size:13px}.pro-nav-children{position:absolute;top:100%;left:0;min-width:215px;max-width:330px;display:grid;gap:2px;padding:13px;box-shadow:var(--sf-shadow);border-radius:10px;z-index:45;background:var(--pro-background);border:1px solid var(--pro-border);color:var(--pro-text)} +.pro-nav-children[hidden],.pro-mega[hidden]{display:none!important}.pro-nav-children a{display:block;font-size:13px;white-space:normal;padding:10px;border-radius:5px}.pro-nav-children a:hover{background:var(--pro-surface)} +.pro-catalog-toggle{padding:11px 3px;white-space:nowrap;font-size:12px;font-weight:700}.pro-mega{position:absolute;top:100%;left:50%;transform:translateX(-50%);width:min(100%,var(--pro-wide));box-shadow:var(--sf-shadow);z-index:41;display:grid;grid-template-columns:215px 1fr;background:var(--pro-background);color:var(--pro-text);border:1px solid var(--pro-border);border-radius:0 0 15px 15px;padding:29px;align-items:start}.pro-mega>span{font-size:12px;letter-spacing:.06em}.pro-mega>div{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:9px 22px;overflow:visible}.pro-mega>div a{white-space:normal;padding:10px 5px;border-bottom:1px solid var(--pro-border)} +.pro-home-hero{overflow:hidden}.pro-home-hero .pro-home-grid{min-height:660px;gap:5%}.pro-home-hero .pro-hero-copy{position:relative;z-index:2}.pro-home-hero .pro-hero-copy h1{font-size:clamp(46px,5.7vw,92px);line-height:1.06;letter-spacing:-.064em;max-width:15ch}.pro-home-hero .pro-hero-copy h1 em{font-style:normal;display:block}.pro-home-hero .pro-hero-copy p{font-size:clamp(15px,1.3vw,19px);line-height:1.75;max-width:44ch}.pro-home-hero .pro-hero-art{min-width:0;min-height:425px;position:relative;isolation:isolate}.pro-home-hero .pro-hero-art>img{width:100%;height:100%;object-fit:cover;position:absolute;inset:0}.pro-hero-art:has(.pro-abstract-car),.pro-hero-art:has(.pro-technical),.pro-hero-art:has(.pro-corporate-shape){background-position:center;background-size:cover;background-repeat:no-repeat}.pro-abstract-car,.pro-technical,.pro-corporate-shape{position:relative;z-index:1;pointer-events:none} +.pro-hero-actions{display:flex;flex-wrap:wrap;align-items:center;gap:15px}.pro-button,.pro-header-cta,.pro-outline-button{min-height:48px;transition:transform .24s ease,box-shadow .24s ease,opacity .24s ease}.pro-button:hover,.pro-header-cta:hover,.pro-outline-button:hover{transform:translateY(-2px);box-shadow:0 10px 22px rgba(0,0,0,.10)} +.pro-section{padding-top:clamp(76px,7vw,112px)!important;padding-bottom:clamp(76px,7vw,112px)!important}.pro-section-head{gap:16px}.pro-section-head h2{font-size:clamp(32px,3.5vw,53px);max-width:22ch}.pro-section-head .pro-text-link{align-self:end} +.pro-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px}.pro-card{min-width:0;display:flex;flex-direction:column;transition:transform .28s ease,box-shadow .28s ease;border:1px solid var(--pro-border);background:var(--pro-background);overflow:hidden}.pro-card:hover{transform:translateY(-6px);box-shadow:var(--sf-shadow-hover)}.pro-card-cover{aspect-ratio:1.42;overflow:hidden;background:var(--pro-surface);position:relative}.pro-card-cover .pro-photo{width:100%;height:100%;object-fit:cover;transition:transform .45s ease}.pro-card:hover .pro-photo{transform:scale(1.045)}.pro-card-body{display:flex;flex-direction:column;flex:1}.pro-card-body h3{font-size:clamp(19px,1.6vw,24px);line-height:1.26}.pro-card-body p{font-size:14px}.pro-card-link{margin-top:auto;padding-top:14px;font-size:13px;font-weight:700} +.pro-art{min-height:100%;width:100%;position:relative;overflow:hidden;display:grid;place-items:center;isolation:isolate}.pro-art-ring{width:60%;aspect-ratio:1;border:1px solid currentColor;opacity:.13;border-radius:50%;transform:rotate(20deg);box-shadow:0 0 0 23px #ffffff10,0 0 0 57px #ffffff07}.pro-art-center{font-size:clamp(38px,5vw,80px);position:absolute;font-weight:800;letter-spacing:-.065em;opacity:.65}.pro-art-label{position:absolute;bottom:19px;left:22px;font-size:10px;letter-spacing:.22em;opacity:.7} +.pro-breadcrumb{display:flex;gap:11px;flex-wrap:wrap;font-size:12px;align-items:center}.pro-breadcrumb a{text-decoration:underline;text-underline-offset:4px}.pro-product-hero{align-items:start;gap:clamp(28px,5vw,80px)}.pro-product-media{aspect-ratio:1.12;background:var(--pro-surface);overflow:hidden}.pro-product-media>img,.pro-product-media>.pro-art{width:100%;height:100%;object-fit:contain}.pro-product-summary{padding:clamp(12px,3vw,50px) 0}.pro-product-summary h1{font-size:clamp(36px,4.3vw,72px)}.pro-detail-layout{border-top:1px solid var(--pro-border);padding-top:50px}.pro-specs>div{display:grid;grid-template-columns:minmax(100px,40%) 1fr;gap:10px;align-items:baseline;padding:15px 0;border-bottom:1px solid var(--pro-border)}.pro-specs strong{overflow-wrap:anywhere}.pro-gallery-thumbs button{flex-basis:96px;height:76px}.pro-gallery-lightbox{backdrop-filter:blur(6px)} +.pro-filter-panel{display:flex;align-items:end;flex-wrap:wrap;gap:16px;background:var(--pro-surface);border:1px solid var(--pro-border);padding:20px;margin-bottom:25px;border-radius:var(--pro-radius)}.pro-filter-panel label{display:grid;gap:7px;min-width:180px;flex:1}.pro-filter-panel input,.pro-filter-panel select{width:100%;background:var(--pro-background);border:1px solid var(--pro-border);padding:12px 14px;color:var(--pro-text);border-radius:6px}.pro-filter-count{white-space:nowrap;font-size:13px;padding:12px 0}.pro-card[hidden]{display:none!important}.pro-filter-empty{padding:38px;border:1px dashed var(--pro-border);text-align:center;grid-column:1/-1} +.pro-inquiry input,.pro-inquiry textarea{min-height:46px}.pro-inquiry textarea{min-height:150px}.pro-inquiry-wrap{gap:clamp(32px,7vw,110px)}.pro-inquiry .pro-button{border:0;justify-self:start}.pro-footer-links a{padding-block:5px;display:inline-block} +.pro-end-cta{overflow:hidden}.pro-end-cta h2{font-size:clamp(30px,4vw,64px)} +.pro-rich{line-height:1.85}.pro-rich img{border-radius:var(--pro-radius);margin-block:24px}.pro-rich table{width:100%;display:block;overflow:auto;border-collapse:collapse}.pro-rich td,.pro-rich th{border:1px solid var(--pro-border);padding:10px 14px}.pro-rich a{text-decoration:underline;text-underline-offset:3px} +@media(min-width:1025px){.pro-navigation>.pro-nav-group:hover .pro-nav-children:not([hidden]){visibility:visible}} +@media(max-width:1150px){.pro-head-inner{gap:15px}.pro-navigation{gap:12px}.pro-logo-name{font-size:15px}.pro-header-cta{padding:13px 16px}} +@media(max-width:1024px){.pro-head-inner{min-height:72px;flex-wrap:wrap}.pro-mobile-toggle{display:inline-flex;align-items:center;justify-content:center;margin-left:auto}.pro-navigation{display:none;width:100%;flex-basis:100%;flex-direction:column;align-items:stretch;gap:0;order:5;margin:0;padding:8px 0 20px;border-top:1px solid var(--pro-border)}.pro-navigation.is-open{display:flex}.pro-navigation>a,.pro-nav-group>a{padding:14px 8px;font-size:15px}.pro-nav-group{display:flex;flex-wrap:wrap;justify-content:space-between}.pro-nav-children{position:static;flex-basis:100%;max-width:none;width:100%;box-shadow:none;border-radius:0;border-left:2px solid var(--pro-accent);margin:0 0 12px 8px}.pro-nav-disclose{min-width:44px;min-height:44px}.pro-catalog-toggle{margin-left:auto}.pro-mega{top:100%;display:block;padding:20px}.pro-mega>div{grid-template-columns:repeat(2,minmax(0,1fr));margin-top:12px}.pro-home-hero .pro-home-grid{min-height:560px}.pro-home-hero .pro-hero-art{min-height:325px}.pro-grid{grid-template-columns:repeat(2,minmax(0,1fr))}} +@media(max-width:700px){.pro-wrap{padding-left:20px;padding-right:20px}.pro-utility{display:none}.pro-head-inner{min-height:66px}.pro-logo-name{max-width:140px;font-size:14px}.pro-brand-logo{max-width:125px}.pro-header-cta{display:none}.pro-catalog-toggle{font-size:11px;padding-inline:7px;margin-left:0}.pro-home-hero .pro-home-grid{display:flex;flex-direction:column;gap:36px;padding-top:48px;padding-bottom:48px}.pro-home-hero .pro-hero-copy h1{font-size:clamp(43px,10vw,68px)}.pro-home-hero .pro-hero-copy p{font-size:15px}.pro-home-hero .pro-hero-art{width:100%;min-height:290px}.pro-home-hero .pro-hero-bottom{display:none}.pro-section{padding-top:68px!important;padding-bottom:68px!important}.pro-section-head{align-items:flex-start}.pro-grid{grid-template-columns:1fr;gap:18px}.pro-card-cover{aspect-ratio:1.45}.pro-product-hero,.pro-detail-layout,.pro-info-grid,.pro-inquiry-wrap{display:grid;grid-template-columns:1fr;gap:30px}.pro-product-summary{padding:0}.pro-specs>div{grid-template-columns:1fr 1fr}.pro-mega{top:100%;max-height:65vh;overflow-y:auto}.pro-mega>div{grid-template-columns:1fr}.pro-filter-panel{display:grid;grid-template-columns:1fr;gap:12px}.pro-filter-panel label{min-width:0}.pro-footer-top{display:grid;grid-template-columns:1fr;gap:27px}.pro-footer-bottom{gap:12px;flex-wrap:wrap}} +@media(max-width:410px){.pro-logo-name{max-width:115px}.pro-logo-symbol{font-size:28px}.pro-catalog-toggle{font-size:10px}.pro-mobile-toggle{min-width:42px}} +@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,*:before,*:after{animation-duration:.01ms!important;transition-duration:.01ms!important;scroll-behavior:auto!important}} + +/* Accessible static catalogue pagination for large inventories. */ +.pro-pages-nav{display:flex;gap:1rem;justify-content:center;align-items:center;margin:2rem 0;flex-wrap:wrap} +.pro-pages-nav a{padding:.7rem 1.1rem;border:1px solid currentColor;border-radius:.4rem;text-decoration:none} +.pro-pages-nav a:focus-visible{outline:3px solid var(--accent,#2563eb);outline-offset:3px} +.pro-pages-nav span{font-size:.875rem} + +/* P6 international sites: small, keyboard-operable language switch. */ +.sf-language-switch{display:inline-flex;gap:6px;align-items:center;flex-wrap:wrap;margin:8px 12px;padding:4px;border:1px solid rgba(120,130,145,.22);border-radius:10px;background:rgba(255,255,255,.08)} +.sf-language-switch a{font:inherit;font-size:12px;line-height:1.5;padding:4px 7px;border-radius:6px;color:inherit;text-decoration:none} +.sf-language-switch a[aria-current="page"]{font-weight:700;text-decoration:underline;text-underline-offset:3px} +.sf-language-switch a:focus-visible{outline:2px solid #2563eb;outline-offset:3px} +@media(max-width:640px){.sf-language-switch{margin:6px 0;width:auto}} + +/* V8.21.3 — Four-theme unified mobile off-canvas navigation & optional tab bar. + Desktop remains unchanged. Phone / tablet use one accessible drawer. */ +.sf-mobile-tabs{display:none!important} +.sf-drawer-header,.sf-mobile-drawer-backdrop,.sf-drawer-extra{display:none} +@media(max-width:1024px){ + .pro-head-inner{flex-wrap:nowrap!important;gap:12px!important} + .pro-mobile-toggle{display:inline-flex;align-items:center;justify-content:center;margin-left:auto!important;flex:0 0 44px;min-width:44px;min-height:44px;position:relative;z-index:3} + .pro-catalog-toggle{display:none!important} + .pro-navigation,.pro-navigation.is-open{display:flex!important;position:fixed!important;inset:0 0 0 auto!important;width:min(88vw,360px)!important;height:100dvh!important;height:100vh;max-height:100dvh!important;flex:unset!important;flex-direction:column!important;align-items:stretch!important;order:unset!important;margin:0!important;padding:0 0 calc(20px + env(safe-area-inset-bottom,0px))!important;overflow-x:hidden;overflow-y:auto!important;background:var(--pro-background,#fff)!important;color:var(--pro-text,#19283c)!important;border:0!important;border-left:1px solid var(--pro-border,#ddd)!important;box-shadow:-15px 0 45px #0002!important;z-index:1201!important;transform:translateX(105%);visibility:hidden;pointer-events:none;transition:transform .24s ease,visibility .24s ease!important;overscroll-behavior:contain} + .pro-navigation.is-open{transform:translateX(0);visibility:visible;pointer-events:auto} + .sf-drawer-header{display:flex!important;align-items:center;justify-content:space-between;gap:12px;padding:20px 18px;border-bottom:1px solid var(--pro-border,#dde3e9);font-size:17px;font-weight:750;position:sticky;top:0;background:var(--pro-background,#fff);z-index:2} + .sf-drawer-close{min-width:44px;min-height:44px;border:1px solid var(--pro-border,#dde3e9);color:inherit;background:transparent;border-radius:10px;font-size:24px;cursor:pointer} + .sf-mobile-drawer-backdrop{display:block;position:fixed;inset:0;z-index:1200;background:#0b1b31a3;opacity:0;visibility:hidden;pointer-events:none;transition:opacity .24s ease,visibility .24s ease} + .sf-mobile-drawer-backdrop.is-open{opacity:1;visibility:visible;pointer-events:auto} + body.sf-drawer-open{overflow:hidden!important} + .pro-navigation>a,.pro-navigation .pro-nav-group>a,.pro-navigation .sf-drawer-extra>a{display:flex;align-items:center;min-height:50px;padding:13px 20px!important;font-size:15px!important;color:inherit!important;white-space:normal;border-bottom:1px solid var(--pro-border,#dde3e9)!important;text-decoration:none!important} + .pro-navigation .pro-nav-group{display:flex;position:relative;flex-wrap:wrap!important;width:100%;gap:0;align-items:center;justify-content:space-between} + .pro-navigation .pro-nav-group>a{flex:1;min-width:0} + .pro-navigation .pro-nav-disclose{margin-right:12px;min-width:44px;min-height:44px;border-radius:9px;background:var(--pro-surface,#f4f6f8)} + .pro-navigation .pro-nav-children{position:static!important;width:100%!important;max-width:100%!important;box-shadow:none!important;border-left:3px solid var(--pro-accent,#e77730);border-radius:0!important;margin:0 0 8px 14px!important;flex-basis:calc(100% - 14px)!important;background:var(--pro-surface,#f6f8fa)} + .pro-navigation .pro-nav-children a{padding:12px 16px!important;font-size:14px!important;color:inherit!important;min-height:44px} + .sf-drawer-extra{display:block;padding:12px 0 5px}.sf-drawer-extra strong{display:block;font-size:12px;letter-spacing:.06em;padding:12px 20px;opacity:.65}.sf-drawer-extra a{font-size:14px!important} + .sf-drawer-close:focus-visible,.pro-mobile-toggle:focus-visible,.pro-nav-disclose:focus-visible,.sf-mobile-tab:focus-visible{outline:3px solid var(--pro-accent,#ff8200);outline-offset:2px} +} +@media(max-width:767px){ + .pro-header-cta{display:none!important} + .pro-head-inner .pro-logo{min-width:0;max-width:calc(100% - 65px)} + .pro-logo-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap} + .pro-home-hero .pro-home-grid{min-height:0!important} + .pro-home-hero .pro-hero-art{min-height:230px} + .pro-card,.pro-card-cover,.pro-product-media{max-width:100%;min-width:0} + .pro-rich img,.pro-content img,.sf-canvas img{max-width:100%;height:auto} + .pro-rich table{max-width:100%;overflow:auto} + .pro-grid,.pro-footer-top{min-width:0} + .sf-mobile-tabs{display:grid!important;position:fixed;z-index:1100;bottom:0;left:0;right:0;grid-template-columns:repeat(var(--sf-mobile-tab-count,4),minmax(0,1fr));align-items:stretch;padding:5px 6px calc(5px + env(safe-area-inset-bottom,0px));min-height:63px;background:var(--pro-background,#fff);color:var(--pro-text,#263446);border-top:1px solid var(--pro-border,#dfe4eb);box-shadow:0 -6px 24px #13223914} + .sf-mobile-tab{appearance:none;border:0!important;background:transparent!important;color:inherit!important;text-decoration:none!important;padding:6px 2px;min-height:50px;min-width:0;display:flex;flex-direction:column;justify-content:center;align-items:center;gap:2px;border-radius:9px;cursor:pointer;font-family:inherit} + .sf-tab-icon{font-size:23px;line-height:1.15;font-weight:500} + .sf-tab-label{font-size:11px;font-weight:600;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} + .sf-mobile-tab[aria-current=page]{color:var(--pro-accent,#e47730)!important;background:var(--pro-surface,#f5f6f8)!important} + body:has(> .sf-mobile-tabs){padding-bottom:calc(76px + env(safe-area-inset-bottom,0px))!important} +} +@media(min-width:768px){.sf-mobile-tabs{display:none!important}} +@media(prefers-reduced-motion:reduce){.pro-navigation,.sf-mobile-drawer-backdrop{transition:none!important}} diff --git a/examples/v830-built-sites/minimal/assets/custom.css b/examples/v830-built-sites/minimal/assets/custom.css new file mode 100644 index 0000000..f197c0a --- /dev/null +++ b/examples/v830-built-sites/minimal/assets/custom.css @@ -0,0 +1 @@ +:root{--accent:#315f92;--sf-font:system-ui,-apple-system,sans-serif;--sf-radius:12px;--sf-space:72px;--sf-width:1200px;--sf-heading-scale:1.0;}body{font-family:var(--sf-font)} .sf-canvas .sf-section,.sf-canvas .section{padding-block:var(--sf-space)}.container,.sf-container{max-width:var(--sf-width)}.btn,.primary,.request,.button,.nav-btn{background-color:#315f92;border-radius:12px}body .sf-canvas h1{font-size:clamp(2.5rem,5vw,calc(4.8rem * var(--sf-heading-scale)))}body .pro-utility[hidden]{display:none!important}@media(max-width:1023px){.sf-canvas .sf-section{padding-block:64px}}@media(max-width:767px){.sf-canvas .sf-section{padding-block:40px}.pro-wrap,.sf-container{padding-left:20px;padding-right:20px}body .pro-utility{display:none!important}} \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/assets/factory.css b/examples/v830-built-sites/minimal/assets/factory.css new file mode 100644 index 0000000..154ffb3 --- /dev/null +++ b/examples/v830-built-sites/minimal/assets/factory.css @@ -0,0 +1,27 @@ +/* SiteForge trusted global shell. Site themes remain visually independent. */ +:root{--sf-shell:#12243d;--sf-shell-accent:#dcae71;--sf-shell-soft:#edf2f8;--sf-shell-fg:#173049} +html{scroll-behavior:smooth}body{overflow-x:hidden}body>.header,body>.utility,body>.top,body>header,body>footer{display:none!important} +.sf-theme-industrial{--sf-shell:#114e79;--sf-shell-accent:#92d5ed;--sf-shell-soft:#ebf6fa;--sf-shell-fg:#0c4267} +.sf-theme-corporate{--sf-shell:#232d62;--sf-shell-accent:#b8bdff;--sf-shell-soft:#f3f3fa;--sf-shell-fg:#333468} +.sf-theme-minimal{--sf-shell:#1e1e1c;--sf-shell-accent:#ded6c5;--sf-shell-soft:#f6f4ef;--sf-shell-fg:#252520} +.sf-site-head{position:relative;z-index:25;background:var(--sf-shell);color:#fff;font-family:system-ui,-apple-system,sans-serif} +.sf-head-inner{max-width:1240px;margin:0 auto;min-height:78px;padding:0 28px;display:flex;align-items:center;gap:28px} +.sf-logo{display:flex;align-items:center;gap:11px;font-size:18px;text-decoration:none!important;color:#fff!important;white-space:nowrap} +.sf-logo-mark{width:36px;height:36px;display:grid;place-items:center;background:var(--sf-shell-accent);color:var(--sf-shell);font-size:22px;font-weight:900;border-radius:9px} +.sf-primary-links{display:flex;gap:23px;margin-left:auto;align-items:center} +.sf-primary-links a,.sf-mega a{color:#fff!important;text-decoration:none!important;font-size:13px;font-weight:650;white-space:nowrap} +.sf-primary-links a:hover{color:var(--sf-shell-accent)!important} +.sf-head-cta{font-size:13px;font-weight:750;text-decoration:none;background:var(--sf-shell-accent);color:var(--sf-shell)!important;padding:13px 18px;border-radius:4px;white-space:nowrap} +.sf-menu-toggle{display:none;margin-left:auto;color:white;border:1px solid #ffffff55;background:none;border-radius:4px;padding:8px 12px;font-size:19px;cursor:pointer} +.sf-mega{display:flex;gap:18px;max-width:1240px;margin:auto;padding:0 28px 9px;overflow-x:auto} +.sf-mega a{display:block;min-width:120px;border-top:1px solid #ffffff2e;padding:12px 8px}.sf-mega small{display:block;color:#ffffff99;max-width:160px;overflow:hidden;text-overflow:ellipsis;font-size:10px;margin-top:6px} +.sf-site-foot{background:var(--sf-shell);color:white!important;font:14px/1.7 system-ui,-apple-system,sans-serif;padding:72px 28px 26px} +.sf-foot-grid{max-width:1200px;margin:auto;display:grid;grid-template-columns:2fr 1fr 1fr;gap:70px}.sf-foot-grid h2{font-size:25px;color:white;margin:0 0 17px}.sf-foot-grid h4{font-size:13px;color:var(--sf-shell-accent);letter-spacing:.07em;margin:0 0 17px}.sf-foot-grid p{color:#ffffffae;max-width:380px}.sf-foot-grid a{display:block;width:fit-content;color:#fff!important;text-decoration:none;margin-bottom:8px}.sf-foot-lower{border-top:1px solid #ffffff33;max-width:1200px;margin:45px auto 0;padding-top:20px;display:flex;justify-content:space-between;color:#ffffff9e;font-size:12px} +.sf-filters{display:flex;align-items:center;flex-wrap:wrap;gap:12px;margin:0 0 30px}.sf-filters input,.sf-filters select{padding:11px 13px;border-radius:6px;border:1px solid #cfd9e4;background:#fff;color:#263a51;max-width:280px}.sf-filter-empty{padding:22px;color:#778598} +.sf-search-page{min-height:76vh;max-width:1060px;padding:90px 24px;margin:auto;font-family:system-ui,sans-serif;color:var(--sf-shell-fg)}.sf-search-page h1{font-size:clamp(35px,5vw,62px);margin:20px 0}.sf-search-page>label{display:block;margin:18px 0 8px}.sf-search-page input{display:block;width:100%;padding:17px;font-size:18px;border:1px solid #b7c6d7;border-radius:8px}.sf-search-page #sf-search-count{margin:22px 0;color:#607589}.sf-search-result{padding:22px 0;border-bottom:1px solid #dae1ea}.sf-search-result a{color:var(--sf-shell-fg);font-size:21px;font-weight:750;text-decoration:none}.sf-search-result small{display:block;color:#7992a7}.sf-search-result p{margin:7px 0;color:#657487} +@media(max-width:1050px){.sf-head-inner{gap:13px}.sf-primary-links{gap:12px}.sf-primary-links a{font-size:12px}.sf-head-cta{padding:10px}} +@media(max-width:850px){.sf-head-inner{min-height:68px}.sf-menu-toggle{display:block}.sf-head-cta{display:none}.sf-primary-links{display:none;position:absolute;top:68px;left:0;right:0;margin:0;background:var(--sf-shell);padding:20px 28px;flex-direction:column;align-items:stretch;box-shadow:0 20px 24px #0002}.sf-primary-links.is-open{display:flex}.sf-mega{display:none}.sf-foot-grid{grid-template-columns:1fr 1fr;gap:35px}} +@media(max-width:560px){.sf-foot-grid{grid-template-columns:1fr}.sf-foot-lower{display:block}.sf-site-foot{padding-top:48px}.sf-head-inner{padding:0 16px}} + +.sf-page-intro{padding:80px 28px;background:var(--sf-shell-soft);color:var(--sf-shell-fg);font-family:system-ui,sans-serif}.sf-page-intro>div{max-width:1200px;margin:auto}.sf-page-intro p{font-size:11px;font-weight:850;letter-spacing:.19em;text-transform:uppercase;color:var(--sf-shell-fg);opacity:.58}.sf-page-intro h1{font-size:clamp(38px,5vw,67px);letter-spacing:-.04em;line-height:1.08;margin:13px 0}.sf-page-intro span{font-size:16px;opacity:.72} +.sf-item[hidden]{display:none!important} diff --git a/examples/v830-built-sites/minimal/assets/pro-base.css b/examples/v830-built-sites/minimal/assets/pro-base.css new file mode 100644 index 0000000..c2c4f61 --- /dev/null +++ b/examples/v830-built-sites/minimal/assets/pro-base.css @@ -0,0 +1,21 @@ +/* SiteForge V3 professional theme primitives. Each commercial theme adds its own art direction. */ +:root{--pro-text:#19283a;--pro-muted:#687587;--pro-border:#dfe5ea;--pro-background:#fff;--pro-surface:#f5f7fa;--pro-accent:#365cb7;--pro-hero:#15263d;--pro-hero-fg:#fff;--pro-radius:12px;--pro-headings:system-ui,-apple-system,sans-serif;--pro-font:system-ui,-apple-system,sans-serif;--pro-wide:1270px} +*,*:before,*:after{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:var(--pro-background);color:var(--pro-text);font-family:var(--pro-font);-webkit-font-smoothing:antialiased;overflow-x:hidden}button,input,select{font:inherit}button,a{touch-action:manipulation}button{cursor:pointer}a{text-decoration:none;color:inherit}a:hover{color:var(--pro-accent)}img{max-width:100%;display:block}h1,h2,h3,h4,p{margin-top:0}h1,h2,h3{font-family:var(--pro-headings);line-height:1.09}h1{letter-spacing:-.052em}h2{letter-spacing:-.042em}h3{letter-spacing:-.028em}p{line-height:1.72}.pro-wrap{max-width:var(--pro-wide);margin:0 auto;padding-left:32px;padding-right:32px}.pro-skip{position:absolute;left:-9999px;z-index:90;background:#fff;color:#000;padding:12px}.pro-skip:focus{left:10px;top:10px}.pro-eyebrow{font-weight:750;font-size:11px;letter-spacing:.17em;text-transform:uppercase;display:block;line-height:1.6;color:var(--pro-accent)}.pro-muted{opacity:.7}.pro-utility{min-height:30px;background:var(--pro-hero);color:#c5d2db;font-size:10px;letter-spacing:.16em}.pro-utility .pro-wrap{display:flex;justify-content:space-between;padding-block:8px}.pro-utility i{font-style:normal;color:var(--pro-accent)}.pro-header{background:var(--pro-background);color:var(--pro-text);border-bottom:1px solid var(--pro-border);position:relative;z-index:35}.pro-head-inner{min-height:84px;display:flex;align-items:center;gap:28px}.pro-logo{display:flex;align-items:center;gap:12px;min-width:170px}.pro-logo-symbol{font-size:32px;line-height:1;font-weight:800;letter-spacing:-.07em;color:var(--pro-accent)}.pro-logo-name{max-width:220px;font-weight:820;font-size:17px;line-height:1.1;letter-spacing:-.035em}.pro-logo-name small{display:block;font-weight:650;font-size:9px;letter-spacing:.19em;margin-top:7px;color:var(--pro-muted)}.pro-navigation{display:flex;align-items:center;gap:24px;margin-left:auto}.pro-navigation a{font-size:13px;font-weight:650;white-space:nowrap;transition:opacity .2s}.pro-navigation a:hover{opacity:.6}.pro-header-cta,.pro-button{display:inline-flex;align-items:center;justify-content:center;gap:22px;background:var(--pro-accent);color:#fff!important;border-radius:var(--pro-radius);font-size:13px;letter-spacing:.01em;font-weight:750;padding:16px 24px;white-space:nowrap;transition:transform .2s,background .2s}.pro-header-cta:hover,.pro-button:hover{transform:translateY(-2px)}.pro-mobile-toggle{display:none}.pro-mega{display:flex;align-items:center;gap:22px;min-height:37px;border-top:1px solid var(--pro-border);padding-block:10px;font-size:11px}.pro-mega>span{font-weight:750;color:var(--pro-muted);white-space:nowrap}.pro-mega>div{display:flex;gap:16px;overflow:auto;scrollbar-width:none}.pro-mega a{white-space:nowrap;font-weight:650}.pro-search-link{font-size:19px!important}.pro-home-hero{position:relative;overflow:hidden}.pro-home-grid{display:grid;grid-template-columns:1.02fr .98fr;align-items:center;gap:5%;min-height:580px;padding-top:85px;padding-bottom:85px}.pro-hero-copy{position:relative;z-index:2}.pro-hero-copy h1{font-size:clamp(48px,6.2vw,91px);line-height:1.03;margin:20px 0 25px;max-width:730px}.pro-hero-copy h1 em{font-style:normal;display:block;color:var(--pro-accent)}.pro-hero-copy p{font-size:17px;max-width:495px;color:var(--pro-muted)}.pro-hero-actions{display:flex;align-items:center;flex-wrap:wrap;gap:25px;margin-top:34px}.pro-outline-button{font-weight:700;border-bottom:1px solid currentColor;padding:12px 0}.pro-hero-art{width:100%;height:435px;position:relative;overflow:hidden;border-radius:var(--pro-radius)}.pro-hero-art>img{width:100%;height:100%;object-fit:cover}.pro-hero-bottom{display:flex;justify-content:space-between;font-size:10px;letter-spacing:.18em;padding-block:22px;border-top:1px solid #ffffff32}.pro-section{padding:106px 0}.pro-section-head{display:flex;align-items:end;justify-content:space-between;gap:25px;margin-bottom:34px}.pro-section-head h2{font-size:clamp(36px,4vw,57px);margin:12px 0 0}.pro-text-link{font-size:13px;font-weight:750;display:inline-flex;gap:18px;align-items:center;border-bottom:1px solid;padding-bottom:7px;color:var(--pro-accent)}.pro-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:22px}.pro-card{display:block;min-width:0;background:var(--pro-background);color:var(--pro-text);border:1px solid var(--pro-border);overflow:hidden;border-radius:var(--pro-radius);transition:transform .25s,box-shadow .25s}.pro-card:hover{transform:translateY(-6px);box-shadow:0 24px 45px #0f25431b}.pro-card-cover{width:100%;height:244px;overflow:hidden;background:var(--pro-surface)}.pro-photo{width:100%;height:100%;object-fit:cover;transition:transform .5s}.pro-card:hover .pro-photo{transform:scale(1.045)}.pro-art{width:100%;height:100%;overflow:hidden;display:grid;place-items:center;position:relative;background:linear-gradient(130deg,#d8e1ed,#f3f6f9)}.pro-art-ring{width:55%;aspect-ratio:1;border:28px solid #ffffff5f;border-radius:50%;box-shadow:0 0 0 42px #ffffff30;transform:rotate(-25deg)}.pro-art-center{position:absolute;font-family:var(--pro-headings);font-weight:800;font-size:76px;letter-spacing:-.08em;color:#45647d90}.pro-art-label{position:absolute;bottom:16px;left:18px;letter-spacing:.16em;font-size:9px;color:#435773}.pro-card-body{padding:25px 25px 28px}.pro-card-meta{display:flex;justify-content:space-between;gap:20px;font-size:10px;font-weight:750;letter-spacing:.1em;text-transform:uppercase;color:var(--pro-accent)}.pro-card h3{font-size:23px;margin:14px 0 9px}.pro-card p{font-size:13px;color:var(--pro-muted);margin-bottom:24px;min-height:44px}.pro-card-link{font-size:12px;font-weight:800;display:flex;justify-content:space-between;color:var(--pro-text);padding-top:14px;border-top:1px solid var(--pro-border)}.pro-empty{grid-column:1/-1;padding:45px;border:1px dashed var(--pro-border);background:var(--pro-surface);color:var(--pro-muted)}.pro-statement{background:var(--pro-surface)}.pro-statement-layout{display:grid;grid-template-columns:1fr 2fr;gap:60px}.pro-statement h2{font-size:clamp(36px,4.5vw,63px);max-width:760px}.pro-statement p{max-width:520px;color:var(--pro-muted)}.pro-brand-pills{display:flex;flex-wrap:wrap;gap:12px}.pro-brand-pills a{padding:18px 28px;border:1px solid var(--pro-border);border-radius:var(--pro-radius);font-weight:750}.pro-brand-pills a:hover{border-color:var(--pro-accent)}.pro-inner-hero{background:var(--pro-surface);padding:92px 0 65px;position:relative;overflow:hidden}.pro-inner-hero h1{max-width:870px;font-size:clamp(43px,6vw,85px);margin:18px 0}.pro-inner-hero p{max-width:650px;color:var(--pro-muted);font-size:17px}.pro-breadcrumb{font-size:12px;color:var(--pro-muted);margin-top:25px;display:flex;gap:12px;align-items:center;flex-wrap:wrap}.pro-breadcrumb strong{color:var(--pro-text)}.pro-list-section{padding:65px 0 110px}.pro-filter-panel{display:grid;grid-template-columns:minmax(220px,2fr) 1fr 1fr auto;align-items:end;gap:14px;margin-bottom:35px}.pro-filter-panel label>span{display:block;font-size:11px;margin-bottom:8px;color:var(--pro-muted);font-weight:750}.pro-filter-panel input,.pro-filter-panel select{display:block;width:100%;padding:14px 15px;border-radius:var(--pro-radius);border:1px solid var(--pro-border);background:var(--pro-background);color:var(--pro-text);outline-offset:2px}.pro-filter-count{font-size:12px;padding-bottom:17px;color:var(--pro-muted)}.pro-filter-scope .pro-card[hidden]{display:none}.pro-product-layout{padding-top:38px}.pro-product-layout .pro-breadcrumb{margin-bottom:38px}.pro-product-hero{display:grid;grid-template-columns:1.18fr .82fr;gap:6%;align-items:center}.pro-product-media{height:460px;overflow:hidden;background:var(--pro-surface);border-radius:var(--pro-radius)}.pro-product-media .pro-photo{height:100%}.pro-product-summary h1{font-size:clamp(45px,5vw,72px);margin:16px 0}.pro-product-summary p{font-size:16px;color:var(--pro-muted)}.pro-product-brand{font-weight:700;color:var(--pro-text)!important}.pro-detail-layout{border-top:1px solid var(--pro-border);display:grid;grid-template-columns:1fr 1fr;gap:8%;margin-top:80px;padding-top:55px}.pro-detail-layout h2{font-size:32px;margin-top:13px}.pro-specs{margin-top:25px}.pro-specs>div{display:grid;grid-template-columns:1fr 1fr;gap:22px;padding:16px 0;border-bottom:1px solid var(--pro-border)}.pro-specs span{color:var(--pro-muted)}.pro-rich{line-height:1.85;font-size:16px;overflow-wrap:anywhere}.pro-rich img{border-radius:var(--pro-radius);margin:25px 0}.pro-rich a{text-decoration:underline}.pro-rich h2{margin-top:30px}.pro-lead{font-size:20px;color:var(--pro-muted)}.pro-brand-hero-grid{display:grid;grid-template-columns:1.1fr .9fr;gap:7%;align-items:center}.pro-brand-media{height:300px;overflow:hidden;border-radius:var(--pro-radius)}.pro-article-hero{text-align:center;padding:110px 0 75px;background:var(--pro-surface)}.pro-article-width{max-width:900px}.pro-article-hero h1{font-size:clamp(40px,5vw,75px);margin:15px 0 25px}.pro-article-hero p{color:var(--pro-muted);font-size:18px}.pro-article-hero time{font-size:12px;color:var(--pro-muted)}.pro-article-content{max-width:930px;padding-top:70px;padding-bottom:90px}.pro-article-cover{width:100%;max-height:530px;object-fit:cover;margin-bottom:40px;border-radius:var(--pro-radius)}.pro-article-content>.pro-text-link{margin-top:35px}.pro-case-detail{max-width:1020px}.pro-case-detail>img{width:100%;max-height:620px;object-fit:cover}.pro-case-meta{display:flex;gap:35px;margin:35px 0;color:var(--pro-muted);font-size:13px}.pro-case-meta strong{display:block;color:var(--pro-text);font-size:18px;margin-top:7px}.pro-info-grid{display:grid;grid-template-columns:.8fr 1.2fr;gap:12%}.pro-info-grid h2{font-size:clamp(31px,4.5vw,54px);margin-top:15px}.pro-contact-email{font-size:20px;color:var(--pro-accent);font-weight:750;word-break:break-word}.pro-info-photo{max-height:450px;object-fit:cover;margin-top:35px;border-radius:var(--pro-radius)}.pro-custom-content .sf-section{background:transparent}.pro-custom-content .sf-section:nth-of-type(even){background:var(--pro-surface)}.pro-end-cta{padding:76px 0;background:var(--pro-hero);color:#fff}.pro-end-cta .pro-wrap{display:flex;align-items:center;justify-content:space-between;gap:40px}.pro-end-cta h2{font-size:clamp(32px,4vw,53px);margin:13px 0}.pro-end-cta p{color:#c5c9d1}.pro-end-cta a{background:var(--pro-accent);color:#fff;font-weight:800;padding:19px 30px;border-radius:var(--pro-radius);white-space:nowrap}.pro-404{text-align:center;padding-block:125px}.pro-404>span{font-size:12px;letter-spacing:.3em}.pro-404 h1{font-size:clamp(150px,20vw,320px);margin:10px 0;letter-spacing:-.08em}.pro-404 p{font-size:18px;color:var(--pro-muted)}.pro-404 a{margin-top:22px}.pro-footer{background:#15212d;color:#fff;padding:75px 0 22px}.pro-footer-top{display:grid;grid-template-columns:1.45fr 1fr 1fr;gap:55px}.pro-footer h2{font-size:32px;margin:12px 0}.pro-footer p{max-width:350px;font-size:13px;color:#afbbc8}.pro-footer .pro-eyebrow{color:#b6c3d2}.pro-footer-links ul{margin:0;padding:0;list-style:none;display:grid;grid-template-columns:1fr 1fr;gap:15px}.pro-footer-links a{font-size:13px;color:#d6e0e8}.pro-footer-bottom{border-top:1px solid #ffffff29;margin-top:60px;padding-top:20px;font-size:10px;letter-spacing:.12em;color:#adb9c3;display:flex;justify-content:space-between}.pro-anchor{display:block;height:0}.pro-category-tiles{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}.pro-category-tiles a{padding:35px 28px;min-height:155px;background:var(--pro-surface);display:flex;flex-direction:column;justify-content:space-between}.pro-category-tiles span{font-size:11px;color:var(--pro-muted)}.pro-category-tiles strong{font-size:24px}.pro-category-tiles b{align-self:end}.sf-site-head .sf-head-inner,.sf-site-head .sf-primary-links{display:none} +@media(max-width:1100px){.pro-head-inner{gap:17px}.pro-navigation{gap:14px}.pro-navigation a{font-size:12px}.pro-home-grid{min-height:500px}.pro-hero-copy h1{font-size:60px}.pro-hero-art{height:350px}} +@media(max-width:860px){.pro-wrap{padding-left:22px;padding-right:22px}.pro-utility{display:none}.pro-head-inner{min-height:70px;flex-wrap:wrap;gap:12px}.pro-mobile-toggle{display:block;margin-left:auto;border:1px solid var(--pro-border);padding:8px 12px;background:transparent;color:var(--pro-text);border-radius:5px}.pro-navigation{display:none;order:10;width:100%;flex-direction:column;align-items:stretch;gap:0;padding-bottom:12px}.pro-navigation.is-open{display:flex}.pro-navigation a{padding:11px 2px;border-bottom:1px solid var(--pro-border)}.pro-header-cta{display:none}.pro-mega{display:none}.pro-home-grid{grid-template-columns:1fr;gap:35px;padding-top:60px;padding-bottom:60px}.pro-hero-art{height:350px}.pro-hero-copy h1{font-size:clamp(45px,9vw,73px)}.pro-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.pro-product-hero,.pro-detail-layout,.pro-info-grid,.pro-brand-hero-grid{grid-template-columns:1fr;gap:35px}.pro-product-media{height:380px}.pro-filter-panel{grid-template-columns:1fr 1fr}.pro-filter-panel label:first-child{grid-column:1/-1}.pro-end-cta .pro-wrap{align-items:start;flex-direction:column}.pro-section{padding:72px 0}.pro-footer-top{grid-template-columns:1fr 1fr}.pro-footer-top>div:first-child{grid-column:1/-1}.pro-category-tiles{grid-template-columns:repeat(2,1fr)}} +@media(max-width:560px){.pro-wrap{padding-left:18px;padding-right:18px}.pro-logo-name{font-size:15px}.pro-hero-copy h1{font-size:43px}.pro-hero-art{height:255px}.pro-hero-bottom{display:none}.pro-home-grid{min-height:0}.pro-grid{grid-template-columns:1fr}.pro-section-head{align-items:start;flex-direction:column}.pro-section-head h2{font-size:37px}.pro-card-cover{height:230px}.pro-filter-panel{grid-template-columns:1fr}.pro-filter-panel label:first-child{grid-column:auto}.pro-filter-count{padding-bottom:4px}.pro-statement-layout,.pro-footer-top{grid-template-columns:1fr;gap:25px}.pro-footer-top>div:first-child{grid-column:auto}.pro-footer-bottom{flex-direction:column;gap:8px}.pro-inner-hero{padding:60px 0}.pro-product-media{height:270px}.pro-product-summary h1{font-size:43px}.pro-category-tiles{grid-template-columns:1fr}.pro-end-cta h2{font-size:38px}.pro-minimal-meta{display:block!important}} + +/* V2 compatibility stylesheet hides direct headers/footers; full themes restore their own. */ +body>header.sf-site-head.pro-header,body>footer.sf-site-foot.pro-footer{display:block!important} + +/* Accessible desktop mega-navigation and mobile disclosure */ +.pro-catalog-toggle{font-size:12px;font-weight:750;border:1px solid var(--pro-border);background:transparent;color:inherit;border-radius:var(--pro-radius);padding:10px 14px;white-space:nowrap} +.pro-mega[hidden]{display:none!important}.pro-mega.is-open{display:flex}.pro-mega>div{padding-block:3px} +@media(max-width:1060px){.pro-catalog-toggle{display:none}} +@media(max-width:860px){.pro-mega.is-open{display:block!important}.pro-mega.is-open>div{display:flex;flex-wrap:wrap;gap:14px;padding:12px 0}.pro-mega>span{white-space:normal}} + +/* V4: responsive nested navigation, gallery and opt-in inquiry integration */ +.pro-nav-group{position:relative;display:flex;align-items:center;gap:3px}.pro-nav-disclose{border:0;background:none;color:inherit;font-size:12px;padding:8px}.pro-nav-children[hidden]{display:none!important}.pro-nav-children{position:absolute;left:0;top:100%;z-index:45;min-width:230px;max-width:360px;padding:10px;background:var(--pro-background);border:1px solid var(--pro-border);box-shadow:0 18px 35px #0002;border-radius:var(--pro-radius);display:flex;flex-direction:column}.pro-nav-children a{padding:10px 12px;white-space:nowrap}.pro-nav-children .pro-nav-leaf{padding-left:28px;color:var(--pro-muted)} +.pro-product-gallery{min-width:0}.pro-gallery-thumbs{display:flex;gap:8px;margin-top:12px;overflow:auto;scrollbar-width:thin;padding-bottom:5px}.pro-gallery-thumbs button{flex:0 0 86px;height:67px;border:2px solid transparent;padding:3px;border-radius:8px;background:var(--pro-surface)}.pro-gallery-thumbs button:focus-visible,.pro-gallery-thumbs button[aria-pressed=true]{border-color:var(--pro-accent)}.pro-gallery-thumbs img{width:100%;height:100%;object-fit:cover;border-radius:4px}.pro-gallery-lightbox{position:fixed;inset:0;background:rgba(10,16,30,.92);z-index:1000;display:grid;place-items:center;padding:6vw}.pro-gallery-lightbox[hidden]{display:none}.pro-gallery-lightbox img{max-width:92vw;max-height:80vh;object-fit:contain}.pro-gallery-lightbox button{position:absolute;right:25px;top:25px;border:1px solid #fff8;background:#222;color:#fff;padding:10px 15px;border-radius:5px} +.pro-inquiry-wrap{display:grid;grid-template-columns:1fr 1fr;gap:70px}.pro-inquiry{display:grid;gap:17px}.pro-inquiry label{display:grid;gap:7px;font-weight:650}.pro-inquiry input,.pro-inquiry textarea{padding:13px;border:1px solid var(--pro-border);border-radius:var(--pro-radius);background:var(--pro-background);color:var(--pro-text);width:100%}.pro-inquiry textarea{min-height:140px}.pro-inquiry .pro-honeypot{position:absolute;left:-10000px;width:1px;height:1px}.pro-inquiry p{font-size:12px;color:var(--pro-muted)} +@media(max-width:860px){.pro-nav-group{display:block}.pro-nav-children{position:static;max-width:none;width:100%;box-shadow:none;border:0;border-left:2px solid var(--pro-accent);padding-left:8px}.pro-nav-group>a{display:inline-block}.pro-inquiry-wrap{grid-template-columns:1fr;gap:20px}} diff --git a/examples/v830-built-sites/minimal/assets/pro.css b/examples/v830-built-sites/minimal/assets/pro.css new file mode 100644 index 0000000..b65732d --- /dev/null +++ b/examples/v830-built-sites/minimal/assets/pro.css @@ -0,0 +1,90 @@ +:root{--pro-text:#272722;--pro-muted:#797972;--pro-border:#d9d8d0;--pro-background:#fafaf7;--pro-surface:#f0f0eb;--pro-accent:#282923;--pro-hero:#272722;--pro-radius:0;--pro-headings:Georgia,Times New Roman,serif;--pro-font:Arial,sans-serif;--pro-wide:1380px} +.pro-header{background:#fafaf7;color:#292920}.pro-head-inner{min-height:96px}.pro-logo{min-width:200px}.pro-logo-symbol{font-family:Georgia,serif;color:#272722;font-size:40px;font-weight:400}.pro-logo-name{font-family:Georgia,serif;font-size:23px;font-weight:500}.pro-logo-name small{font-family:Arial,sans-serif;font-size:9px}.pro-navigation a{font-size:12px;font-weight:550}.pro-header-cta{border-radius:0;background:transparent;color:#262621!important;border-bottom:1px solid #222;padding:10px 0}.pro-minimal-hero{background:#f4f3ec;color:#252521;border-bottom:1px solid #d7d7cc}.pro-minimal-hero>.pro-wrap{padding-top:68px;padding-bottom:90px}.pro-minimal-meta{display:flex;justify-content:space-between;color:#727267;font-size:10px;letter-spacing:.16em}.pro-minimal-hero h1{font-weight:400;font-family:Georgia,serif;letter-spacing:-.072em;font-size:clamp(65px,10vw,153px);line-height:1.03;margin:100px 0 85px}.pro-minimal-hero h1 em{font-weight:400;font-style:italic;color:#8f8e82}.pro-minimal-bottom{display:flex;justify-content:space-between;align-items:end;gap:40px;border-top:1px solid #c9c8bf;padding-top:28px}.pro-minimal-bottom p{font-size:17px;max-width:450px;margin:0}.pro-minimal-bottom a{font-weight:750;font-size:11px;letter-spacing:.11em;white-space:nowrap}.pro-minimal-bottom a span{padding-left:25px}.pro-section-head h2{font-weight:400;font-size:clamp(40px,5vw,70px)}.pro-grid{gap:34px 20px}.pro-card{border:0;background:transparent;border-radius:0}.pro-card:hover{box-shadow:none}.pro-card-cover{height:310px;background:#eae9e1}.pro-card-body{padding:23px 0}.pro-card h3{font-family:Georgia,serif;font-size:27px;font-weight:400}.pro-art{background:linear-gradient(145deg,#deddd2,#ebeae5)}.pro-art-ring{border-color:#ffffff8a}.pro-art-center{color:#aba89b}.pro-card-link{border-color:#c7c6bf}.pro-statement{background:#e9e7dc}.pro-statement h2{font-family:Georgia,serif;font-weight:400;font-size:clamp(43px,6vw,83px)}.pro-statement .pro-text-link{color:#292a22}.pro-inner-hero{background:#f0efe8;border-bottom:1px solid #deddd3}.pro-inner-hero h1{font-family:Georgia,serif;font-weight:400;font-size:clamp(60px,9vw,117px)}.pro-article-hero{background:#eeede5}.pro-article-hero h1{font-family:Georgia,serif;font-weight:400}.pro-article-content{max-width:830px}.pro-product-summary h1{font-family:Georgia,serif;font-weight:400}.pro-footer{background:#242520}.pro-footer h2{font-family:Georgia,serif;font-size:40px;font-weight:400}.pro-end-cta{background:#282822}.pro-end-cta h2{font-family:Georgia,serif;font-weight:400}.pro-end-cta a{background:#fff;color:#242520!important}.pro-404 h1{font-family:Georgia,serif;font-weight:400;color:#8f8e82}.pro-dot{color:#a8a595} + +/* SiteForge V5 commercial signature */ +.pro-minimal-hero .pro-hero-art{background-image:url("./visual/hero.svg")!important;background-position:center;background-size:cover;} + +.pro-minimal-hero{background:#efeee8!important}.pro-minimal-hero .pro-wrap{background-image:url("./visual/hero.svg");background-repeat:no-repeat;background-size:48% auto;background-position:right 56%}.pro-minimal-hero h1{max-width:930px;position:relative;text-shadow:0 1px #ffffff70}.pro-card{border:0;border-bottom:1px solid #c8c7c0;background:transparent;border-radius:0}.pro-card-cover{background:#e7e5dc}.pro-art{background:linear-gradient(155deg,#e8e7e0,#c8c9bd);color:#585d55}.pro-card-body{padding-left:0;padding-right:0}.pro-featured{background:#faf9f5}.pro-section-head h2{font-weight:400}.pro-statement{border-block:1px solid #dddcd2;background:#f1efe7}.pro-footer{background:#22251e;color:#f6f4ec}.pro-button,.pro-header-cta{border-radius:0} +@media(max-width:700px){.pro-minimal-hero .pro-wrap{background-size:80% auto;background-position:center bottom;padding-bottom:250px}} + +/* V8.29 presentation refinement: minimal. Preserve per-theme design language. */ +body.pro-minimal{--pro-studio-ring:rgba(45,45,42,.13);--pro-focus-color:#35352d;--pro-interact-radius:2px} +body.pro-minimal .pro-wrap{max-width:100%;min-width:0} +body.pro-minimal .pro-hero-copy,body.pro-minimal .pro-card-body,body.pro-minimal .pro-card-copy{min-width:0;overflow-wrap:anywhere} +body.pro-minimal .pro-hero-copy h1{font-size:clamp(2.45rem,5.15vw,5.6rem);line-height:1.08;max-width:18ch;text-wrap:balance} +body.pro-minimal .pro-section-head h2{font-size:clamp(1.85rem,3vw,3.25rem);text-wrap:balance} +body.pro-minimal .pro-card,body.pro-minimal .pro-product-card{transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease} +@media(hover:hover){body.pro-minimal .pro-card:hover,body.pro-minimal .pro-product-card:hover{transform:translateY(-3px);box-shadow:0 14px 36px var(--pro-studio-ring)}} +body.pro-minimal :where(button,a,input,select,textarea):focus-visible{outline:3px solid var(--pro-focus-color);outline-offset:3px} +body.pro-minimal img{max-width:100%;height:auto} +body.pro-minimal .pro-card-cover img,body.pro-minimal .pro-gallery-main img{object-fit:cover;max-height:100%} +body.pro-minimal .pro-mobile-toggle,body.pro-minimal .pro-nav-disclose{min-height:44px;min-width:44px} +@media(max-width:860px){body.pro-minimal .pro-home-grid,body.pro-minimal .pro-product-layout,body.pro-minimal .pro-inquiry-wrap{min-width:0}body.pro-minimal .pro-card-grid,body.pro-minimal .pro-grid{gap:clamp(12px,3vw,23px)}} +@media(max-width:560px){body.pro-minimal .pro-wrap{padding-left:max(16px,env(safe-area-inset-left));padding-right:max(16px,env(safe-area-inset-right))}body.pro-minimal .pro-hero-copy h1{font-size:clamp(2rem,9vw,3.2rem)}body.pro-minimal .pro-section-head h2{font-size:clamp(1.75rem,7vw,2.5rem)}body.pro-minimal .pro-section{padding-block:clamp(34px,9vw,60px)}body.pro-minimal .pro-card-cover{height:auto;aspect-ratio:4/3}body.pro-minimal .pro-card-cover img{width:100%;height:100%;object-fit:cover}} +@media(prefers-reduced-motion:reduce){body.pro-minimal .pro-card,body.pro-minimal .pro-product-card{transition:none!important;transform:none!important}} + + +/* V8.30 REAL PAGE COMPOSITION. Built-in theme version 1.3.0 only. + Content-driven sections do not invent client names, certifications or KPIs. */ +.pro-v30-page{--v30-ink:var(--pro-text);--v30-secondary:var(--pro-muted);--v30-line:var(--pro-border);--v30-panel:var(--pro-surface);--v30-max:1180px;color:var(--v30-ink);overflow:clip} +.pro-v30-page .pro-wrap{max-width:var(--v30-max);min-width:0} +.pro-v30-page h1,.pro-v30-page h2{overflow-wrap:anywhere;text-wrap:balance;line-height:1.11} +.pro-v30-page h1{font-size:clamp(2.55rem,5.2vw,5.6rem);margin:18px 0 22px;letter-spacing:-.035em} +.pro-v30-page h2{font-size:clamp(1.8rem,3.3vw,3rem);margin:16px 0 26px;letter-spacing:-.02em} +.pro-v30-page p{line-height:1.75;overflow-wrap:anywhere} +.pro-v30-page img{max-width:100%} +.pro-v30-intro-layout{display:grid;grid-template-columns:minmax(0,1fr) 190px;gap:8vw;align-items:end} +.pro-v30-page-intro{padding:clamp(68px,10vw,128px) 0 clamp(55px,8vw,94px);background:var(--v30-panel)} +.pro-v30-intro-main>p{max-width:610px;font-size:clamp(16px,2vw,21px);color:var(--v30-secondary)} +.pro-v30-intro-aside{border-left:1px solid var(--v30-line);padding-left:27px;display:grid;gap:8px;align-content:end;min-height:120px} +.pro-v30-overline,.pro-v30-caption{font-size:11px;letter-spacing:.12em;color:var(--v30-secondary)} +.pro-v30-index-number{font-size:64px;line-height:1;font-weight:650;letter-spacing:-.08em} +.pro-v30-index-toolbar{display:flex;justify-content:space-between;align-items:end;gap:22px;margin-bottom:28px} +.pro-v30-index-body{background:var(--pro-background)} +.pro-v30-index-body .pro-section-head,.pro-v30-index-toolbar h2{margin:8px 0} +.pro-v30-subtle-link,.pro-v30-text-action{display:inline-flex;gap:10px;text-decoration:none;font-weight:750;font-size:13px;align-items:center;min-height:44px} +.pro-v30-subtle-link:hover,.pro-v30-text-action:hover{text-decoration:underline} +.pro-v30-results{margin-top:clamp(28px,5vw,54px)} +.pro-v30-product-top{padding:26px 0 clamp(60px,8vw,110px);background:var(--v30-panel)} +.pro-v30-crumb{display:flex;flex-wrap:wrap;gap:11px;align-items:center;font-size:12px;color:var(--v30-secondary);margin:8px 0 46px} +.pro-v30-crumb a{text-decoration:underline;text-underline-offset:4px} +.pro-v30-product-head{display:grid;grid-template-columns:minmax(290px,.78fr) minmax(0,1.22fr);align-items:center;gap:clamp(30px,6vw,90px)} +.pro-v30-product-intro>p{font-size:clamp(16px,2vw,19px);color:var(--v30-secondary);max-width:48ch} +.pro-v30-tags{display:flex;gap:8px;flex-wrap:wrap;margin:24px 0 30px}.pro-v30-tags span{padding:8px 13px;border:1px solid var(--v30-line);font-size:12px;border-radius:2px} +.pro-v30-action{display:inline-flex;align-items:center;justify-content:center;min-height:48px} +.pro-v30-main-media{background:var(--pro-surface);aspect-ratio:4/3;overflow:hidden;display:grid;place-items:center;border-radius:var(--pro-radius)} +.pro-v30-main-media .pro-photo{width:100%;height:100%;object-fit:contain} +.pro-v30-product-details{display:grid;grid-template-columns:minmax(0,1.3fr) minmax(270px,.7fr);gap:clamp(30px,7vw,104px)} +.pro-v30-details-main .pro-rich{max-width:760px}.pro-v30-details-side{align-self:start;border-top:3px solid var(--pro-accent);padding-top:25px} +.pro-v30-details-side .pro-specs>div{grid-template-columns:minmax(0,1fr) minmax(0,1.1fr);gap:16px}.pro-v30-details-side .pro-specs strong{overflow-wrap:anywhere} +.pro-v30-reading-head{padding:clamp(50px,8vw,100px) 0 clamp(60px,8vw,100px);background:var(--v30-panel)} +.pro-v30-reading-title{max-width:940px;margin:auto}.pro-v30-reading-title>p{font-size:clamp(16px,2.1vw,22px);max-width:65ch;color:var(--v30-secondary)} +.pro-v30-reading-title time{display:block;margin-top:24px;font-size:13px;color:var(--v30-secondary)} +.pro-v30-reading-layout{display:grid;grid-template-columns:180px minmax(0,750px);gap:clamp(35px,7vw,110px);padding-block:clamp(55px,8vw,110px)} +.pro-v30-reading-aside{display:flex;flex-direction:column;gap:18px;align-self:start;position:sticky;top:30px;font-size:13px} +.pro-v30-reading-rule{height:1px;background:var(--v30-line)} +.pro-v30-reading-content{min-width:0}.pro-v30-reading-content figure{margin:0 0 45px}.pro-v30-reading-content figure img{display:block;width:100%;height:auto;max-height:550px;object-fit:cover} +.pro-v30-reading-content .pro-rich{line-height:1.9;font-size:clamp(16px,1.75vw,18px)}.pro-v30-reading-content .pro-rich>*+*{margin-top:1.3em} +.pro-v30-about-opening{padding:clamp(75px,10vw,130px) 0;background:var(--v30-panel)} +.pro-v30-about-heading{display:grid;grid-template-columns:1.3fr .7fr;gap:9%;align-items:end}.pro-v30-about-heading>p{font-size:clamp(17px,2vw,23px);color:var(--v30-secondary);padding-bottom:12px} +.pro-v30-about-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(36px,8vw,120px);align-items:center} +.pro-v30-about-media{min-height:360px;aspect-ratio:5/4;background:var(--v30-panel);overflow:hidden}.pro-v30-about-media img{width:100%;height:100%;object-fit:cover} +.pro-v30-media-placeholder{height:100%;min-height:360px;display:grid;place-items:center;color:var(--v30-secondary);letter-spacing:.18em;font-size:12px;border:1px solid var(--v30-line)} +.pro-v30-about-copy .pro-rich{max-width:620px}.pro-v30-about-cases{background:var(--v30-panel)} +.pro-v30-contact-header{background:var(--v30-panel);padding:clamp(75px,10vw,135px) 0}.pro-v30-contact-header p{font-size:clamp(17px,2vw,21px);max-width:58ch;color:var(--v30-secondary)} +.pro-v30-contact-layout{display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);gap:clamp(40px,8vw,120px)} +.pro-v30-contact-channel{display:grid;gap:10px;margin-top:45px;border-top:1px solid var(--v30-line);padding-top:25px}.pro-v30-contact-channel span{font-size:12px;color:var(--v30-secondary)}.pro-v30-contact-channel a{font-size:clamp(15px,2vw,24px);overflow-wrap:anywhere;font-weight:650} +.pro-v30-contact-form-wrap{padding:clamp(22px,4vw,48px);background:var(--v30-panel);min-width:0} +.pro-v30-contact-form-wrap .pro-inquiry{margin-top:22px}.pro-v30-contact-form-wrap .pro-inquiry input,.pro-v30-contact-form-wrap textarea{background:var(--pro-background)} +.pro-v30-contact-note{display:grid;align-content:space-between;min-height:270px;gap:24px}.pro-v30-decorative-number{font-size:90px;line-height:1;justify-self:end;color:var(--pro-accent)} +.pro-v30-home-editorial{background:var(--pro-surface)} +.pro-v30-page :where(a,button,input,textarea,select):focus-visible{outline:3px solid var(--pro-accent);outline-offset:3px} +@media(max-width:950px){.pro-v30-product-head,.pro-v30-product-details,.pro-v30-about-grid,.pro-v30-contact-layout{grid-template-columns:1fr;gap:38px}.pro-v30-product-visual{order:-1}.pro-v30-about-heading{grid-template-columns:1fr;gap:4px}.pro-v30-about-media{max-height:430px}.pro-v30-reading-layout{grid-template-columns:1fr;gap:24px}.pro-v30-reading-aside{position:static;flex-direction:row;align-items:center;flex-wrap:wrap}.pro-v30-reading-rule{display:none}} +@media(max-width:600px){.pro-v30-page .pro-wrap{padding-inline:max(18px,env(safe-area-inset-left));}.pro-v30-page h1{font-size:clamp(2.2rem,9.2vw,3.4rem)}.pro-v30-intro-layout{grid-template-columns:1fr;gap:18px}.pro-v30-intro-aside{display:none}.pro-v30-index-toolbar{align-items:start;flex-direction:column;gap:0}.pro-v30-crumb{margin-bottom:24px}.pro-v30-product-top{padding-bottom:42px}.pro-v30-main-media{aspect-ratio:5/4}.pro-v30-product-details{gap:45px}.pro-v30-reading-title{margin:0}.pro-v30-reading-content figure{margin-bottom:22px}.pro-v30-about-media,.pro-v30-media-placeholder{min-height:220px}.pro-v30-contact-form-wrap{padding:20px}.pro-v30-contact-layout{gap:30px}} +@media(prefers-reduced-motion:reduce){.pro-v30-page *{scroll-behavior:auto!important}} + +/* Theme-specific editorial composition */ + .pro-v30-editorial-index{--v30-max:1260px}.pro-v30-editorial-index .pro-v30-page-intro{background:#f0efe8}.pro-v30-editorial-index h1,.pro-v30-article-minimal h1,.pro-v30-about-minimal h1,.pro-v30-product-minimal h1{font-family:Georgia,Times,serif;font-weight:400;letter-spacing:-.06em}.pro-v30-editorial-index .pro-v30-index-number{font-family:Georgia,serif;font-weight:400}.pro-v30-product-minimal .pro-v30-product-top{background:#f1f0ea}.pro-v30-product-minimal .pro-v30-main-media{border-radius:0;background:#eae9e1}.pro-v30-article-minimal .pro-v30-reading-head{background:#f3f1e9}.pro-v30-article-minimal .pro-v30-reading-layout{grid-template-columns:160px minmax(0,700px)}.pro-v30-about-minimal .pro-v30-about-opening{border-bottom:1px solid #d8d8ce}.pro-v30-about-minimal .pro-v30-about-media{filter:saturate(.8)}.pro-v30-contact-minimal .pro-v30-contact-form-wrap{border:1px solid #d7d6ce;background:transparent} + +/* Retain existing gallery runtime behavior with re-composed product layout. */ +.pro-v30-page .pro-product-media{height:auto;min-height:0} diff --git a/examples/v830-built-sites/minimal/assets/pro.js b/examples/v830-built-sites/minimal/assets/pro.js new file mode 100644 index 0000000..9cf100d --- /dev/null +++ b/examples/v830-built-sites/minimal/assets/pro.js @@ -0,0 +1,72 @@ +'use strict';(()=>{ + const menu=document.querySelector('[data-pro-menu]'); const nav=document.querySelector('#pro-navigation'); + if(menu&&nav){menu.addEventListener('click',()=>{const open=menu.getAttribute('aria-expanded')!=='true';menu.setAttribute('aria-expanded',String(open));nav.classList.toggle('is-open',open);menu.setAttribute('aria-label',open?'关闭导航':'打开导航');});} + // Drawer navigation. The same markup is used across the four professional themes. + const mobileNav=document.querySelector('#pro-navigation'); + let drawerBackdrop=null,drawerClose=null,returnFocus=null; + if(menu&&mobileNav){ + const originalParent=mobileNav.parentNode,originalNext=mobileNav.nextSibling; + const heading=document.createElement('div');heading.className='sf-drawer-header'; + const title=document.createElement('strong');title.textContent='网站导航'; + drawerClose=document.createElement('button');drawerClose.type='button';drawerClose.className='sf-drawer-close';drawerClose.textContent='×';drawerClose.setAttribute('aria-label','关闭网站导航'); + heading.append(title,drawerClose);mobileNav.prepend(heading); + drawerBackdrop=document.createElement('div');drawerBackdrop.className='sf-mobile-drawer-backdrop';drawerBackdrop.hidden=false;document.body.append(drawerBackdrop); + function setDrawer(open,focusBack=true){ + const isMobile=window.matchMedia('(max-width:1024px)').matches; + open=Boolean(open&&isMobile); + if(open){returnFocus=document.activeElement;document.body.append(mobileNav);} + else if(mobileNav.parentNode!==originalParent){if(originalNext&&originalNext.parentNode===originalParent)originalParent.insertBefore(mobileNav,originalNext);else originalParent.append(mobileNav);} + mobileNav.classList.toggle('is-open',open);drawerBackdrop.classList.toggle('is-open',open); + document.body.classList.toggle('sf-drawer-open',open); + menu.setAttribute('aria-expanded',String(open));menu.setAttribute('aria-label',open?'关闭导航':'打开导航'); + mobileNav.setAttribute('aria-hidden',String(!open&&isMobile)); + if('inert' in mobileNav)mobileNav.inert=!open&&isMobile; + if(open)drawerClose.focus(); + else if(focusBack&&returnFocus instanceof HTMLElement){returnFocus.focus();returnFocus=null;} + } + // Replace the old inline-expansion listener: use capture to stop the old listener. + menu.addEventListener('click',e=>{if(!window.matchMedia('(max-width:1024px)').matches)return;e.stopImmediatePropagation();setDrawer(!mobileNav.classList.contains('is-open'));},true); + drawerClose.addEventListener('click',()=>setDrawer(false)); + drawerBackdrop.addEventListener('click',()=>setDrawer(false)); + document.querySelectorAll('[data-mobile-open-menu]').forEach(b=>b.addEventListener('click',()=>setDrawer(true))); + mobileNav.addEventListener('click',e=>{if(e.target.closest('a'))setDrawer(false,false)}); + document.addEventListener('keydown',e=>{ + if(e.key==='Escape'&&mobileNav.classList.contains('is-open')){e.preventDefault();setDrawer(false);} + if(e.key!=='Tab'||!mobileNav.classList.contains('is-open'))return; + const els=[...mobileNav.querySelectorAll('button:not([disabled]),a[href]')].filter(el=>el.getClientRects().length&&!el.closest('[hidden]')); + if(!els.length)return;const first=els[0],last=els[els.length-1]; + if(e.shiftKey&&document.activeElement===first){e.preventDefault();last.focus();} + else if(!e.shiftKey&&document.activeElement===last){e.preventDefault();first.focus();} + }); + window.matchMedia('(max-width:1024px)').addEventListener('change',()=>setDrawer(false,false)); + if('inert' in mobileNav&&window.matchMedia('(max-width:1024px)').matches)mobileNav.inert=true; + // Do not strand catalogue links when the old mobile mega-button is hidden. + const megaLinks=document.querySelectorAll('[data-pro-mega] a'); + if(megaLinks.length){const wrap=document.createElement('div');wrap.className='sf-drawer-extra';const h=document.createElement('strong');h.textContent='更多分类与系列';wrap.append(h); + [...megaLinks].slice(0,20).forEach(a=>{const clone=a.cloneNode(true);wrap.append(clone);});mobileNav.append(wrap);} + } + const tabbar=document.querySelector('[data-mobile-tabs]'); + if(tabbar){tabbar.style.setProperty('--sf-mobile-tab-count',String(tabbar.children.length));} + const megaButton=document.querySelector('[data-pro-catalog]'), mega=document.querySelector('[data-pro-mega]'); + if(megaButton&&mega){function setMega(open){mega.hidden=!open;mega.classList.toggle('is-open',open);megaButton.setAttribute('aria-expanded',String(open));} + megaButton.addEventListener('click',()=>setMega(mega.hidden)); + document.addEventListener('keydown',e=>{if(e.key==='Escape')setMega(false);}); + document.addEventListener('click',e=>{if(!mega.hidden&&!mega.contains(e.target)&&!megaButton.contains(e.target))setMega(false);}); + } + document.querySelectorAll('.pro-nav-disclose').forEach(button=>{button.addEventListener('click',()=>{let panel=button.parentElement.querySelector('.pro-nav-children');let visible=button.getAttribute('aria-expanded')==='true';button.setAttribute('aria-expanded',String(!visible));panel.hidden=visible;});}); + document.querySelectorAll('.pro-gallery-thumbs').forEach(container=>{const main=container.parentElement.querySelector('.pro-product-media img');const buttons=[...container.querySelectorAll('[data-gallery-image]')]; + buttons.forEach(b=>{b.addEventListener('click',()=>{buttons.forEach(x=>x.setAttribute('aria-pressed',String(x===b)));if(main){main.src=b.dataset.galleryImage;main.alt=b.querySelector('img')?.alt||'';}});}); + if(!main)return;main.tabIndex=0;main.style.cursor='zoom-in';const open=()=>{const pane=document.createElement('div');pane.className='pro-gallery-lightbox';pane.setAttribute('role','dialog');pane.setAttribute('aria-label','产品大图预览');let img=document.createElement('img');img.src=main.src;img.alt=main.alt;const close=document.createElement('button');close.type='button';close.textContent='关闭 ×';pane.append(img,close);document.body.append(pane);const done=()=>{pane.remove();document.removeEventListener('keydown',esc);main.focus();};const esc=e=>{if(e.key==='Escape')done();};document.addEventListener('keydown',esc);close.addEventListener('click',done);pane.addEventListener('click',e=>{if(e.target===pane)done();});close.focus();};main.addEventListener('click',open);main.addEventListener('keydown',e=>{if(e.key==='Enter')open();}); + }); + document.querySelectorAll('.pro-filter-scope').forEach(scope=>{ + const panel=scope.previousElementSibling;if(!panel||!panel.classList.contains('pro-filter-panel'))return; + const cards=Array.from(scope.querySelectorAll('.pro-card')); + const blank=document.createElement('div');blank.className='pro-filter-empty';blank.hidden=true;blank.textContent='没有找到符合条件的内容,请调整关键词或筛选条件。';scope.append(blank); + const q=panel.querySelector('[data-pro-filter-search]'),b=panel.querySelector('[data-pro-filter-brand]'),c=panel.querySelector('[data-pro-filter-category]'),count=panel.querySelector('[data-pro-filter-count]'); + function options(sel,key){const vals=[...new Set(cards.map(x=>x.dataset[key]||'').filter(Boolean))].sort();vals.forEach(x=>sel.add(new Option(x,x)));if(!vals.length)sel.closest('label').hidden=true;} + options(b,'brand');options(c,'category'); + function run(){const str=q.value.trim().toLocaleLowerCase();let visible=0; + cards.forEach(el=>{const hit=el.textContent.toLocaleLowerCase().includes(str)&&(!b.value||el.dataset.brand===b.value)&&(!c.value||el.dataset.category===c.value);el.hidden=!hit;visible+=Number(hit);});count.textContent=`共 ${visible} 条`;blank.hidden=visible!==0;} + [q,b,c].forEach(x=>x.addEventListener(x===q?'input':'change',run));run(); + }); +})(); diff --git a/examples/v830-built-sites/minimal/assets/site-runtime.js b/examples/v830-built-sites/minimal/assets/site-runtime.js new file mode 100644 index 0000000..e4715e8 --- /dev/null +++ b/examples/v830-built-sites/minimal/assets/site-runtime.js @@ -0,0 +1,31 @@ +'use strict'; +(()=>{ + const $=s=>document.querySelector(s), $$=s=>[...document.querySelectorAll(s)]; + const menu=$('.sf-menu-toggle');if(menu){menu.addEventListener('click',()=>{let open=menu.getAttribute('aria-expanded')!=='true';menu.setAttribute('aria-expanded',String(open));$('#sf-primary-links')?.classList.toggle('is-open',open);});} + // Filter actual static content cards, no API is needed at runtime. + $$('.sf-collection').forEach(grid=>{ + const cards=$$('.sf-item',grid); + if(cards.length<2)return; + const toolbar=document.createElement('div');toolbar.className='sf-filters'; + const search=document.createElement('input');search.type='search';search.placeholder='筛选当前列表';search.setAttribute('aria-label','筛选当前列表'); + const status=document.createElement('span');status.setAttribute('aria-live','polite');status.style.fontSize='12px'; + const brand=document.createElement('select');brand.setAttribute('aria-label','按品牌筛选'); + const category=document.createElement('select');category.setAttribute('aria-label','按分类筛选'); + function fill(el,field,all){el.append(new Option(all,''));const vals=[...new Set(cards.map(x=>x.dataset[field]||'').filter(Boolean))].sort();vals.forEach(v=>el.append(new Option(v,v)));if(!vals.length)el.hidden=true;} + fill(brand,'brand','全部品牌');fill(category,'category','全部分类'); + toolbar.append(search,brand,category,status);grid.parentNode.insertBefore(toolbar,grid); + function apply(){let val=search.value.trim().toLocaleLowerCase();let visible=0;cards.forEach(card=>{let hit=card.textContent.toLocaleLowerCase().includes(val)&&(!brand.value||card.dataset.brand===brand.value)&&(!category.value||card.dataset.category===category.value);card.hidden=!hit;if(hit)visible++;});status.textContent=`共 ${visible} 项`;} + search.addEventListener('input',apply);brand.addEventListener('change',apply);category.addEventListener('change',apply);apply(); + }); + const input=$('#sf-search'),root=$('#sf-search-results'),count=$('#sf-search-count'); + if(input&&root){ + let data=[];const params=new URLSearchParams(location.search);input.value=params.get('q')||''; + let debounce=null; + const render=()=>{let q=input.value.trim().toLocaleLowerCase();let found=q?data.filter(d=>`${d.title} ${d.summary} ${d.brand} ${d.type}`.toLocaleLowerCase().includes(q)).slice(0,100):data.slice(0,30); + root.replaceChildren();count.textContent=`${found.length} 条结果${!q?'(显示前30条)':''}`; + found.forEach(d=>{let article=document.createElement('article'),a=document.createElement('a'),small=document.createElement('small'),p=document.createElement('p');article.className='sf-search-result';a.textContent=d.title;a.href=d.url.replace(/^\//,'');small.textContent=d.type;p.textContent=d.summary;article.append(a,small,p);root.append(article);}); + };const base=document.querySelector('base')?.href||location.href; + fetch(new URL('search-index.json',base)).then(r=>{if(!r.ok)throw Error('index unavailable');return r.json();}).then(v=>{data=v;render()}).catch(()=>{count.textContent='搜索索引加载失败,请检查站点文件部署路径';}); + input.addEventListener('input',()=>{clearTimeout(debounce);debounce=setTimeout(render,100)}); + } +})(); diff --git a/examples/v830-built-sites/minimal/assets/theme.css b/examples/v830-built-sites/minimal/assets/theme.css new file mode 100644 index 0000000..65e1dca --- /dev/null +++ b/examples/v830-built-sites/minimal/assets/theme.css @@ -0,0 +1,4 @@ +*{box-sizing:border-box}body{margin:0;color:#171717;background:#faf9f6;font:16px/1.6 Arial,Helvetica,sans-serif}a{color:inherit;text-decoration:none}.container{width:min(1260px,90%);margin:auto}.header{height:110px;display:flex;align-items:center;justify-content:space-between;gap:20px;border-bottom:1px solid #cccac4}.brand{font-family:Georgia,"Times New Roman",serif;font-size:30px;font-weight:bold;letter-spacing:-1px}.brand span{font-size:12px;vertical-align:top}.header nav{display:flex;gap:33px;font-size:12px;flex-wrap:wrap}.header nav a:hover{text-decoration:underline}.contact{font-size:12px;font-weight:bold;border-bottom:1px solid black;padding-bottom:5px}.hero{padding:48px 0 0}.topline{display:flex;justify-content:space-between;font-size:10px;letter-spacing:2.3px;font-weight:bold}.hero h1,.inner-hero h1{font-family:Georgia,"Times New Roman",serif;font-size:clamp(65px,9.1vw,155px);line-height:1;letter-spacing:-8px;font-weight:400;margin:85px 0 40px}.hero-bottom{display:flex;justify-content:space-between;align-items:end;margin:35px 0 64px;gap:25px}.hero-bottom p{font-size:18px;max-width:490px;margin:0}.hero-bottom a{font-size:12px;letter-spacing:1.5px;border-bottom:1px solid black;padding-bottom:8px}.hero-image{height:425px;background:#deddd4;overflow:hidden;position:relative;display:flex;align-items:center;justify-content:center}.hero-image img{height:100%;width:100%;object-fit:cover}.graphic{background:#cec8bc}.shape{position:absolute;border-radius:50%;background:linear-gradient(125deg,#ede9e1,#98918a);box-shadow:25px 30px 40px #59544c22}.shape.a{height:550px;width:550px;left:5%;top:-230px}.shape.b{width:280px;height:280px;right:15%;bottom:-120px;background:#989e97}.shape.c{width:160px;height:160px;right:40%;top:0;background:#ece9e3}.graphic>span{position:relative;font-size:25px;letter-spacing:7px;font-weight:500;line-height:1.5}.inner-hero{padding:80px 0;border-bottom:1px solid #d3d0ca}.inner-hero h1{font-size:clamp(48px,8vw,115px);margin:40px 0}.inner-hero p{font-size:18px;color:#777;max-width:660px}.content{padding:70px 0 130px}.list-head{display:grid;grid-template-columns:1fr 2fr;align-items:center;margin:30px 0 40px;border-bottom:1px solid black}.list-head span{font-size:10px;letter-spacing:2px}.list-head h2{font-family:Georgia,serif;font-weight:400;font-size:54px;letter-spacing:-2px}.list{display:grid;grid-template-columns:repeat(2,1fr);gap:80px 35px}.item{display:block}.item:hover h3{text-decoration:underline}.thumb{height:290px;background:#e3e1d8;display:grid;place-items:center}.thumb img{width:100%;height:100%;object-fit:contain}.thumb span{font-family:Georgia,serif;font-size:140px;color:#c0bcb2}.info{padding:25px 0}.info>span{font-size:10px;letter-spacing:1.5px}.info h3{font-family:Georgia,serif;font-size:36px;font-weight:400;margin:12px 0}.info p{color:#666;max-width:400px}.info b{font-size:11px;letter-spacing:1px}.rich-content{margin:25px 0}.section{padding:45px 0}.block-hero{padding:50px 0}.block-hero h1{font-family:Georgia,serif;font-size:60px;font-weight:400}.feature-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:30px}.feature{border-top:1px solid #8f8a84;padding-top:20px}.feature-mark{font-size:12px}.stats{display:grid;grid-template-columns:repeat(4,1fr)}.stat strong{font-family:Georgia,serif;display:block;font-size:47px;font-weight:400}.stat span{font-size:11px;letter-spacing:1px}.cta{padding:55px;background:#e4e0d8}.cta h2{font-family:Georgia,serif;font-weight:400;font-size:44px}.btn{display:inline-block;background:#222;color:white;padding:13px 20px;font-size:12px}.detail-img img{max-width:100%;max-height:550px}footer{border-top:1px solid #b9b5ae;padding:70px 0 25px}.footer-lead{font-family:Georgia,serif;font-size:clamp(45px,6vw,90px);line-height:1.05;letter-spacing:-4px}.footer-lead span{color:#909084}.footer-bottom{display:flex;justify-content:space-between;border-top:1px solid #d5d1c9;margin-top:90px;padding-top:25px;font-size:11px;color:#777}@media(max-width:850px){.header{height:auto;padding:26px 0;flex-wrap:wrap}.header nav{order:3;width:100%}.hero h1{letter-spacing:-4px;margin-top:60px}.hero-image{height:320px}.list{gap:35px}.list-head{grid-template-columns:1fr}.footer-lead{letter-spacing:-2px}}@media(max-width:560px){.list,.feature-grid,.stats{grid-template-columns:1fr}.hero h1{font-size:67px}.hero-bottom,.topline,.footer-bottom{flex-direction:column;align-items:start;gap:15px}.hero-image{height:240px}.list-head h2{font-size:40px}.inner-hero{padding:50px 0}} + +/* V8.29 baseline: accessible touch/focus and reduced motion */ +:where(a,button,input,select,textarea):focus-visible{outline:3px solid currentColor;outline-offset:3px}@media(max-width:560px){img{max-width:100%;height:auto}body{overflow-wrap:anywhere}}@media(prefers-reduced-motion:reduce){*,*:before,*:after{scroll-behavior:auto!important;transition:none!important;animation-duration:.01ms!important}} diff --git a/examples/v830-built-sites/minimal/assets/visual/hero.svg b/examples/v830-built-sites/minimal/assets/visual/hero.svg new file mode 100644 index 0000000..f43879d --- /dev/null +++ b/examples/v830-built-sites/minimal/assets/visual/hero.svg @@ -0,0 +1 @@ +STUDIES IN FORM diff --git a/examples/v830-built-sites/minimal/brand/index.html b/examples/v830-built-sites/minimal/brand/index.html new file mode 100644 index 0000000..a0ff4b1 --- /dev/null +++ b/examples/v830-built-sites/minimal/brand/index.html @@ -0,0 +1,41 @@ +品牌展示跳转至正文 + + +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/brands/arc/index.html b/examples/v830-built-sites/minimal/brands/arc/index.html new file mode 100644 index 0000000..636fa79 --- /dev/null +++ b/examples/v830-built-sites/minimal/brands/arc/index.html @@ -0,0 +1,38 @@ +ARC跳转至正文 + + +
    +
    BRAND PROFILE / PARTNERS

    ARC

    ARC 品牌产品与应用。

    +
    ARBRAND
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/brands/index.html b/examples/v830-built-sites/minimal/brands/index.html new file mode 100644 index 0000000..729e549 --- /dev/null +++ b/examples/v830-built-sites/minimal/brands/index.html @@ -0,0 +1,41 @@ +品牌中心跳转至正文 + + +
    +
    +
    CURATED INDEX / INDEX

    品牌中心

    探索与产品相关的品牌。

    BROWSE / EXPLORE03本页展示内容
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/brands/mono/index.html b/examples/v830-built-sites/minimal/brands/mono/index.html new file mode 100644 index 0000000..84440c8 --- /dev/null +++ b/examples/v830-built-sites/minimal/brands/mono/index.html @@ -0,0 +1,30 @@ +MONO跳转至正文 + + +
    +
    BRAND PROFILE / PARTNERS

    MONO

    MONO 品牌产品与应用。

    +
    MOBRAND
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/brands/nova/index.html b/examples/v830-built-sites/minimal/brands/nova/index.html new file mode 100644 index 0000000..497faa2 --- /dev/null +++ b/examples/v830-built-sites/minimal/brands/nova/index.html @@ -0,0 +1,38 @@ +NOVA跳转至正文 + + +
    +
    BRAND PROFILE / PARTNERS

    NOVA

    NOVA 品牌产品与应用。

    +
    NOBRAND
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/case/index.html b/examples/v830-built-sites/minimal/case/index.html new file mode 100644 index 0000000..b9b5446 --- /dev/null +++ b/examples/v830-built-sites/minimal/case/index.html @@ -0,0 +1,41 @@ +案例展示跳转至正文 + + +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/cases/1/index.html b/examples/v830-built-sites/minimal/cases/1/index.html new file mode 100644 index 0000000..37d0f58 --- /dev/null +++ b/examples/v830-built-sites/minimal/cases/1/index.html @@ -0,0 +1,12 @@ +精选项目 · 01跳转至正文 + + +
    +
    SELECTED WORK / PROJECT

    精选项目 · 01

    展示项目背景、过程与成果。

    项目地点
    Demo location
    所属行业
    Demo industry

    本页仅为项目结构示例,并非实际完成的工程项目。

    浏览更多案例 →
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/cases/2/index.html b/examples/v830-built-sites/minimal/cases/2/index.html new file mode 100644 index 0000000..9afd9bb --- /dev/null +++ b/examples/v830-built-sites/minimal/cases/2/index.html @@ -0,0 +1,12 @@ +精选项目 · 02跳转至正文 + + +
    +
    SELECTED WORK / PROJECT

    精选项目 · 02

    展示项目背景、过程与成果。

    项目地点
    Demo location
    所属行业
    Demo industry

    本页仅为项目结构示例,并非实际完成的工程项目。

    浏览更多案例 →
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/cases/3/index.html b/examples/v830-built-sites/minimal/cases/3/index.html new file mode 100644 index 0000000..574ae02 --- /dev/null +++ b/examples/v830-built-sites/minimal/cases/3/index.html @@ -0,0 +1,12 @@ +精选项目 · 03跳转至正文 + + +
    +
    SELECTED WORK / PROJECT

    精选项目 · 03

    展示项目背景、过程与成果。

    项目地点
    Demo location
    所属行业
    Demo industry

    本页仅为项目结构示例,并非实际完成的工程项目。

    浏览更多案例 →
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/cases/index.html b/examples/v830-built-sites/minimal/cases/index.html new file mode 100644 index 0000000..d664a5b --- /dev/null +++ b/examples/v830-built-sites/minimal/cases/index.html @@ -0,0 +1,41 @@ +项目案例跳转至正文 + + +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/categories/term-79e34764f8ce/index.html b/examples/v830-built-sites/minimal/categories/term-79e34764f8ce/index.html new file mode 100644 index 0000000..f2a2e01 --- /dev/null +++ b/examples/v830-built-sites/minimal/categories/term-79e34764f8ce/index.html @@ -0,0 +1,29 @@ +旗舰系列跳转至正文 + + +
    +
    DISCOVER / CATEGORY

    旗舰系列

    分类产品与相关信息

    首页/旗舰系列
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/categories/term-8d6647722ef3/index.html b/examples/v830-built-sites/minimal/categories/term-8d6647722ef3/index.html new file mode 100644 index 0000000..5b3e5da --- /dev/null +++ b/examples/v830-built-sites/minimal/categories/term-8d6647722ef3/index.html @@ -0,0 +1,29 @@ +专业系列跳转至正文 + + +
    +
    DISCOVER / CATEGORY

    专业系列

    分类产品与相关信息

    首页/专业系列
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/categories/term-95acf900fafc/index.html b/examples/v830-built-sites/minimal/categories/term-95acf900fafc/index.html new file mode 100644 index 0000000..e0f958c --- /dev/null +++ b/examples/v830-built-sites/minimal/categories/term-95acf900fafc/index.html @@ -0,0 +1,29 @@ +畅销系列跳转至正文 + + +
    +
    DISCOVER / CATEGORY

    畅销系列

    分类产品与相关信息

    首页/畅销系列
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/categories/term-a68a8656a4dc/index.html b/examples/v830-built-sites/minimal/categories/term-a68a8656a4dc/index.html new file mode 100644 index 0000000..97e9116 --- /dev/null +++ b/examples/v830-built-sites/minimal/categories/term-a68a8656a4dc/index.html @@ -0,0 +1,29 @@ +定制系列跳转至正文 + + +
    +
    DISCOVER / CATEGORY

    定制系列

    分类产品与相关信息

    首页/定制系列
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/commercial-readiness.json b/examples/v830-built-sites/minimal/commercial-readiness.json new file mode 100644 index 0000000..0681795 --- /dev/null +++ b/examples/v830-built-sites/minimal/commercial-readiness.json @@ -0,0 +1,34 @@ +{ + "ready_for_review": true, + "commercially_certified": false, + "blockers": [], + "warnings": [ + { + "code": "brand_logo", + "message": "尚未替换成企业正式 Logo" + }, + { + "code": "placeholder_images", + "count": 72, + "message": "部分页面仍使用示意图,正式发布前请替换为真实且有使用权的图片" + }, + { + "code": "demo_content", + "message": "检测到演示或默认文案,正式发布前请逐页核对" + }, + { + "code": "form_not_configured", + "message": "尚未配置 HTTPS 询盘接收服务;目前仅提供邮件联系" + }, + { + "code": "legal_pages", + "message": "请根据目标国家/地区法律审查是否需要隐私政策与 Cookie 声明" + } + ], + "metrics": { + "html_pages": 38, + "artwork_fallbacks": 72, + "pages_with_body": 18 + }, + "note": "仅为本地结构化交付清单,不等于合法合规、内容准确、无障碍、性能或生产上线认证" +} \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/contact/index.html b/examples/v830-built-sites/minimal/contact/index.html new file mode 100644 index 0000000..0849372 --- /dev/null +++ b/examples/v830-built-sites/minimal/contact/index.html @@ -0,0 +1,16 @@ +联系我们跳转至正文 + + +
    +
    CONNECT / CONTACT

    联系我们

    欢迎通过邮件与我们的演示团队取得联系。

    +
    LET'S START A CONVERSATION

    开启对话

    本页为演示内容。您可以在网站工厂中直接修改和替换。

    + + +
    HOW TO REACH US

    您可以通过本页提供的联系渠道咨询产品、项目或合作事项。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/faq/index.html b/examples/v830-built-sites/minimal/faq/index.html new file mode 100644 index 0000000..166cb0f --- /dev/null +++ b/examples/v830-built-sites/minimal/faq/index.html @@ -0,0 +1,13 @@ +常见问题跳转至正文 + + +
    +
    EXPLORE

    常见问题

    更多问题可以联系我们。

    +
    ABOUT / DISCOVER

    常见问题

    本页为演示内容。您可以在网站工厂中直接修改和替换。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/index.html b/examples/v830-built-sites/minimal/index.html new file mode 100644 index 0000000..7a4fe16 --- /dev/null +++ b/examples/v830-built-sites/minimal/index.html @@ -0,0 +1,64 @@ +首页跳转至正文 + + +
    +
    INDEPENDENT / CREATIVE / CONSIDEREDNO. 001 — ESTABLISH A PRESENCE

    MONO STUDIO
    MAKE IT MATTER.

    少而精,让每一项作品更清晰

    EXPLORE WORK ↗
    + +
    02 / ABOUT

    少一点噪音,多一点重点。

    少而精,让每一项作品更清晰

    READ OUR STORY ↗
    + +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/news/1/index.html b/examples/v830-built-sites/minimal/news/1/index.html new file mode 100644 index 0000000..d4c5152 --- /dev/null +++ b/examples/v830-built-sites/minimal/news/1/index.html @@ -0,0 +1,13 @@ +企业动态 · 01跳转至正文 + + +
    +
    IDEAS / JOURNAL

    企业动态 · 01

    在这里发布新闻资讯与品牌动态。

    +

    这是可替换的新闻正文内容,可包含图片、表格和链接。

    ← 返回索引
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/news/2/index.html b/examples/v830-built-sites/minimal/news/2/index.html new file mode 100644 index 0000000..aada146 --- /dev/null +++ b/examples/v830-built-sites/minimal/news/2/index.html @@ -0,0 +1,13 @@ +企业动态 · 02跳转至正文 + + +
    +
    IDEAS / JOURNAL

    企业动态 · 02

    在这里发布新闻资讯与品牌动态。

    +

    这是可替换的新闻正文内容,可包含图片、表格和链接。

    ← 返回索引
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/news/3/index.html b/examples/v830-built-sites/minimal/news/3/index.html new file mode 100644 index 0000000..fa83907 --- /dev/null +++ b/examples/v830-built-sites/minimal/news/3/index.html @@ -0,0 +1,13 @@ +企业动态 · 03跳转至正文 + + +
    +
    IDEAS / JOURNAL

    企业动态 · 03

    在这里发布新闻资讯与品牌动态。

    +

    这是可替换的新闻正文内容,可包含图片、表格和链接。

    ← 返回索引
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/news/index.html b/examples/v830-built-sites/minimal/news/index.html new file mode 100644 index 0000000..a617f17 --- /dev/null +++ b/examples/v830-built-sites/minimal/news/index.html @@ -0,0 +1,41 @@ +新闻资讯跳转至正文 + + +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/nginx-snippet.conf b/examples/v830-built-sites/minimal/nginx-snippet.conf new file mode 100644 index 0000000..5156189 --- /dev/null +++ b/examples/v830-built-sites/minimal/nginx-snippet.conf @@ -0,0 +1,4 @@ +# SiteForge 生成:将本文件内容合并到 Nginx server {} 内 +index index.html; +error_page 404 /404.html; +location / { try_files $uri $uri/ =404; } diff --git a/examples/v830-built-sites/minimal/post/index.html b/examples/v830-built-sites/minimal/post/index.html new file mode 100644 index 0000000..0631568 --- /dev/null +++ b/examples/v830-built-sites/minimal/post/index.html @@ -0,0 +1,41 @@ +新闻展示跳转至正文 + + +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/product/index.html b/examples/v830-built-sites/minimal/product/index.html new file mode 100644 index 0000000..0852c7c --- /dev/null +++ b/examples/v830-built-sites/minimal/product/index.html @@ -0,0 +1,81 @@ +产品展示跳转至正文 + + +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/products/1/index.html b/examples/v830-built-sites/minimal/products/1/index.html new file mode 100644 index 0000000..d217a81 --- /dev/null +++ b/examples/v830-built-sites/minimal/products/1/index.html @@ -0,0 +1,17 @@ +Objects Alpha跳转至正文 + + +
    +
    +
    CURATED INDEX / DETAILS

    Objects Alpha

    Objects Alpha — 针对多样应用的演示产品。

    NOVA旗舰系列
    咨询相关信息 ↗
    +
    +
    ObPRODUCT
    +
    +
    OVERVIEW / 详细介绍

    详细介绍

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/products/2/index.html b/examples/v830-built-sites/minimal/products/2/index.html new file mode 100644 index 0000000..c1d9693 --- /dev/null +++ b/examples/v830-built-sites/minimal/products/2/index.html @@ -0,0 +1,17 @@ +Objects Beta跳转至正文 + + +
    +
    +
    CURATED INDEX / DETAILS

    Objects Beta

    Objects Beta — 针对多样应用的演示产品。

    NOVA旗舰系列
    咨询相关信息 ↗
    +
    +
    ObPRODUCT
    +
    +
    OVERVIEW / 详细介绍

    详细介绍

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/products/3/index.html b/examples/v830-built-sites/minimal/products/3/index.html new file mode 100644 index 0000000..037afcd --- /dev/null +++ b/examples/v830-built-sites/minimal/products/3/index.html @@ -0,0 +1,17 @@ +Objects Gamma跳转至正文 + + +
    +
    +
    CURATED INDEX / DETAILS

    Objects Gamma

    Objects Gamma — 针对多样应用的演示产品。

    ARC畅销系列
    咨询相关信息 ↗
    +
    +
    ObPRODUCT
    +
    +
    OVERVIEW / 详细介绍

    详细介绍

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/products/4/index.html b/examples/v830-built-sites/minimal/products/4/index.html new file mode 100644 index 0000000..4dbdc8c --- /dev/null +++ b/examples/v830-built-sites/minimal/products/4/index.html @@ -0,0 +1,17 @@ +Objects Delta跳转至正文 + + +
    +
    +
    CURATED INDEX / DETAILS

    Objects Delta

    Objects Delta — 针对多样应用的演示产品。

    ARC畅销系列
    咨询相关信息 ↗
    +
    +
    ObPRODUCT
    +
    +
    OVERVIEW / 详细介绍

    详细介绍

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/products/5/index.html b/examples/v830-built-sites/minimal/products/5/index.html new file mode 100644 index 0000000..6c7a3c0 --- /dev/null +++ b/examples/v830-built-sites/minimal/products/5/index.html @@ -0,0 +1,17 @@ +Objects Epsilon跳转至正文 + + +
    +
    +
    CURATED INDEX / DETAILS

    Objects Epsilon

    Objects Epsilon — 针对多样应用的演示产品。

    MONO定制系列
    咨询相关信息 ↗
    +
    +
    ObPRODUCT
    +
    +
    OVERVIEW / 详细介绍

    详细介绍

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/products/6/index.html b/examples/v830-built-sites/minimal/products/6/index.html new file mode 100644 index 0000000..71b5c40 --- /dev/null +++ b/examples/v830-built-sites/minimal/products/6/index.html @@ -0,0 +1,17 @@ +Objects Zeta跳转至正文 + + +
    +
    +
    CURATED INDEX / DETAILS

    Objects Zeta

    Objects Zeta — 针对多样应用的演示产品。

    MONO定制系列
    咨询相关信息 ↗
    +
    +
    ObPRODUCT
    +
    +
    OVERVIEW / 详细介绍

    详细介绍

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/products/7/index.html b/examples/v830-built-sites/minimal/products/7/index.html new file mode 100644 index 0000000..37640a3 --- /dev/null +++ b/examples/v830-built-sites/minimal/products/7/index.html @@ -0,0 +1,17 @@ +Objects Eta跳转至正文 + + +
    +
    +
    CURATED INDEX / DETAILS

    Objects Eta

    Objects Eta — 针对多样应用的演示产品。

    NOVA专业系列
    咨询相关信息 ↗
    +
    +
    ObPRODUCT
    +
    +
    OVERVIEW / 详细介绍

    详细介绍

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/products/8/index.html b/examples/v830-built-sites/minimal/products/8/index.html new file mode 100644 index 0000000..338f6d2 --- /dev/null +++ b/examples/v830-built-sites/minimal/products/8/index.html @@ -0,0 +1,17 @@ +Objects Theta跳转至正文 + + +
    +
    +
    CURATED INDEX / DETAILS

    Objects Theta

    Objects Theta — 针对多样应用的演示产品。

    ARC专业系列
    咨询相关信息 ↗
    +
    +
    ObPRODUCT
    +
    +
    OVERVIEW / 详细介绍

    详细介绍

    产品说明

    此处可以展示产品特点、应用场景和可用规格。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/products/index.html b/examples/v830-built-sites/minimal/products/index.html new file mode 100644 index 0000000..ba11bf2 --- /dev/null +++ b/examples/v830-built-sites/minimal/products/index.html @@ -0,0 +1,81 @@ +产品中心跳转至正文 + + +
    + + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/robots.txt b/examples/v830-built-sites/minimal/robots.txt new file mode 100644 index 0000000..dd4c108 --- /dev/null +++ b/examples/v830-built-sites/minimal/robots.txt @@ -0,0 +1,3 @@ +User-agent: * +Allow: / +Sitemap: https://minimal.example.test/sitemap.xml diff --git a/examples/v830-built-sites/minimal/search-index.json b/examples/v830-built-sites/minimal/search-index.json new file mode 100644 index 0000000..d2134a8 --- /dev/null +++ b/examples/v830-built-sites/minimal/search-index.json @@ -0,0 +1 @@ +[{"title": "ARC", "url": "/brands/arc/", "summary": "ARC 品牌产品与应用。", "type": "brand", "brand": ""}, {"title": "MONO", "url": "/brands/mono/", "summary": "MONO 品牌产品与应用。", "type": "brand", "brand": ""}, {"title": "NOVA", "url": "/brands/nova/", "summary": "NOVA 品牌产品与应用。", "type": "brand", "brand": ""}, {"title": "精选项目 · 01", "url": "/cases/1/", "summary": "展示项目背景、过程与成果。", "type": "case", "brand": ""}, {"title": "精选项目 · 02", "url": "/cases/2/", "summary": "展示项目背景、过程与成果。", "type": "case", "brand": ""}, {"title": "精选项目 · 03", "url": "/cases/3/", "summary": "展示项目背景、过程与成果。", "type": "case", "brand": ""}, {"title": "产品中心", "url": "/products/", "summary": "查看系列、类别及产品资料。", "type": "page", "brand": ""}, {"title": "关于我们", "url": "/about/", "summary": "企业介绍、发展理念、合作能力与团队故事。", "type": "page", "brand": ""}, {"title": "品牌中心", "url": "/brands/", "summary": "探索与产品相关的品牌。", "type": "page", "brand": ""}, {"title": "常见问题", "url": "/faq/", "summary": "更多问题可以联系我们。", "type": "page", "brand": ""}, {"title": "新闻资讯", "url": "/news/", "summary": "了解最新消息与团队动态。", "type": "page", "brand": ""}, {"title": "服务与解决方案", "url": "/services/", "summary": "从咨询到交付的全链路服务。", "type": "page", "brand": ""}, {"title": "联系我们", "url": "/contact/", "summary": "欢迎通过邮件与我们的演示团队取得联系。", "type": "page", "brand": ""}, {"title": "项目案例", "url": "/cases/", "summary": "精选项目展示。", "type": "page", "brand": ""}, {"title": "企业动态 · 01", "url": "/news/1/", "summary": "在这里发布新闻资讯与品牌动态。", "type": "post", "brand": ""}, {"title": "企业动态 · 02", "url": "/news/2/", "summary": "在这里发布新闻资讯与品牌动态。", "type": "post", "brand": ""}, {"title": "企业动态 · 03", "url": "/news/3/", "summary": "在这里发布新闻资讯与品牌动态。", "type": "post", "brand": ""}, {"title": "Objects Alpha", "url": "/products/1/", "summary": "Objects Alpha — 针对多样应用的演示产品。", "type": "product", "brand": "NOVA"}, {"title": "Objects Beta", "url": "/products/2/", "summary": "Objects Beta — 针对多样应用的演示产品。", "type": "product", "brand": "NOVA"}, {"title": "Objects Delta", "url": "/products/4/", "summary": "Objects Delta — 针对多样应用的演示产品。", "type": "product", "brand": "ARC"}, {"title": "Objects Epsilon", "url": "/products/5/", "summary": "Objects Epsilon — 针对多样应用的演示产品。", "type": "product", "brand": "MONO"}, {"title": "Objects Eta", "url": "/products/7/", "summary": "Objects Eta — 针对多样应用的演示产品。", "type": "product", "brand": "NOVA"}, {"title": "Objects Gamma", "url": "/products/3/", "summary": "Objects Gamma — 针对多样应用的演示产品。", "type": "product", "brand": "ARC"}, {"title": "Objects Theta", "url": "/products/8/", "summary": "Objects Theta — 针对多样应用的演示产品。", "type": "product", "brand": "ARC"}, {"title": "Objects Zeta", "url": "/products/6/", "summary": "Objects Zeta — 针对多样应用的演示产品。", "type": "product", "brand": "MONO"}, {"title": "供应与交付方案", "url": "/services/solution/", "summary": "灵活、可配置的供应交付服务。", "type": "service", "brand": ""}] \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/search/index.html b/examples/v830-built-sites/minimal/search/index.html new file mode 100644 index 0000000..7739622 --- /dev/null +++ b/examples/v830-built-sites/minimal/search/index.html @@ -0,0 +1,13 @@ +站内搜索跳转至正文 + + +
    +
    SEARCH / CONTENT

    站内搜索

    搜索本网站的产品、品牌、新闻和案例。

    +
    + +
    + +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/service/index.html b/examples/v830-built-sites/minimal/service/index.html new file mode 100644 index 0000000..12d503a --- /dev/null +++ b/examples/v830-built-sites/minimal/service/index.html @@ -0,0 +1,25 @@ +服务展示跳转至正文 + + +
    +
    +
    CURATED INDEX / INDEX

    服务展示

    Explore our service

    BROWSE / EXPLORE01本页展示内容
    +
    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/services/index.html b/examples/v830-built-sites/minimal/services/index.html new file mode 100644 index 0000000..c87d729 --- /dev/null +++ b/examples/v830-built-sites/minimal/services/index.html @@ -0,0 +1,13 @@ +服务与解决方案跳转至正文 + + +
    +
    EXPLORE

    服务与解决方案

    从咨询到交付的全链路服务。

    +
    ABOUT / DISCOVER

    服务与解决方案

    本页为演示内容。您可以在网站工厂中直接修改和替换。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/services/solution/index.html b/examples/v830-built-sites/minimal/services/solution/index.html new file mode 100644 index 0000000..b049134 --- /dev/null +++ b/examples/v830-built-sites/minimal/services/solution/index.html @@ -0,0 +1,13 @@ +供应与交付方案跳转至正文 + + +
    +
    EXPLORE

    供应与交付方案

    灵活、可配置的供应交付服务。

    +
    ABOUT / DISCOVER

    供应与交付方案

    灵活、可配置的供应交付服务。

    + +
    +
    LET'S CONNECT

    从这里开始下一步。

    少而精,让每一项作品更清晰

    联系我们 ↗
    +
    + + + \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/siteforge-report.json b/examples/v830-built-sites/minimal/siteforge-report.json new file mode 100644 index 0000000..fbd50a7 --- /dev/null +++ b/examples/v830-built-sites/minimal/siteforge-report.json @@ -0,0 +1,27 @@ +{ + "site": "MONO STUDIO", + "locale": "zh-CN", + "alternate_pages": 0, + "version": "c9a4dc6156ca", + "pages": 36, + "theme": "minimal", + "theme_version": "1.3.0", + "warnings": [], + "errors": [], + "external_assets": [], + "missing_local_images": [], + "broken_links": [], + "legacy_links": [], + "canonical_mismatches": [], + "slashless_routes": [], + "redirects": 0, + "mirrored_images": 0, + "quality_status": "passed", + "blueprint_blocks": 0, + "commercial_readiness": { + "ready_for_review": true, + "commercially_certified": false, + "blockers": 0, + "warnings": 5 + } +} \ No newline at end of file diff --git a/examples/v830-built-sites/minimal/sitemap.xml b/examples/v830-built-sites/minimal/sitemap.xml new file mode 100644 index 0000000..748636f --- /dev/null +++ b/examples/v830-built-sites/minimal/sitemap.xml @@ -0,0 +1,37 @@ + +https://minimal.example.test/ +https://minimal.example.test/about/ +https://minimal.example.test/brand/ +https://minimal.example.test/brands/ +https://minimal.example.test/brands/arc/ +https://minimal.example.test/brands/mono/ +https://minimal.example.test/brands/nova/ +https://minimal.example.test/case/ +https://minimal.example.test/cases/ +https://minimal.example.test/cases/1/ +https://minimal.example.test/cases/2/ +https://minimal.example.test/cases/3/ +https://minimal.example.test/categories/term-79e34764f8ce/ +https://minimal.example.test/categories/term-8d6647722ef3/ +https://minimal.example.test/categories/term-95acf900fafc/ +https://minimal.example.test/categories/term-a68a8656a4dc/ +https://minimal.example.test/contact/ +https://minimal.example.test/faq/ +https://minimal.example.test/news/ +https://minimal.example.test/news/1/ +https://minimal.example.test/news/2/ +https://minimal.example.test/news/3/ +https://minimal.example.test/post/ +https://minimal.example.test/product/ +https://minimal.example.test/products/ +https://minimal.example.test/products/1/ +https://minimal.example.test/products/2/ +https://minimal.example.test/products/3/ +https://minimal.example.test/products/4/ +https://minimal.example.test/products/5/ +https://minimal.example.test/products/6/ +https://minimal.example.test/products/7/ +https://minimal.example.test/products/8/ +https://minimal.example.test/service/ +https://minimal.example.test/services/ +https://minimal.example.test/services/solution/ \ No newline at end of file diff --git a/reports/V8_22_验收报告.html b/reports/V8_22_验收报告.html new file mode 100644 index 0000000..1d59e32 --- /dev/null +++ b/reports/V8_22_验收报告.html @@ -0,0 +1 @@ +SiteForge V8.22 高级可视化编辑器验收
    SiteForge Enterprise · 2026-10-23

    V8.22 高级可视化编辑器 — 集成验收

    分组 Python 测试
    348
    42 个模块
    Node 专项测试
    9
    安全边界与操作
    HTTP + Worker
    PASS
    隔离 SQLite 环境

    一键回归仍有偶发进程停滞;Chromium 被运行环境阻止访问本机 HTTP。不能据此声称真实浏览器全流程或生产环境已经验收通过。

    本次实现

    画布选中区块、拖拽调整顺序、快捷工具栏、直接编辑顶层文案、布局列宽控制、下方插入组件,继续沿用既有草稿/版本/审批流程。

    回归记录

    批次测试数结果原始日志
    前段批次 143PASSreports/v822-regression_logs/round1-batch1.log
    前段批次 222PASSreports/v822-regression_logs/round1-batch2.log
    前段批次 350PASSreports/v822-regression_logs/round1-batch3.log
    前段批次 428PASSreports/v822-regression_logs/round1-batch4.log
    前段批次 529PASSreports/v822-regression_logs/round1-batch5.log
    前段批次 625PASSreports/v822-regression_logs/round1-batch6.log
    独立后段 136PASSreports/v822-tail-logs/tail-01.log
    独立后段 215PASSreports/v822-tail-logs/tail-02.log
    独立后段 311PASSreports/v822-tail-logs/tail-03.log
    独立后段 48PASSreports/v822-tail-logs/tail-04.log
    独立后段 514PASSreports/v822-tail-logs/tail-05.log
    独立后段 612PASSreports/v822-tail-logs/tail-06.log
    独立后段 713PASSreports/v822-tail-logs/tail-07.log
    独立后段 822PASSreports/v822-tail-logs/tail-08.log
    WordPress 末组 A10PASSreports/v822-tail-logs/tail-09a.log
    WordPress 末组 B10PASSreports/v822-tail-logs/tail-09b.log

    未完成门禁

    真实 PostgreSQL/Redis、Docker 多 Worker、上线/回滚、官方 Art Design Pro 工程编译、复杂 WordPress 实站、浏览器经 HTTP 登录到编辑器的全链路验收均未关闭。

    完整说明见报告 Markdown 与 JSON。交互预览不接入生产数据。

    \ No newline at end of file diff --git a/reports/V8_22_验收报告.json b/reports/V8_22_验收报告.json new file mode 100644 index 0000000..8b53d28 --- /dev/null +++ b/reports/V8_22_验收报告.json @@ -0,0 +1,117 @@ +{ + "version": "8.22.0-dev.1", + "date": "2026-10-23", + "baseline": "8.21.3-dev.1", + "python_regression": { + "modules": 42, + "passed": 348, + "failed_in_completed_groups": 0, + "one_click_runner_status": "NOT_PASSED: repeated intermittent test subprocess hang", + "execution": "first 24 modules in 6 grouped batches; last 18 modules in 8 pairs + 2 standalone tests", + "groups": [ + { + "id": "前段批次 1", + "passed": 43, + "status": "PASS", + "log": "reports/v822-regression_logs/round1-batch1.log" + }, + { + "id": "前段批次 2", + "passed": 22, + "status": "PASS", + "log": "reports/v822-regression_logs/round1-batch2.log" + }, + { + "id": "前段批次 3", + "passed": 50, + "status": "PASS", + "log": "reports/v822-regression_logs/round1-batch3.log" + }, + { + "id": "前段批次 4", + "passed": 28, + "status": "PASS", + "log": "reports/v822-regression_logs/round1-batch4.log" + }, + { + "id": "前段批次 5", + "passed": 29, + "status": "PASS", + "log": "reports/v822-regression_logs/round1-batch5.log" + }, + { + "id": "前段批次 6", + "passed": 25, + "status": "PASS", + "log": "reports/v822-regression_logs/round1-batch6.log" + }, + { + "id": "独立后段 1", + "passed": 36, + "status": "PASS", + "log": "reports/v822-tail-logs/tail-01.log" + }, + { + "id": "独立后段 2", + "passed": 15, + "status": "PASS", + "log": "reports/v822-tail-logs/tail-02.log" + }, + { + "id": "独立后段 3", + "passed": 11, + "status": "PASS", + "log": "reports/v822-tail-logs/tail-03.log" + }, + { + "id": "独立后段 4", + "passed": 8, + "status": "PASS", + "log": "reports/v822-tail-logs/tail-04.log" + }, + { + "id": "独立后段 5", + "passed": 14, + "status": "PASS", + "log": "reports/v822-tail-logs/tail-05.log" + }, + { + "id": "独立后段 6", + "passed": 12, + "status": "PASS", + "log": "reports/v822-tail-logs/tail-06.log" + }, + { + "id": "独立后段 7", + "passed": 13, + "status": "PASS", + "log": "reports/v822-tail-logs/tail-07.log" + }, + { + "id": "独立后段 8", + "passed": 22, + "status": "PASS", + "log": "reports/v822-tail-logs/tail-08.log" + }, + { + "id": "WordPress 末组 A", + "passed": 10, + "status": "PASS", + "log": "reports/v822-tail-logs/tail-09a.log" + }, + { + "id": "WordPress 末组 B", + "passed": 10, + "status": "PASS", + "log": "reports/v822-tail-logs/tail-09b.log" + } + ] + }, + "javascript_node_tests": 9, + "http_worker_e2e": "PASS: SQLite sandbox, Web -> login/CSRF -> site/page -> enqueue -> worker -> ZIP -> preview", + "browser_canvas": "PASS: isolated sandbox srcdoc Chromium, select/duplicate/add-after/keyboard-resize", + "browser_demo": "PASS: Chromium page.set_content, duplicate/undo/add/device/save", + "browser_live_http": "BLOCKED_BY_ADMINISTRATOR (environment restriction)", + "enterprise_postgres_redis_docker_remote_publish": "NOT_TESTED", + "art_design_pro_official_full_build": "NOT_TESTED" +} \ No newline at end of file diff --git a/reports/V8_22_验收报告.md b/reports/V8_22_验收报告.md new file mode 100644 index 0000000..468a432 --- /dev/null +++ b/reports/V8_22_验收报告.md @@ -0,0 +1,62 @@ +# SiteForge Enterprise V8.22.0-dev.1 — 高级可视化编辑器验收报告 + +**验收日期:2026-10-23** +**源代码基线:V8.21.3** +**状态:开发集成版(不能宣布生产可上线)** + +## 本轮交付 + +- 将静态构建相同的声明式区块渲染为可操作画布;点击区块显示高亮及操作条。 +- 从画布直接移动、拖拽排序、复制、删除区块及在当前区块下方插入组件。 +- 对顶层区块的标题和支持的描述执行双击编辑(保留 HTML 安全渲染)。 +- 对声明式多列布局提供桌面端拖动列宽、键盘调整列宽,约束每列权重在 0.5~4,服务端仍用原有蓝图校验。 +- 直接操作继续走原草稿版本、撤销历史、冲突检查和发布审批,不修改数据库 Schema 或已发布静态构建。 +- 保留四套主题移动端抽屉导航、可选底部 Tabs 及此前所有功能。 + +## 验证 + +**42 个 Python 模块的 348 项自动化用例均在独立组合中通过。** 旧一键回归进程在第 7 批偶发卡住;因此不得声明“一键回归通过”。 + +| 分组 | 用例 | 结果 | 日志 | +|---|---:|---|---| +| 前段批次 1 | 43 | PASS | `reports/v822-regression_logs/round1-batch1.log` | +| 前段批次 2 | 22 | PASS | `reports/v822-regression_logs/round1-batch2.log` | +| 前段批次 3 | 50 | PASS | `reports/v822-regression_logs/round1-batch3.log` | +| 前段批次 4 | 28 | PASS | `reports/v822-regression_logs/round1-batch4.log` | +| 前段批次 5 | 29 | PASS | `reports/v822-regression_logs/round1-batch5.log` | +| 前段批次 6 | 25 | PASS | `reports/v822-regression_logs/round1-batch6.log` | +| 独立后段 1 | 36 | PASS | `reports/v822-tail-logs/tail-01.log` | +| 独立后段 2 | 15 | PASS | `reports/v822-tail-logs/tail-02.log` | +| 独立后段 3 | 11 | PASS | `reports/v822-tail-logs/tail-03.log` | +| 独立后段 4 | 8 | PASS | `reports/v822-tail-logs/tail-04.log` | +| 独立后段 5 | 14 | PASS | `reports/v822-tail-logs/tail-05.log` | +| 独立后段 6 | 12 | PASS | `reports/v822-tail-logs/tail-06.log` | +| 独立后段 7 | 13 | PASS | `reports/v822-tail-logs/tail-07.log` | +| 独立后段 8 | 22 | PASS | `reports/v822-tail-logs/tail-08.log` | +| WordPress 末组 A | 10 | PASS | `reports/v822-tail-logs/tail-09a.log` | +| WordPress 末组 B | 10 | PASS | `reports/v822-tail-logs/tail-09b.log` | + +- Node 测试:9 项通过;新增未知区块 ID、越界宽度、非法文字字段等边界校验。 +- Python 全模块编译、Node JS 语法检查:通过。 +- HTTP + Worker E2E:通过(隔离 SQLite,仅验证登录、建站、Worker 静态构建、ZIP、预览)。 +- Chromium 真实渲染的 sandbox srcdoc 画布:选中、复制、下方插入、键盘调列宽通过。 +- Chromium 离线交互演示:复制、撤销、添加、设备切换、模拟保存通过。 +- **真正通过 HTTP 登录进入编辑器的 Chromium 测试未完成**:浏览器对 localhost 报 `ERR_BLOCKED_BY_ADMINISTRATOR`,测试脚本 `scripts/studio_canvas_smoke_v822.py` 已提供用于正常环境执行。 +- 未执行真实 PostgreSQL/Redis/Docker 多 Worker、远程部署、Art Design Pro 官方工程编译及真实客户站数据迁移。 + +## 完成边界与后续 + +本轮交付是**区块画布级可视化操作**,不是任意坐标、任意绝对定位或完整 Figma 式设计器。嵌套布局中的子组件仍主要依靠右侧表单编辑;自由画布组合、复用组件级联升级、多用户实时协作、全端真实设备测试仍需后续推进。 + +## 快速检查 + +```bash +python -m pytest -q tests/test_v822_canvas.py tests/test_studio_v86.py +node --test tests_js/*.test.cjs +python scripts/http_end_to_end.py +python scripts/studio_canvas_isolated_browser_v822.py +# 正常具备本地 HTTP 浏览器访问权限的环境: +SITEFORGE_CHROMIUM=/usr/bin/chromium python scripts/studio_canvas_smoke_v822.py +``` + +交互预览:`examples/Studio_V8_22_画布级可视化编辑器_交互演示.html`(模拟数据,不写入真实站点)。 diff --git a/reports/V8_23_集成验收.html b/reports/V8_23_集成验收.html new file mode 100644 index 0000000..bd7837a --- /dev/null +++ b/reports/V8_23_集成验收.html @@ -0,0 +1 @@ +SiteForge V8.23 验收报告
    SiteForge Enterprise / Engineering acceptance

    V8.23 高级可视化编辑器 · 集成验收

    基于 V8.22 完整源码,验证多列子组件画布编辑、快捷布局与旧系统兼容。开发集成版,不代表生产上线已验收。

    352Python 用例通过
    43测试模块
    15/15回归批次通过
    0失败 / 超时批次

    本轮开发

    • 直接点击列内子组件、双击纯文本修改、复制/删除/同列排序。
    • 右侧嵌套内容属性表单与设备列宽快捷预设。
    • 严格验证父布局与子组件 ID,继续使用 iframe 沙箱及原有版本草稿与权限机制。
    • 原有四套主题、手机抽屉菜单、底部 Tabs、静态构建不改变。

    隔离批次原项目回归

    批次包含模块用例结果耗时
    01test_commercial_v5.py、test_connectors_v84.py、test_connectors_v85.py35通过7.6s
    02test_console_v819.py、test_core_v4.py、test_editor_easy_v8212.py22通过8.1s
    03test_editor_ux_v8211.py、test_enterprise.py、test_enterprise_v7.py19通过5.9s
    04test_factory.py、test_factory_v2.py、test_mobile_tabs_v8213.py39通过13.3s
    05test_multilingual_v815.py、test_nested_v823.py、test_p0_71.py13通过7.6s
    06test_p0_backup.py、test_p0_p4_completion_v88.py、test_p0_p4_completion_v89.py26通过10.7s
    07test_p1_platform.py、test_production_v816.py、test_professional_ui_v811.py22通过6.1s
    08test_regression_runner_v817.py、test_release_native_v814.py、test_release_reviews_v7.py16通过6.9s
    09test_release_v813.py、test_site_design_v87.py、test_siteforge_v817_audit.py45通过12.6s
    10test_studio_v86.py、test_theme_pro_v3.py、test_v818_pg_recovery.py22通过13.1s
    11test_v818_sqlite_pg_transfer.py、test_v821_editor_history_and_mapping.py、test_v822_canvas.py12通过5.5s
    12test_v8_art_installer.py、test_v8_workflows.py、test_wordpress_baseline.py20通过4.8s
    13test_worker_queue_v6.py、test_workspace_v810.py、test_workspace_v812.py19通过11.7s
    14test_wp_complex_v820.py、test_wp_migration_v81.py、test_wp_migration_v82.py32通过9.1s
    15test_wp_migration_v83.py10通过5.1s

    其他实际检查

    • 通过 JavaScript 历史 9 项测试与 V8.23 嵌套操作纯函数专项检查。
    • 通过 Chromium 沙箱内画布点击、复制、内联编辑;离线操作演示浏览器测试无脚本错误。
    • 通过 HTTP + Worker 登录、CSRF、创建页面、构建、静态 ZIP 下载和预览。
    • 通过 Python 编译、JavaScript 语法以及版本/主题/CI 静态校验。
    • 未验收 Chromium 在真实 localhost 后台登录后操作(访问被管理员策略阻止)。
    • 未验收 Art Design Pro 官方工程的完整编译、真实 PostgreSQL/Redis、多 Worker 和生产发布。
    已通过项不能外推为官方前端编译完成或生产部署完成;离线 HTML 演示仅用于查看交互,不能写入正式网站数据。

    快速复现

    bash scripts/check.sh python scripts/http_end_to_end.py python scripts/studio_nested_browser_v823.py

    详细说明:docs/V8_23_ADVANCED_STUDIO.md

    \ No newline at end of file diff --git a/reports/V8_25_summary.json b/reports/V8_25_summary.json new file mode 100644 index 0000000..713faed --- /dev/null +++ b/reports/V8_25_summary.json @@ -0,0 +1,15 @@ +{ + "version": "8.25.0-dev.1", + "generated_utc": "2026-10-23T06:17:16.783401+00:00", + "python_cases_passed": 370, + "batches_passed": 23, + "batches_total": 23, + "failed_batches": 0, + "node_js_cases_passed": 13, + "http_worker_e2e": "passed", + "chromium_offline_demo": "passed (desktop/mobile, isolated HTML)", + "official_art_build": "not_tested", + "postgres_redis_docker_production": "not_tested", + "authenticated_real_browser": "not_tested", + "all_python_batches_passed": true +} \ No newline at end of file diff --git a/reports/V8_25_验收报告.html b/reports/V8_25_验收报告.html new file mode 100644 index 0000000..1eb59e4 --- /dev/null +++ b/reports/V8_25_验收报告.html @@ -0,0 +1,24 @@ +SiteForge V8.25 集成验收报告
    ◈ SiteForge EnterpriseV8.25.0-dev.1 · 开发集成版
    INTEGRATION ACCEPTANCE

    V8.25 · 公共组件与全站设计系统

    根据真实隔离测试批次的原始输出自动汇总;组件更新仅生成新草稿,不触及已发布页面。

    370
    Python 用例通过
    23/23
    隔离测试批次通过
    13
    JavaScript 用例通过
    0
    失败或超时批次

    本阶段集成结果

    ✓ 公共组件不可变版本历史、源组件更新乐观锁、引用页面扫描与过期预检保护

    ✓ 本地修改、跨网站访问、并发草稿变更与非法引用拦截

    ✓ 批量同步事务:第二个页面失败则整批草稿回滚,不直接修改发布页面

    ✓ HTTP + Worker 建站、构建、下载 ZIP 和预览;隔离 Chromium PC/手机交互演示

    尚未验证:真实 PostgreSQL/Redis 多 Worker、正式 Docker 部署、线上 Agent/SFTP/S3 发布、官方 Art Design Pro 编译及登录后台后的浏览器 E2E。这些不属于本报告的通过项。

    分批回归明细

    + + + + + + + + + + + + + + + + + + + + + +
    批次模块通过用例耗时(秒)状态
    01test_commercial_v5.py, test_connectors_v84.py206.77passed
    02test_connectors_v85.py, test_console_v819.py236.95passed
    03test_core_v4.py, test_deep_nested_v824.py199.55passed
    04test_editor_easy_v8212.py, test_editor_ux_v8211.py63.19passed
    05test_enterprise.py, test_enterprise_v7.py169.12passed
    06test_factory.py, test_factory_v2.py2422.35passed
    07test_mobile_tabs_v8213.py, test_multilingual_v815.py2010.41passed
    08test_nested_v823.py, test_p0_71.py85.36passed
    09test_p0_backup.py, test_p0_p4_completion_v88.py1911.91passed
    10test_p0_p4_completion_v89.py, test_p1_platform.py1411.28passed
    11test_production_v816.py, test_professional_ui_v811.py1547.32passed
    12test_regression_runner_v817.py, test_release_native_v814.py114.36passed
    13test_release_reviews_v7.py, test_release_v813.py145.3passed
    14test_site_design_v87.py, test_siteforge_v817_audit.py368.26passed
    15test_studio_v86.py, test_theme_pro_v3.py1513.84passed
    16test_v818_pg_recovery.py, test_v818_sqlite_pg_transfer.py113.59passed
    17test_v821_editor_history_and_mapping.py, test_v822_canvas.py85.73passed
    18test_v825_shared_components.py, test_v8_art_installer.py115.8passed
    19test_v8_workflows.py, test_wordpress_baseline.py194.69passed
    20test_worker_queue_v6.py, test_workspace_v810.py1010.48passed
    21test_workspace_v812.py, test_wp_complex_v820.py216.13passed
    22test_wp_migration_v81.py, test_wp_migration_v82.py209.18passed
    23test_wp_migration_v83.py105.12passed

    原始证据:reports/v825-regression/batch-*.log、reports/v825-regression/result.json。本报告不代表已经在正式客户网站上线。

    \ No newline at end of file diff --git a/reports/V8_25_验收报告.md b/reports/V8_25_验收报告.md new file mode 100644 index 0000000..a836205 --- /dev/null +++ b/reports/V8_25_验收报告.md @@ -0,0 +1,47 @@ +# V8.25 开发集成验收报告 + +- 完整 Python 回归:370 个用例,23 个隔离批次,失败批次 0。 +- Node.js JavaScript 单元测试:13 项通过。 +- 真实 HTTP + Worker 端到端:登录/CSRF、创建站点、创建页面、入队、Worker 构建、ZIP 与预览通过。 +- Chromium 隔离 HTML 演示:PC / 390px 手机布局、引用勾选与选择性同步交互通过,脚本错误 0。 +- Python 编译、JS 语法、版本/主题/Worker 静态校验通过。 + +## 功能验收 + +公共组件不可变版本、历史快照校验、选择性同步、旧版迁移、跨站点权限、本地修改保护、草稿原子更新/异常整体回滚及已发布页面保持不变均有专项测试。 + +## 仍未完成的真实环境验收 + +- 真实 PostgreSQL/Redis、多 Worker、Docker、恢复演练与线上发布。 +- Art Design Pro 官方前端工程编译。 +- 真实登录后台的 Chromium E2E、手机真机测试。 + +## 各批详情 + +| 批次 | 测试模块 | 用例通过 | 耗时(s) | 结果 | +|---|---|---:|---:|---| +| 01 | test_commercial_v5.py, test_connectors_v84.py | 20 | 6.77 | passed | +| 02 | test_connectors_v85.py, test_console_v819.py | 23 | 6.95 | passed | +| 03 | test_core_v4.py, test_deep_nested_v824.py | 19 | 9.55 | passed | +| 04 | test_editor_easy_v8212.py, test_editor_ux_v8211.py | 6 | 3.19 | passed | +| 05 | test_enterprise.py, test_enterprise_v7.py | 16 | 9.12 | passed | +| 06 | test_factory.py, test_factory_v2.py | 24 | 22.35 | passed | +| 07 | test_mobile_tabs_v8213.py, test_multilingual_v815.py | 20 | 10.41 | passed | +| 08 | test_nested_v823.py, test_p0_71.py | 8 | 5.36 | passed | +| 09 | test_p0_backup.py, test_p0_p4_completion_v88.py | 19 | 11.91 | passed | +| 10 | test_p0_p4_completion_v89.py, test_p1_platform.py | 14 | 11.28 | passed | +| 11 | test_production_v816.py, test_professional_ui_v811.py | 15 | 47.32 | passed | +| 12 | test_regression_runner_v817.py, test_release_native_v814.py | 11 | 4.36 | passed | +| 13 | test_release_reviews_v7.py, test_release_v813.py | 14 | 5.3 | passed | +| 14 | test_site_design_v87.py, test_siteforge_v817_audit.py | 36 | 8.26 | passed | +| 15 | test_studio_v86.py, test_theme_pro_v3.py | 15 | 13.84 | passed | +| 16 | test_v818_pg_recovery.py, test_v818_sqlite_pg_transfer.py | 11 | 3.59 | passed | +| 17 | test_v821_editor_history_and_mapping.py, test_v822_canvas.py | 8 | 5.73 | passed | +| 18 | test_v825_shared_components.py, test_v8_art_installer.py | 11 | 5.8 | passed | +| 19 | test_v8_workflows.py, test_wordpress_baseline.py | 19 | 4.69 | passed | +| 20 | test_worker_queue_v6.py, test_workspace_v810.py | 10 | 10.48 | passed | +| 21 | test_workspace_v812.py, test_wp_complex_v820.py | 21 | 6.13 | passed | +| 22 | test_wp_migration_v81.py, test_wp_migration_v82.py | 20 | 9.18 | passed | +| 23 | test_wp_migration_v83.py | 10 | 5.12 | passed | + +报告来源:`reports/v825-regression/batch-*.log` 和 `result.json`。**模拟与离线测试不能视为生产服务器验收。** diff --git a/reports/V8_30_mobile_browser_audit.json b/reports/V8_30_mobile_browser_audit.json new file mode 100644 index 0000000..cf20fb3 --- /dev/null +++ b/reports/V8_30_mobile_browser_audit.json @@ -0,0 +1,6 @@ +{ + "checks": 72, + "issues": [], + "script_errors": [], + "status": "passed" +} \ No newline at end of file diff --git a/reports/V8_30_主题设计与兼容验收.html b/reports/V8_30_主题设计与兼容验收.html new file mode 100644 index 0000000..b9d3c7b --- /dev/null +++ b/reports/V8_30_主题设计与兼容验收.html @@ -0,0 +1 @@ +SiteForge V8.30 验收报告
    SITEFORGE · V8.30.0-dev.1 / LOCAL INTEGRATION

    四套主题真实页面设计验收

    本报告来自隔离环境的自动化测试及示例静态构建。它不是正式服务器生产验收。

    390
    Python 测试通过
    39
    JavaScript 测试通过
    144
    生成页面
    72
    手机组合检查

    静态构建质量

    主题生成页面错误警告
    automotive3608
    industrial3608
    corporate3608
    minimal3608

    视觉与兼容性

    四套主题均提供首页、列表、详情、文章、关于和联系页面的专有视觉设计;375、390、430px 真实 Chromium 视口检查 72/72 通过,未发现横向溢出或脚本错误。

    老版本 v1.2.0 完整存档并通过锁定版本构建检查;原 URL、SEO、数据层不变。

    交付边界

    正式 Art Design Pro 编译、真实企业内容视觉验收、真实 iOS/Android 设备、PostgreSQL/Redis 多 Worker 与正式服务器发布仍未完成,不得标记为已通过。

    打开四套主题 × 六类页面预览 →

    \ No newline at end of file diff --git a/reports/V8_31_汽车主题验收报告.html b/reports/V8_31_汽车主题验收报告.html new file mode 100644 index 0000000..826f1d0 --- /dev/null +++ b/reports/V8_31_汽车主题验收报告.html @@ -0,0 +1,2 @@ +SiteForge V8.31 汽车主题设计与集成验收
    SiteForge Enterprise / Automotive Redesign

    V8.31 汽车主题设计与集成验收

    以 magicbridgeauto.com 的品牌导航、车型浏览与咨询流程为参考,对 V8.30 汽车主题进行完整行业化改造。使用 SiteForge 已有内容数据和静态构建系统,不复制参考站的原始照片、Logo 和数据。

    8.31.0-dev.1 · automotive@1.4.0
    394Python 历史回归通过
    39JavaScript 自动化通过
    26/26隔离批次通过
    30跨视口页面检查无异常

    真实构建效果

    汽车主题桌面首页
    桌面端首页 / 实际静态构建 / 演示数据
    汽车主题移动端首页
    390px 手机端首页 / 双列车型卡片

    完成页面结构

    页面类型本轮主要变化
    首页从车型视觉 Banner、搜索、品牌到车型推荐及服务介绍
    车型列表可搜索、可按品牌/类型筛选的车型卡片
    品牌详情品牌介绍、车型目录与关联内容
    车型详情图片画廊、车型资料与询盘入口
    公司介绍清晰展示业务能力和联系方式
    联系我们完整联系方式与咨询入口

    技术与兼容性验收

    • 四套主题均成功完成真实静态生成:各 36 页,质量报告均 0 错误、0 警告。
    • 汽车主题在 375、390、430、768、1440px 宽度下,六类页面共 30 组测试;横向溢出、h1 重复与脚本报错均为 0。
    • 真实 Chromium 交互测试:品牌大菜单、车型搜索(仅匹配预期车型)、手机抽屉打开/关闭均通过。
    • 原平台 HTTP + Worker 登录、CSRF、创建网站、生成 ZIP、预览全流程通过。
    • 保留汽车主题 1.0.0–1.3.0 归档。修复固定旧版本却意外加载最新主题 HTML 片段的兼容缺陷。
    • 其他三套主题仍为 1.3.0,现有数据路径、SEO 生成、可视化编辑器与发布审批继续保留。

    产品边界与下一步

    本轮是汽车主题 UI 与信息架构参考改造,不是原站业务数据的 1:1 复制。预览中的企业、品牌、车型均为虚构演示资料。要正式用于业务,请在管理后台上传有权使用的高清车辆图片、品牌信息、参数和联系方式,并核对真实多品牌导航。Art Design Pro 官方完整工程编译、实际生产 PostgreSQL/Redis、真实远程发布、iOS/Android 实机操作仍需另行验收。

    复核入口

    完整代码与测试脚本见项目源码。tests/test_v831_automotive_ref.py;reports/v829-regression/result.json;reports/v831/browser_results.json;README_V8_31.md。

    \ No newline at end of file diff --git a/reports/v823-regression/result.json b/reports/v823-regression/result.json new file mode 100644 index 0000000..60437ee --- /dev/null +++ b/reports/v823-regression/result.json @@ -0,0 +1,227 @@ +{ + "version": "8.24.0-dev.1", + "generated_utc": "2026-10-23T05:52:43.722866+00:00", + "groups": [ + { + "batch": 1, + "files": [ + "test_commercial_v5.py", + "test_connectors_v84.py" + ], + "status": "passed", + "seconds": 10.53, + "summary": ".................... [100%]\n20 passed in 4.39s\n\n" + }, + { + "batch": 2, + "files": [ + "test_connectors_v85.py", + "test_console_v819.py" + ], + "status": "passed", + "seconds": 5.77, + "summary": "....................... [100%]\n23 passed in 3.01s\n\n" + }, + { + "batch": 3, + "files": [ + "test_core_v4.py", + "test_deep_nested_v824.py" + ], + "status": "passed", + "seconds": 7.15, + "summary": "................ [100%]\n16 passed in 4.64s\n\n" + }, + { + "batch": 4, + "files": [ + "test_editor_easy_v8212.py", + "test_editor_ux_v8211.py" + ], + "status": "failed", + "seconds": 2.4, + "summary": "=====\nFAILED tests/test_editor_easy_v8212.py::test_no_change_to_block_blueprint_or_database_schema - AssertionError: assert (False)\n + where False = ('8.23.')\n + where = '8.24.0-dev.1'.startswith\n1 failed, 5 passed in 0.21s\n\n" + }, + { + "batch": 5, + "files": [ + "test_enterprise.py", + "test_enterprise_v7.py" + ], + "status": "passed", + "seconds": 6.37, + "summary": "................ [100%]\n16 passed in 3.41s\n\n" + }, + { + "batch": 6, + "files": [ + "test_factory.py", + "test_factory_v2.py" + ], + "status": "passed", + "seconds": 11.11, + "summary": "........................ [100%]\n24 passed in 8.33s\n\n" + }, + { + "batch": 7, + "files": [ + "test_mobile_tabs_v8213.py", + "test_multilingual_v815.py" + ], + "status": "passed", + "seconds": 8.55, + "summary": ".................... [100%]\n20 passed in 5.20s\n\n" + }, + { + "batch": 8, + "files": [ + "test_nested_v823.py", + "test_p0_71.py" + ], + "status": "passed", + "seconds": 8.56, + "summary": "........ [100%]\n8 passed in 1.72s\n\n" + }, + { + "batch": 9, + "files": [ + "test_p0_backup.py", + "test_p0_p4_completion_v88.py" + ], + "status": "passed", + "seconds": 6.37, + "summary": "................... [100%]\n19 passed in 3.34s\n\n" + }, + { + "batch": 10, + "files": [ + "test_p0_p4_completion_v89.py", + "test_p1_platform.py" + ], + "status": "passed", + "seconds": 9.35, + "summary": ".............. [100%]\n14 passed in 6.43s\n\n" + }, + { + "batch": 11, + "files": [ + "test_production_v816.py", + "test_professional_ui_v811.py" + ], + "status": "passed", + "seconds": 4.9, + "summary": "............... [100%]\n15 passed in 2.25s\n\n" + }, + { + "batch": 12, + "files": [ + "test_regression_runner_v817.py", + "test_release_native_v814.py" + ], + "status": "passed", + "seconds": 4.2, + "summary": "........... [100%]\n11 passed in 1.65s\n\n" + }, + { + "batch": 13, + "files": [ + "test_release_reviews_v7.py", + "test_release_v813.py" + ], + "status": "passed", + "seconds": 5.37, + "summary": ".............. [100%]\n14 passed in 2.29s\n\n" + }, + { + "batch": 14, + "files": [ + "test_site_design_v87.py", + "test_siteforge_v817_audit.py" + ], + "status": "passed", + "seconds": 9.73, + "summary": ".................................... [100%]\n36 passed in 6.78s\n\n" + }, + { + "batch": 15, + "files": [ + "test_studio_v86.py", + "test_theme_pro_v3.py" + ], + "status": "passed", + "seconds": 11.52, + "summary": "............... [100%]\n15 passed in 8.54s\n\n" + }, + { + "batch": 16, + "files": [ + "test_v818_pg_recovery.py", + "test_v818_sqlite_pg_transfer.py" + ], + "status": "passed", + "seconds": 3.53, + "summary": "........... [100%]\n11 passed in 0.93s\n\n" + }, + { + "batch": 17, + "files": [ + "test_v821_editor_history_and_mapping.py", + "test_v822_canvas.py" + ], + "status": "passed", + "seconds": 4.76, + "summary": "........ [100%]\n8 passed in 2.07s\n\n" + }, + { + "batch": 18, + "files": [ + "test_v8_art_installer.py", + "test_v8_workflows.py" + ], + "status": "passed", + "seconds": 4.94, + "summary": ".............. [100%]\n14 passed in 2.13s\n\n" + }, + { + "batch": 19, + "files": [ + "test_wordpress_baseline.py", + "test_worker_queue_v6.py" + ], + "status": "passed", + "seconds": 9.08, + "summary": "............ [100%]\n12 passed in 6.46s\n\n" + }, + { + "batch": 20, + "files": [ + "test_workspace_v810.py", + "test_workspace_v812.py" + ], + "status": "passed", + "seconds": 5.38, + "summary": "............. [100%]\n13 passed in 2.66s\n\n" + }, + { + "batch": 21, + "files": [ + "test_wp_complex_v820.py", + "test_wp_migration_v81.py" + ], + "status": "passed", + "seconds": 5.19, + "summary": "...................... [100%]\n22 passed in 2.73s\n\n" + }, + { + "batch": 22, + "files": [ + "test_wp_migration_v82.py", + "test_wp_migration_v83.py" + ], + "status": "passed", + "seconds": 8.31, + "summary": ".................... [100%]\n20 passed in 5.75s\n\n" + } + ], + "all_passed": false +} \ No newline at end of file diff --git a/reports/v824-regression/result.json b/reports/v824-regression/result.json new file mode 100644 index 0000000..271a4de --- /dev/null +++ b/reports/v824-regression/result.json @@ -0,0 +1,227 @@ +{ + "version": "8.24.0-dev.1", + "generated_utc": "2026-10-23T05:56:01.776527+00:00", + "groups": [ + { + "batch": 1, + "files": [ + "test_commercial_v5.py", + "test_connectors_v84.py" + ], + "status": "passed", + "seconds": 7.36, + "summary": ".................... [100%]\n20 passed in 4.30s\n\n" + }, + { + "batch": 2, + "files": [ + "test_connectors_v85.py", + "test_console_v819.py" + ], + "status": "passed", + "seconds": 6.09, + "summary": "....................... [100%]\n23 passed in 3.24s\n\n" + }, + { + "batch": 3, + "files": [ + "test_core_v4.py", + "test_deep_nested_v824.py" + ], + "status": "passed", + "seconds": 8.34, + "summary": ".................. [100%]\n18 passed in 5.22s\n\n" + }, + { + "batch": 4, + "files": [ + "test_editor_easy_v8212.py", + "test_editor_ux_v8211.py" + ], + "status": "passed", + "seconds": 2.73, + "summary": "...... [100%]\n6 passed in 0.19s\n\n" + }, + { + "batch": 5, + "files": [ + "test_enterprise.py", + "test_enterprise_v7.py" + ], + "status": "passed", + "seconds": 7.92, + "summary": "................ [100%]\n16 passed in 4.66s\n\n" + }, + { + "batch": 6, + "files": [ + "test_factory.py", + "test_factory_v2.py" + ], + "status": "passed", + "seconds": 13.23, + "summary": "........................ [100%]\n24 passed in 9.86s\n\n" + }, + { + "batch": 7, + "files": [ + "test_mobile_tabs_v8213.py", + "test_multilingual_v815.py" + ], + "status": "passed", + "seconds": 7.54, + "summary": ".................... [100%]\n20 passed in 5.05s\n\n" + }, + { + "batch": 8, + "files": [ + "test_nested_v823.py", + "test_p0_71.py" + ], + "status": "passed", + "seconds": 4.97, + "summary": "........ [100%]\n8 passed in 1.98s\n\n" + }, + { + "batch": 9, + "files": [ + "test_p0_backup.py", + "test_p0_p4_completion_v88.py" + ], + "status": "passed", + "seconds": 6.25, + "summary": "................... [100%]\n19 passed in 3.23s\n\n" + }, + { + "batch": 10, + "files": [ + "test_p0_p4_completion_v89.py", + "test_p1_platform.py" + ], + "status": "passed", + "seconds": 9.47, + "summary": ".............. [100%]\n14 passed in 6.79s\n\n" + }, + { + "batch": 11, + "files": [ + "test_production_v816.py", + "test_professional_ui_v811.py" + ], + "status": "passed", + "seconds": 5.08, + "summary": "............... [100%]\n15 passed in 2.28s\n\n" + }, + { + "batch": 12, + "files": [ + "test_regression_runner_v817.py", + "test_release_native_v814.py" + ], + "status": "passed", + "seconds": 4.03, + "summary": "........... [100%]\n11 passed in 1.63s\n\n" + }, + { + "batch": 13, + "files": [ + "test_release_reviews_v7.py", + "test_release_v813.py" + ], + "status": "passed", + "seconds": 4.78, + "summary": ".............. [100%]\n14 passed in 2.23s\n\n" + }, + { + "batch": 14, + "files": [ + "test_site_design_v87.py", + "test_siteforge_v817_audit.py" + ], + "status": "passed", + "seconds": 9.07, + "summary": ".................................... [100%]\n36 passed in 5.67s\n\n" + }, + { + "batch": 15, + "files": [ + "test_studio_v86.py", + "test_theme_pro_v3.py" + ], + "status": "passed", + "seconds": 13.3, + "summary": "............... [100%]\n15 passed in 10.02s\n\n" + }, + { + "batch": 16, + "files": [ + "test_v818_pg_recovery.py", + "test_v818_sqlite_pg_transfer.py" + ], + "status": "passed", + "seconds": 3.96, + "summary": "........... [100%]\n11 passed in 0.88s\n\n" + }, + { + "batch": 17, + "files": [ + "test_v821_editor_history_and_mapping.py", + "test_v822_canvas.py" + ], + "status": "passed", + "seconds": 4.93, + "summary": "........ [100%]\n8 passed in 2.14s\n\n" + }, + { + "batch": 18, + "files": [ + "test_v8_art_installer.py", + "test_v8_workflows.py" + ], + "status": "passed", + "seconds": 6.3, + "summary": ".............. [100%]\n14 passed in 2.89s\n\n" + }, + { + "batch": 19, + "files": [ + "test_wordpress_baseline.py", + "test_worker_queue_v6.py" + ], + "status": "passed", + "seconds": 9.87, + "summary": "............ [100%]\n12 passed in 6.83s\n\n" + }, + { + "batch": 20, + "files": [ + "test_workspace_v810.py", + "test_workspace_v812.py" + ], + "status": "passed", + "seconds": 5.07, + "summary": "............. [100%]\n13 passed in 2.54s\n\n" + }, + { + "batch": 21, + "files": [ + "test_wp_complex_v820.py", + "test_wp_migration_v81.py" + ], + "status": "passed", + "seconds": 5.63, + "summary": "...................... [100%]\n22 passed in 3.05s\n\n" + }, + { + "batch": 22, + "files": [ + "test_wp_migration_v82.py", + "test_wp_migration_v83.py" + ], + "status": "passed", + "seconds": 8.06, + "summary": ".................... [100%]\n20 passed in 5.45s\n\n" + } + ], + "all_passed": true +} \ No newline at end of file diff --git a/reports/v825-regression/result.json b/reports/v825-regression/result.json new file mode 100644 index 0000000..49ee7fd --- /dev/null +++ b/reports/v825-regression/result.json @@ -0,0 +1,236 @@ +{ + "version": "8.25.0-dev.1", + "generated_utc": "2026-10-23T06:15:39.511366+00:00", + "groups": [ + { + "batch": 1, + "files": [ + "test_commercial_v5.py", + "test_connectors_v84.py" + ], + "status": "passed", + "seconds": 6.77, + "summary": ".................... [100%]\n20 passed in 4.04s\n\n" + }, + { + "batch": 2, + "files": [ + "test_connectors_v85.py", + "test_console_v819.py" + ], + "status": "passed", + "seconds": 6.95, + "summary": "....................... [100%]\n23 passed in 3.63s\n\n" + }, + { + "batch": 3, + "files": [ + "test_core_v4.py", + "test_deep_nested_v824.py" + ], + "status": "passed", + "seconds": 9.55, + "summary": "................... [100%]\n19 passed in 6.38s\n\n" + }, + { + "batch": 4, + "files": [ + "test_editor_easy_v8212.py", + "test_editor_ux_v8211.py" + ], + "status": "passed", + "seconds": 3.19, + "summary": "...... [100%]\n6 passed in 0.27s\n\n" + }, + { + "batch": 5, + "files": [ + "test_enterprise.py", + "test_enterprise_v7.py" + ], + "status": "passed", + "seconds": 9.12, + "summary": "................ [100%]\n16 passed in 4.97s\n\n" + }, + { + "batch": 6, + "files": [ + "test_factory.py", + "test_factory_v2.py" + ], + "status": "passed", + "seconds": 22.35, + "summary": "........................ [100%]\n24 passed in 18.47s\n\n" + }, + { + "batch": 7, + "files": [ + "test_mobile_tabs_v8213.py", + "test_multilingual_v815.py" + ], + "status": "passed", + "seconds": 10.41, + "summary": ".................... [100%]\n20 passed in 6.30s\n\n" + }, + { + "batch": 8, + "files": [ + "test_nested_v823.py", + "test_p0_71.py" + ], + "status": "passed", + "seconds": 5.36, + "summary": "........ [100%]\n8 passed in 1.91s\n\n" + }, + { + "batch": 9, + "files": [ + "test_p0_backup.py", + "test_p0_p4_completion_v88.py" + ], + "status": "passed", + "seconds": 11.91, + "summary": "................... [100%]\n19 passed in 4.22s\n\n" + }, + { + "batch": 10, + "files": [ + "test_p0_p4_completion_v89.py", + "test_p1_platform.py" + ], + "status": "passed", + "seconds": 11.28, + "summary": ".............. [100%]\n14 passed in 7.95s\n\n" + }, + { + "batch": 11, + "files": [ + "test_production_v816.py", + "test_professional_ui_v811.py" + ], + "status": "passed", + "seconds": 47.32, + "summary": "............... [100%]\n15 passed in 18.92s\n\n" + }, + { + "batch": 12, + "files": [ + "test_regression_runner_v817.py", + "test_release_native_v814.py" + ], + "status": "passed", + "seconds": 4.36, + "summary": "........... [100%]\n11 passed in 1.64s\n\n" + }, + { + "batch": 13, + "files": [ + "test_release_reviews_v7.py", + "test_release_v813.py" + ], + "status": "passed", + "seconds": 5.3, + "summary": ".............. [100%]\n14 passed in 2.29s\n\n" + }, + { + "batch": 14, + "files": [ + "test_site_design_v87.py", + "test_siteforge_v817_audit.py" + ], + "status": "passed", + "seconds": 8.26, + "summary": ".................................... [100%]\n36 passed in 5.36s\n\n" + }, + { + "batch": 15, + "files": [ + "test_studio_v86.py", + "test_theme_pro_v3.py" + ], + "status": "passed", + "seconds": 13.84, + "summary": "............... [100%]\n15 passed in 10.72s\n\n" + }, + { + "batch": 16, + "files": [ + "test_v818_pg_recovery.py", + "test_v818_sqlite_pg_transfer.py" + ], + "status": "passed", + "seconds": 3.59, + "summary": "........... [100%]\n11 passed in 0.96s\n\n" + }, + { + "batch": 17, + "files": [ + "test_v821_editor_history_and_mapping.py", + "test_v822_canvas.py" + ], + "status": "passed", + "seconds": 5.73, + "summary": "........ [100%]\n8 passed in 2.27s\n\n" + }, + { + "batch": 18, + "files": [ + "test_v825_shared_components.py", + "test_v8_art_installer.py" + ], + "status": "passed", + "seconds": 5.8, + "summary": "........... [100%]\n11 passed in 3.15s\n\n" + }, + { + "batch": 19, + "files": [ + "test_v8_workflows.py", + "test_wordpress_baseline.py" + ], + "status": "passed", + "seconds": 4.69, + "summary": "................... [100%]\n19 passed in 2.10s\n\n" + }, + { + "batch": 20, + "files": [ + "test_worker_queue_v6.py", + "test_workspace_v810.py" + ], + "status": "passed", + "seconds": 10.48, + "summary": ".......... [100%]\n10 passed in 7.30s\n\n" + }, + { + "batch": 21, + "files": [ + "test_workspace_v812.py", + "test_wp_complex_v820.py" + ], + "status": "passed", + "seconds": 6.13, + "summary": "..................... [100%]\n21 passed in 2.97s\n\n" + }, + { + "batch": 22, + "files": [ + "test_wp_migration_v81.py", + "test_wp_migration_v82.py" + ], + "status": "passed", + "seconds": 9.18, + "summary": ".................... [100%]\n20 passed in 6.04s\n\n" + }, + { + "batch": 23, + "files": [ + "test_wp_migration_v83.py" + ], + "status": "passed", + "seconds": 5.12, + "summary": ".......... [100%]\n10 passed in 2.38s\n\n" + } + ], + "all_passed": true +} \ No newline at end of file diff --git a/reports/v826-regression/result.json b/reports/v826-regression/result.json new file mode 100644 index 0000000..b06fd22 --- /dev/null +++ b/reports/v826-regression/result.json @@ -0,0 +1,237 @@ +{ + "version": "8.26.0-dev.1", + "generated_utc": "2026-10-23T06:55:03.816817+00:00", + "groups": [ + { + "batch": 1, + "files": [ + "test_commercial_v5.py", + "test_connectors_v84.py" + ], + "status": "passed", + "seconds": 14.81, + "summary": ".................... [100%]\n20 passed in 8.87s\n\n" + }, + { + "batch": 2, + "files": [ + "test_connectors_v85.py", + "test_console_v819.py" + ], + "status": "passed", + "seconds": 8.82, + "summary": "....................... [100%]\n23 passed in 4.48s\n\n" + }, + { + "batch": 3, + "files": [ + "test_core_v4.py", + "test_deep_nested_v824.py" + ], + "status": "passed", + "seconds": 10.38, + "summary": "................... [100%]\n19 passed in 6.82s\n\n" + }, + { + "batch": 4, + "files": [ + "test_editor_easy_v8212.py", + "test_editor_ux_v8211.py" + ], + "status": "passed", + "seconds": 3.29, + "summary": "...... [100%]\n6 passed in 0.23s\n\n" + }, + { + "batch": 5, + "files": [ + "test_enterprise.py", + "test_enterprise_v7.py" + ], + "status": "passed", + "seconds": 9.87, + "summary": "................ [100%]\n16 passed in 5.30s\n\n" + }, + { + "batch": 6, + "files": [ + "test_factory.py", + "test_factory_v2.py" + ], + "status": "passed", + "seconds": 16.44, + "summary": "........................ [100%]\n24 passed in 12.21s\n\n" + }, + { + "batch": 7, + "files": [ + "test_mobile_tabs_v8213.py", + "test_multilingual_v815.py" + ], + "status": "passed", + "seconds": 9.74, + "summary": ".................... [100%]\n20 passed in 5.88s\n\n" + }, + { + "batch": 8, + "files": [ + "test_nested_v823.py", + "test_p0_71.py" + ], + "status": "passed", + "seconds": 5.27, + "summary": "........ [100%]\n8 passed in 1.94s\n\n" + }, + { + "batch": 9, + "files": [ + "test_p0_backup.py", + "test_p0_p4_completion_v88.py" + ], + "status": "passed", + "seconds": 8.84, + "summary": "................... [100%]\n19 passed in 4.26s\n\n" + }, + { + "batch": 10, + "files": [ + "test_p0_p4_completion_v89.py", + "test_p1_platform.py" + ], + "status": "passed", + "seconds": 12.21, + "summary": ".............. [100%]\n14 passed in 8.00s\n\n" + }, + { + "batch": 11, + "files": [ + "test_production_v816.py", + "test_professional_ui_v811.py" + ], + "status": "passed", + "seconds": 7.73, + "summary": "............... [100%]\n15 passed in 3.46s\n\n" + }, + { + "batch": 12, + "files": [ + "test_regression_runner_v817.py", + "test_release_native_v814.py" + ], + "status": "passed", + "seconds": 4.94, + "summary": "........... [100%]\n11 passed in 1.77s\n\n" + }, + { + "batch": 13, + "files": [ + "test_release_reviews_v7.py", + "test_release_v813.py" + ], + "status": "passed", + "seconds": 6.97, + "summary": ".............. [100%]\n14 passed in 3.41s\n\n" + }, + { + "batch": 14, + "files": [ + "test_site_design_v87.py", + "test_siteforge_v817_audit.py" + ], + "status": "passed", + "seconds": 8.91, + "summary": ".................................... [100%]\n36 passed in 5.83s\n\n" + }, + { + "batch": 15, + "files": [ + "test_studio_v86.py", + "test_theme_pro_v3.py" + ], + "status": "passed", + "seconds": 10.86, + "summary": "............... [100%]\n15 passed in 7.97s\n\n" + }, + { + "batch": 16, + "files": [ + "test_v818_pg_recovery.py", + "test_v818_sqlite_pg_transfer.py" + ], + "status": "passed", + "seconds": 4.07, + "summary": "........... [100%]\n11 passed in 0.99s\n\n" + }, + { + "batch": 17, + "files": [ + "test_v821_editor_history_and_mapping.py", + "test_v822_canvas.py" + ], + "status": "passed", + "seconds": 6.21, + "summary": "........ [100%]\n8 passed in 2.71s\n\n" + }, + { + "batch": 18, + "files": [ + "test_v825_shared_components.py", + "test_v826_global_design.py" + ], + "status": "passed", + "seconds": 8.74, + "summary": "................ [100%]\n16 passed in 5.28s\n\n" + }, + { + "batch": 19, + "files": [ + "test_v8_art_installer.py", + "test_v8_workflows.py" + ], + "status": "passed", + "seconds": 5.79, + "summary": ".............. [100%]\n14 passed in 2.38s\n\n" + }, + { + "batch": 20, + "files": [ + "test_wordpress_baseline.py", + "test_worker_queue_v6.py" + ], + "status": "passed", + "seconds": 9.3, + "summary": "............ [100%]\n12 passed in 6.38s\n\n" + }, + { + "batch": 21, + "files": [ + "test_workspace_v810.py", + "test_workspace_v812.py" + ], + "status": "passed", + "seconds": 6.97, + "summary": "............. [100%]\n13 passed in 3.23s\n\n" + }, + { + "batch": 22, + "files": [ + "test_wp_complex_v820.py", + "test_wp_migration_v81.py" + ], + "status": "passed", + "seconds": 6.56, + "summary": "...................... [100%]\n22 passed in 3.12s\n\n" + }, + { + "batch": 23, + "files": [ + "test_wp_migration_v82.py", + "test_wp_migration_v83.py" + ], + "status": "passed", + "seconds": 9.28, + "summary": ".................... [100%]\n20 passed in 6.33s\n\n" + } + ], + "all_passed": true +} \ No newline at end of file diff --git a/reports/v826/V8_26_集成验收.html b/reports/v826/V8_26_集成验收.html new file mode 100644 index 0000000..acd4cbc --- /dev/null +++ b/reports/v826/V8_26_集成验收.html @@ -0,0 +1,7 @@ +SiteForge V8.26 集成验收 +
    SITEFORGE / TEST EVIDENCE

    V8.26 · 全站设计与导航管理

    完整源码的本地集成回归,包含原始日志和明确的环境验证边界。

    +
    376Python 测试通过
    23/23隔离回归批次
    13/13JavaScript 单测
    0失败或超时批次
    +

    已完成的功能验证

    • 可视化导航新增、编辑与多级结构;原安全路径校验继续生效
    • 草稿差异清单、版本绑定审核令牌与过期阻断
    • 历史快照站点隔离、恢复为新草稿及线上内容不变
    • HTTP 登录/CSRF、站点及页面创建、Worker 构建、ZIP 下载、预览
    • 隔离 Chromium 页面新增导航、保存、审核及历史交互;脚本错误 0
    +

    未完成的真实环境验收

    正式 Art Design Pro 工程编译、真实登录后台的浏览器 E2E、生产 PostgreSQL/Redis 多 Worker、真实 Docker 灾备和远程部署均未执行。离线 Chromium 不能替代正式后台浏览器验收。
    +

    分批回归明细

    模块通过数耗时结果
    test_commercial_v5.py、test_connectors_v84.py2014.81 s通过
    test_connectors_v85.py、test_console_v819.py238.82 s通过
    test_core_v4.py、test_deep_nested_v824.py1910.38 s通过
    test_editor_easy_v8212.py、test_editor_ux_v8211.py63.29 s通过
    test_enterprise.py、test_enterprise_v7.py169.87 s通过
    test_factory.py、test_factory_v2.py2416.44 s通过
    test_mobile_tabs_v8213.py、test_multilingual_v815.py209.74 s通过
    test_nested_v823.py、test_p0_71.py85.27 s通过
    test_p0_backup.py、test_p0_p4_completion_v88.py198.84 s通过
    test_p0_p4_completion_v89.py、test_p1_platform.py1412.21 s通过
    test_production_v816.py、test_professional_ui_v811.py157.73 s通过
    test_regression_runner_v817.py、test_release_native_v814.py114.94 s通过
    test_release_reviews_v7.py、test_release_v813.py146.97 s通过
    test_site_design_v87.py、test_siteforge_v817_audit.py368.91 s通过
    test_studio_v86.py、test_theme_pro_v3.py1510.86 s通过
    test_v818_pg_recovery.py、test_v818_sqlite_pg_transfer.py114.07 s通过
    test_v821_editor_history_and_mapping.py、test_v822_canvas.py86.21 s通过
    test_v825_shared_components.py、test_v826_global_design.py168.74 s通过
    test_v8_art_installer.py、test_v8_workflows.py145.79 s通过
    test_wordpress_baseline.py、test_worker_queue_v6.py129.3 s通过
    test_workspace_v810.py、test_workspace_v812.py136.97 s通过
    test_wp_complex_v820.py、test_wp_migration_v81.py226.56 s通过
    test_wp_migration_v82.py、test_wp_migration_v83.py209.28 s通过

    原始结果:reports/v826-regression/ · reports/v826/summary.json · HTTP / JS / browser 日志。

    \ No newline at end of file diff --git a/reports/v826/summary.json b/reports/v826/summary.json new file mode 100644 index 0000000..6be69d1 --- /dev/null +++ b/reports/v826/summary.json @@ -0,0 +1,12 @@ +{ + "version": "8.26.0-dev.1", + "python_tests_passed": 376, + "python_batches_passed": 23, + "python_batches_failed": 0, + "javascript_tests_passed": 13, + "http_worker_e2e": "passed", + "isolated_chromium_demo": "passed_with_set_content", + "real_logged_in_browser": "not_verified", + "production_pg_redis_docker": "not_verified", + "official_art_build": "not_verified" +} \ No newline at end of file diff --git a/reports/v827/V8_27_集成验收报告.html b/reports/v827/V8_27_集成验收报告.html new file mode 100644 index 0000000..667ec68 --- /dev/null +++ b/reports/v827/V8_27_集成验收报告.html @@ -0,0 +1,7 @@ +SiteForge V8.27 集成验收 +

    SiteForge V8.27 — 简洁后台与建站向导验收

    版本:8.27.0-dev.1 · 源码开发集成版 · 隔离环境验证

    +
    379Python 测试合计通过(含隔离复测)
    23JavaScript 单测通过
    通过HTTP + Worker 端到端
    +

    新增实际功能

    三步创建网站、自动识别下一步、WordPress 迁移分流、基于数据库/任务记录的状态展示、保存与上线概念区分、移动端易读布局。

    真实工作台 JS 的隔离浏览器截图
    +

    移动端验证

    390px 视口、抽屉初始关闭、无横向溢出;检查分步创建表单和引导步骤。

    移动端操作指引
    +

    Python 分批回归

    24 批中有 22 批直接通过。第 10 批组合运行超时,两个模块分别运行 7/7 通过;第 22 批旧断言绑定旧 UI 结构,改为校验新独立模型后 21/21 通过。原始超时与失败日志均保留,不称为一键全绿。

    批次测试模块原始/复测状态说明
    01test_commercial_v5.py, test_connectors_v84.pypassed
    02test_connectors_v85.py, test_console_v819.pypassed
    03test_core_v4.py, test_deep_nested_v824.pypassed
    04test_editor_easy_v8212.py, test_editor_ux_v8211.pypassed
    05test_enterprise.py, test_enterprise_v7.pypassed
    06test_factory.py, test_factory_v2.pypassed
    07test_mobile_tabs_v8213.py, test_multilingual_v815.pypassed
    08test_nested_v823.py, test_p0_71.pypassed
    09test_p0_backup.py, test_p0_p4_completion_v88.pypassed
    10test_p0_p4_completion_v89.py, test_p1_platform.pytimeout / separately passed两模块单独复测:7 + 7 = 14 通过
    11test_production_v816.py, test_professional_ui_v811.pypassed
    12test_regression_runner_v817.py, test_release_native_v814.pypassed
    13test_release_reviews_v7.py, test_release_v813.pypassed
    14test_site_design_v87.py, test_siteforge_v817_audit.pypassed
    15test_studio_v86.py, test_theme_pro_v3.pypassed
    16test_v818_pg_recovery.py, test_v818_sqlite_pg_transfer.pypassed
    17test_v821_editor_history_and_mapping.py, test_v822_canvas.pypassed
    18test_v825_shared_components.py, test_v826_global_design.pypassed
    19test_v827_guided_workspace.py, test_v8_art_installer.pypassed
    20test_v8_workflows.py, test_wordpress_baseline.pypassed
    21test_worker_queue_v6.py, test_workspace_v810.pypassed
    22test_workspace_v812.py, test_wp_complex_v820.pyassertion migration / retested旧结构断言已迁移,21 项重新通过
    23test_wp_migration_v81.py, test_wp_migration_v82.pypassed
    24test_wp_migration_v83.pypassed
    +
    未通过的正式验收门槛:原一键回归稳定性、正式 Art Design Pro 工程编译、真实后台登录浏览器 E2E、PostgreSQL/Redis 多 Worker、生产远程发布与灾备。演示使用模拟数据,不会操作真实网站。
    \ No newline at end of file diff --git a/reports/v827/v827-create-wizard-mobile.png b/reports/v827/v827-create-wizard-mobile.png new file mode 100644 index 0000000000000000000000000000000000000000..3144f19d653754238c4a27920cecae3689c85453 GIT binary patch literal 164763 zcmXtfWmsEX({3pgcZwHxcemmMhvHT!?heJ>JrLZBL-62I+}&MUoZ>Dg&v&l(=a#I! zGuPTPbIU}jD$AlF6Cr>2@Bs}VC#C-315Egb4+t%YAE9T!61$ooK45+TNQrCw%s$Qe zWc*o{IQ)PW-_w(hI&u4)Ra(AW&C~P#uEwXld0yYDoSbDKy1kti)6;Y5d24ONo|g^~ z7`leCHD{Zile5t7b)URqxDey$Kh8~`zA1)$CdOip)d>#_psBR(RIS8qqgOR2Cv&hVw>X=y51PJj4z*SH!9Xfs6~=BPjx&b z9e`|&tV1zJ2ByZTZcU9Dp%D-5Z|@n`OV6Y!U(vJ1BDH4+47DZECr=tW!>?k73R}_0 z*l;9NO%p#=o=pfgMfh6HC`vQIXxdi6R4XAvbcTpIuO$|CbE4idVe-am3#h{f2){K} zN~M+j)6(8rUY?&{o;UpB*IJ;eLw~8Jr>jR`JL|G5%`y9ukGm2EiON{;qJb2H;%?FY zKAq`Qd}c*wRI#iig=rFX(3;pWR!fh)7g{N-1EN*}XC#vhG;dI8%Kv#p=_{bcDe*wi z4jEG!QHYC!B`geK{Ob~*OK9DtHFM%1^5zBew)rep?>iNZuQ~u14|n^{mG5-qC66?> z57ZW#VUMfvM+d!)E6yb+*Xalqcan30;Xplm?qPdhv^1jWUr*sO2trIUZZw$Qps-+F zb~!OPcpi04n_}5jG7dbw7S{G^aVoPaVi+%xWVM{^Z+>IkV$LrOhk@xyjF5GYN|v$# z4wykdw6OCAc{cHrOAn(uuBul+I9{|W`cYHd2k8M!v4qkj!Xz7~7JLu3MY6Oor6hED@7a22 z{5FeJO?y%RNvf00c^>XFVYQ0O??oj^y>`JFg&UHy-}S!{iB^i6p9>rAmtxY4>sg9<;cPm(nO$#gXz6hH4xP16%iW1o?7bBJQYI zC(-z$;zT!z#svvLl3j9;Yr>aOy$@WET>N3Lyja;7McjV`$~E2khXA!xa$1Dm)TRc-Au{e&_Y>UR~i(Oqat{w*f#nUPM3e91Z#Y{p8=|FooMb3aw*x$UGmn933$+ag6-va##?i zqn5Jhi9BOvh3(04adPWp*!X-Sssh}mq!qL=j<$p< zWXt$bMrQ}NE$C!@e1!BrFWPVHo&4eW;q=`oFD289lJ_l~iOsa6L^C}6y{z4$swp{V z0AwoSna3=WVZflZDK->v*42Ae0WT|r>woM^kP@cOQBtFz=b&U$ZDFh-;}6b(%#JM_ zzREy9a1c-28|fmK?9Z1vhSDl|ob-sYxPSlJwzm`))!>xWo4O1a9x~+QM*7DOBQZU- z>3-P*xvparo^Fp#ENv&+!v7*{a7ycUW$6`Y7vIMg;aO^K4C*+jQ^Cd(t-fDeE-MM4 zb8|Npg{D@m52Kj$yqSih{l>L>ZR&)_zrViB=JZH!{A>4v@dh!hZ)k5Yp1|w@2DNIS zaJtpbVYRM%^MT+X$gl9}X4XLL`7V0d_2TDyx|}}oM9nu3ZKAlOqG|Y)&j$tad`g!B zZY9jT;8C3rlg^xco)D@Wat^K3=*mHF7QMVa%Uk58e>i^wB|J>P4Iwmeh<`RI?jFc5 z@7D&uka?b1ORmR)z503zL&uNDgI6mu2h-UR%1DJ0mK*bBfy<8i_QYA4jFmQaVDRcR z)%MX2Fz5Tv8#jsW&7HfZ1LJ!4FCgmkg+-AU8FX0_QgL6ey?tXb|NZU#o2oM(^k2;i z;F+R%RR3VZ>@Owp#12l*I)GUK!MEr5?3-Jcgs9^>uY;hR=Y+2_{jInlO*}k2Ost)x z?|LCx56x{QsWB)7>owYLWu*Gw zw9`ZP1EaNq4oFmVW1sNj;l9;MOm?hu(yMSpfwb+{OBl}Qe%+@BK; zhDKEV^lo|dZf_S5^6_c?C*Xwo7yCO>m9WET!34|F_z%P1M-6~PIW@tI{Gt)-j7&c+ zHyNEJOdJ~w8o^A}B;dDi>ND&n z8f$9@#P?0F;h3YK(D<7oBJL_^=r-bBLvu-N6snLrudXT6EwZOut!a)tf{T&;mniBZ zEdwp*W5xQ(VC21%!dPO2q|@>2j@Z+6fw`ey5qgfyhv}EA)V0b56#ysM0V?4 z-Ep9wZSAN>WSzF}b+cE|!=ycuPq#8=2=bnN>qlI)ahrAjhDY7k3MnPv?~ZV>h}@19 zXScgL2NV)6SQw1qC=759|Mh7{z8p>Z$$ot4n0`#2b)s<$)nt>Ys?|n@fvdpW_3)e% z{)N!}Ny@vOJJpSr;?M7yIcFq>Il9>Wpr(rB%=e~K)|#?qWLo$bC$%9GON6_^!D2>ip<=*q+RpO2aE9|aI z=*!ge%4(NG8%^t?{CvU$2&1%f$<)=X{O+qZFAoX)NgDiy8*C${$;AS`v$^r!)JYC0 z|2nw#wnAom@b05`26@{9tO=1u2xp0yn8tR2oCaGZab%OG`xEr(5m{r|)_drAks%77 z<{*|op{em9<%T(DBhU+X{~s0nyh)9@*+FrUrEDmCcm(`gvsbfv!EcAivm6o<@&H^A z2)SUKb#&>==WU-WMM^kCPPdhQwXz-WP!t};ZY`y(&L&qMV2!>J8;^#E zki1N?<&wEZdl;9-=C~+i`wgQdMPSL!Dla-4gE0&IgZE{q_rFM0HkD>@I|fCjsl7Sm z=)K5kmvf$ii3 zQzPai7j;R18?}T)Ep3O$M)DjN&Hb;6Z(Q{zRdHWtRob+v5bh1TEKu%x*7{hcr-Zs| zbtqb0D34OJzQYMPxwu8D$ZxnF!qvS0snL9hkuvH&%&lq&8i9XC%n-HnoG8gr#38B- zCoNDv9)&oa<4d(D2uM#f_r{$Z5asEDH1lT=LwL2^?Wyci%gEbpI@`VM?NiFwYHXyA zCx#5?I$1Q4Eq(fJxDPN11^uBlhPbY(y`eZFh6a_APZpFH0a>dW=27Bgr4yrrY*^Q2~oEiXZUONe2 z@Pyd!aKxb1dngsum`Z)reRD_c7oRKK_s>X-Brg^N86jc7#*#M=kAM?$dpi*xdqJ|Y zvU)D$i_A)@5svgdXwru7O!zm-Op-~+^X*^rLzG@c^&xOkBlGYSaUrcC9xbp|3}8Y5 z18u(CZ_!G3u?Jcg7Z-UT5SrpYkzQO%Kz#x0aaB>28Ky<^ugIlwWH5V(KSBYAShQz? zY`5PGHUlx(63%~xD-yV-T)6A%GXBdr!zi^2$Uf(