feat(learn): add standalone /learn pages backed by Page Data
Serve lightweight child/parent learning assistant pages at /learn without MindSpace injection, with a rebuild script and Portal static route. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Build lightweight /learn/* pages without MindSpace injection."""
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
SRC = ROOT / 'MindSpace/a70ff537-8908-486e-9b6c-042e07cc25db/public'
|
||||
OUT = ROOT / 'public/learn'
|
||||
VER = '20260915j'
|
||||
|
||||
CHILD_PAGE = 'dcb1f3f0-db96-4dab-a009-7a9c393ebe77'
|
||||
PARENT_PAGE = 'f9c80392-9417-46fd-af89-a91a239d3bfc'
|
||||
|
||||
|
||||
def extract_style(html: str) -> str:
|
||||
m = re.search(r'<style>([\s\S]*?)</style>', html)
|
||||
return m.group(1) if m else ''
|
||||
|
||||
|
||||
def extract_app_script(html: str) -> str:
|
||||
m = re.search(r'<script>\s*(var state=[\s\S]*?\)\(\);)\s*</script>', html)
|
||||
if not m:
|
||||
raise ValueError('app script not found')
|
||||
return m.group(1)
|
||||
|
||||
|
||||
def shell(title: str, style: str, page_id: str, access: str, body: str, script: str) -> str:
|
||||
access_json = '{"pageId":"%s","accessMode":"%s"}' % (page_id, access)
|
||||
return f'''<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
|
||||
<title>{title}</title>
|
||||
<meta name="mindspace-page-data-page-id" content="{page_id}">
|
||||
<script>window.__MINDSPACE_PAGE_DATA__={access_json};</script>
|
||||
<style>{style}</style>
|
||||
<script src="/assets/page-data-client.js?v={VER}"></script>
|
||||
<script src="/learn/learning-assistant-data.js?v={VER}"></script>
|
||||
<link rel="icon" type="image/png" href="/brand/tkmind-icon.png">
|
||||
</head>
|
||||
{body}
|
||||
<script>
|
||||
{script}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
'''
|
||||
|
||||
|
||||
def main():
|
||||
OUT.mkdir(parents=True, exist_ok=True)
|
||||
child_src = (SRC / 'learning-assistant.html').read_text(encoding='utf-8')
|
||||
parent_src = (SRC / 'learning-assistant-parent.html').read_text(encoding='utf-8')
|
||||
child_style = extract_style(child_src)
|
||||
parent_style = extract_style(parent_src)
|
||||
child_script = extract_app_script(child_src)
|
||||
parent_script = extract_app_script(parent_src)
|
||||
|
||||
child_script = child_script.replace('learning-assistant-parent.html', '/learn/parent.html')
|
||||
parent_script = parent_script.replace('learning-assistant.html', '/learn/')
|
||||
|
||||
child_body = '''<body>
|
||||
<div class="wrap" id="app"><div class="card"><div class="empty">加载中…</div></div></div>
|
||||
<div class="tabbar" id="tabbar"></div>
|
||||
'''
|
||||
|
||||
parent_body = '''<body>
|
||||
<div class="wrap pl" id="app"><div class="card"><div class="empty">加载中…</div></div></div>
|
||||
'''
|
||||
|
||||
(OUT / 'index.html').write_text(
|
||||
shell('我的学习小助手', child_style, CHILD_PAGE, 'public', child_body, child_script),
|
||||
encoding='utf-8',
|
||||
)
|
||||
(OUT / 'parent.html').write_text(
|
||||
shell('家长后台', parent_style, PARENT_PAGE, 'password', parent_body, parent_script),
|
||||
encoding='utf-8',
|
||||
)
|
||||
data_js = (SRC / 'learning-assistant-data.js').read_text(encoding='utf-8')
|
||||
data_js = re.sub(r'DATA_VER="[^"]+"', f'DATA_VER="{VER}"', data_js)
|
||||
(OUT / 'learning-assistant-data.js').write_text(data_js, encoding='utf-8')
|
||||
print('built', OUT)
|
||||
print(' index.html', (OUT / 'index.html').stat().st_size, 'bytes')
|
||||
print(' parent.html', (OUT / 'parent.html').stat().st_size, 'bytes')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env python3
|
||||
from pathlib import Path
|
||||
|
||||
p = Path("/Users/john/Project/Memind/server.mjs")
|
||||
text = p.read_text()
|
||||
if '"/learn"' in text and "public/learn" in text:
|
||||
print("ALREADY_PATCHED")
|
||||
raise SystemExit(0)
|
||||
|
||||
needle = """ app2.use(
|
||||
"/assets",
|
||||
staticMiddleware(
|
||||
pathApi.join(h5Root, "public/assets"),
|
||||
{ maxAge: "1d" }
|
||||
)
|
||||
);
|
||||
app2.get(
|
||||
"/dev/wechat-share-preview","""
|
||||
|
||||
insert = """ app2.use(
|
||||
"/assets",
|
||||
staticMiddleware(
|
||||
pathApi.join(h5Root, "public/assets"),
|
||||
{ maxAge: "1d" }
|
||||
)
|
||||
);
|
||||
app2.use(
|
||||
"/learn",
|
||||
staticMiddleware(
|
||||
pathApi.join(h5Root, "public/learn"),
|
||||
{ maxAge: "5m", index: "index.html" }
|
||||
)
|
||||
);
|
||||
app2.get(
|
||||
"/dev/wechat-share-preview","""
|
||||
|
||||
if needle not in text:
|
||||
print("NEEDLE_NOT_FOUND")
|
||||
raise SystemExit(1)
|
||||
|
||||
p.write_text(text.replace(needle, insert, 1))
|
||||
print("PATCHED_OK")
|
||||
Reference in New Issue
Block a user