v0.10.19: G2 页脚 Footer 一比一复刻(原站 elementor_library post 58)
- 导入脚本 scripts/import-footer-template.ts:从 legacy dump 提取 post 58 的 _elementor_data 写入 contents(type=template, slug=footer),并按线上 post-58.css/DOM 补齐快照后改动 (f95e22e Google Preferred Source、405d251 width:auto、2481635 桌面外距) - Layout/getLayoutData 下发 footerDoc,Footer 改用 ElementorRenderer 直出原模板, 短代码按 widget id 注入:menu-2 移动端折叠菜单、gtranslate 语言下拉(原生 select.gt_selector) - Renderer 增强:section html_tag/边框/content_position、column 响应式宽度与 populated padding/margin(tablet/mobile)、widget 响应式盒模型、icon widget(fixed 返回顶部)、 icon-list 图标/间距/文字排版与 CSS 变量悬停、image 宽度、divider Elementor DOM、 text-editor 对齐与 current-date-time 动态年份、shortcode 预渲染上下文 - slim 白名单补齐响应式/图标/动态标签字段;app.css 新增 FA Solid/Regular 字体、 页脚 scoped 规则、elementor-hidden-* 响应式可见性 - 实测 1436:页脚总高 590.4 与原站全等(列宽/内层列/logo/社交/下拉逐项一致); 390:56/15/347/337/97/46.4/61 逐项全等;语言切换写 ui_lang cookie;返回顶部回滚 0 - bun test 11 pass;版本 0.10.19
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
/**
|
||||
* # 组件 网站公共布局 Layout
|
||||
* 组合 Header + 页面内容 + Footer;样式入口(Tailwind v4 + shadcn/ui)在此引入一次。
|
||||
* 布局数据(菜单/分类)由各路由 loader 通过 getLayoutData() 取得后传入。
|
||||
* 布局数据(菜单/分类/页脚 Elementor 模板)由各路由 loader 通过 getLayoutData() 取得后传入。
|
||||
*/
|
||||
import "../../styles/app.css";
|
||||
import { Header } from "./Header";
|
||||
import { Footer, type FooterCategory } from "./Footer";
|
||||
import { createServerFn } from "@tanstack/react-start";
|
||||
import { getMenuTree, getProductCategoryTree, type MenuNode } from "~/server/data";
|
||||
import { getFooterTemplate, getMenuTree, getProductCategoryTree, type MenuNode } from "~/server/data";
|
||||
import type { ElElement } from "~/components/elementor/Renderer";
|
||||
|
||||
/** # 类型 布局数据(Header/Footer 所需) */
|
||||
export type LayoutData = {
|
||||
@@ -17,12 +18,24 @@ export type LayoutData = {
|
||||
footerMenu: MenuNode[];
|
||||
/** # 成员变量 产品分类树(含计数) **/
|
||||
categories: FooterCategory[];
|
||||
/** # 成员变量 页脚 Elementor 模板文档(原站 elementor_library post 58) **/
|
||||
footerDoc: ElElement[] | null;
|
||||
};
|
||||
|
||||
/** # 函数 Server Function:获取布局数据(菜单 + 分类) */
|
||||
export const getLayoutData = createServerFn({ method: "GET" }).handler(async (): Promise<LayoutData> => {
|
||||
const [menu, footerMenu, cats] = await Promise.all([getMenuTree("max_mega_menu_1"), getMenuTree("menu-2"), getProductCategoryTree()]);
|
||||
return { menu, footerMenu, categories: cats };
|
||||
/** # 函数 Server Function:获取布局数据(菜单 + 分类 + 页脚模板)
|
||||
* 返回类型标 any:Elementor 文档的 settings 是递归 unknown(JSON),TanStack 的
|
||||
* 序列化静态校验无法展开递归 Record,会误报不可序列化;运行时就是纯 JSON。
|
||||
*/
|
||||
export const getLayoutData = createServerFn({ method: "GET" }).handler(async (): Promise<any> => {
|
||||
const [menu, footerMenu, cats, footer] = await Promise.all([
|
||||
getMenuTree("max_mega_menu_1"),
|
||||
getMenuTree("menu-2"),
|
||||
getProductCategoryTree(),
|
||||
getFooterTemplate().catch(() => null),
|
||||
]);
|
||||
const el = (footer?.meta as { elementor?: unknown } | null)?.elementor;
|
||||
const footerDoc = Array.isArray(el) ? (el as ElElement[]) : null;
|
||||
return { menu, footerMenu, categories: cats, footerDoc } satisfies LayoutData;
|
||||
});
|
||||
|
||||
/** # 类型 Layout 属性 */
|
||||
@@ -31,7 +44,7 @@ export function Layout(props: { layout: LayoutData; children: React.ReactNode })
|
||||
<>
|
||||
<Header menu={props.layout.menu} />
|
||||
<main>{props.children}</main>
|
||||
<Footer categories={props.layout.categories} menu={props.layout.footerMenu} />
|
||||
<Footer categories={props.layout.categories} menu={props.layout.footerMenu} doc={props.layout.footerDoc} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user