diff --git a/docs/regression-guards/mindspace-seo-geo.md b/docs/regression-guards/mindspace-seo-geo.md index 49f5821..aeaeafa 100644 --- a/docs/regression-guards/mindspace-seo-geo.md +++ b/docs/regression-guards/mindspace-seo-geo.md @@ -9,6 +9,8 @@ 3. **总开关默认开启**:`mindspace_config.seo_geo_config` 缺省为全开;库内已保存的旧值仍以数据库为准,需在 memind_adm MindSpace 配置页保存后才会改写生产。 4. **配置来源**:memind_adm MindSpace 配置页 → `PATCH /admin-api/mindspace/config` → Portal `loadMindSpaceConfigCached()`。 5. **百度推送**:仅在 admin 开启 `seo.baiduPush` 且页面可索引时触发;公开页发布与 Plaza 发帖共用该开关。 +6. **作者侧 SEO/GEO 必填**:每个 `public/*.html` 必须包含 `title`、`description`、`mindspace-geo`(summary/keywords/faq)与语义化 `

` 分节;`npm run check:mindspace-cover --scope all` 默认校验 MindSpace + 平台静态页(含 `/learn`)。服务端对缺失 FAQ 会尝试从 `h2+p` 自动抽取 JSON-LD。 +7. **存量回填**:`npm run backfill:mindspace-geo` 可批量补齐 `mindspace-geo` / `description` / 缺失 `

`,并清理失效 cover 引用;Plaza SSR 页通过 `platform-seo-html.mjs` 注入 canonical / OG / JSON-LD。 ## 必跑验证 diff --git a/health-report-page.mjs b/health-report-page.mjs index e6b0177..ce60956 100644 --- a/health-report-page.mjs +++ b/health-report-page.mjs @@ -115,6 +115,15 @@ export function buildHealthReportHtml(observations = [], { now = Date.now(), tit ${escapeHtml(title)} + + +
@@ -155,5 +169,11 @@

Welcome, John

+

TKMind · 智趣

+ +

内容概要

+

John 的专属欢迎页面 - TKMind 为您呈现

+

Hello!讲什么?

+

John 的专属欢迎页面 - TKMind 为您呈现

diff --git a/public/learn/index.html b/public/learn/index.html index d32a35f..3f5746a 100644 --- a/public/learn/index.html +++ b/public/learn/index.html @@ -4,7 +4,10 @@ 我的学习小助手 - + + + +
加载中…
@@ -110,5 +126,13 @@ function submitVal(id){var v=document.getElementById('vInput').value;var r=docum async function submit(id,value,remark){try{var j=await LearnStore.checkin(id,value,remark);var s='
🎉
完成啦!
今天已经完成 '+j.done+' / '+j.total+' 项
'+(j.allDone?'⭐ 太棒了,今天全部完成!':'再完成 '+(j.total-j.done)+' 项,今天就是全绿!')+'
+'+j.points+' 能量
点一下继续
';document.body.insertAdjacentHTML('beforeend',s);await load();render()}catch(e){alert(e.message)}} (async function(){try{await LearnStore.init();await load();render()}catch(e){document.getElementById('app').innerHTML='
'+esc(e.message)+'
'}})(); +

TKMind · 智趣

+ +

内容概要

+

TKMind 儿童学习打卡与习惯养成助手,帮助小朋友完成每日任务、查看成长记录,并与家长后台协同。

+

学习小助手能做什么?

+

提供每日任务清单、完成打卡、历史记录、日历与成长统计,帮助培养学习习惯。

+

家长如何配置任务?

+

家长可访问家长后台添加学员、设置任务模板与查看统计数据。

diff --git a/public/learn/parent.html b/public/learn/parent.html index d85392b..293ec03 100644 --- a/public/learn/parent.html +++ b/public/learn/parent.html @@ -1,10 +1,14 @@ + 家长后台 - + + + +
加载中…
@@ -112,5 +129,11 @@ function render(){var app=document.getElementById('app');if(!state.pw){app.inner async function go(tab){state.tab=tab;try{await loadAll();render()}catch(e){state.pw='';localStorage.removeItem('learn_pw');render()}} (async function(){if(state.pw){try{await LearnStore.init({password:state.pw});await loadAll()}catch(e){state.pw='';localStorage.removeItem('learn_pw')}}try{render()}catch(e){document.getElementById('app').innerHTML='
'+esc(e.message)+'
'}})(); +

TKMind · 智趣

+ +

内容概要

+

TKMind 学习助手家长后台,用于配置儿童学员、任务模板、管理密码与查看学习统计。

+

家长后台有什么功能?

+

可添加学员、配置每日任务模板、修改管理密码并查看儿童学习统计。

diff --git a/public/oa-drive/index.html b/public/oa-drive/index.html index ca6fad1..b9be6b0 100644 --- a/public/oa-drive/index.html +++ b/public/oa-drive/index.html @@ -1,13 +1,30 @@ + + OA 网盘 · Memind + + +

OA 网盘 · Memind

OA 网盘 @@ -156,5 +173,11 @@ +

TKMind · 智趣

+ +

内容概要

+

以下文件已存在,请选择处理方式:

+

OA 网盘 · Memind讲什么?

+

以下文件已存在,请选择处理方式:

diff --git a/scripts/backfill-mindspace-geo.mjs b/scripts/backfill-mindspace-geo.mjs new file mode 100644 index 0000000..abcf9e9 --- /dev/null +++ b/scripts/backfill-mindspace-geo.mjs @@ -0,0 +1,86 @@ +#!/usr/bin/env node +/** + * Batch backfill mindspace-geo / description / minimal cover for HTML pages. + * + * Usage: + * node scripts/backfill-mindspace-geo.mjs [--dry-run] [--no-fix-warnings] + * node scripts/backfill-mindspace-geo.mjs --scope all --user + * node scripts/backfill-mindspace-geo.mjs --file public/hello-john.html + */ +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { backfillMindspaceSeoGeoHtml } from '../mindspace-geo-backfill.mjs'; +import { collectHtmlTargets } from '../mindspace-seo-audit.mjs'; + +const repoRoot = path.join(path.dirname(fileURLToPath(import.meta.url)), '..'); +const DEFAULT_PUBLISH_ROOT = 'MindSpace'; + +function parseArgs(argv) { + let scope = 'all'; + let root = path.join(repoRoot, DEFAULT_PUBLISH_ROOT); + let publicRoot = path.join(repoRoot, 'public'); + let userId = null; + let file = null; + let dryRun = false; + let forceGeo = false; + let fixWarnings = true; + + for (let i = 2; i < argv.length; i += 1) { + const arg = argv[i]; + if (arg === '--dry-run') dryRun = true; + else if (arg === '--force-geo') forceGeo = true; + else if (arg === '--no-fix-warnings') fixWarnings = false; + else if (arg === '--scope' && argv[i + 1]) { + scope = argv[i + 1]; + i += 1; + } else if (arg === '--root' && argv[i + 1]) { + root = path.resolve(argv[i + 1]); + i += 1; + } else if (arg === '--public-root' && argv[i + 1]) { + publicRoot = path.resolve(argv[i + 1]); + i += 1; + } else if (arg === '--user' && argv[i + 1]) { + userId = argv[i + 1]; + i += 1; + } else if (arg === '--file' && argv[i + 1]) { + file = path.resolve(argv[i + 1]); + i += 1; + } else if (arg === '--help' || arg === '-h') { + console.log(`Usage: node scripts/backfill-mindspace-geo.mjs [--scope mindspace|platform|all] [--dry-run] [--force-geo] [--user ] [--file ]`); + process.exit(0); + } + } + + return { scope, root, publicRoot, userId, file, dryRun, forceGeo, fixWarnings }; +} + +const { scope, root, publicRoot, userId, file, dryRun, forceGeo, fixWarnings } = parseArgs(process.argv); +const targets = collectHtmlTargets({ scope, mindspaceRoot: root, publicRoot, userId, file }); + +let changed = 0; +let skipped = 0; + +for (const htmlPath of targets) { + const before = fs.readFileSync(htmlPath, 'utf8'); + const after = backfillMindspaceSeoGeoHtml(before, { + forceGeo, + fixWarnings, + htmlFilePath: htmlPath, + }); + if (after === before) { + skipped += 1; + continue; + } + changed += 1; + if (dryRun) { + console.log(`[dry-run] would update ${htmlPath}`); + continue; + } + fs.writeFileSync(htmlPath, after, 'utf8'); + console.log(`updated ${htmlPath}`); +} + +console.log( + `${dryRun ? '[dry-run] ' : ''}done: ${changed} updated, ${skipped} unchanged, ${targets.length} scanned (scope=${scope})`, +); diff --git a/scripts/bootstrap-premium-page-templates.mjs b/scripts/bootstrap-premium-page-templates.mjs index 2e9ec2d..54297a9 100644 --- a/scripts/bootstrap-premium-page-templates.mjs +++ b/scripts/bootstrap-premium-page-templates.mjs @@ -33,6 +33,7 @@ const upgraded = { {{PAGE_TITLE}} +