@uneven/tpl-runtime
v0.2.4
Published
SWP TP4 cross-platform medical device template runtime
Readme
@uneven/tpl-runtime
TP4 医疗设备模板的无框架 DOM 运行时。核心包不依赖 Vue、Pinia 或业务 API,可用于 Vue 2.7、Vue 3 和纯 Web 设备页面。
当前版本:0.2.4。版本变化见 CHANGELOG.md。
当前能力
- TP4/旧模板版本路由;
parseTemplateAsTP4可将 V1/V2/V3 迁移为 TP4,设备端也可通过宿主legacyAdapter回退现有 ParserV3。 editor.bounds精确布局,缺失时回退 0-based Grid。- fixed 逻辑画布等比缩放。
primitive.text/image/rect与 Renderer Registry。- 图片动态值为空或加载失败时回退模板静态图;
id=qrcode根据绑定值生成 SVG 二维码。 - 数据路径解析与按数据源增量区域刷新。
- Android/Linux/Harmony Platform Adapter。
- bed/door/beside/whiteboard/watchboard Device Profile。
- 护理看板模块协议、住院汇总/护理统计/备注渲染器与患者卡片循环渲染。
patientList顶层字段和sickInfo嵌套字段兼容;缺少共享卡片时生成可编辑的默认卡片树。- HCareLabel 与自由
representativeElements。 - 可复制的诊断信息,不因未知组件导致整页崩溃。
安装
npm install @uneven/tpl-runtime项目开发依赖使用 pnpm 安装:
cd packages/template-runtime
pnpm install构建输出:ESM、UMD/CJS 和 TypeScript 声明。
校验与发布
发布 0.2.2 前依次执行:
pnpm typecheck
pnpm test
pnpm build
npm pack --dry-run
npm publish --access public --registry=https://registry.npmjs.org/作用域包按 public 权限发布。发布前确认 package.json、README 当前版本与 CHANGELOG 最新版本一致;npm 不允许覆盖已发布的同名同版本包。
0.2.2 兼容修复
- 床头模板的
nursingLevel在患者未返回nursingColor时保留设计器背景色,不再被运行时覆盖成白色。 - 兼容旧 Android flat 护理标签:
renderType=1可直接读取labelName色块子节点,不要求存在labelBack包裹层。 - flat 护理标签的预览文案、背景色、文字色和布局优先继承实际子组件配置,避免迁移后样式失真。
- 本次更新不改变 TP4 schema 和公开 API,现有宿主接入方式无需调整。
基础使用
import {
AndroidPlatformAdapter,
BedDeviceProfile,
createTemplateRuntime,
} from "@uneven/tpl-runtime";
const runtime = createTemplateRuntime({
container: document.querySelector("#template-root")!,
template: templateContent,
platformAdapter: new AndroidPlatformAdapter(fileUrlPrefix),
deviceProfile: new BedDeviceProfile(),
legacyAdapter: {
mount(template, container) {
// 交给 medical-device-v2 的 ParserV3 宿主组件。
mountExistingParserV3(template, container);
},
},
});
await runtime.mount();
runtime.updateDataBatch({
bedDeviceInfoVo: device.bedDeviceInfoVo,
bedSickInfoVo: device.bedSickInfoVo,
bedSickNursingLabelList: device.bedSickNursingLabelList,
});正式预览和设备运行默认不渲染 editor.hidden: true 的区域或子组件。设计器可传入
renderMode: 'design' 保留这些元素的 DOM;运行时会添加
data-device-hidden="true" 及对应 class,供宿主虚化显示并继续选择、编辑。
患者卡片元素使用可扩展的声明式 events,当前支持显示判断和患者详情动作;旧版
visible / action 字段仍可读取,但新配置应写入下列结构:
events: {
visibility: { when: 'notEmpty', path: 'sickName' },
click: {
action: 'patient.detail.open',
payload: { sourceId: 'patientList' },
},
}显示判断支持 empty、notEmpty、equals、notEquals、contains、
notContains、greaterThan、greaterOrEqual、lessThan 和 lessOrEqual。
patient.detail.open 由运行时使用当前卡片数据打开内置患者详情弹窗,并继续通过
onAction 和 tpl-runtime:action 通知宿主。
V3 兼容与宿主事件
运行时会识别旧模板的专用 ID,并通过 onAction 派发语义事件。弹窗、路由和 Android JSBridge 仍由宿主实现:
const runtime = createTemplateRuntime({
container,
template,
onAction(event) {
// swiper.next 已由运行时完成翻页,同时仍会通知宿主。
// 其余事件包括 do_nursing、do_reinforce、do_info、do_setup、
// loadBedMedicalWorkStation、bed.call、doctor.intro、nurse.intro、
// careLabel.open、food、allergy、guard 和 popupMenu。
handleTemplateAction(event);
},
legacy: {
medicalStationMode: false,
logoVersion: 3,
assets: {
"sip.error": "/offline/sip-error.png",
"network.error": "/offline/network-error.png",
"network.signal.4": "/offline/signal-4.png",
"logo.hospital": "/logo/hospital.png",
"logo.brand": "/logo/brand.png",
"avatar.doctor": "/offline/doctor.png",
"avatar.nurse": "/offline/nurse.png",
"careLabel.fallback": "/offline/care-label.png",
"bed.button6": "/offline/bed/button6.png",
"door.horizontal.button1": "/offline/door/button1.png",
},
},
});
runtime.updateData("__legacySystem", {
sipShow: true,
networkShow: false,
fourGShow: true,
strength: "4",
});V3 兼容层当前包括:sickInTime 日期截断、护理级别和门口机床位动态颜色、生日条件、输液状态、环境数据显示规则、Logo/网络/SIP/头像及按钮资源、Swiper、按钮事件、文本自适应/跑马灯/省略号、护理标签交互、fieldSlice 和旧节点 ID 清洗。系统图片及离线图片不内置医院项目资产,需由宿主通过 legacy.assets 提供。
旧模板字号单位
调用 parseTemplateAsTP4 时应传入模板对应的 systemType。迁移层会把历史无单位字号规范为显式单位:
| 来源 | Android / Harmony | Linux |
| --------------------------- | --------------------- | --------------------- |
| V1 / V2 fontSize | rem | px |
| V1 / V2 font | px | px |
| V3 extraProperty.fontSize | px | px |
| 原生 V4 | 保持原值,数字按 px | 保持原值,数字按 px |
显式 px、rem 等 CSS 单位始终优先。已保存但尚未规范化字号的 TP4 文档,会根据 meta.migratedFrom、meta.systemType 和 meta.rootFontSize 在渲染时兼容换算;该规则不根据“小数/整数”猜测版本。
medical-device-v2 接入
参考 examples/medical-device-v2.ts。推荐在现有 src/pages/home/index.tsx 外增加版本路由:TP4 挂载本包,旧 JSON 继续渲染 ParserV3。Pinia 只由宿主 Adapter 读取,本包不直接依赖设备 Store。
Android/Linux 的文件前缀、JSBridge、本地资源和交互差异放入 PlatformAdapter;床头机/门口机等数据整形和专用组件放入 DeviceProfile。
门口机的 HBedList 由 DoorDeviceProfile 注册。renderer 根据 bedDeviceList 的实际条数匹配 templateRules,并为每条床位数据建立独立绑定作用域后循环渲染。床位模板、数量区间和字段布局属于模板/设备能力,不得下沉到 PlatformAdapter。
护理看板由 WatchboardDeviceProfile 注册专用模块和患者网格 renderer。宿主在保存或加载 TP4 文档时可调用 normalizeWatchboardDocument(document):它只补齐跨端协议默认值、正式页/患者卡片编辑页角色和缺失的共享卡片,不负责识别管理端私有的旧 JSON。已经带有 watchboardPresetVersion 的展示配置和已有共享卡片不会被覆盖。
患者网格渲染 shared.patientCardTemplate 时,会强制将共享卡片根节点归一化为相对定位并铺满当前 Grid 单元格。共享根节点上的 left、top、百分比宽高仅作为设计器画布几何信息,设备端不得用它们参与重复卡片排版;根节点内部元素仍按卡片自身坐标系正常定位。
fileUrlPrefix 必须传设备当前的文件服务根地址,例如 http://host:9700/swp。模板中的 /swp_upload/... 和接口返回的相对图片地址都会通过该前缀解析;完整 HTTP、data、blob、file、content URL 会保持不变。
扩展组件
registry.register("whiteboard.module", whiteboardRenderer);
registry.registerLegacy("HVideo", videoRenderer);扩展设备类型时新增 DeviceProfile,扩展系统端时新增 PlatformAdapter,不要修改 Parser。
生命周期
设备页面卸载时必须调用 runtime.destroy(),释放 ResizeObserver、数据订阅和 Platform Adapter。
当前边界
- 当前内置基础组件、护理标签、白板模块、看板模块和患者卡片协议;医院私有组件仍通过插件注册。
- responsive 布局预留,当前 fixed 模式完整实现。
- transforms 结构已保留,业务变换函数可在后续版本注册。
