medical-form-printer 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.zh-CN.md CHANGED
@@ -4,39 +4,40 @@
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
  [![Node.js Version](https://img.shields.io/node/v/medical-form-printer.svg)](https://nodejs.org)
6
6
 
7
- 一个基于 Schema 驱动的医疗表单打印渲染库,将结构化表单数据转换为可打印的 HTML 和 PDF 文档。专为医疗健康应用设计,支持复杂布局、智能分页和跨环境一致性渲染。
7
+ 基于 Schema 驱动的医疗表单打印渲染库,将结构化表单数据转换为可打印的 HTML 和 PDF 文档。专为医疗健康应用设计,支持复杂布局、智能分页和跨环境一致性渲染。
8
8
 
9
9
  [English Documentation](./README.md)
10
10
 
11
+ ## 目录
12
+
13
+ - [特性](#特性)
14
+ - [安装](#安装)
15
+ - [快速开始](#快速开始)
16
+ - [设计理念](#设计理念)
17
+ - [区块类型](#区块类型)
18
+ - [API 参考](#api-参考)
19
+ - [CSS 隔离](#css-隔离)
20
+ - [示例](#示例)
21
+
11
22
  ## 特性
12
23
 
13
- - 🖨️ **双环境支持** - 同时支持浏览器和 Node.js 环境
14
- - 📄 **丰富的区块类型** - 信息网格、数据表格、复选框网格、签名区域、备注等
24
+ - 🖨️ **双环境支持** - 同时支持浏览器和 Node.js
25
+ - 📄 **丰富的区块类型** - 信息网格、数据表格、复选框网格、签名区域等
15
26
  - 🎨 **主题定制** - 完全可定制的字体、颜色、间距和尺寸
16
27
  - 📑 **PDF 生成** - 通过 Puppeteer 生成高保真 PDF(Node.js)
17
28
  - 🔗 **PDF 合并** - 将多个文档合并为单个 PDF
18
29
  - 📐 **智能分页** - 自动分页,支持表头重复和溢出处理
19
30
  - 🔒 **CSS 隔离** - 内嵌字体和命名空间样式,确保一致渲染
20
- - 🔌 **可扩展** - 注册自定义区块渲染器以支持特殊内容
31
+ - 🔌 **可扩展** - 注册自定义区块渲染器
21
32
  - 📦 **TypeScript 优先** - 完整的类型定义和 JSDoc 文档
22
33
 
23
34
  ## 安装
24
35
 
25
36
  ```bash
26
- # npm
27
37
  npm install medical-form-printer
28
-
29
- # yarn
30
- yarn add medical-form-printer
31
-
32
- # pnpm
33
- pnpm add medical-form-printer
34
-
35
- # bun
36
- bun add medical-form-printer
37
38
  ```
38
39
 
39
- 如需在 Node.js 中生成 PDF,请安装 Puppeteer 作为对等依赖:
40
+ 如需在 Node.js 中生成 PDF,请安装 Puppeteer
40
41
 
41
42
  ```bash
42
43
  npm install puppeteer
@@ -49,12 +50,11 @@ npm install puppeteer
49
50
  ```typescript
50
51
  import { renderToHtml } from 'medical-form-printer'
51
52
 
52
- const printSchema = {
53
+ const schema = {
53
54
  pageSize: 'A4',
54
55
  orientation: 'portrait',
55
56
  header: {
56
57
  hospital: '示例医院',
57
- department: '产后康复中心',
58
58
  title: '患者评估表',
59
59
  },
60
60
  sections: [
@@ -62,487 +62,370 @@ const printSchema = {
62
62
  type: 'info-grid',
63
63
  config: {
64
64
  columns: 4,
65
- rows: [
66
- {
67
- cells: [
68
- { label: '姓名', field: 'name', type: 'text' },
69
- { label: '年龄', field: 'age', type: 'number' },
70
- { label: '日期', field: 'admissionDate', type: 'date' },
71
- { label: '房间', field: 'roomNumber', type: 'text' },
72
- ]
73
- }
74
- ]
65
+ rows: [{
66
+ cells: [
67
+ { label: '姓名', field: 'name' },
68
+ { label: '年龄', field: 'age' },
69
+ { label: '日期', field: 'date', type: 'date' },
70
+ { label: '房间', field: 'room' },
71
+ ]
72
+ }]
75
73
  }
76
74
  }
77
- ],
78
- footer: {
79
- showPageNumber: true
80
- }
75
+ ]
81
76
  }
82
77
 
83
- const formData = {
84
- name: 'Jane Doe',
85
- age: 28,
86
- admissionDate: '2024-01-15',
87
- roomNumber: 'A-101'
88
- }
89
-
90
- // 渲染为 HTML
91
- const html = renderToHtml(printSchema, formData, {
92
- watermark: '内部使用'
93
- })
94
-
95
- // 显示在 iframe 或 div 中
96
- document.getElementById('preview').innerHTML = html
78
+ const data = { name: '张三', age: 28, date: '2024-01-15', room: 'A-101' }
79
+ const html = renderToHtml(schema, data)
97
80
  ```
98
81
 
99
- ### Node.js 使用(PDF 生成)
82
+ ### Node.js 使用(PDF
100
83
 
101
84
  ```typescript
102
- import { renderToPdf, mergePdfs } from 'medical-form-printer/node'
85
+ import { renderToPdf } from 'medical-form-printer/node'
103
86
  import fs from 'fs'
104
87
 
105
- // 生成单个 PDF
106
- const pdfBuffer = await renderToPdf(printSchema, formData, {
107
- watermark: '机密文件'
108
- })
109
- fs.writeFileSync('assessment.pdf', pdfBuffer)
110
-
111
- // 合并多个表单为一个 PDF
112
- const mergedPdf = await mergePdfs([
113
- { schema: maternalSchema, data: maternalData },
114
- { schema: newbornSchema, data: newbornData },
115
- ])
116
- fs.writeFileSync('complete-record.pdf', mergedPdf)
88
+ const pdfBuffer = await renderToPdf(schema, data)
89
+ fs.writeFileSync('form.pdf', pdfBuffer)
117
90
  ```
118
91
 
119
- ## API 参考
92
+ ## 设计理念
120
93
 
121
- ### 核心渲染
94
+ ### 为什么选择扁平的 Section 模型?
122
95
 
123
- #### `renderToHtml(schema, data, options?)`
124
-
125
- 将打印 Schema 和表单数据渲染为 HTML 字符串。
126
-
127
- ```typescript
128
- import { renderToHtml } from 'medical-form-printer'
96
+ 许多文档渲染系统使用深度嵌套的组件层级:
129
97
 
130
- const html = renderToHtml(printSchema, formData, {
131
- theme: customTheme,
132
- watermark: '草稿',
133
- watermarkOpacity: 0.1
134
- })
98
+ ```
99
+ Document → Page → Container → Row → Cell → Element
135
100
  ```
136
101
 
137
- **参数:**
138
- - `schema: PrintSchema` - 定义布局和区块的打印 Schema
139
- - `data: FormData` - 要渲染的表单数据
140
- - `options?: RenderOptions` - 可选的渲染配置
102
+ 我们刻意选择了**扁平的 section 模型**,原因如下:
141
103
 
142
- **返回:** `string` - 完整的 HTML 文档
104
+ #### 1. 打印文档 UI 组件
143
105
 
144
- #### `renderToIsolatedHtml(schema, data, options?)`
106
+ 打印文档是**静态输出**。医疗表单不需要响应点击的 `<Button>`——它只需要在正确位置渲染复选框符号(☑/□)。嵌套组件树带来的是额外开销而非收益。
145
107
 
146
- 使用 CSS 隔离模式渲染,确保跨环境样式一致性。
108
+ #### 2. 领域驱动设计
147
109
 
148
- ```typescript
149
- import { renderToIsolatedHtml } from 'medical-form-printer'
110
+ Section 直接映射到**真实的医疗表单概念**:
150
111
 
151
- const html = renderToIsolatedHtml(printSchema, formData, {
152
- watermark: '内部使用'
153
- })
154
- ```
112
+ | Section 类型 | 真实概念 |
113
+ |-------------|---------|
114
+ | `info-grid` | 患者基本信息区块 |
115
+ | `table` | 护理记录表格 |
116
+ | `checkbox-grid` | 症状检查清单 |
117
+ | `signature-area` | 审批签名区 |
155
118
 
156
- 所有内容都包装在隔离容器中,具有:
157
- - 命名空间 CSS 类(以 `mpr-` 为前缀)
158
- - 内嵌思源宋体字体
159
- - 样式隔离,确保可预测的渲染效果
119
+ 医护人员用这些术语思考,而不是抽象的"容器"和"元素"。
160
120
 
161
- #### `renderToIsolatedFragment(schema, data, options?)`
121
+ #### 3. 分页友好的架构
162
122
 
163
- 渲染隔离的 HTML 片段,用于嵌入现有页面。
123
+ 扁平的 section 使**分页计算可预测**:
164
124
 
165
125
  ```typescript
166
- import { renderToIsolatedFragment } from 'medical-form-printer'
167
-
168
- const fragment = renderToIsolatedFragment(printSchema, formData)
169
- document.getElementById('preview').innerHTML = fragment
126
+ type MeasurableItemType =
127
+ | 'header' // 页面头部 - 测量一次
128
+ | 'section' // 原子区块 - 不可拆分
129
+ | 'table-header' // 在续页重复显示
130
+ | 'table-row' // 可以单独分页
131
+ | 'signature' // 通常固定在最后一页
132
+ | 'footer' // 页面底部 - 测量一次
170
133
  ```
171
134
 
172
- ### PDF 生成(Node.js)
173
-
174
- #### `renderToPdf(schema, data, options?)`
175
-
176
- 从打印 Schema 生成 PDF 缓冲区。
135
+ #### 4. Schema 简洁性
177
136
 
178
137
  ```typescript
179
- import { renderToPdf } from 'medical-form-printer/node'
138
+ // 嵌套方式(冗长)
139
+ {
140
+ type: 'container',
141
+ children: [{
142
+ type: 'container',
143
+ children: [
144
+ { type: 'label', text: '姓名:' },
145
+ { type: 'field', binding: 'name' }
146
+ ]
147
+ }]
148
+ }
180
149
 
181
- const pdfBuffer = await renderToPdf(printSchema, formData, {
182
- watermark: '机密',
183
- pdfOptions: {
184
- format: 'A4',
185
- printBackground: true
150
+ // 扁平方式(简洁)
151
+ {
152
+ type: 'info-grid',
153
+ config: {
154
+ rows: [{ cells: [{ label: '姓名', field: 'name' }] }]
186
155
  }
187
- })
156
+ }
188
157
  ```
189
158
 
190
- **参数:**
191
- - `schema: PrintSchema` - 打印 Schema
192
- - `data: FormData` - 表单数据
193
- - `options?: RenderOptions & { pdfOptions?: PdfOptions }` - 渲染和 PDF 选项
194
-
195
- **返回:** `Promise<Buffer>` - PDF 文件缓冲区
196
-
197
- #### `mergePdfs(documents, options?)`
198
-
199
- 将多个文档合并为单个 PDF。
159
+ #### 5. 简单的可扩展性
200
160
 
201
161
  ```typescript
202
- import { mergePdfs } from 'medical-form-printer/node'
203
-
204
- const mergedPdf = await mergePdfs([
205
- { schema: schema1, data: data1 },
206
- { schema: schema2, data: data2 },
207
- ], {
208
- watermark: '完整记录'
162
+ registerSectionRenderer('vital-signs-chart', (config, data) => {
163
+ return '<div class="chart">...</div>'
209
164
  })
210
165
  ```
211
166
 
212
- ### 自定义区块渲染器
167
+ 无需抽象基类或访问者模式。
213
168
 
214
- #### `registerSectionRenderer(type, renderer)`
169
+ ### 权衡取舍
215
170
 
216
- 注册自定义区块渲染器以支持特殊内容。
171
+ 这个设计专门为**打印文档生成**优化。如需深度嵌套布局或交互式组件,请考虑通用 HTML 模板库或 UI 框架。
217
172
 
218
- ```typescript
219
- import { registerSectionRenderer } from 'medical-form-printer'
220
-
221
- registerSectionRenderer('vital-signs-chart', (config, data, options) => {
222
- const values = data[config.dataField] || []
223
- return `
224
- <div class="vital-signs-chart">
225
- <h3>${config.title}</h3>
226
- <!-- 自定义图表渲染 -->
227
- </div>
228
- `
229
- })
230
- ```
173
+ ## 区块类型
231
174
 
232
- #### `getSectionRenderer(type)`
175
+ | 类型 | 描述 | 使用场景 |
176
+ |------|------|----------|
177
+ | `info-grid` | 键值对网格布局 | 患者基本信息 |
178
+ | `table` | 带列的数据表格 | 护理记录 |
179
+ | `checkbox-grid` | 复选框选项网格 | 症状检查清单 |
180
+ | `signature-area` | 签名字段 | 审批签字 |
181
+ | `notes` | 静态文本内容 | 说明文字 |
182
+ | `free-text` | 多行文本输入 | 备注 |
233
183
 
234
- 获取已注册的区块渲染器。
184
+ ### 信息网格
235
185
 
236
186
  ```typescript
237
- import { getSectionRenderer } from 'medical-form-printer'
238
-
239
- const renderer = getSectionRenderer('info-grid')
187
+ {
188
+ type: 'info-grid',
189
+ config: {
190
+ columns: 4,
191
+ rows: [{
192
+ cells: [
193
+ { label: '姓名', field: 'name' },
194
+ { label: '年龄', field: 'age', type: 'number' },
195
+ { label: '状态', field: 'status', type: 'checkbox', options: ['在院'] }
196
+ ]
197
+ }]
198
+ }
199
+ }
240
200
  ```
241
201
 
242
- ### 分页
243
-
244
- #### `renderPaginatedHtml(config)`
245
-
246
- 使用智能分页渲染多页内容。
202
+ ### 表格
247
203
 
248
204
  ```typescript
249
- import {
250
- renderPaginatedHtml,
251
- calculatePageBreaks,
252
- PAGE_A4
253
- } from 'medical-form-printer'
205
+ {
206
+ type: 'table',
207
+ title: '护理记录',
208
+ config: {
209
+ dataField: 'records',
210
+ columns: [
211
+ { header: '日期', field: 'date', type: 'date', width: '20%' },
212
+ { header: '备注', field: 'notes' }
213
+ ]
214
+ }
215
+ }
216
+ ```
254
217
 
255
- const pageBreaks = calculatePageBreaks(measuredItems, {
256
- pageHeight: PAGE_A4.height,
257
- headerHeight: 60,
258
- footerHeight: 40,
259
- repeatTableHeaders: true
260
- })
218
+ #### 多行表头
219
+
220
+ 表格支持复杂的多行表头,可使用 colspan 和 rowspan 进行单元格合并:
261
221
 
262
- const html = renderPaginatedHtml({
263
- schema: printSchema,
264
- data: formData,
265
- pageBreakResult: pageBreaks,
266
- measuredItems: items,
222
+ ```typescript
223
+ {
224
+ type: 'table',
225
+ title: '生命体征',
267
226
  config: {
268
- isolated: true,
269
- showHeaderOnEachPage: true,
270
- continuationSuffix: '(续)'
227
+ dataField: 'vitalSigns',
228
+ columns: [
229
+ { header: '日期', field: 'date', type: 'date' },
230
+ { header: '收缩压', field: 'systolic', type: 'number' },
231
+ { header: '舒张压', field: 'diastolic', type: 'number' },
232
+ { header: '体温', field: 'temperature', type: 'number' },
233
+ ],
234
+ headerRows: [
235
+ {
236
+ cells: [
237
+ { text: '日期', rowspan: 2 },
238
+ { text: '血压 (mmHg)', colspan: 2 },
239
+ { text: '体温 (℃)', rowspan: 2 },
240
+ ]
241
+ },
242
+ {
243
+ cells: [
244
+ { text: '收缩压', field: 'systolic' },
245
+ { text: '舒张压', field: 'diastolic' },
246
+ ]
247
+ }
248
+ ]
271
249
  }
272
- })
250
+ }
273
251
  ```
274
252
 
275
- #### 页面尺寸预设
253
+ ### 复选框网格
276
254
 
277
255
  ```typescript
278
- import { PAGE_A4, PAGE_A5, PAGE_16K, PAGE_PRESETS } from 'medical-form-printer'
279
-
280
- // PAGE_A4: { width: 210, height: 297 } (mm)
281
- // PAGE_A5: { width: 148, height: 210 } (mm)
282
- // PAGE_16K: { width: 185, height: 260 } (mm)
256
+ {
257
+ type: 'checkbox-grid',
258
+ config: {
259
+ field: 'symptoms',
260
+ columns: 4,
261
+ options: [
262
+ { value: 'fever', label: '发热' },
263
+ { value: 'headache', label: '头痛' }
264
+ ]
265
+ }
266
+ }
283
267
  ```
284
268
 
285
- #### 单位转换
269
+ ### 签名区域
286
270
 
287
271
  ```typescript
288
- import { mmToPx, pxToMm, mmToPt, ptToMm } from 'medical-form-printer'
289
-
290
- const heightPx = mmToPx(297) // 297mm → 像素
291
- const heightMm = pxToMm(1123) // 像素 → mm
272
+ {
273
+ type: 'signature-area',
274
+ config: {
275
+ fields: [
276
+ { label: '患者签名', field: 'patientSig' },
277
+ { label: '日期', field: 'sigDate', type: 'date' }
278
+ ]
279
+ }
280
+ }
292
281
  ```
293
282
 
294
- ### 样式
283
+ ## API 参考
284
+
285
+ ### 核心渲染
295
286
 
296
- #### `generateCss(theme?)`
287
+ | 函数 | 描述 |
288
+ |------|------|
289
+ | `renderToHtml(schema, data, options?)` | 渲染为 HTML 字符串 |
290
+ | `renderToIsolatedHtml(schema, data, options?)` | 使用 CSS 隔离渲染 |
291
+ | `renderToIsolatedFragment(schema, data, options?)` | 渲染隔离片段用于嵌入 |
297
292
 
298
- 生成打印渲染的 CSS 样式。
293
+ ### PDF 生成(Node.js)
299
294
 
300
295
  ```typescript
301
- import { generateCss, defaultTheme } from 'medical-form-printer'
296
+ import { renderToPdf, mergePdfs } from 'medical-form-printer/node'
297
+
298
+ // 单个 PDF
299
+ const pdf = await renderToPdf(schema, data, { watermark: '草稿' })
302
300
 
303
- const css = generateCss(defaultTheme)
301
+ // 合并多个文档
302
+ const merged = await mergePdfs([
303
+ { schema: schema1, data: data1 },
304
+ { schema: schema2, data: data2 }
305
+ ])
304
306
  ```
305
307
 
306
- #### `generateIsolatedCss(theme?)`
308
+ ### 分页(策略模式)
307
309
 
308
- 生成带有内嵌字体和命名空间类的隔离 CSS。
310
+ ```typescript
311
+ import {
312
+ createDefaultPaginationContext,
313
+ SmartPaginationStrategy
314
+ } from 'medical-form-printer'
315
+
316
+ // 自动选择策略
317
+ const context = createDefaultPaginationContext()
318
+ const html = context.render(schema, data, { isolated: true })
319
+
320
+ // 或使用特定策略
321
+ const strategy = new SmartPaginationStrategy()
322
+ if (strategy.shouldApply(schema)) {
323
+ const html = strategy.render(schema, data)
324
+ }
325
+ ```
326
+
327
+ ### 自定义区块渲染器
309
328
 
310
329
  ```typescript
311
- import { generateIsolatedCss } from 'medical-form-printer'
330
+ import { registerSectionRenderer, getSectionRenderer } from 'medical-form-printer'
312
331
 
313
- const css = generateIsolatedCss()
314
- // 包含 @font-face、隔离容器和所有组件样式
332
+ registerSectionRenderer('custom-chart', (config, data, options) => {
333
+ return `<div class="chart">${config.title}</div>`
334
+ })
315
335
  ```
316
336
 
317
- #### 主题定制
337
+ ### 主题定制
318
338
 
319
339
  ```typescript
320
340
  import { renderToHtml, mergeTheme, defaultTheme } from 'medical-form-printer'
321
341
 
322
- const customTheme = mergeTheme(defaultTheme, {
323
- fonts: {
324
- body: '"Microsoft YaHei", "PingFang SC", sans-serif',
325
- heading: '"Microsoft YaHei", "PingFang SC", sans-serif'
326
- },
327
- colors: {
328
- primary: '#1a1a1a',
329
- border: '#333333',
330
- background: '#ffffff'
331
- },
332
- fontSize: {
333
- body: '10pt',
334
- heading: '14pt',
335
- small: '8pt'
336
- },
337
- spacing: {
338
- section: '12pt',
339
- cell: '4pt'
340
- }
342
+ const theme = mergeTheme(defaultTheme, {
343
+ colors: { primary: '#1a1a1a', border: '#333' },
344
+ fontSize: { body: '10pt', heading: '14pt' }
341
345
  })
342
346
 
343
- const html = renderToHtml(schema, data, { theme: customTheme })
347
+ const html = renderToHtml(schema, data, { theme })
348
+ ```
349
+
350
+ ### 页面尺寸与单位
351
+
352
+ ```typescript
353
+ import { PAGE_A4, PAGE_A5, PAGE_16K, mmToPx, pxToMm } from 'medical-form-printer'
354
+
355
+ // PAGE_A4: { width: 210, height: 297 } (mm)
356
+ const heightPx = mmToPx(297) // mm → 像素
344
357
  ```
345
358
 
346
359
  ### 格式化工具
347
360
 
348
361
  ```typescript
349
- import {
350
- formatDate,
351
- formatBoolean,
352
- formatNumber,
353
- formatValue,
354
- isChecked
355
- } from 'medical-form-printer'
362
+ import { formatDate, formatBoolean, formatNumber } from 'medical-form-printer'
356
363
 
357
- formatDate('2024-01-15') // '2024-01-15'
364
+ formatDate('2024-01-15') // '2024-01-15'
358
365
  formatDate('2024-01-15', { format: 'YYYY年MM月DD日' }) // '2024年01月15日'
359
- formatBoolean(true) // '✓'
360
- formatBoolean(false) // ''
361
- formatNumber(1234.5, { decimals: 2 }) // '1234.50'
362
- isChecked('yes', ['yes', 'true']) // true
366
+ formatBoolean(true) // '✓'
367
+ formatNumber(1234.5, { decimals: 2 }) // '1234.50'
363
368
  ```
364
369
 
365
- ### HTML 构建工具
370
+ ## CSS 隔离
366
371
 
367
- ```typescript
368
- import {
369
- HtmlBuilder,
370
- h,
371
- fragment,
372
- when,
373
- each,
374
- escapeHtml
375
- } from 'medical-form-printer'
372
+ 确保跨环境一致渲染:
376
373
 
377
- // 流式 HTML 构建
378
- const html = h('div', { class: 'container' },
379
- h('h1', {}, '标题'),
380
- when(showContent, () => h('p', {}, '内容')),
381
- each(items, (item) => h('li', {}, item.name))
382
- )
374
+ ```typescript
375
+ import { renderToIsolatedHtml, CSS_NAMESPACE } from 'medical-form-printer'
383
376
 
384
- // 安全的 HTML 转义
385
- const safe = escapeHtml('<script>alert("xss")</script>')
377
+ const html = renderToIsolatedHtml(schema, data)
378
+ // CSS_NAMESPACE = 'mpr'(所有类以 mpr- 为前缀)
386
379
  ```
387
380
 
381
+ 隔离模式提供:
382
+ - 命名空间 CSS 类(`mpr-` 前缀)
383
+ - 内嵌思源宋体字体
384
+ - CSS 隔离确保可预测渲染
385
+
388
386
  ## PrintSchema 结构
389
387
 
390
388
  ```typescript
391
389
  interface PrintSchema {
392
390
  pageSize: 'A4' | 'A5' | '16K'
393
391
  orientation: 'portrait' | 'landscape'
392
+ baseUnit?: number // 缩放因子(默认: 1)
394
393
  header: {
395
394
  hospital: string
396
395
  department?: string
397
396
  title: string
398
- subtitle?: string
399
397
  }
400
398
  sections: PrintSection[]
401
399
  footer?: {
402
400
  showPageNumber?: boolean
403
- pageNumberFormat?: string
404
401
  notes?: string
405
402
  }
406
403
  }
407
404
  ```
408
405
 
409
- ## 区块类型
410
-
411
- | 类型 | 描述 | 使用场景 |
412
- |------|------|----------|
413
- | `info-grid` | 键值对网格布局 | 患者基本信息、人口统计 |
414
- | `table` | 带列的数据表格 | 护理记录、用药日志 |
415
- | `checkbox-grid` | 复选框选项网格 | 评估清单、症状选择 |
416
- | `signature-area` | 带标签的签名字段 | 审批、确认签字 |
417
- | `notes` | 静态文本内容 | 说明、免责声明 |
418
- | `free-text` | 多行文本输入 | 备注、观察记录 |
419
-
420
- ### 信息网格区块
421
-
422
- ```typescript
423
- {
424
- type: 'info-grid',
425
- config: {
426
- columns: 4,
427
- rows: [
428
- {
429
- cells: [
430
- { label: '姓名', field: 'name', type: 'text' },
431
- { label: '年龄', field: 'age', type: 'number', span: 1 },
432
- { label: '日期', field: 'date', type: 'date' },
433
- { label: '状态', field: 'status', type: 'checkbox', options: ['在院'] }
434
- ]
435
- }
436
- ]
437
- }
438
- }
439
- ```
440
-
441
- ### 表格区块
442
-
443
- ```typescript
444
- {
445
- type: 'table',
446
- title: '护理记录',
447
- config: {
448
- dataField: 'nursingRecords',
449
- columns: [
450
- { header: '日期', field: 'date', type: 'date', width: '15%' },
451
- { header: '时间', field: 'time', type: 'text', width: '10%' },
452
- { header: '体温', field: 'temperature', type: 'number', width: '15%' },
453
- { header: '备注', field: 'notes', type: 'text' }
454
- ]
455
- }
456
- }
457
- ```
458
-
459
- ### 复选框网格区块
460
-
461
- ```typescript
462
- {
463
- type: 'checkbox-grid',
464
- title: '症状评估',
465
- config: {
466
- field: 'symptoms',
467
- columns: 4,
468
- options: [
469
- { value: 'fever', label: '发热' },
470
- { value: 'headache', label: '头痛' },
471
- { value: 'fatigue', label: '乏力' },
472
- { value: 'nausea', label: '恶心' }
473
- ]
474
- }
475
- }
476
- ```
477
-
478
- ### 签名区域区块
479
-
480
- ```typescript
481
- {
482
- type: 'signature-area',
483
- config: {
484
- fields: [
485
- { label: '患者签名', field: 'patientSignature' },
486
- { label: '护士签名', field: 'nurseSignature' },
487
- { label: '日期', field: 'signatureDate', type: 'date' }
488
- ]
489
- }
490
- }
491
- ```
492
-
493
- ## CSS 隔离
494
-
495
- 为确保跨环境一致渲染,请使用隔离模式:
496
-
497
- ```typescript
498
- import {
499
- renderToIsolatedHtml,
500
- CSS_NAMESPACE,
501
- ISOLATION_ROOT_CLASS,
502
- namespaceClass,
503
- namespaceClasses
504
- } from 'medical-form-printer'
505
-
506
- // CSS_NAMESPACE = 'mpr'
507
- // ISOLATION_ROOT_CLASS = 'mpr-root'
508
-
509
- // 命名空间工具
510
- namespaceClass('header') // 'mpr-header'
511
- namespaceClasses(['header', 'footer']) // ['mpr-header', 'mpr-footer']
512
- ```
513
-
514
- 隔离模式提供:
515
- - 所有类以 `mpr-` 命名空间为前缀
516
- - 内嵌思源宋体字体(CJK 字符子集)
517
- - CSS 隔离(`contain: layout style`)
518
- - 无论宿主页面样式如何,都能保持一致渲染
519
-
520
406
  ## 示例
521
407
 
522
- 请参阅 [examples](./examples) 目录获取完整的工作示例:
408
+ 参见 [examples](./examples) 目录:
523
409
 
524
- - [浏览器示例](./examples/browser) - 原生 HTML/JS 使用
525
- - [Node.js 示例](./examples/node) - PDF 生成与文件输出
410
+ - [浏览器示例](./examples/browser) - 原生 HTML/JS
411
+ - [Node.js 示例](./examples/node) - PDF 生成
526
412
 
527
413
  ## Storybook
528
414
 
529
- 通过 Storybook 可以查看交互式组件文档:
530
-
531
415
  ```bash
532
416
  npm run storybook
533
417
  ```
534
418
 
535
419
  ## 贡献
536
420
 
537
- 欢迎贡献!请阅读我们的[贡献指南](./CONTRIBUTING.md)了解行为准则和提交 Pull Request 的流程。
421
+ 参见 [CONTRIBUTING.md](./CONTRIBUTING.md)
538
422
 
539
423
  ## 许可证
540
424
 
541
- [MIT](./LICENSE) © 2024
425
+ [MIT](./LICENSE)
542
426
 
543
427
  ## 链接
544
428
 
545
- - [GitHub 仓库](https://github.com/wangchengshi-ship-it/medical-form-printer)
546
- - [npm](https://www.npmjs.com/package/medical-form-printer)
547
- - [问题追踪](https://github.com/wangchengshi-ship-it/medical-form-printer/issues)
429
+ - [GitHub](https://github.com/wangchengshi-ship-it/medical-form-printer)
430
+ - [npm](https://www.npmjs.com/package/medical-form-printer)
548
431
  - [更新日志](./CHANGELOG.md)