v0.10.18: H18 最新博文(8bc6b68)完成 + 文章分类关系数据修复

- PostsWidget 忠实重写(skin cards):预取架构 loader 按 widget 收集术语→查文章→
  PostsDataContext 分发;卡 DOM/缩略图比率 0.66/NEWS 徽章(uppercase)/日期 F j,Y/
  摘要 18 词(空回退正文);右列纯文本卡(44px 两行钳制+箭头图标,custom_css 注入)
- posts cards 基础 CSS + slim 白名单 cards_*/_skin/posts_include* 全键
- scripts/repair-content-terms.ts:从 legacy dump wp_term_relationships 提取 67709 对,
  经 legacy_id 映射补插 1162 条 content_terms(Blog 302/News 22 篇,原仅 61 篇有关联)
- 补 icon-arrow-light-orange.png;双端节内几何/样式全等(sec 521),截图目视一致
This commit is contained in:
bigcode
2026-11-02 00:27:15 +08:00
parent f614d10c94
commit 27fa9e605f
8 changed files with 297 additions and 44 deletions
+34 -4
View File
@@ -4,10 +4,38 @@
*/
import { createFileRoute, Link } from "@tanstack/react-router";
import { getLayoutData, Layout } from "~/components/website/Layout";
import { ElementorRenderer, extractElementor } from "~/components/elementor/Renderer";
import { ElementorRenderer, extractElementor, type ElElement } from "~/components/elementor/Renderer";
import { ProductCard } from "~/components/website/ProductCard";
import { Button } from "~/components/ui/button";
import { getHomePage, getProductCategoryTree, listProducts, listPosts } from "~/server/data";
import { getHomePage, getProductCategoryTree, listProducts, listPosts, listPostsByTermLegacy, type PostCardItem } from "~/server/data";
/** # 函数 收集 Elementor 文档中 posts widget 的查询并预取文章(H18)
* posts widget(skin cards)按 settings.posts_include_term_ids(WP 术语 legacy_id)+
* cards_posts_per_page 查询最新文章,结果按 widget id 传给渲染器。
* 参数 meta 首页 contents.meta
* 返回值 widgetId → 文章卡数组的映射
*/
async function loadPostsWidgets(meta: Record<string, unknown> | null): Promise<Record<string, PostCardItem[]>> {
const out: Record<string, PostCardItem[]> = {};
if (!meta) return out;
const walk = async (els: ElElement[] | undefined) => {
for (const el of els || []) {
if (el.widgetType === "posts" && el.id) {
const st = (el.settings || {}) as Record<string, unknown>;
const termIds = Array.isArray(st.posts_include_term_ids) ? (st.posts_include_term_ids as number[]) : [];
const perPage = Number(st.cards_posts_per_page) || 5;
if (termIds.length) {
out[el.id] = await listPostsByTermLegacy(Number(termIds[0]), perPage).catch(() => []);
}
}
await walk(el.elements);
}
};
const elementor = (meta.elementor ?? null) as { elements?: ElElement[] } | ElElement[] | null;
// 文档可能为裸数组或 {elements} 包装两种形态(extractElementor 同款兼容)
await walk(Array.isArray(elementor) ? elementor : elementor?.elements);
return out;
}
export const Route = createFileRoute("/")({
loader: async () => {
@@ -20,7 +48,9 @@ export const Route = createFileRoute("/")({
listPosts(1, 3).catch(() => ({ items: [], total: 0, page: 1, pageSize: 3 })),
]);
const meta = (home?.meta ?? null) as Record<string, unknown> | null;
return { layout, home, meta, cats, products, posts };
// Elementor posts widget 预取(H18:左右两个 posts widget)
const postsData = await loadPostsWidgets(meta);
return { layout, home, meta, cats, products, posts, postsData };
},
head: ({ loaderData }) => ({
meta: [
@@ -43,7 +73,7 @@ function HomePage() {
return (
<Layout layout={data.layout}>
{elementor ? (
<ElementorRenderer doc={elementor} />
<ElementorRenderer doc={elementor} postsData={data.postsData} />
) : (
<FallbackHome cats={data.cats} products={data.products} posts={data.posts} />
)}