From 2cbfc82a08d27c1248e7ac232a93be089f8e4c97 Mon Sep 17 00:00:00 2001 From: bigcode Date: Sun, 1 Nov 2026 09:41:41 +0800 Subject: [PATCH] =?UTF-8?q?v0.10.8=20=E9=A6=96=E9=A1=B5=20H6=20=E5=AE=A3?= =?UTF-8?q?=E8=A8=80=E6=9D=A1=20+=20H7=20=E5=9B=9B=E5=88=97=E5=9B=BE?= =?UTF-8?q?=E6=A0=87=E5=8D=A1=201:1:section=20=E6=A0=B9=20padding/?= =?UTF-8?q?=E5=88=97=20gap=20=E9=BB=98=E8=AE=A4=20populated=20padding(10px?= =?UTF-8?q?=20=E5=85=A8=E5=90=91)/WidgetNode=20=E5=8F=8C=E5=B1=82=20el-w-a?= =?UTF-8?q?uto=20=E4=BF=AE=E5=A4=8D=20width:100%=20=E5=BC=BA=E6=8E=A8;EAEL?= =?UTF-8?q?=20=E5=8F=96=E8=AF=81=E6=94=B9=E4=BB=A5=E5=8E=9F=E7=AB=99?= =?UTF-8?q?=E5=AE=9E=E9=99=85=E5=8A=A0=E8=BD=BD=E7=9A=84=20eael-18.css=20?= =?UTF-8?q?=E4=B8=BA=E5=87=86(icon/content=20=E9=BB=98=E8=AE=A4=20block?= =?UTF-8?q?=E3=80=81title=20width:max-content=20maxW100%);H2~H7=20?= =?UTF-8?q?=E5=85=A8=E9=87=8F=20computed=20=E5=BD=92=E9=9B=B6(=E4=BB=85=20?= =?UTF-8?q?0.8px=20=E9=A1=B5=E7=BA=A7=E6=BC=82=E7=A7=BB),=E6=B8=85?= =?UTF-8?q?=E7=90=86=E8=A2=AB=E5=8F=96=E4=BB=A3=E7=9A=84=20scoped=20?= =?UTF-8?q?=E8=A1=A5=E4=B8=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/sections-inventory.md | 12 +++- package.json | 2 +- src/components/elementor/Renderer.tsx | 54 +++++++++++------- src/components/elementor/slim.ts | 2 + src/styles/app.css | 82 ++++++++++++++++++++------- 5 files changed, 109 insertions(+), 43 deletions(-) diff --git a/docs/sections-inventory.md b/docs/sections-inventory.md index 040986310..6c7d5af2c 100644 --- a/docs/sections-inventory.md +++ b/docs/sections-inventory.md @@ -38,9 +38,9 @@ | H2 | 产品线入口 ×6 | image-box ×6(6 条产品线图标卡) | ✅ v0.10.5(图片上方图标+标题 16px/400/#333、figure 30% 宽、hover 亮度 90%、五列右侧 v-line 竖线、列 10px 内边距、≤767 50% 两列;ImageBoxWidget 重构为 Elementor 忠实 DOM 供 H13/about 复用) | | H3 | 「Dusun Hardware & Service」标题条 | heading | ✅ v0.10.6(Poppins®600/40px/48 行高/#000 居中、widget 底 padding 24px、section 上 padding 64px;Poppins 与原站一致走系统 fallback 不载字体文件;typographyCss/_padding/resolveGlobals 修复基建) | | H4 | 硬件与服务系列 ×5 组 | 每组 heading+text+image+eael-info-box ×2(五列卡组) | ✅ v0.10.7(heading 橙线下划线/20px/#333、text-editor BFC 62.4、image widget link/shrink 动画、eael-info-box icon-on-left 完整结构、列卡渐变+边框+margin 折叠(实测 sec 529.6/列 513.6/inf2 y1429.4 与原站一致);WidgetNode 双层容器(elementor-widget + widget-container)对齐原站 margin 折叠语义) | -| H5 | 可定制/易生产 双主张条 | heading ×2(双栏大字) | ⬜ | -| H6 | 从概念到量产 宣言条 | 全大写 heading(ACCELERATE YOUR IOT DEVICE LAUNCH…) | ⬜ | -| H7 | OS/芯片平台/语言/协议 四列 | heading ×4 图标列 | ⬜ | +| H5 | 可定制/易生产 双主张条 | heading ×2(双栏大字) | ✅ v0.10.7(long-arrow 背景条、列 380、文字 20px/500/#fff 单行、arrow 194×39) | +| H6 | 从概念到量产 宣言条 | 全大写 heading(ACCELERATE YOUR IOT DEVICE LAUNCH…) | ✅ v0.10.8(Poppins 24px/600/行高 1 由 DB 内联、≤767 20px、列 59bc2e1 四向 10px、sec 根 padding 10px,五层盒模型 y 全对齐 0.8px 页级漂移内) | +| H7 | OS/芯片平台/语言/协议 四列 | heading ×4 图标列 | ✅ v0.10.8(外卡 66de90a 渐变+边框+圆角 8/16/16/0、四列 335.5 虚线分隔、_element_width:auto 图标横排 4+3 换行、el-w-auto 双层类修复 width:100% 强推回归) | | H8 | 热门嵌入式硬件 标题 | heading | ⬜ | | H9 | 热门硬件切换器(html) | html widget(原站 JS 切换逻辑,需看原站行为) | ⬜ | | H10 | 技术产品 Tab 行 ×3 | heading+image+image-box ×4+button(三段 Tab 面板) | ⬜ | @@ -113,6 +113,12 @@ cookie-policy:19 段纯文本。 4. **公司页**(about-us 24 版块最后收拾)。 > 每完成一个版块:与原站同页同区截图对比 → 头less Chromium 验算 computed style → 版本号 +1。 +> +> 取证基建补充(v0.10.8):原站 EAEL 样式实际加载 `uploads/essential-addons-elementor/eael-18.css` +> (合并包),并非 `view/*.min.css` 单件——后续 H9/H11 等 EAEL 版块以 eael-18.css 为准; +> Elementor 通用布局三要素已落地 Renderer:section 根 padding、列 gap 默认 populated padding +> (no 0/narrow 5/default 10/extended 15/wide 20/wider 30)、widget-wrap flex wrap + 子元素 width:100% +> + `_element_width:auto` 例外。 ## 七、已知遗留(非当前版块范围,后续版块收口) diff --git a/package.json b/package.json index 340942923..c10c4bd81 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dusuniot-rebuild", - "version": "0.10.7", + "version": "0.10.8", "private": true, "type": "module", "scripts": { diff --git a/src/components/elementor/Renderer.tsx b/src/components/elementor/Renderer.tsx index ac487e93d..458068dd4 100644 --- a/src/components/elementor/Renderer.tsx +++ b/src/components/elementor/Renderer.tsx @@ -282,18 +282,20 @@ function collectResponsiveCss(elements: ElElement[]): string { return css; } -/** # 组件 单个元素节点分发(section/column/container/widget) */ -function ElementNode({ el }: { el: ElElement }) { +/** # 组件 单个元素节点分发(section/column/container/widget) + * 参数 gapPad 所属 section 的默认列内边距(Elementor gap 档位,仅 column 消费) + */ +function ElementNode({ el, gapPad }: { el: ElElement; gapPad?: string }) { const type = s(el.elType); if (type === "widget") return ; if (type === "section" || type === "container") return ; - if (type === "column") return ; + if (type === "column") return ; // 未知结构:有子元素则递归,否则忽略 if (el.elements?.length) { return ( <> {el.elements.map((c, i) => ( - + ))} ); @@ -303,23 +305,29 @@ function ElementNode({ el }: { el: ElElement }) { /** # 组件 section / container:背景 + 内部布局 * 取证(原站实测/post CSS):boxed 内容容器 = margin auto + flex wrap 的定宽行; - * 内容宽度 content_width 优先,否则沿用 Elementor kit 默认 1140px; - * 自带 padding 只取 settings.padding(不再叠加通用 px/py)。 + * 内容宽度 content_width 优先,否则沿用 Elementor kit 默认 1140px。 + * padding 挂在 section 根(原站 computed padding 在 .elementor-section 上,行容器无 padding, + * 根 padding 同时把行往内推:1436 视口 + 1.6px 侧 padding 时行仍为整宽 1360,实测一致)。 + * gap 档位决定子列的默认 populated padding(frontend.min.css:no 0 / narrow 5 / default 10 / + * extended 15 / wide 20 / wider 30;settings 缺省 = default)。 */ +const GAP_PAD: Record = { + no: "0px", narrow: "5px", default: "10px", extended: "15px", wide: "20px", wider: "30px", +}; function SectionNode({ el }: { el: ElElement }) { const settings = resolveGlobals(el.settings || {}); const style = sectionBgStyle(settings); const width = sizeCss(settings.content_width) || sizeCss((settings as Record).width) || "1140px"; + const secPad = paddingCss(settings.padding); + if (secPad) style.padding = secPad; const inner: CSSProperties = {}; if (s(settings.layout) === "full_width") { - // 通栏 section:内容不设上限、无内边距(如首页 hero 轮播) + // 通栏 section:内容不设上限(如首页 hero 轮播) inner.maxWidth = "none"; - inner.padding = "0"; } else { inner.maxWidth = width; - const innerPad = paddingCss(settings.padding); - if (innerPad) inner.padding = innerPad; } + const gapPad = GAP_PAD[s(settings.gap) || "default"] || "10px"; // section 高度模式(Elementor: min-height / full),配合 custom_height; // 取证(原站 09fe4b7 实测):height 未设置时 custom_height 不生效(min-height 0px), // 故仅在显式 height 模式下应用 @@ -331,7 +339,7 @@ function SectionNode({ el }: { el: ElElement }) {
{(el.elements || []).map((c, i) => ( - + ))}
@@ -342,8 +350,11 @@ function SectionNode({ el }: { el: ElElement }) { * 外层参与 flex 布局(按 _inline_size 百分比否则均分),不承载盒样式; * 内层承载 populated 的盒样式:_margin(margin,移动卡片间距且不影响 flex 宽度,与原站一致)、 * padding、背景、边框、圆角。 + * padding:列自带 settings.padding 优先;否则用所属 section 的 gap 默认值 + * (frontend.min.css .elementor-column-gap-default > … > .elementor-element-populated{padding:10px}, + * 实测 H6 列 59bc2e1 四向 10px、H7 列 66de90a 设置覆盖为 8/16/16/0,两端一致)。 */ -function ColumnNode({ el }: { el: ElElement }) { +function ColumnNode({ el, gapPad }: { el: ElElement; gapPad?: string }) { const settings = resolveGlobals(el.settings || {}); const outer: CSSProperties = { minWidth: 0, flex: "1 1 0" }; const inline = settings._inline_size; @@ -359,8 +370,7 @@ function ColumnNode({ el }: { el: ElElement }) { inner.width = "100%"; inner.margin = mg; } - const pad = paddingCss(settings.padding); - if (pad) inner.padding = pad; + inner.padding = paddingCss(settings.padding) || gapPad || "10px"; const bg = sectionBgStyle(settings); Object.assign(inner, { backgroundColor: bg.backgroundColor, backgroundImage: bg.backgroundImage }); const radius = paddingCss(settings.border_radius); @@ -375,9 +385,9 @@ function ColumnNode({ el }: { el: ElElement }) { } return (
-
+
{(el.elements || []).map((c, i) => ( - + ))}
@@ -421,16 +431,22 @@ function WidgetNode({ el }: { el: ElElement }) { ); + // 原站 .elementor-widget-wrap > .elementor-element { width:100% }: + // widget 默认满宽(flex wrap 中独占一行),_element_width=auto 时按内容宽(横排) + const widthAuto = s(settings._element_width) === "auto"; const cls = s(settings._css_classes) || undefined; + const baseCls = cls ? (widthAuto ? cls + " el-w-auto" : cls) : widthAuto ? "el-w-auto" : undefined; const hasContainerStyle = Object.keys(style).length > 0; if (hasContainerStyle) { return ( -
-
{inner}
+ // 外层也要带 el-w-auto:列内基础规则按 :not(.el-w-auto) 放行 width:auto 的根, + // 否则 width-auto widget(如图标)被 width:100% 强推成每行一个(H7 回归根因) +
+
{inner}
); } - return
{inner}
; + return
{inner}
; } /** # 组件 单个 widget 渲染错误边界:异常 widget 降级为空,不拖垮整页 */ diff --git a/src/components/elementor/slim.ts b/src/components/elementor/slim.ts index 96da4c5e4..b3c790482 100644 --- a/src/components/elementor/slim.ts +++ b/src/components/elementor/slim.ts @@ -102,6 +102,8 @@ const SETTING_KEYS = new Set([ "hover_animation", // widget 高级盒模型(如 eael-info-box 边框卡:_border_* + _padding/_margin) "_margin", + // widget 宽度模式(auto → 按内容宽横排,如 H7 图标行) + "_element_width", // widget 容器背景(如 H4 标题下的橙线图) "_background_image", "_background_position", diff --git a/src/styles/app.css b/src/styles/app.css index 2e424e2a3..bc2301b41 100644 --- a/src/styles/app.css +++ b/src/styles/app.css @@ -261,7 +261,7 @@ background-repeat: no-repeat; background-position: center right; } - [data-el="e38a898"] > div > [data-el] > div { padding: 10px; } + /* 六列的 10px 内边距由列 gap 默认 padding 通用逻辑提供(ColumnNode),此处不再重复 */ [data-el="e38a898"] .el-imagebox-img { width: 30%; } [data-el="e38a898"] .el-imagebox:hover .el-imagebox-img img { filter: brightness(90%) contrast(100%) saturate(100%) blur(0px) hue-rotate(0deg); @@ -280,7 +280,8 @@ * text-editor:display flow-root 建立 BFC(子元素 p 的下外距计入容器高度,与原站 * 实测 62.4 = 2 行 48 + p margin 14.4 一致),p 下外距 0.9em(原站 hello 环境 14.4px)。 */ - .el-col > div > [data-el]:not(:last-child) { margin-bottom: 20px; } + .el-col > div > [data-el]:not(.el-w-auto) { width: 100%; } + .el-col > div > [data-el]:not(:last-child):not(.el-w-auto) { margin-bottom: 20px; } .el-texteditor { display: flow-root; } .el-texteditor p { margin: 0 0 0.9em; } @@ -298,21 +299,20 @@ .el-anim-shrink { transition-duration: 0.3s; transition-property: transform; } .el-anim-shrink:hover, .el-anim-shrink:focus, .el-anim-shrink:active { transform: scale(0.9); } - /* ===== EAEL infobox 基础(info-box.min.css 对应块): - * 图在左为 flex 行;内容列 padding-left 15px;标题行高 1(margin 由页面级覆盖); - * 图标列垂直居中。 + /* ===== EAEL infobox 基础(取证:原站实际加载 uploads/essential-addons-elementor/eael-18.css, + * 并未加载 view/info-box.min.css——后者仅在带 content-align--* 修饰类时才给 icon/content 上 flex, + * 本站 infobox 只有 icon-on-left 类,故 icon/content 均为默认 block、img 默认 inline 32×32; + * 2026-11-01 原站样式表命中探针实测) + * box 为 flex 行;内容列 padding-left 15px + flex item;title-section 纵向 flex。 */ .eael-infobox.icon-on-left { display: flex; position: relative; } .eael-infobox.icon-on-left .infobox-content { padding-left: 15px; flex: 1 1 auto; min-width: 0; } - .eael-infobox .infobox-icon { - display: flex; justify-content: flex-start; align-self: center; - /* flex 行内拉伸:H4 实测 icon 容器 39px(img 32px + 7px 排版余量), - * 与 .eael-infobox 盒 42px 对齐 */ - } .eael-infobox .infobox-icon img { transition: all 300ms ease-in-out 0s; } - .eael-infobox .infobox-content { display: flex; flex-direction: column; justify-content: center; } .eael-infobox .infobox-content .infobox-title-section { display: flex; flex-direction: column; } - .eael-infobox .infobox-content .title { line-height: 1; } + .eael-infobox .infobox-content .infobox-title-section .title { + width: max-content; max-width: 100%; overflow-wrap: break-word; word-break: break-word; + } + .eael-infobox.icon-on-left .infobox-content .title { line-height: 1; margin: 0 0 10px 0; } .eael-infobox .infobox-content p { margin: 0 0 15px; } /* ===== 首页 H4 硬件与服务系列 ×5(post-18.css 对应块;1436px 实测 2026-11-01) @@ -329,14 +329,15 @@ [data-el="7c9ceeb"] .infobox-icon, [data-el="9ff518a"] .infobox-icon, [data-el="2c9eb1c"] .infobox-icon, [data-el="1aa62bd"] .infobox-icon, [data-el="64432f0"] .infobox-icon, [data-el="2ba29de"] .infobox-icon { + align-self: center; margin: 3px 0 0 0; height: 39px; } - [data-el="314b8d5"] .infobox-content .title, [data-el="8417167"] .infobox-content .title, - [data-el="9e1009f"] .infobox-content .title, [data-el="2032426"] .infobox-content .title, - [data-el="7c9ceeb"] .infobox-content .title, [data-el="9ff518a"] .infobox-content .title, - [data-el="2c9eb1c"] .infobox-content .title, [data-el="1aa62bd"] .infobox-content .title, - [data-el="64432f0"] .infobox-content .title, [data-el="2ba29de"] .infobox-content .title { + [data-el="314b8d5"] .eael-infobox .infobox-content .title, [data-el="8417167"] .eael-infobox .infobox-content .title, + [data-el="9e1009f"] .eael-infobox .infobox-content .title, [data-el="2032426"] .eael-infobox .infobox-content .title, + [data-el="7c9ceeb"] .eael-infobox .infobox-content .title, [data-el="9ff518a"] .eael-infobox .infobox-content .title, + [data-el="2c9eb1c"] .eael-infobox .infobox-content .title, [data-el="1aa62bd"] .eael-infobox .infobox-content .title, + [data-el="64432f0"] .eael-infobox .infobox-content .title, [data-el="2ba29de"] .eael-infobox .infobox-content .title { color: #4d4d4d; font-size: 14px; margin: 7px 0 0 -10px; @@ -358,12 +359,53 @@ } } @media (max-width: 767px) { - [data-el="9ff518a"] .infobox-content .title, [data-el="2c9eb1c"] .infobox-content .title, - [data-el="1aa62bd"] .infobox-content .title, [data-el="64432f0"] .infobox-content .title, - [data-el="2ba29de"] .infobox-content .title { + [data-el="9ff518a"] .eael-infobox .infobox-content .title, [data-el="2c9eb1c"] .eael-infobox .infobox-content .title, + [data-el="1aa62bd"] .eael-infobox .infobox-content .title, [data-el="64432f0"] .eael-infobox .infobox-content .title, + [data-el="2ba29de"] .eael-infobox .infobox-content .title { margin: 7px 0 0 -6px; } } + + /* ===== 首页 H6 宣言条(post-18.css 对应块;1436 实测 2026-11-01) + * 标题排版(Poppins 24px/600/行高 1,≤767 20px)由 DB typography 内联提供, + * 列 59bc2e1 的四向 10px 由 gap 默认 padding 通用逻辑提供; + * 此处仅保留 post-18 的 text-align:center 与移动端字号覆盖(需 !important 压过内联 24px)。 + */ + [data-el="e50246d"] { text-align: center; } + @media (max-width: 767px) { + [data-el="e50246d"] .el-heading-title { font-size: 20px !important; } + } + + /* ===== 首页 H5 双主张条(post-18.css 对应块;1436 实测 2026-11-01) + * 大列 b504916 的 wrap 即视觉条:long-arrow.png(1353×54)居中不重复(settings padding 全 0); + * 中列 f158695 与两侧列的 padding 由 settings/gap 默认逻辑提供;列宽 380(structure 30 三列); + * 文字 20px/500/#FFF 居中。 + */ + [data-el="b504916"] > div { + background: url("/uploads/2023/09/long-arrow.png") 50% 50% no-repeat; + } + + /* ===== 首页 H7 OS/芯片平台/语言/协议 四列(post-18.css 对应块;1436 实测) + * 外卡 66de90a:渐变 #F4F5F9→透明 + 1px #E0E5F9 边框 + 4px 圆角 + padding 8/16/16/0; + * 内四列 b99f434/c8bd50b/821fd51 右侧虚线分隔(dashed #E0E5F9),列 padding-top 16px; + * ≤767 分隔虚线改下边框,section 左右 padding 1rem。 + */ + [data-el="66de90a"] > div { + background: linear-gradient(180deg, #F4F5F9 0%, rgba(244, 245, 249, 0) 100%); + border: 1px solid #E0E5F9; + border-radius: 4px; + padding: 8px 16px 16px 0; + } + [data-el="b99f434"] > div, [data-el="c8bd50b"] > div, [data-el="821fd51"] > div { + border-right: 1px dashed #E0E5F9; + } + @media (max-width: 767px) { + [data-el="b99f434"] > div, [data-el="c8bd50b"] > div, [data-el="821fd51"] > div { + border-right: 0; + border-bottom: 1px dashed #E0E5F9; + } + [data-el="338fb86"] { padding-inline: 1rem; } + } } @media (max-width: 900px) {