v0.10.12: H12 Industries and Use Cases(eael-adv-tabs)完成 + H11 回归修复

- AdvTabsWidget: 忠实 EAEL DOM(li id/data-tab/aria-controls/aria-expanded)+ React 点击切换,
  active/inactive 类、内容面板 id=<slug>-tab;标题字体 Roboto
- H12 scoped 生成规则: li bg #F4F5F8 + 底边 3px(默认同背景色,active/hover #ED6C00),
  内容面板 color #333 + padding 16px 0 0 + 顶边 1px #C7CBDA(li 高 59 与原站全等)
- image-box 修复: content_vertical_alignment 设置驱动 wrapper align-items(middle→center,
  防 fig 被 flex stretch 拉高 2px);figure 内 <a> 块化消行盒下伸;ec11f3f 图宽 30%
  仅存于 post-18 生成 CSS,DB 无对应键,scoped 补规则
- 审计方法修正: 先滚动全页触发 lazy 图加载再测量(视口外 lazy 图曾致 H11 虚假 -82.2px)
- 实测 H0-H12 全部 section 高度与原站全等,页级漂移 0.8px;截图目视一致;点击切换正常
This commit is contained in:
bigcode
2026-11-01 22:10:59 +08:00
parent 46bd8d7655
commit 1c190d00ca
4 changed files with 95 additions and 20 deletions
+53 -17
View File
@@ -539,7 +539,7 @@ function WidgetNodeInner({ el }: { el: ElElement }) {
case "flip-box":
return <FlipBoxWidget settings={settings} />;
case "eael-adv-tabs":
return <AdvTabsWidget settings={settings} />;
return <AdvTabsWidget el={el} settings={settings} />;
case "eael-data-table":
return <DataTableWidget settings={settings} />;
case "eael-testimonial":
@@ -880,17 +880,21 @@ function ImageBoxWidget({ settings }: { settings: Record<string, unknown> }) {
: "h3") as "div";
const Tag = tag as "div";
// position left/right:wrapper 为 flex 行(widget-image-box.min.css .elementor-position-left
// .elementor-image-box-wrapper{display:flex;align-items:center},实测 H11 卡内图标行);
// .elementor-image-box-wrapper{display:flex},实测 H11 卡内图标行);
// 图宽 image_size%(post-18 由 image_size 控件生成 .elementor-image-box-img{width:18%})、
// 左侧布局 fig 右距 15px;标题底距 title_bottom_space(H11 实测 4px)
const isRow = pos === "left" || pos === "right";
const imgW = sizeCss(settings.image_size);
const titleSpace = sizeCss(settings.title_bottom_space);
// flex/边距在 app.css 的 .el-imagebox-pos-* 规则(带 768 断点),这里只带 per-widget 图宽
// 内容垂直对齐(content_vertical_alignment 控件,仅 left/right 行布局生效):
// 由 per-widget 生成规则输出 align-items(514e513 middle → center 实测;否则 flex 默认 stretch)
const vaMap: Record<string, string> = { top: "flex-start", middle: "center", bottom: "flex-end" };
const va = isRow ? vaMap[s(settings.content_vertical_alignment)] : undefined;
// flex/边距在 app.css 的 .el-imagebox-pos-* 规则(带 768 断点),这里只带 per-widget 图宽与垂直对齐
const figStyle: CSSProperties | undefined = isRow && imgW ? { width: imgW } : undefined;
return (
<div className={"el-imagebox" + posCls}>
<div className="el-imagebox-wrapper">
<div className="el-imagebox-wrapper" style={va ? { alignItems: va } : undefined}>
{url ? (
<figure className="el-imagebox-img" style={figStyle}>
{link ? (
@@ -1019,29 +1023,61 @@ function FlipBoxWidget({ settings }: { settings: Record<string, unknown> }) {
}
/** # 组件 eael-adv-tabs(EAEL 高级标签页):结构同 tabs,键名不同 */
function AdvTabsWidget({ settings }: { settings: Record<string, unknown> }) {
/** # 组件 EAEL adv-tabs widget(H12 Industries and Use Cases,6 标签横排)
* DOM 对齐原站(1436 实测 2026-11-01):#eael-advance-tabs-<id>.eael-advance-tabs.eael-tabs-horizontal >
* .eael-tabs-nav > ul[role=tablist] > li.eael-tab-item-trigger.eael-tab-nav-item(.active/.inactive,
* pad 16px 24px,flex 1 1 auto) > span.eael-tab-title.title-after-icon;
* .eael-tabs-content > div.eael-tab-content-item.clearfix#<slug>-tab(.active/.inactive,pad 16px 0 0)。
* 内容 tab_content 为自包含 HTML(use-fl/use-fr 图文布局),custom_css 经 collectCustomCss 注入。
* 基础样式移植 eael-18.css(app.css「EAEL adv-tabs」块);激活/文字色由 post-18 生成规则
* (li bg 26331af #F4F5F8、激活 #ED6C00、未激活 #333)落在 scoped 规则。
*/
function AdvTabsWidget({ el, settings }: { el: ElElement; settings: Record<string, unknown> }) {
const raw = Array.isArray(settings.eael_adv_tabs_tab)
? (settings.eael_adv_tabs_tab as { eael_adv_tabs_tab_title?: string; eael_adv_tabs_tab_content?: string }[])
: [];
const items = raw
.map((t) => ({ title: s(t.eael_adv_tabs_tab_title), content: s(t.eael_adv_tabs_tab_content) }))
.filter((t) => t.title || t.content);
const [active, setActive] = useState(0);
if (!items.length) return null;
// 内容面板 id:标题 slug 化(原站 building-automation / building-automation-tab 等)
const slug = (t: string) => t.toLowerCase().trim().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-");
return (
<Tabs defaultValue="adv-0" className="mb-[18px]">
<TabsList>
<div id={`eael-advance-tabs-${el.id}`} className="eael-advance-tabs eael-tabs-horizontal">
<div className="eael-tabs-nav">
<ul role="tablist">
{items.map((t, i) => (
<li
key={i}
id={slug(t.title)}
className={"eael-tab-item-trigger eael-tab-nav-item " + (i === active ? "active" : "inactive")}
role="tab"
data-tab={i + 1}
aria-selected={i === active}
aria-controls={`${slug(t.title)}-tab`}
aria-expanded="false"
tabIndex={i === active ? 0 : -1}
onClick={() => setActive(i)}
>
<span className="eael-tab-title title-after-icon">{t.title}</span>
</li>
))}
</ul>
</div>
<div className="eael-tabs-content">
{items.map((t, i) => (
<TabsTrigger key={i} value={`adv-${i}`}>
{t.title}
</TabsTrigger>
<div
key={i}
id={`${slug(t.title)}-tab`}
className={"clearfix eael-tab-content-item " + (i === active ? "active" : "inactive")}
role="tabpanel"
style={{ display: i === active ? "block" : "none" }}
dangerouslySetInnerHTML={{ __html: t.content }}
/>
))}
</TabsList>
{items.map((t, i) => (
<TabsContent key={i} value={`adv-${i}`}>
<div className="content-html" dangerouslySetInnerHTML={{ __html: t.content }} />
</TabsContent>
))}
</Tabs>
</div>
</div>
);
}