Archived
`apps/api/src/app/activity-ops/*`(service / store / instance-state / instance-steps / launch-params / summaries / view-html / view-scope)+ `routes/activities.ts`;契约 `activity-ops.ts` / `api/activity-ops.ts` (与队友按文档补的那版 43 个导出同名,多 INSTANCE_REASON_KINDS / STEP_RESULTS / launchOptionSchema); 迁移 0035_activity_ops;《API文档-活动模块》按契约回写。 设计端活动库 GET/POST `/api/gov/activities` 改名 `/api/gov/activity-packages`,`/api/gov/activities/*` 整个让给运营端(前端 import 路由对象,零改动);activity-registry CONTRACT.md 与路由总表同步。 2026-08-27 另一会话做的,一直留在工作树没入库;与同批另两条提交互相依赖,以合并提交为验证单位。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0167qWjeyBwvfdGovd7FWbCu
30 lines
1.5 KiB
TypeScript
30 lines
1.5 KiB
TypeScript
/**
|
|
* L2 沙箱视图 —— 活动包里名为 `activity-ledger` 的视图模版(关键台账数据看板:最近一次已放行实例的落账快照,
|
|
* 行由基座按清单 `viewTemplates[].data` 的声明从正式表圈出,见 `view-scope.ts`)。
|
|
*
|
|
* 模版本身**无脚本**(安装静态审 `templateIsSafe` 拦着);而 iframe 是 `sandbox="allow-scripts"`
|
|
* 无同源,父页量不到它的高 —— 报高的脚本由服务端在**出口那一刻**注入,协议只有一条消息:
|
|
* `postMessage({ type: 'jcai:view-height', height }, '*')`(load + ResizeObserver + 1s 兜底)。
|
|
*/
|
|
import { ACTIVITY_VIEW_HEIGHT_MESSAGE } from '@contracts';
|
|
|
|
export const LEDGER_TEMPLATE = 'activity-ledger';
|
|
|
|
export function heightScript(): string {
|
|
return (
|
|
`<script>(function(){var T=${JSON.stringify(ACTIVITY_VIEW_HEIGHT_MESSAGE)};` +
|
|
'function h(){var b=document.body;return Math.max(document.documentElement.scrollHeight,b?b.scrollHeight:0)}' +
|
|
"function post(){try{window.parent.postMessage({type:T,height:h()},'*')}catch(e){}}" +
|
|
"window.addEventListener('load',post);" +
|
|
"if(typeof ResizeObserver!=='undefined'){new ResizeObserver(post).observe(document.documentElement)}" +
|
|
'setInterval(post,1000);post()})();</script>'
|
|
);
|
|
}
|
|
|
|
/** 插在 `</body>` 之前(没有就追加在末尾);模版原文一个字不改 */
|
|
export function injectHeightScript(html: string): string {
|
|
const script = heightScript();
|
|
const at = html.toLowerCase().lastIndexOf('</body>');
|
|
return at < 0 ? `${html}\n${script}` : `${html.slice(0, at)}${script}${html.slice(at)}`;
|
|
}
|