v0.10.8 首页 H6 宣言条 + H7 四列图标卡 1:1:section 根 padding/列 gap 默认 populated padding(10px 全向)/WidgetNode 双层 el-w-auto 修复 width:100% 强推;EAEL 取证改以原站实际加载的 eael-18.css 为准(icon/content 默认 block、title width:max-content maxW100%);H2~H7 全量 computed 归零(仅 0.8px 页级漂移),清理被取代的 scoped 补丁
This commit is contained in:
@@ -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 <WidgetNode el={el} />;
|
||||
if (type === "section" || type === "container") return <SectionNode el={el} />;
|
||||
if (type === "column") return <ColumnNode el={el} />;
|
||||
if (type === "column") return <ColumnNode el={el} gapPad={gapPad} />;
|
||||
// 未知结构:有子元素则递归,否则忽略
|
||||
if (el.elements?.length) {
|
||||
return (
|
||||
<>
|
||||
{el.elements.map((c, i) => (
|
||||
<ElementNode key={c.id || i} el={c} />
|
||||
<ElementNode key={c.id || i} el={c} gapPad={gapPad} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
@@ -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<string, string> = {
|
||||
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<string, unknown>).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 }) {
|
||||
<section style={style} data-el={el.id}>
|
||||
<div className="mx-auto flex flex-wrap" style={inner}>
|
||||
{(el.elements || []).map((c, i) => (
|
||||
<ElementNode key={c.id || i} el={c} />
|
||||
<ElementNode key={c.id || i} el={c} gapPad={gapPad} />
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
@@ -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 (
|
||||
<div className="el-col min-w-0" style={outer} data-el={el.id}>
|
||||
<div className="px-2.5" style={inner}>
|
||||
<div style={{ display: "flex", flexWrap: "wrap", alignContent: "flex-start", width: "100%", ...inner }}>
|
||||
{(el.elements || []).map((c, i) => (
|
||||
<ElementNode key={c.id || i} el={c} />
|
||||
<ElementNode key={c.id || i} el={c} gapPad={gapPad} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
@@ -421,16 +431,22 @@ function WidgetNode({ el }: { el: ElElement }) {
|
||||
<WidgetNodeInner el={el} />
|
||||
</WidgetGuard>
|
||||
);
|
||||
// 原站 .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 (
|
||||
<div data-el={el.id}>
|
||||
<div className={cls} style={style}>{inner}</div>
|
||||
// 外层也要带 el-w-auto:列内基础规则按 :not(.el-w-auto) 放行 width:auto 的根,
|
||||
// 否则 width-auto widget(如图标)被 width:100% 强推成每行一个(H7 回归根因)
|
||||
<div className={widthAuto ? "el-w-auto" : undefined} data-el={el.id}>
|
||||
<div className={baseCls} style={{ width: widthAuto ? "auto" : "100%", ...style }}>{inner}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return <div className={cls} data-el={el.id}>{inner}</div>;
|
||||
return <div className={baseCls} style={{ width: widthAuto ? "auto" : "100%" }} data-el={el.id}>{inner}</div>;
|
||||
}
|
||||
|
||||
/** # 组件 单个 widget 渲染错误边界:异常 widget 降级为空,不拖垮整页 */
|
||||
|
||||
@@ -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",
|
||||
|
||||
+62
-20
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user