@hailin-zheng/editor-core 1.1.17 → 1.1.19

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/index-cjs.js CHANGED
@@ -8,6 +8,7 @@ var acor = require('acorn');
8
8
  var astring = require('astring');
9
9
  var estraverse = require('estraverse');
10
10
  var bwipjs = require('bwip-js');
11
+ var moment$1 = require('moment/moment');
11
12
 
12
13
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
13
14
 
@@ -33,6 +34,7 @@ var moment__default = /*#__PURE__*/_interopDefaultLegacy(moment);
33
34
  var acor__namespace = /*#__PURE__*/_interopNamespace(acor);
34
35
  var estraverse__namespace = /*#__PURE__*/_interopNamespace(estraverse);
35
36
  var bwipjs__default = /*#__PURE__*/_interopDefaultLegacy(bwipjs);
37
+ var moment__default$1 = /*#__PURE__*/_interopDefaultLegacy(moment$1);
36
38
 
37
39
  /**
38
40
  * 元素事件
@@ -78,6 +80,9 @@ class ContentMenuItem {
78
80
  */
79
81
  class MouseElementEvent extends ElementEvent {
80
82
  }
83
+ class InputElementEvent extends ElementEvent {
84
+ data;
85
+ }
81
86
  class MousedownElementEvent extends ElementEvent {
82
87
  }
83
88
  class KeyboradElementEvent extends ElementEvent {
@@ -1466,7 +1471,7 @@ class ViewOptions {
1466
1471
  viewBackcolor = 'rgb(230,230,230)';
1467
1472
  paraSymbolColor = 'rgb(128,128,128)';
1468
1473
  dataGroupColor = 'rgb(0,80,179)';
1469
- defaultLineHeight = 1.5;
1474
+ defaultLineHeight = 1;
1470
1475
  //新增-留痕块文本颜色
1471
1476
  trackInsColor = '#ff4d4f';
1472
1477
  //删除-留痕块文本颜色
@@ -1801,7 +1806,7 @@ class ParagraphProps extends INotifyPropertyChanged {
1801
1806
  //textProps!: TextProps;
1802
1807
  indent = 0;
1803
1808
  hanging = 0;
1804
- lineHeight = 1.5;
1809
+ lineHeight = 1;
1805
1810
  textAlign = 'left';
1806
1811
  numberType = exports.ParagraphNumberType.none;
1807
1812
  //段前距
@@ -1901,6 +1906,8 @@ class CheckBoxProps extends INotifyPropertyChanged {
1901
1906
  isChecked;
1902
1907
  //用于复选框分组
1903
1908
  groupName;
1909
+ trueChar = '√';
1910
+ falseChar = '×';
1904
1911
  clone(dest) {
1905
1912
  const clone = dest ?? new CheckBoxProps();
1906
1913
  super.cloneAttachedProperty(clone);
@@ -2076,7 +2083,6 @@ class DataEleBaseProps extends INotifyPropertyChanged {
2076
2083
  editable;
2077
2084
  deleteable;
2078
2085
  minLength;
2079
- type;
2080
2086
  underline;
2081
2087
  expression;
2082
2088
  hidden;
@@ -2095,7 +2101,6 @@ class DataEleBaseProps extends INotifyPropertyChanged {
2095
2101
  target.secretBrowse = source.secretBrowse;
2096
2102
  target.printable = source.printable;
2097
2103
  target.minLength = source.minLength;
2098
- target.type = source.type;
2099
2104
  target.underline = source.underline;
2100
2105
  target.expression = source.expression;
2101
2106
  target.hidden = source.hidden;
@@ -2107,7 +2112,6 @@ class DataEleBaseProps extends INotifyPropertyChanged {
2107
2112
  props["id"] = this.id;
2108
2113
  props["name"] = this.name;
2109
2114
  props["fieldName"] = this.fieldName;
2110
- props["type"] = this.type;
2111
2115
  if (this.caption) {
2112
2116
  props["caption"] = this.caption;
2113
2117
  }
@@ -2147,7 +2151,6 @@ class DataEleBaseProps extends INotifyPropertyChanged {
2147
2151
  class DataEleBaseTextProps extends DataEleBaseProps {
2148
2152
  constructor() {
2149
2153
  super();
2150
- super.type = 'text';
2151
2154
  }
2152
2155
  valueTextProps;
2153
2156
  nullText;
@@ -2163,7 +2166,6 @@ class DataEleBaseTextProps extends DataEleBaseProps {
2163
2166
  }
2164
2167
  getSerializeProps(options) {
2165
2168
  const props = {
2166
- type: this.type,
2167
2169
  valueTextProps: this.valueTextProps.getSerializeProps(options),
2168
2170
  nullText: this.nullText,
2169
2171
  nullTextProps: this.nullTextProps.getSerializeProps(options)
@@ -2193,7 +2195,6 @@ class DataEleBaseTextProps extends DataEleBaseProps {
2193
2195
  class DataEleListProps extends DataEleBaseTextProps {
2194
2196
  constructor() {
2195
2197
  super();
2196
- super.type = 'droplist';
2197
2198
  }
2198
2199
  options = [];
2199
2200
  dropDownStyle;
@@ -2259,16 +2260,23 @@ class CommProps extends INotifyPropertyChanged {
2259
2260
  };
2260
2261
  }
2261
2262
  }
2263
+ const trueChar = '✓';
2264
+ const falseChar = '×';
2262
2265
  class DataEleCheckProps extends DataEleBaseProps {
2263
2266
  constructor() {
2264
2267
  super();
2265
- super.type = 'check';
2266
2268
  }
2269
+ border = true;
2267
2270
  size;
2268
2271
  checked;
2269
2272
  checkedValue = '';
2270
2273
  groupName;
2271
2274
  multiSelect = false;
2275
+ drawStateChar = false;
2276
+ trueChar = trueChar;
2277
+ falseChar = falseChar;
2278
+ trueStateColor = '#f00000';
2279
+ falseStateColor = '#000000';
2272
2280
  clone(dest) {
2273
2281
  const clone = dest ?? new DataEleCheckProps();
2274
2282
  super.cloneBaseProps(clone);
@@ -2277,6 +2285,12 @@ class DataEleCheckProps extends DataEleBaseProps {
2277
2285
  clone.groupName = this.groupName;
2278
2286
  clone.multiSelect = this.multiSelect;
2279
2287
  clone.checkedValue = this.checkedValue;
2288
+ clone.drawStateChar = this.drawStateChar;
2289
+ clone.trueChar = this.trueChar;
2290
+ clone.falseChar = this.falseChar;
2291
+ clone.border = this.border;
2292
+ clone.trueStateColor = this.trueStateColor;
2293
+ clone.falseStateColor = this.falseStateColor;
2280
2294
  return clone;
2281
2295
  }
2282
2296
  getSerializeProps(options) {
@@ -2285,8 +2299,26 @@ class DataEleCheckProps extends DataEleBaseProps {
2285
2299
  size: this.size,
2286
2300
  groupName: this.groupName,
2287
2301
  multiSelect: this.multiSelect,
2288
- checkedValue: this.checkedValue
2302
+ checkedValue: this.checkedValue,
2289
2303
  };
2304
+ if (this.drawStateChar) {
2305
+ props.drawStateChar = this.drawStateChar;
2306
+ }
2307
+ if (this.trueChar !== trueChar) {
2308
+ props.trueChar = this.trueChar;
2309
+ }
2310
+ if (this.falseChar !== falseChar) {
2311
+ props.falseChar = this.falseChar;
2312
+ }
2313
+ if (this.border) {
2314
+ props.border = this.border;
2315
+ }
2316
+ if (this.trueStateColor !== '#f00000') {
2317
+ props.trueStateColor = this.trueStateColor;
2318
+ }
2319
+ if (this.falseStateColor !== '#000000') {
2320
+ props.falseStateColor = this.falseStateColor;
2321
+ }
2290
2322
  this.getBaseProps(props, options);
2291
2323
  return props;
2292
2324
  }
@@ -2297,12 +2329,17 @@ class DataEleCheckProps extends DataEleBaseProps {
2297
2329
  this.groupName = props.groupName;
2298
2330
  this.multiSelect = props.multiSelect;
2299
2331
  this.checkedValue = props.checkedValue;
2332
+ this.drawStateChar = props.drawStateChar;
2333
+ this.trueChar = props.trueChar;
2334
+ this.falseChar = props.falseChar;
2335
+ this.trueStateColor = props.trueStateColor;
2336
+ this.falseStateColor = props.falseStateColor;
2337
+ this.border = props.border;
2300
2338
  }
2301
2339
  }
2302
2340
  class DataEleImageProps extends DataEleBaseProps {
2303
2341
  constructor() {
2304
2342
  super();
2305
- super.type = 'img';
2306
2343
  }
2307
2344
  width;
2308
2345
  height;
@@ -2336,10 +2373,6 @@ class DataEleImageProps extends DataEleBaseProps {
2336
2373
  }
2337
2374
  }
2338
2375
  class DataEleDateProps extends DataEleBaseTextProps {
2339
- constructor() {
2340
- super();
2341
- super.type = 'date';
2342
- }
2343
2376
  minValue;
2344
2377
  maxValue;
2345
2378
  format;
@@ -3166,7 +3199,7 @@ class DataElementRenderObject extends InlineGroupRenderObject {
3166
3199
  bgColor = viewOptions.dataEleErrorBgColor;
3167
3200
  }
3168
3201
  if (bgColor) {
3169
- render.overlaysContext.fillRect(position.x, position.y - 2, this.rect.width, this.rect.height + 4, bgColor);
3202
+ render.overlaysContext.fillRect(position.x, position.y, this.rect.width, this.rect.height, bgColor);
3170
3203
  }
3171
3204
  if (this.element.props.secretBrowse && viewOptions.secretBrowse) {
3172
3205
  render.contentContext.ctx.filter = "blur(10px)";
@@ -3203,7 +3236,7 @@ class DataElementRenderObject extends InlineGroupRenderObject {
3203
3236
  textProps.fontSize = 16;
3204
3237
  textProps.fontName = viewOptions.defaultFontName;
3205
3238
  textProps.color = '#fff';
3206
- const titleWidth = render.contentContext.measureText2(caption, textProps);
3239
+ const titleWidth = render.contentContext.measureTextWidth(caption, textProps);
3207
3240
  const x = position.x;
3208
3241
  const y = position.y - 20;
3209
3242
  render.contentContext.fillRect(x, y, titleWidth + 10, 20, 'blue');
@@ -4086,8 +4119,8 @@ class DocumentContainerRender extends BlockContainerRenderObject {
4086
4119
  }
4087
4120
 
4088
4121
  class TextGroupElement extends LeafElement {
4089
- //props: TextProps;
4090
4122
  textMeasures = [];
4123
+ fontBoundingBox;
4091
4124
  isMeasure = false;
4092
4125
  constructor() {
4093
4126
  super('text');
@@ -4127,6 +4160,7 @@ class TextGroupElement extends LeafElement {
4127
4160
  createRenderObject(data) {
4128
4161
  if (!this.isMeasure || this.modifyFlag !== exports.ModifyFlag.None || !this.cacheRender) {
4129
4162
  data.renderCtx.contentContext.measureTextUnits(this.textMeasures, this.props);
4163
+ this.fontBoundingBox = data.renderCtx.contentContext.measureTextMetrics(this.props.getFont());
4130
4164
  this.isMeasure = true;
4131
4165
  }
4132
4166
  const render = new TextGroupRenderObject(this);
@@ -4200,10 +4234,7 @@ class TextGroupRenderObject extends LeafRenderObject {
4200
4234
  if (this.element.props.border) {
4201
4235
  render.contentContext.strokeRect(position.x, position.y, this.rect.width, this.rect.height);
4202
4236
  }
4203
- render.contentContext.drawTextUnits(this, position.x, position.y);
4204
- // if (this.element.isMouseenter) {
4205
- // ctx.overlaysContext.strokeRect(position.x, position.y, this.rect.width, this.rect.height, CommonUtil.randomColor());
4206
- // }
4237
+ render.contentContext.drawTextUnits(this, position.x, position.y, this.element.fontBoundingBox.fontBoundingBoxAscent);
4207
4238
  }
4208
4239
  constructor(element) {
4209
4240
  super(element);
@@ -4222,7 +4253,7 @@ class TextGroupRenderObject extends LeafRenderObject {
4222
4253
  }
4223
4254
  measure() {
4224
4255
  this.rect.width = this.textMeasures.reduce((prev, curr) => prev + curr.actualSize, 0);
4225
- this.rect.height = this.element.props.fontSize;
4256
+ this.rect.height = this.element.fontBoundingBox.fontBoundingBoxAscent + this.element.fontBoundingBox.fontBoundingBoxDescent;
4226
4257
  }
4227
4258
  }
4228
4259
  class TextGroupFactory extends ElementFactory {
@@ -4411,6 +4442,10 @@ class SelectionState {
4411
4442
  constructor() {
4412
4443
  this.clear();
4413
4444
  }
4445
+ destroy() {
4446
+ this.onChangedEvent.unsubscribe();
4447
+ this.clear();
4448
+ }
4414
4449
  clear() {
4415
4450
  this.range = null;
4416
4451
  this.startOffset = -1;
@@ -5619,10 +5654,15 @@ class TableUtil {
5619
5654
  }
5620
5655
  const remainWidth = tbWidth - sum;
5621
5656
  const ratio = remainWidth / percentSum;
5657
+ let count = 0;
5622
5658
  for (let i = 0; i < percentCols.length; i++) {
5623
5659
  const width = percentCols[i];
5624
5660
  if (typeof width === 'string') {
5625
5661
  percentCols[i] = Math.floor(Number.parseFloat(width) * ratio);
5662
+ if (i === percentCols.length - 1) {
5663
+ percentCols[i] = remainWidth - count;
5664
+ }
5665
+ count += percentCols[i];
5626
5666
  }
5627
5667
  }
5628
5668
  return percentCols;
@@ -6266,7 +6306,6 @@ class ElementUtil {
6266
6306
  dest.secretBrowse = props.secretBrowse;
6267
6307
  dest.deleteable = props.deleteable;
6268
6308
  dest.underline = props.underline;
6269
- dest.type = props.type;
6270
6309
  dest.expression = props.expression;
6271
6310
  dest.hidden = props.hidden;
6272
6311
  return dest;
@@ -6337,9 +6376,9 @@ class ElementUtil {
6337
6376
  }
6338
6377
  static remeasureTableRow(rowRender, foreceColIndex = -1) {
6339
6378
  const rowEle = rowRender.element;
6340
- let maxCellHeight = rowEle.props.minHeight > 19 ? rowEle.props.minHeight : 19;
6379
+ let maxCellHeight = rowEle.props.minHeight > 20 ? rowEle.props.minHeight : 20;
6341
6380
  //限制行最小高度
6342
- maxCellHeight = maxCellHeight < 19 ? 19 : maxCellHeight;
6381
+ maxCellHeight = maxCellHeight < 20 ? 20 : maxCellHeight;
6343
6382
  //获取行内非纵向合并单元格的最高单元格高度
6344
6383
  for (let i = 0; i < rowRender.length; i++) {
6345
6384
  const cellRender = rowRender.getChild(i);
@@ -7685,6 +7724,19 @@ class ElementUtil {
7685
7724
  static getDataElement(ele) {
7686
7725
  return this.getParent(ele, item => item instanceof DataElementInlineGroup);
7687
7726
  }
7727
+ static getOSPlatform() {
7728
+ const userAgent = navigator.userAgent;
7729
+ if (userAgent.indexOf('Windows') > -1) {
7730
+ return 'Windows';
7731
+ }
7732
+ if (userAgent.indexOf('Mac') > -1) {
7733
+ return 'Mac';
7734
+ }
7735
+ if (userAgent.indexOf('Linux') > -1) {
7736
+ return 'Linux';
7737
+ }
7738
+ return 'Windows';
7739
+ }
7688
7740
  }
7689
7741
 
7690
7742
  class RenderContext {
@@ -7799,7 +7851,7 @@ class PaintContent {
7799
7851
  this.ctx.fill();
7800
7852
  this.ctx.restore();
7801
7853
  }
7802
- drawTextUnits(textGroupRender, x, y) {
7854
+ drawTextUnits(textGroupRender, x, y, baseLine) {
7803
7855
  const textEle = textGroupRender.element;
7804
7856
  const textProps = textEle.props;
7805
7857
  const { width, height } = textGroupRender.rect;
@@ -7822,12 +7874,10 @@ class PaintContent {
7822
7874
  this.drawHoriLine(x, y, width, textProps.color, 1);
7823
7875
  }
7824
7876
  let horX = 0;
7825
- let vertHeight = height - (height / 7);
7877
+ let vertHeight = baseLine;
7826
7878
  if (textProps.vertAlign === 'superscript') {
7827
7879
  //到top
7828
7880
  vertHeight -= textProps.fontSize * 2 / 5;
7829
- //top在向上收缩 -top行间距
7830
- //vertHeight -= textProps.fontSize * this.getParaLineHeight(textEle) / 20
7831
7881
  }
7832
7882
  for (let i = 0; i < textGroupRender.textMeasures.length; i++) {
7833
7883
  const unit = textGroupRender.textMeasures[i];
@@ -7836,6 +7886,15 @@ class PaintContent {
7836
7886
  }
7837
7887
  this.ctx.restore();
7838
7888
  }
7889
+ drawText2(str, font, color, x, y, width, height) {
7890
+ const textMetrics = this.measureTextMetrics(font, str);
7891
+ this.ctx.save();
7892
+ this.ctx.fillStyle = color;
7893
+ this.ctx.font = font;
7894
+ let vertHeight = textMetrics.actualBoundingBoxAscent;
7895
+ this.ctx.fillText(str, x + (width - (textMetrics.actualBoundingBoxLeft + textMetrics.actualBoundingBoxRight)) / 2 - textMetrics.actualBoundingBoxLeft, y + vertHeight + (height - (textMetrics.actualBoundingBoxAscent + textMetrics.actualBoundingBoxDescent)) / 2);
7896
+ this.ctx.restore();
7897
+ }
7839
7898
  getParaLineHeight(textEle) {
7840
7899
  const para = ElementUtil.getParentByType(textEle, ParagraphElement);
7841
7900
  if (!para) {
@@ -7846,10 +7905,23 @@ class PaintContent {
7846
7905
  measureText(text, textProps) {
7847
7906
  this.ctx.fillStyle = textProps.color;
7848
7907
  this.ctx.font = textProps.getFont();
7849
- const textMeasure = this.ctx.measureText(text);
7850
- return { width: textMeasure.width, height: textProps.fontSize };
7908
+ const { width, fontBoundingBoxDescent, fontBoundingBoxAscent } = this.ctx.measureText(text);
7909
+ return { width: width, height: fontBoundingBoxAscent + fontBoundingBoxDescent };
7851
7910
  }
7852
- measureText2(text, font) {
7911
+ measureTextMetrics(font, str = 'M') {
7912
+ this.ctx.font = font;
7913
+ const textMetrics = this.ctx.measureText(str);
7914
+ return {
7915
+ fontBoundingBoxAscent: textMetrics.fontBoundingBoxAscent,
7916
+ fontBoundingBoxDescent: textMetrics.fontBoundingBoxDescent,
7917
+ actualBoundingBoxAscent: textMetrics.actualBoundingBoxAscent,
7918
+ actualBoundingBoxDescent: textMetrics.actualBoundingBoxDescent,
7919
+ actualBoundingBoxLeft: textMetrics.actualBoundingBoxLeft,
7920
+ actualBoundingBoxRight: textMetrics.actualBoundingBoxRight,
7921
+ width: textMetrics.width
7922
+ };
7923
+ }
7924
+ measureTextWidth(text, font) {
7853
7925
  this.ctx.font = font.fontSize + 'px ' + font.fontName;
7854
7926
  return this.ctx.measureText(text).width;
7855
7927
  }
@@ -8684,11 +8756,22 @@ class DataElementCheckRenderObject extends LeafRenderObject {
8684
8756
  render(e) {
8685
8757
  const { render, position } = e;
8686
8758
  const element = this.element;
8687
- if (this.element.props.multiSelect) {
8688
- render.contentContext.drawCheckBox(position.x + 2, position.y, element.props.size, element.props.size, element.props.checked);
8759
+ if (element.props.drawStateChar) {
8760
+ const font = `${element.props.size - 2}px 微软雅黑`;
8761
+ const str = element.props.checked ? element.props.trueChar : element.props.falseChar;
8762
+ const color = element.props.checked ? element.props.trueStateColor : element.props.falseStateColor;
8763
+ e.render.contentContext.drawText2(str, font, color, position.x, position.y, element.props.size, element.props.size);
8764
+ if (element.props.border) {
8765
+ e.render.contentContext.strokeRect(position.x + 2, position.y, element.props.size, element.props.size);
8766
+ }
8689
8767
  }
8690
8768
  else {
8691
- render.contentContext.drawRadioBox(position.x + 2, position.y, element.props.size, element.props.size, element.props.checked);
8769
+ if (element.props.multiSelect) {
8770
+ render.contentContext.drawCheckBox(position.x + 2, position.y, element.props.size, element.props.size, element.props.checked);
8771
+ }
8772
+ else {
8773
+ render.contentContext.drawRadioBox(position.x + 2, position.y, element.props.size, element.props.size, element.props.checked);
8774
+ }
8692
8775
  }
8693
8776
  }
8694
8777
  }
@@ -8705,15 +8788,15 @@ class DataElementCheckFactory extends ElementFactory {
8705
8788
  createDataEleProps(dest, props) {
8706
8789
  const dataEleProps = dest;
8707
8790
  ElementUtil.readEleBaseProps(dataEleProps, props);
8708
- //dataEleProps.id = props.id ?? nanoid(5);
8709
- //dataEleProps.name = props.name;
8710
- //dataEleProps.caption = props.caption;
8711
- //dataEleProps.type = props.type;
8712
8791
  dataEleProps.checked = props.checked;
8713
8792
  dataEleProps.size = props.size;
8714
8793
  dataEleProps.groupName = props.groupName;
8715
8794
  dataEleProps.multiSelect = props.multiSelect ?? false;
8716
8795
  dataEleProps.checkedValue = props.checkedValue;
8796
+ dataEleProps.drawStateChar = props.drawStateChar ?? false;
8797
+ dataEleProps.trueChar = props.trueChar ?? trueChar;
8798
+ dataEleProps.falseChar = props.falseChar ?? falseChar;
8799
+ dataEleProps.border = props.border ?? true;
8717
8800
  return dataEleProps;
8718
8801
  }
8719
8802
  }
@@ -11345,6 +11428,7 @@ class ParagraphMeasure {
11345
11428
  }
11346
11429
  },
11347
11430
  parent: null,
11431
+ isCloseToBody,
11348
11432
  applyNewLine() {
11349
11433
  createInnerLineFunc();
11350
11434
  },
@@ -11530,6 +11614,7 @@ class ParagraphMeasure {
11530
11614
  parentLine.updateHeight(child);
11531
11615
  },
11532
11616
  parent: parentLine,
11617
+ isCloseToBody: parentLine.isCloseToBody,
11533
11618
  applyNewLine() {
11534
11619
  parentLine.applyNewLine();
11535
11620
  render = ele.createRenderObject({ options, renderCtx });
@@ -11591,7 +11676,7 @@ class ParagraphMeasure {
11591
11676
  arrangeLeafRender(parentLine, render) {
11592
11677
  if (parentLine.lineWidth() + render.rect.width > parentLine.limitWidth) {
11593
11678
  if (render instanceof TextGroupRenderObject) {
11594
- const { firstItem, lastItem } = this.cutTextRender(render, parentLine.limitWidth - parentLine.lineWidth(), parentLine.lineWidth() === 0);
11679
+ const { firstItem, lastItem } = this.cutTextRender(render, parentLine.limitWidth - parentLine.lineWidth(), parentLine.lineWidth() === 0, parentLine.isCloseToBody);
11595
11680
  if (firstItem) {
11596
11681
  parentLine.add(firstItem);
11597
11682
  }
@@ -11599,6 +11684,10 @@ class ParagraphMeasure {
11599
11684
  parentLine.applyNewLine();
11600
11685
  this.arrangeLeafRender(parentLine, lastItem);
11601
11686
  }
11687
+ if (!firstItem && !lastItem) {
11688
+ parentLine.applyNewLine();
11689
+ this.arrangeLeafRender(parentLine, render);
11690
+ }
11602
11691
  }
11603
11692
  else if (render instanceof FillNullSpaceRenderObject) {
11604
11693
  const { firstItem, lastItem } = this.cutFillNullRender(render, parentLine.limitWidth - parentLine.lineWidth());
@@ -11638,7 +11727,7 @@ class ParagraphMeasure {
11638
11727
  }
11639
11728
  }
11640
11729
  }
11641
- cutTextRender(render, limitWidth, lineEmpty) {
11730
+ cutTextRender(render, limitWidth, lineEmpty, isCloseToBody) {
11642
11731
  let sumWidth = 0;
11643
11732
  const cutRender = render.clone();
11644
11733
  cutRender.textMeasures.length = 0;
@@ -11652,13 +11741,13 @@ class ParagraphMeasure {
11652
11741
  break;
11653
11742
  }
11654
11743
  }
11655
- // //后置标点处理
11656
- // i = this.patchHandlePostPunctuation(render, nextRender, i, inCloseBody, lineEmpty);
11657
- // //前置标点处理
11658
- // i = this.patchHandleLeadingPunctuation(render, i, lineEmpty);
11659
- // if (i <= 0) {
11660
- // return {firstItem: null, lastItem: null};
11661
- // }
11744
+ //后置标点处理
11745
+ i = this.patchHandlePostPunctuation(render, i, isCloseToBody, lineEmpty);
11746
+ //前置标点处理
11747
+ i = this.patchHandleLeadingPunctuation(render, i, lineEmpty);
11748
+ if (i <= 0) {
11749
+ return { firstItem: null, lastItem: null };
11750
+ }
11662
11751
  cutRender.textMeasures = render.textMeasures.splice(0, i);
11663
11752
  render.measure();
11664
11753
  cutRender.measure();
@@ -11668,6 +11757,7 @@ class ParagraphMeasure {
11668
11757
  * 处理前置标点,前置标点不能出现在末尾
11669
11758
  * @param render
11670
11759
  * @param i
11760
+ * @param lineEmpty
11671
11761
  */
11672
11762
  patchHandleLeadingPunctuation(render, i, lineEmpty) {
11673
11763
  if (i === 1 && lineEmpty) {
@@ -11682,15 +11772,10 @@ class ParagraphMeasure {
11682
11772
  * 处理后置标点,后置标点不能出现在行首
11683
11773
  * @param render
11684
11774
  * @param i
11775
+ * @param inCloseBody
11685
11776
  * @param lineEmpty
11686
11777
  */
11687
- patchHandlePostPunctuation(render, nextRender, i, inCloseBody, lineEmpty) {
11688
- if (i === render.textMeasures.length - 1) {
11689
- //紧跟着的字符包含后置标点
11690
- if (this.containerStartSymbolInTextStart(nextRender)) {
11691
- i--;
11692
- }
11693
- }
11778
+ patchHandlePostPunctuation(render, i, inCloseBody, lineEmpty) {
11694
11779
  if (inCloseBody && this.containPostPunctuation(render.textMeasures[i]?.char)) {
11695
11780
  if (this.containPostPunctuation(render.textMeasures[i + 1]?.char)) {
11696
11781
  i--;
@@ -13904,7 +13989,7 @@ class DocumentEvent {
13904
13989
  }
13905
13990
  const event = new GetTrackTipsEvent(this.docCtx);
13906
13991
  event.source = element;
13907
- DocumentEvent.invokeEvent('GetTrackTips', element, event, 'Bubbling', this.docCtx);
13992
+ DocumentEvent.invokeEvent('GetTrackTips', element, event, 'Bubbling');
13908
13993
  if (event.trackTips) {
13909
13994
  this.trackTipsChanged.next({ pos: { ...this.currentPos }, tips: event.trackTips });
13910
13995
  this.prevTrackInfo = true;
@@ -13956,7 +14041,7 @@ class DocumentEvent {
13956
14041
  this.endHitInfo = this.startHitInfo;
13957
14042
  const mousedownEvent = new MousedownElementEvent(this.docCtx);
13958
14043
  mousedownEvent.source = startElement;
13959
- DocumentEvent.invokeEvent('ElementMousedown', startElement, mousedownEvent, 'All', this.docCtx);
14044
+ DocumentEvent.invokeEvent('ElementMousedown', startElement, mousedownEvent, 'All');
13960
14045
  }
13961
14046
  else {
13962
14047
  this.clearHitInfo();
@@ -14089,7 +14174,7 @@ class DocumentEvent {
14089
14174
  //const { render: { renderPosition: { x: rx, y: ry } } } = this.currentMouseoverRender;
14090
14175
  //const rp = this.currentMouseoverRender?.absoluteRenderRect as Rect;
14091
14176
  const rp = ElementUtil.getRenderAbsolutePaintRect(cellRender);
14092
- rp.y -= this.viewOptions.pageOffset.y;
14177
+ //rp.y -= this.viewOptions.pageOffset.y;
14093
14178
  const relativePos = { x: mousePos.x - rp.x, y: mousePos.y - rp.y };
14094
14179
  const isInCellBorder = CommonUtil.isInRectBorder(cellRender.rect, 2, relativePos);
14095
14180
  cursorType = ElementUtil.getBorderCursor(isInCellBorder.borderType);
@@ -14206,7 +14291,7 @@ class DocumentEvent {
14206
14291
  const startElement = this.startHitInfo.render.element;
14207
14292
  const mousedownEvent = new MousedownElementEvent(this.docCtx);
14208
14293
  mousedownEvent.source = startElement;
14209
- DocumentEvent.invokeEvent('ElementClick', startElement, mousedownEvent, "All", this.docCtx);
14294
+ DocumentEvent.invokeEvent('ElementClick', startElement, mousedownEvent, "All");
14210
14295
  //this.refreshDocument();
14211
14296
  }
14212
14297
  const { startControl, startOffset, collapsed } = this.selectionState;
@@ -14218,7 +14303,7 @@ class DocumentEvent {
14218
14303
  dropEvent.source = startControl;
14219
14304
  dropEvent.sourceOffset = startOffset;
14220
14305
  dropEvent.dragElement = this.focusedElement;
14221
- if (DocumentEvent.invokeEvent('ElementDrop', startControl, dropEvent, 'All', this.docCtx)) {
14306
+ if (DocumentEvent.invokeEvent('ElementDrop', startControl, dropEvent, 'All')) {
14222
14307
  return;
14223
14308
  }
14224
14309
  this.docCtx.docChange.moveElement(startControl, startOffset, this.focusedElement, this.startHitInfo.offset, this.selectionState);
@@ -14254,7 +14339,7 @@ class DocumentEvent {
14254
14339
  if (hitInfo) {
14255
14340
  docEvent.source = hitInfo.element;
14256
14341
  docEvent.sourceRender = hitInfo.render;
14257
- const res = DocumentEvent.invokeEvent('ElementDblClick', hitInfo.element, docEvent, 'All', this.docCtx);
14342
+ const res = DocumentEvent.invokeEvent('ElementDblClick', hitInfo.element, docEvent, 'All');
14258
14343
  if (res) {
14259
14344
  return;
14260
14345
  }
@@ -14435,7 +14520,7 @@ class DocumentEvent {
14435
14520
  * @param eventStage
14436
14521
  * @param docCtx
14437
14522
  */
14438
- static invokeEvent(type, sourceElement, event, eventStage, docCtx) {
14523
+ static invokeEvent(type, sourceElement, event, eventStage) {
14439
14524
  const parents = ElementUtil.getParentElements(sourceElement);
14440
14525
  //先执行捕获阶段,在执行冒泡
14441
14526
  for (let i = parents.length - 1; i > -parents.length; i--) {
@@ -14905,7 +14990,7 @@ class DocumentEvent {
14905
14990
  });
14906
14991
  document.execCommand('copy');
14907
14992
  };
14908
- if (navigator.appVersion.indexOf('Mac') >= 0) {
14993
+ if (ElementUtil.getOSPlatform() === 'Mac') {
14909
14994
  if (evt.metaKey && evt.keyCode === 67) {
14910
14995
  copy();
14911
14996
  }
@@ -14954,6 +15039,7 @@ class DocumentInput {
14954
15039
  onTabKeyEvent = new Subject$1();
14955
15040
  constructor(node, docCtx) {
14956
15041
  this.docCtx = docCtx;
15042
+ const os = ElementUtil.getOSPlatform();
14957
15043
  node.addEventListener('input', evt => {
14958
15044
  const { startControl, startOffset } = this.docCtx.selectionState;
14959
15045
  this.onInputEvent.next({
@@ -14969,7 +15055,7 @@ class DocumentInput {
14969
15055
  const evt = nodeEvt.sourceEvt;
14970
15056
  const keyEvent = new KeyboradElementEvent(this.docCtx);
14971
15057
  keyEvent.sourceEvent = evt;
14972
- if (DocumentEvent.invokeEvent('ElementKeyDown', this.docCtx.selectionState.startControl, keyEvent, 'Capture', this.docCtx)) {
15058
+ if (DocumentEvent.invokeEvent('ElementKeyDown', this.docCtx.selectionState.startControl, keyEvent, 'Capture')) {
14973
15059
  return;
14974
15060
  }
14975
15061
  if (evt.keyCode === 8) {
@@ -15001,7 +15087,11 @@ class DocumentInput {
15001
15087
  else if (evt.keyCode === 46) {
15002
15088
  this.onDeleteEvent.next(evt);
15003
15089
  }
15004
- else if (evt.ctrlKey && evt.keyCode === 65) {
15090
+ else if (evt.ctrlKey && evt.keyCode === 65 && os !== 'Mac') {
15091
+ evt.preventDefault();
15092
+ this.onSelectAllEvent.next();
15093
+ }
15094
+ else if (evt.metaKey && evt.keyCode === 65 && os === 'Mac') {
15005
15095
  evt.preventDefault();
15006
15096
  this.onSelectAllEvent.next();
15007
15097
  }
@@ -15096,7 +15186,13 @@ class DocumentChange {
15096
15186
  this.onInputBySelectRange(data);
15097
15187
  return;
15098
15188
  }
15099
- //判断是否需要创建新的留痕区域
15189
+ const inputEvent = new InputElementEvent(this.docCtx);
15190
+ inputEvent.data = data.data;
15191
+ DocumentEvent.invokeEvent('ElementInput', startControl, inputEvent, 'All');
15192
+ if (inputEvent.isCancel) {
15193
+ return;
15194
+ }
15195
+ //判断是否需要创建新留痕区域
15100
15196
  if (enableTrackChanges && !this.isInCorrectTrackRegion(startControl, exports.TrackRunTypeEnum.Inserted)) {
15101
15197
  this.newInputTrackChanges(data, startControl, startOffset);
15102
15198
  return;
@@ -15203,7 +15299,7 @@ class DocumentChange {
15203
15299
  }
15204
15300
  }
15205
15301
  /**
15206
- * 创建新的留痕块,并返回留痕块输入定位文本
15302
+ * 创建新留痕块,并返回留痕块输入定位文本
15207
15303
  * @param startControl
15208
15304
  * @param startOffset
15209
15305
  * @param trackType
@@ -15359,7 +15455,7 @@ class DocumentChange {
15359
15455
  eventElement.source = startControl;
15360
15456
  eventElement.sourceEvent = evt;
15361
15457
  eventElement.sourceOffset = startOffset;
15362
- const res = DocumentEvent.invokeEvent('BackspaceKey', startControl, eventElement, 'Capture', this.docCtx);
15458
+ const res = DocumentEvent.invokeEvent('BackspaceKey', startControl, eventElement, 'Capture');
15363
15459
  if (res && res.isCancel) {
15364
15460
  return;
15365
15461
  }
@@ -15382,7 +15478,7 @@ class DocumentChange {
15382
15478
  eventElement.source = startControl;
15383
15479
  eventElement.sourceEvent = evt;
15384
15480
  eventElement.sourceOffset = startOffset;
15385
- const res = DocumentEvent.invokeEvent('DeleteKey', startControl, eventElement, 'Capture', this.docCtx);
15481
+ const res = DocumentEvent.invokeEvent('DeleteKey', startControl, eventElement, 'Capture');
15386
15482
  if (res && res.isCancel) {
15387
15483
  return;
15388
15484
  }
@@ -16141,6 +16237,25 @@ class DocumentChange {
16141
16237
  });
16142
16238
  }
16143
16239
  }
16240
+ static setParaStyle(ss, setterFunc) {
16241
+ if (ss.collapsed && ss.startControl) {
16242
+ const para = ElementUtil.getParentByType(ss.startControl, ParagraphElement);
16243
+ if (para) {
16244
+ setterFunc(para.props);
16245
+ }
16246
+ }
16247
+ else {
16248
+ const range = ss.selectedRange;
16249
+ if (!range) {
16250
+ return;
16251
+ }
16252
+ RangeUtil.recursionTraversalRangeHandler(range, (itemRange) => {
16253
+ if (itemRange.target instanceof ParagraphElement) {
16254
+ setterFunc(itemRange.target.props);
16255
+ }
16256
+ });
16257
+ }
16258
+ }
16144
16259
  /**
16145
16260
  * 复制
16146
16261
  * @param evt
@@ -17726,7 +17841,6 @@ function setCurrentActiveAppContext(ctx) {
17726
17841
  currentActiveAppContext = ctx;
17727
17842
  }
17728
17843
  function renderApp(root, renderCtx, nodeEvent) {
17729
- window['root'] = root;
17730
17844
  // const nodeEvent = new NodeEvent(root, renderCtx.mainContext.ctx.canvas);
17731
17845
  let delayTask = false;
17732
17846
  const flushTask = () => {
@@ -17745,8 +17859,10 @@ function renderApp(root, renderCtx, nodeEvent) {
17745
17859
  };
17746
17860
  flushTask();
17747
17861
  root.onChangedEvent.subscribe(() => {
17862
+ if (root.isDisposed) {
17863
+ return;
17864
+ }
17748
17865
  flushTask();
17749
- //console.log('准备创建任务'+taskId)
17750
17866
  });
17751
17867
  nodeEvent.onSignal.subscribe(() => {
17752
17868
  flushTask();
@@ -19011,6 +19127,7 @@ class SurfaceView extends NodeItems {
19011
19127
  renderSchedule;
19012
19128
  nodeEvent;
19013
19129
  renderCtx;
19130
+ isDisposed = false;
19014
19131
  onSizeChanged = new Subject();
19015
19132
  constructor(canvas, input) {
19016
19133
  super();
@@ -19093,6 +19210,10 @@ class SurfaceView extends NodeItems {
19093
19210
  clearPopNodes() {
19094
19211
  this.popNodes = [];
19095
19212
  }
19213
+ destroy() {
19214
+ this.clearChildren();
19215
+ this.isDisposed = true;
19216
+ }
19096
19217
  initInputEvent() {
19097
19218
  let composition = false;
19098
19219
  this.input.addEventListener('input', evt => {
@@ -20302,131 +20423,1461 @@ function pointInPoly(pt, poly) {
20302
20423
  return c;
20303
20424
  }
20304
20425
 
20305
- /**
20306
- * Node宽度定义
20307
- * 1.在单页模式下,文档最小宽度为单个文档宽度+合适的外边距
20308
- * 2.在多页模式下,文档最小宽度为单个文档宽度+合适的外边距
20309
- */
20310
- class CanvasTextEditor extends AbsolutePanel {
20311
- editCanvas;
20312
- editInput;
20313
- contentCtx;
20314
- viewOptions;
20315
- docCtx;
20316
- docComment;
20317
- renderContext;
20318
- documentPaint;
20319
- elementReader;
20320
- documentEvent;
20321
- documentSelection;
20322
- documentInput;
20323
- documentChange;
20324
- selectionOverlays;
20325
- //private docRule: DocRule;
20326
- historyMange;
20327
- selectionChanged = new Subject$1();
20328
- beforeRenderSubject = new Subject$1();
20329
- afterRenderSubject = new Subject$1();
20330
- selectionState;
20331
- //显示右键菜单
20332
- onContextMenuItemChanged = new Subject$1();
20333
- onDblClickEvent = new Subject$1();
20334
- onClickEvent = new Subject$1();
20335
- onScrollViewEvent = new Subject$1();
20336
- //文档改变事件:内容及样式,业务模块需要根据此事件,来追踪当前文档是否改变的状态
20337
- onDocChangedEvent = new Subject$1();
20338
- //执行flushTask,refreshDoc之前,此时可以在文档计算排版之前改变内容
20339
- onBeforeRefreshDocument = new Subject$1();
20340
- constructor(editCanvas, editInput) {
20426
+ const timelineConfig = {
20427
+ fontSize: 12,
20428
+ fontName: '宋体',
20429
+ /**
20430
+ * 单个时刻的宽度,像素
20431
+ */
20432
+ timeTickWidth: 14,
20433
+ /**
20434
+ * 纵轴一个单位的高度
20435
+ */
20436
+ timeValueHeight: 20,
20437
+ /**
20438
+ * 单个时刻宽度代表的小时数
20439
+ */
20440
+ timeTickHours: 4,
20441
+ /**
20442
+ * 体温点的大小
20443
+ */
20444
+ temperaturePointSize: 4,
20445
+ /**
20446
+ * 心率点的大小
20447
+ */
20448
+ heartRatePointSize: 4,
20449
+ temperatureModels: [42, 41, 40, 39, 38, 37, 36, 35],
20450
+ heartRateModels: [180, 160, 140, 120, 100, 80, 40, 20],
20451
+ valueRuleCounts: 8,
20452
+ /**
20453
+ * 时刻头部高度
20454
+ */
20455
+ tickHeaderHeight: 20,
20456
+ /**
20457
+ * 体温符号
20458
+ */
20459
+ temperatureSymbol: '℃',
20460
+ heartRateSymbol: 'BPM'
20461
+ };
20462
+ class TimelineBaseControl extends AbsolutePanel {
20463
+ startTime;
20464
+ showDays = 0;
20465
+ constructor() {
20341
20466
  super();
20342
- this.editCanvas = editCanvas;
20343
- this.editInput = editInput;
20344
- this.viewOptions = new ViewOptions();
20345
- this.documentSelection = new DocumentSelection();
20346
- this.docCtx = new EditorContext(this.documentSelection.selectionState, this.viewOptions);
20347
- this.viewOptions.copyRightInfo = '电子病历编辑器(XXX版权所有)';
20348
- this.viewOptions.drawCharRectColor = 'green';
20349
- this.viewOptions.showLineRect = true;
20350
- this.viewOptions.docSpace = 20;
20351
- this.viewOptions.reviewWindowWidth = 200;
20352
- this.viewOptions.defaultFontName = '宋体';
20353
- //this.viewOptions.scale = 2;
20354
- //整个画布的尺寸
20355
- this.viewOptions.viewSettings = {
20356
- width: 1000,
20357
- height: 200
20358
- };
20359
- this.viewOptions.editUser = {
20360
- id: '6666',
20361
- name: '管理员'
20362
- };
20363
- this.viewOptions.fullPageView = false;
20364
- this.createDocViewer();
20365
- this.docComment = new DocumentComment(this.docCtx);
20366
- this.contentCtx = editCanvas.getContext('2d');
20367
- this.renderContext = new RenderContext(new PaintContent(this.contentCtx));
20368
- this.renderContext.init({ width: 500, height: 500, scale: 1 });
20369
- this.selectionState = this.documentSelection.selectionState;
20370
- this.selectionOverlays = new SelectionOverlays(this.documentSelection.selectionState);
20371
- this.documentPaint = new DocumentPaint(this.renderContext, this.docCtx, this.selectionOverlays.selectedSets);
20372
- this.elementReader = new ElementReader(this.docCtx);
20373
- //this.docRule = new DocRule(this.ruleCanvas, this.docCtx);
20374
- this.documentInput = new DocumentInput(this, this.docCtx);
20375
- this.documentChange = new DocumentChange(this.elementReader, this.docCtx, this.docComment, this.documentInput);
20376
- this.documentEvent = new DocumentEvent(this, this.documentPaint, this.docCtx, this.documentInput);
20377
- this.historyMange = new ElementTrackManage(this.docCtx, this.elementReader);
20378
- this.documentEvent.hitInfoChanged.subscribe((hitInfo) => {
20379
- this.hitInfoChanged(hitInfo);
20380
- });
20381
- this.documentEvent.clickEvent.subscribe((evt) => {
20382
- this.docClickHandle(evt);
20383
- });
20384
- this.documentEvent.dblClickEvent.subscribe((evt) => {
20385
- this.docDblClickHandle(evt);
20386
- });
20387
- this.documentEvent.changeCursor.subscribe((cursor) => {
20388
- this.changeCursor(cursor);
20389
- });
20390
- this.documentEvent.contextMenu.subscribe(evt => {
20391
- this.onContextMenu(evt);
20392
- });
20393
- this.documentEvent.trackTipsChanged.subscribe(data => {
20467
+ this.border = 1;
20468
+ this.borderColor = '#000';
20469
+ this.bgColor = '#fff';
20470
+ }
20471
+ measureOverride(e, availableSize) {
20472
+ this.build(e);
20473
+ return super.measureOverride(e, availableSize);
20474
+ }
20475
+ isBuild = false;
20476
+ build(e) {
20477
+ if (this.isBuild) {
20478
+ return;
20479
+ }
20480
+ this.clearChildren();
20481
+ this.buildOverride(e);
20482
+ this.isBuild = true;
20483
+ }
20484
+ reBuild() {
20485
+ this.isBuild = false;
20486
+ }
20487
+ buildOverride(e) {
20488
+ }
20489
+ }
20490
+ class TickContainer extends AbsolutePanel {
20491
+ tickControl;
20492
+ _startTime;
20493
+ _showDays = 0;
20494
+ scrollX = 0;
20495
+ get startTime() {
20496
+ return this._startTime;
20497
+ }
20498
+ set startTime(value) {
20499
+ this._startTime = value;
20500
+ this.tickControl.startTime = value;
20501
+ }
20502
+ get showDays() {
20503
+ return this._showDays;
20504
+ }
20505
+ set showDays(value) {
20506
+ this._showDays = value;
20507
+ this.tickControl.showDays = value;
20508
+ }
20509
+ arrangeOverride(e, finalSize) {
20510
+ this.controls.filter(item => item !== this.tickControl).forEach(item => {
20511
+ const itemRect = {
20512
+ x: item.x,
20513
+ y: item.y,
20514
+ width: item.desiredSize.width,
20515
+ height: item.desiredSize.height
20516
+ };
20517
+ item.arrange(e, itemRect);
20394
20518
  });
20395
- this.docCtx.docChange = this.documentChange;
20396
- //this.listenContainerHeight();
20397
- this.start();
20398
- this.refreshDocRule();
20399
- this.docCtx.syncRefresh = () => {
20400
- this.flushToSchedule();
20401
- };
20402
- this.viewOptions.onChange.subscribe((type) => {
20403
- this.resetViewer(type);
20519
+ this.tickControl.arrange(e, { x: this.tickControl.x - this.scrollX,
20520
+ y: this.tickControl.y,
20521
+ width: this.tickControl.desiredSize.width,
20522
+ height: this.tickControl.desiredSize.height });
20523
+ return finalSize;
20524
+ }
20525
+ }
20526
+
20527
+ class TemperaturePoint extends NodeCore {
20528
+ type;
20529
+ value;
20530
+ constructor(type = 'axillary', value) {
20531
+ super();
20532
+ this.type = type;
20533
+ this.value = value;
20534
+ this.bgColor = 'blue';
20535
+ this.width = timelineConfig.temperaturePointSize;
20536
+ this.height = timelineConfig.temperaturePointSize;
20537
+ this.addEventListener('mouseenter', evt => {
20538
+ this.bgColor = 'red';
20539
+ const onMouseLeave = () => {
20540
+ this.bgColor = 'blue';
20541
+ this.removeEventListener('mouseleave', onMouseLeave);
20542
+ };
20543
+ this.addEventListener('mouseleave', onMouseLeave);
20404
20544
  });
20405
20545
  }
20406
- /**
20407
- * 设置标尺
20408
- */
20409
- refreshDocRule() {
20410
- let docLeft = 0; //CommonUtil.getOffsetX(this.editCanvas.parentElement as HTMLDivElement);
20411
- let pagePL = 0, pagePR = 0;
20412
- if (this.documentPaint.docContainer) {
20413
- docLeft += this.documentPaint.docContainer.rect.x;
20546
+ renderOutline(renderCtx) {
20547
+ translate(renderCtx, this.finalRect.x, this.finalRect.y);
20548
+ translate(renderCtx, this.border + this.padding, this.border + this.padding);
20549
+ }
20550
+ render(e) {
20551
+ if (this.type === 'axillary') {
20552
+ this.renderAxillary(e);
20414
20553
  }
20415
- if (this.docCtx.document?.props?.padding) {
20416
- const { left, right } = this.docCtx.document.props.padding;
20417
- pagePL = left;
20418
- pagePR = right;
20554
+ else if (this.type === 'oral') {
20555
+ this.renderOral(e);
20556
+ }
20557
+ else if (this.type === 'anal') {
20558
+ this.renderAnal(e);
20419
20559
  }
20420
- this.rule.setRuleOptions({ width: this.viewOptions.docPageSettings.width, pagePL, pagePR, docLeft });
20421
20560
  }
20422
- createDocViewer() {
20423
- this.viewOptions.mmToPixelsRatio = this.measureMMToPixs();
20424
- const width = Math.floor(210 * this.viewOptions.mmToPixelsRatio);
20425
- const height = Math.floor(297 * this.viewOptions.mmToPixelsRatio);
20426
- this.viewOptions.docPageSettings = new PageOptions(width, height);
20427
- // this.docScroll.onscroll = (evt) => {
20428
- // //this.onScrollViewHandler(evt);
20429
- // };
20561
+ /**
20562
+ * 绘制腋下温度 X
20563
+ * @private
20564
+ */
20565
+ renderAxillary(e) {
20566
+ const { width, height } = this.finalRect;
20567
+ const x = 0, y = 0;
20568
+ e.render.strokeLines([{ x, y }, { x: x + width, y: y + height }], 3, this.bgColor);
20569
+ e.render.strokeLines([{ x: x + width, y }, { x, y: y + height }], 3, this.bgColor);
20570
+ }
20571
+ /**
20572
+ * 绘制肛下温度 ○
20573
+ * @private
20574
+ */
20575
+ renderAnal(e) {
20576
+ const width = this.finalRect.width;
20577
+ const ctx = e.render.ctx;
20578
+ ctx.save();
20579
+ ctx.beginPath();
20580
+ ctx.strokeStyle = this.bgColor;
20581
+ ctx.lineWidth = 2;
20582
+ ctx.arc(width / 2, width / 2, width, 0, 2 * Math.PI);
20583
+ ctx.stroke();
20584
+ ctx.restore();
20585
+ }
20586
+ /**
20587
+ * 绘制口腔温度 ●
20588
+ * @private
20589
+ */
20590
+ renderOral(e) {
20591
+ const width = this.finalRect.width;
20592
+ e.render.fillCircular(width / 2, width / 2, width, this.bgColor);
20593
+ }
20594
+ }
20595
+ class HeartRatePoint extends NodeCore {
20596
+ value;
20597
+ constructor() {
20598
+ super();
20599
+ this.bgColor = 'red';
20600
+ this.width = timelineConfig.heartRatePointSize * 2;
20601
+ this.height = timelineConfig.heartRatePointSize * 2;
20602
+ this.addEventListener('mouseenter', evt => {
20603
+ this.bgColor = 'green';
20604
+ const tipLabel = new LabelNode();
20605
+ tipLabel.text = this.value;
20606
+ tipLabel.fontSize = timelineConfig.fontSize;
20607
+ tipLabel.shadowBlur = 5;
20608
+ tipLabel.shadowColor = '#000';
20609
+ tipLabel.bgColor = '#fff';
20610
+ tipLabel.x = this.x;
20611
+ tipLabel.y = this.y - tipLabel.fontSize - 2;
20612
+ this.parent?.addChild(tipLabel);
20613
+ const onMouseLeave = () => {
20614
+ this.bgColor = 'red';
20615
+ this.parent?.removeChild(tipLabel);
20616
+ this.removeEventListener('mouseleave', onMouseLeave);
20617
+ };
20618
+ this.addEventListener('mouseleave', onMouseLeave);
20619
+ });
20620
+ }
20621
+ renderOutline(renderCtx) {
20622
+ translate(renderCtx, this.finalRect.x, this.finalRect.y);
20623
+ translate(renderCtx, this.border + this.padding, this.border + this.padding);
20624
+ }
20625
+ render(e) {
20626
+ const heartRatePointSize = this.finalRect.width / 2;
20627
+ e.render.fillCircular(heartRatePointSize, heartRatePointSize, heartRatePointSize, this.bgColor);
20628
+ }
20629
+ }
20630
+ class TimeLinePath extends NodeCore {
20631
+ startPos;
20632
+ endPos;
20633
+ lineColor = '#000';
20634
+ lineWidth = 1;
20635
+ constructor() {
20636
+ super();
20637
+ this.allowHitTest = true;
20638
+ this.enableClip = false;
20639
+ }
20640
+ renderOutline(renderCtx) {
20641
+ translate(renderCtx, this.finalRect.x, this.finalRect.y);
20642
+ translate(renderCtx, this.border + this.padding, this.border + this.padding);
20643
+ }
20644
+ render(e) {
20645
+ e.render.strokeLines([this.startPos, this.endPos], this.lineWidth, this.lineColor);
20646
+ }
20647
+ }
20648
+
20649
+ class TimelineControl extends AbsolutePanel {
20650
+ render(e) {
20651
+ }
20652
+ constructor() {
20653
+ super();
20654
+ this.border = 1;
20655
+ this.borderColor = '#000';
20656
+ }
20657
+ measureOverride(e, availableSize) {
20658
+ const height = this.controls.reduce((prev, curr) => {
20659
+ curr.measure(e, availableSize);
20660
+ return prev + curr.desiredSize.height;
20661
+ }, 0);
20662
+ return {
20663
+ height, width: availableSize.width
20664
+ };
20665
+ }
20666
+ arrangeOverride(e, finalSize) {
20667
+ this.controls.reduce((prev, curr) => {
20668
+ const itemRect = {
20669
+ x: 0,
20670
+ y: prev,
20671
+ width: curr.desiredSize.width,
20672
+ height: curr.desiredSize.height
20673
+ };
20674
+ curr.arrange(e, itemRect);
20675
+ return prev + curr.desiredSize.height;
20676
+ }, 0);
20677
+ return finalSize;
20678
+ }
20679
+ rebuild() {
20680
+ treeForEach(this, item => {
20681
+ if (item instanceof NodeItems) {
20682
+ return item.controls;
20683
+ }
20684
+ else {
20685
+ return [];
20686
+ }
20687
+ }, (item) => {
20688
+ if (item instanceof TimelineBaseControl) {
20689
+ item.reBuild();
20690
+ }
20691
+ });
20692
+ }
20693
+ }
20694
+ function treeForEach(root, children, callback) {
20695
+ callback(root);
20696
+ children(root).forEach(node => {
20697
+ treeForEach(node, children, callback);
20698
+ });
20699
+ }
20700
+ /**
20701
+ * 中间网格数据绘制区域
20702
+ */
20703
+ class TimeGridContainer extends AbsolutePanel {
20704
+ get gridHeight() {
20705
+ return this._gridHeight;
20706
+ }
20707
+ set gridHeight(value) {
20708
+ this._gridHeight = value;
20709
+ this.timelineGridControl.height = value;
20710
+ this.timeValueRuleContainer.height = value;
20711
+ }
20712
+ _startTime;
20713
+ _showDays = 7;
20714
+ get startTime() {
20715
+ return this._startTime;
20716
+ }
20717
+ set startTime(value) {
20718
+ this._startTime = value;
20719
+ this.timelineGridControl.startTime = value;
20720
+ }
20721
+ get showDays() {
20722
+ return this._showDays;
20723
+ }
20724
+ set showDays(value) {
20725
+ this._showDays = value;
20726
+ this.timelineGridControl.showDays = value;
20727
+ }
20728
+ /**
20729
+ * 网格区域高度
20730
+ */
20731
+ _gridHeight = 0;
20732
+ scrollX = 0;
20733
+ timelineGridControl;
20734
+ timeValueRuleContainer;
20735
+ constructor() {
20736
+ super();
20737
+ this.timelineGridControl = new TimelineGridControl();
20738
+ this.addChild(this.timelineGridControl);
20739
+ this.timeValueRuleContainer = new TimeValueRuleContainer();
20740
+ this.addChild(this.timeValueRuleContainer);
20741
+ }
20742
+ init() {
20743
+ this.timelineGridControl.init();
20744
+ }
20745
+ measureOverride(e, availableSize) {
20746
+ this.timelineGridControl.measure(e, availableSize);
20747
+ const height = this.timelineGridControl.desiredSize.height;
20748
+ this.timeValueRuleContainer.measure(e, { height, width: availableSize.width });
20749
+ return { height, width: availableSize.width };
20750
+ }
20751
+ arrangeOverride(e, finalSize) {
20752
+ this.controls.filter(item => item !== this.timelineGridControl).forEach(item => {
20753
+ const itemRect = {
20754
+ x: item.x,
20755
+ y: item.y,
20756
+ width: item.desiredSize.width,
20757
+ height: item.desiredSize.height
20758
+ };
20759
+ item.arrange(e, itemRect);
20760
+ });
20761
+ this.timelineGridControl.arrange(e, {
20762
+ x: this.timelineGridControl.x - this.scrollX,
20763
+ y: this.timelineGridControl.y,
20764
+ width: this.timelineGridControl.desiredSize.width,
20765
+ height: this.timelineGridControl.desiredSize.height
20766
+ });
20767
+ return finalSize;
20768
+ }
20769
+ render(e) {
20770
+ }
20771
+ }
20772
+ class TimeValueRuleContainer extends AbsolutePanel {
20773
+ getLayoutWidth() {
20774
+ return this.controls.reduce((prev, curr) => prev + curr.width, 0);
20775
+ }
20776
+ init() {
20777
+ this.controls.reduce((prev, curr) => {
20778
+ curr.x = prev;
20779
+ return prev + curr.width;
20780
+ }, 0);
20781
+ }
20782
+ renderOutline(renderCtx) {
20783
+ translate(renderCtx, this.finalRect.x, this.finalRect.y);
20784
+ translate(renderCtx, this.border + this.padding, this.border + this.padding);
20785
+ }
20786
+ render(e) {
20787
+ }
20788
+ }
20789
+ /**
20790
+ * 标题区域
20791
+ * 时间刻度:日期、住院天数、手术天数、时刻
20792
+ * 数值标尺区域、数据网格区域
20793
+ * 文本时间轴区域
20794
+ */
20795
+ class TimelineGridControl extends TimelineBaseControl {
20796
+ get isShowTemperature() {
20797
+ return this._isShowTemperature;
20798
+ }
20799
+ set isShowTemperature(value) {
20800
+ this.propertyChanged('isShowTemperature', this._isShowTemperature, value);
20801
+ this._isShowTemperature = value;
20802
+ }
20803
+ get isShowHeartRate() {
20804
+ return this._isShowHeartRate;
20805
+ }
20806
+ set isShowHeartRate(value) {
20807
+ this.propertyChanged('isShowHeartRate', this._isShowHeartRate, value);
20808
+ this._isShowHeartRate = value;
20809
+ }
20810
+ //体温数据
20811
+ temperatureData = [];
20812
+ //心率数据
20813
+ heartRateData = [];
20814
+ //体温时间轴值模型
20815
+ temperatureTimeLineValueModel = [];
20816
+ //心率时间轴值模型
20817
+ heartRateTimeLineValueModel = [];
20818
+ //图章数据
20819
+ eventData = [];
20820
+ _isShowTemperature = true;
20821
+ _isShowHeartRate = true;
20822
+ mousePos = null;
20823
+ constructor() {
20824
+ super();
20825
+ this.startTime = moment__default$1["default"](moment__default$1["default"]().format("YYYY-MM-DD")).toDate();
20826
+ this.addEventListener('mousemove', evt => {
20827
+ const pos = evt.pos;
20828
+ const nodePos = getNodePosition(this, { x: 0, y: 0 });
20829
+ this.mousePos = { x: pos.x - nodePos.x, y: pos.y - nodePos.y };
20830
+ });
20831
+ this.addEventListener('mouseleave', evt => {
20832
+ this.mousePos = null;
20833
+ });
20834
+ }
20835
+ randomNum = (start, end) => {
20836
+ return Math.floor(Math.random() * (end - start) + start);
20837
+ };
20838
+ getLayoutWidth() {
20839
+ return this.showDays * (24 / timelineConfig.timeTickHours) * timelineConfig.timeTickWidth;
20840
+ }
20841
+ init() {
20842
+ this.temperatureTimeLineValueModel = timelineConfig.temperatureModels.map((item, index, arr) => ({
20843
+ value: item,
20844
+ offset: (index + 1) / (arr.length + 1)
20845
+ }));
20846
+ this.heartRateTimeLineValueModel = timelineConfig.heartRateModels.map((item, index, arr) => ({
20847
+ value: item,
20848
+ offset: (index + 1) / (arr.length + 1)
20849
+ }));
20850
+ const { timeTickHours } = timelineConfig;
20851
+ for (let i = 0; i < this.showDays; i++) {
20852
+ for (let j = 0; j < 24; j += timeTickHours) {
20853
+ this.temperatureData.push({
20854
+ date: moment__default$1["default"](this.startTime).add(i, 'days').add(j, 'hours').toDate(),
20855
+ value: this.randomNum(33, 43) + this.randomNum(0, 10) / 10
20856
+ //value: 43
20857
+ });
20858
+ this.heartRateData.push({
20859
+ date: moment__default$1["default"](this.startTime).add(i, 'days').add(j, 'hours').toDate(),
20860
+ value: this.randomNum(70, 150)
20861
+ });
20862
+ }
20863
+ this.eventData.push({ date: moment__default$1["default"](this.startTime).add(i, 'days').toDate(), value: '入\r\n院' });
20864
+ }
20865
+ this.temperatureData.sort((prev, curr) => {
20866
+ return curr.date > prev.date ? 1 : -1;
20867
+ });
20868
+ this.heartRateData.sort((prev, curr) => curr.date > prev.date ? 1 : -1);
20869
+ }
20870
+ buildOverride(e) {
20871
+ this.buildTemperature(e);
20872
+ this.buildHearRate(e);
20873
+ this.buildStampUnit(e);
20874
+ const tipLabel = new LabelNode();
20875
+ tipLabel.text = '外\r\n科\r\n手\r\n术';
20876
+ tipLabel.borderColor = '#000';
20877
+ tipLabel.border = 1;
20878
+ tipLabel.shadowBlur = 5;
20879
+ tipLabel.shadowColor = 'red';
20880
+ tipLabel.fontSize = 12;
20881
+ tipLabel.bgColor = '#fff';
20882
+ tipLabel.color = 'red';
20883
+ tipLabel.textWrapping = 'wrap';
20884
+ //tipLabel.width = 14;
20885
+ tipLabel.x = 100;
20886
+ tipLabel.y = 30;
20887
+ this.addChild(tipLabel);
20888
+ }
20889
+ render(e) {
20890
+ const { timeValueHeight, timeTickHours, timeTickWidth } = timelineConfig;
20891
+ const ticks = 24 / timeTickHours;
20892
+ for (let i = 0; i < this.showDays; i++) {
20893
+ for (let j = 1; j <= ticks; j++) {
20894
+ const x = i * timeTickWidth * ticks + j * timeTickWidth;
20895
+ const color = j < ticks ? '#69c0ff' : '#ffadd2';
20896
+ e.render.strokeLines([{
20897
+ x,
20898
+ y: 0
20899
+ }, { x, y: this.finalRect.height }], 0.5, color);
20900
+ }
20901
+ }
20902
+ for (let i = timeValueHeight; i < this.finalRect.height; i += timeValueHeight) {
20903
+ e.render.strokeLines([{
20904
+ x: 0,
20905
+ y: i
20906
+ }, { x: this.finalRect.width, y: i }], 0.5, '#69c0ff');
20907
+ }
20908
+ this.renderTemperatureGuideLine(e);
20909
+ if (this.mousePos) {
20910
+ e.render.strokeLines([{ x: 0, y: this.mousePos.y }, { x: this.finalRect.width, y: this.mousePos.y }]);
20911
+ e.render.strokeLines([{ x: this.mousePos.x, y: 0 }, { x: this.mousePos.x, y: this.finalRect.height }]);
20912
+ }
20913
+ }
20914
+ renderTemperatureGuideLine(e) {
20915
+ const timelineValue = this.temperatureTimeLineValueModel.map(item => ({
20916
+ value: item.value,
20917
+ offset: this.height * item.offset
20918
+ }));
20919
+ //绘制正常36-37度,辅助线
20920
+ const startPoint = 36.5;
20921
+ const endPoint = 37.3;
20922
+ const startFilter = timelineValue.filter(item => item.value >= startPoint);
20923
+ const endFilter = timelineValue.filter(item => item.value >= endPoint);
20924
+ let startY = 0;
20925
+ let endY = 0;
20926
+ if (startFilter.length > 1) {
20927
+ const curr = startFilter[startFilter.length - 1];
20928
+ const next = startFilter[startFilter.length - 2];
20929
+ startY = curr.offset + (curr.value - startPoint) * (next.offset - curr.offset) / (curr.value - next.value);
20930
+ }
20931
+ if (endFilter.length > 1) {
20932
+ const curr = endFilter[endFilter.length - 1];
20933
+ const next = endFilter[endFilter.length - 2];
20934
+ endY = curr.offset + (curr.value - endPoint) * (next.offset - curr.offset) / (curr.value - next.value);
20935
+ }
20936
+ e.render.strokeLines([{ x: 0, y: startY }, { x: this.finalRect.width, y: startY }], 1, 'red');
20937
+ e.render.strokeLines([{ x: 0, y: endY }, { x: this.finalRect.width, y: endY }], 1, 'red');
20938
+ }
20939
+ buildTemperature(e) {
20940
+ if (this.temperatureData.length === 0) {
20941
+ return;
20942
+ }
20943
+ const height = this.height;
20944
+ const { timeValueHeight, timeTickHours, timeTickWidth, temperaturePointSize } = timelineConfig;
20945
+ const timelineValue = this.temperatureTimeLineValueModel.map(item => ({
20946
+ value: item.value,
20947
+ offset: height * item.offset
20948
+ }));
20949
+ //获取体温点纵向坐标
20950
+ const getTimelineVerValue = (val) => {
20951
+ const filter = timelineValue.filter(item => item.value >= val);
20952
+ if (filter.length) {
20953
+ if (filter.length > 1) {
20954
+ const curr = filter[filter.length - 1];
20955
+ const next = filter[filter.length - 2];
20956
+ return curr.offset + (curr.value - val) * (next.offset - curr.offset) / (curr.value - next.value);
20957
+ }
20958
+ else {
20959
+ return filter[0].offset;
20960
+ }
20961
+ }
20962
+ return -1;
20963
+ };
20964
+ let prevPos = null;
20965
+ for (let i = 0; i < this.showDays; i++) {
20966
+ const ticks = 24 / timeTickHours;
20967
+ for (let j = 0; j < ticks; j++) {
20968
+ const hourOffset = j * timeTickHours;
20969
+ const x = i * timeTickWidth * ticks + j * timeTickWidth;
20970
+ const startTime = moment__default$1["default"](this.startTime).add(i, 'days').add(hourOffset, 'hours');
20971
+ const endTime = moment__default$1["default"](this.startTime).add(i, 'days').add(hourOffset + timeTickHours, 'hours');
20972
+ const predicate = (item) => {
20973
+ return moment__default$1["default"](item).isBetween(startTime, endTime, null, '(]');
20974
+ };
20975
+ const currTimePoints = this.temperatureData.filter(item => predicate(item.date));
20976
+ currTimePoints.forEach(item => {
20977
+ let currX = x;
20978
+ const diffMinutes = moment__default$1["default"](item.date).diff(startTime, 'minutes');
20979
+ const offsetMinutes = diffMinutes * timeTickWidth / (timeTickHours * 60);
20980
+ currX += offsetMinutes;
20981
+ let currY = getTimelineVerValue(item.value);
20982
+ //超出显示范围
20983
+ if (currY > height) {
20984
+ currY = height;
20985
+ this.setExceededValueTip(e, item.value + '℃', currX, currY - 20);
20986
+ }
20987
+ if (currY < 0) {
20988
+ currY = 0;
20989
+ this.setExceededValueTip(e, item.value + '℃', currX, currY + 5);
20990
+ }
20991
+ const point = new TemperaturePoint('axillary', item.value);
20992
+ point.x = currX - point.width / 2;
20993
+ point.y = currY - point.width / 2;
20994
+ this.addChild(point);
20995
+ if (prevPos) {
20996
+ const linePath = new TimeLinePath();
20997
+ linePath.lineColor = 'blue';
20998
+ linePath.startPos = prevPos;
20999
+ linePath.endPos = { x: currX, y: currY };
21000
+ this.addChild(linePath);
21001
+ }
21002
+ prevPos = { x: currX, y: currY };
21003
+ });
21004
+ }
21005
+ }
21006
+ }
21007
+ setExceededValueTip(e, tip, x, y) {
21008
+ const tipLabel = new LabelNode();
21009
+ tipLabel.text = tip;
21010
+ tipLabel.borderColor = '#000';
21011
+ tipLabel.border = 1;
21012
+ tipLabel.shadowBlur = 5;
21013
+ tipLabel.shadowColor = '#000';
21014
+ tipLabel.fontSize = 10;
21015
+ tipLabel.bgColor = '#fff';
21016
+ const tipLabelWidth = e.render.measureText2(tipLabel.text, tipLabel);
21017
+ tipLabel.x = x -= tipLabelWidth / 2;
21018
+ tipLabel.y = y;
21019
+ this.addChild(tipLabel);
21020
+ }
21021
+ buildHearRate(e) {
21022
+ const height = this.height;
21023
+ const { timeTickHours, timeTickWidth, heartRateSymbol } = timelineConfig;
21024
+ const timelineValue = this.heartRateTimeLineValueModel.map(item => ({
21025
+ value: item.value,
21026
+ offset: height * item.offset
21027
+ }));
21028
+ //获取心率纵向坐标
21029
+ const getTimelineVerValue = (val) => {
21030
+ const filter = timelineValue.filter(item => item.value >= val);
21031
+ if (filter.length) {
21032
+ if (filter.length > 1) {
21033
+ const curr = filter[filter.length - 1];
21034
+ const next = filter[filter.length - 2];
21035
+ return curr.offset + (curr.value - val) * (next.offset - curr.offset) / (curr.value - next.value);
21036
+ }
21037
+ else {
21038
+ return filter[0].offset;
21039
+ }
21040
+ }
21041
+ return -1;
21042
+ };
21043
+ //const getTimelineHorValue=()
21044
+ let prevPos = null;
21045
+ for (let i = 0; i < this.showDays; i++) {
21046
+ const ticks = 24 / timeTickHours;
21047
+ for (let j = 0; j < ticks; j++) {
21048
+ const hourOffset = j * timeTickHours;
21049
+ const x = i * timeTickWidth * ticks + j * timeTickWidth;
21050
+ const startTime = moment__default$1["default"](this.startTime).add(i, 'days').add(hourOffset, 'hours');
21051
+ const endTime = moment__default$1["default"](this.startTime).add(i, 'days').add(hourOffset + timeTickHours, 'hours');
21052
+ const predicate = (item) => {
21053
+ return moment__default$1["default"](item).isBetween(startTime, endTime, null, '(]');
21054
+ };
21055
+ const currTimePoints = this.heartRateData.filter(item => predicate(item.date));
21056
+ currTimePoints.forEach(item => {
21057
+ let currX = x;
21058
+ const diffMinutes = moment__default$1["default"](item.date).diff(startTime, 'minutes');
21059
+ const offsetMinutes = diffMinutes * timeTickWidth / (timeTickHours * 60);
21060
+ currX += offsetMinutes;
21061
+ let currY = getTimelineVerValue(item.value);
21062
+ //超出显示范围
21063
+ if (currY > height) {
21064
+ currY = height;
21065
+ this.setExceededValueTip(e, item.value + heartRateSymbol, currX, currY - 20);
21066
+ }
21067
+ if (currY < 0) {
21068
+ currY = 0;
21069
+ this.setExceededValueTip(e, item.value + heartRateSymbol, currX, currY + 5);
21070
+ }
21071
+ const point = new HeartRatePoint();
21072
+ point.value = item.value + '次/分';
21073
+ point.x = currX - point.width / 2;
21074
+ point.y = currY - point.width / 2;
21075
+ this.addChild(point);
21076
+ if (prevPos) {
21077
+ const linePath = new TimeLinePath();
21078
+ linePath.lineColor = 'red';
21079
+ linePath.startPos = prevPos;
21080
+ linePath.endPos = { x: currX, y: currY };
21081
+ this.addChild(linePath);
21082
+ }
21083
+ prevPos = { x: currX, y: currY };
21084
+ });
21085
+ }
21086
+ }
21087
+ }
21088
+ buildStampUnit(e) {
21089
+ if (!this.eventData.length) {
21090
+ return;
21091
+ }
21092
+ const { timeTickHours, timeTickWidth, heartRateSymbol } = timelineConfig;
21093
+ for (let i = 0; i < this.showDays; i++) {
21094
+ const ticks = 24 / timeTickHours;
21095
+ for (let j = 0; j < ticks; j++) {
21096
+ const hourOffset = j * timeTickHours;
21097
+ const x = i * timeTickWidth * ticks + j * timeTickWidth;
21098
+ const startTime = moment__default$1["default"](this.startTime).add(i, 'days').add(hourOffset, 'hours');
21099
+ const endTime = moment__default$1["default"](this.startTime).add(i, 'days').add(hourOffset + timeTickHours, 'hours');
21100
+ const predicate = (item) => {
21101
+ return moment__default$1["default"](item).isBetween(startTime, endTime, null, '(]');
21102
+ };
21103
+ const currTimePoints = this.eventData.filter(item => predicate(item.date));
21104
+ currTimePoints.forEach(item => {
21105
+ let currX = x;
21106
+ const diffMinutes = moment__default$1["default"](item.date).diff(startTime, 'minutes');
21107
+ const offsetMinutes = diffMinutes * timeTickWidth / (timeTickHours * 60);
21108
+ currX += offsetMinutes;
21109
+ const tipLabel = new LabelNode();
21110
+ tipLabel.text = item.value;
21111
+ tipLabel.borderColor = '#000';
21112
+ tipLabel.border = 1;
21113
+ tipLabel.shadowBlur = 5;
21114
+ tipLabel.shadowColor = 'red';
21115
+ tipLabel.fontSize = 12;
21116
+ tipLabel.bgColor = '#fff';
21117
+ tipLabel.color = 'red';
21118
+ tipLabel.textWrapping = 'wrap';
21119
+ //tipLabel.width = 14;
21120
+ tipLabel.x = currX;
21121
+ tipLabel.y = 30;
21122
+ this.addChild(tipLabel);
21123
+ });
21124
+ }
21125
+ }
21126
+ }
21127
+ }
21128
+ /**
21129
+ * 心率数值标尺控件
21130
+ */
21131
+ class HeartRateValueRuleControl extends TimelineBaseControl {
21132
+ constructor() {
21133
+ super();
21134
+ this.width = 50;
21135
+ }
21136
+ //体温时间轴值模型
21137
+ heartRateTimeLineValueModel = [];
21138
+ buildOverride(e) {
21139
+ const width = this.width;
21140
+ const height = this.height;
21141
+ const label = new LabelNode();
21142
+ label.text = '心率';
21143
+ label.fontSize = timelineConfig.fontSize;
21144
+ label.fontName = timelineConfig.fontName;
21145
+ label.y = 5;
21146
+ this.addChild(label);
21147
+ const textProps = new TextProps();
21148
+ textProps.fontSize = timelineConfig.fontSize;
21149
+ textProps.fontName = timelineConfig.fontName;
21150
+ label.x = (width - e.render.measureText(label.text, textProps).width) / 2;
21151
+ const timelineValue = this.heartRateTimeLineValueModel.map(item => ({
21152
+ value: item.value,
21153
+ offset: (height) * item.offset
21154
+ }));
21155
+ timelineValue.forEach(item => {
21156
+ const valueLabel = new LabelNode();
21157
+ valueLabel.fontName = timelineConfig.fontName;
21158
+ valueLabel.fontSize = timelineConfig.fontSize;
21159
+ valueLabel.text = item.value + '';
21160
+ valueLabel.x = (width - e.render.measureText(valueLabel.text, textProps).width) / 2;
21161
+ valueLabel.y = item.offset;
21162
+ this.addChild(valueLabel);
21163
+ });
21164
+ }
21165
+ render(e) {
21166
+ }
21167
+ }
21168
+ /**
21169
+ * 体温数值标尺控件
21170
+ */
21171
+ class TemperatureValueRuleControl extends TimelineBaseControl {
21172
+ constructor() {
21173
+ super();
21174
+ this.width = 50;
21175
+ }
21176
+ //体温时间轴值模型
21177
+ temperatureTimeLineValueModel = [];
21178
+ buildOverride(e) {
21179
+ const width = this.width;
21180
+ const height = this.height;
21181
+ const label = new LabelNode();
21182
+ label.text = '体温';
21183
+ label.fontSize = timelineConfig.fontSize;
21184
+ label.fontName = timelineConfig.fontName;
21185
+ label.y = 5;
21186
+ this.addChild(label);
21187
+ label.x = (width - e.render.measureText2(label.text, label)) / 2;
21188
+ const timelineValue = this.temperatureTimeLineValueModel.map(item => ({
21189
+ value: item.value,
21190
+ offset: (height) * item.offset
21191
+ }));
21192
+ timelineValue.forEach(item => {
21193
+ const valueLabel = new LabelNode();
21194
+ valueLabel.fontName = timelineConfig.fontName;
21195
+ valueLabel.fontSize = timelineConfig.fontSize;
21196
+ valueLabel.text = item.value + '';
21197
+ valueLabel.x = (width - e.render.measureText2(valueLabel.text, valueLabel)) / 2;
21198
+ valueLabel.y = item.offset;
21199
+ this.addChild(valueLabel);
21200
+ });
21201
+ }
21202
+ render(e) {
21203
+ }
21204
+ }
21205
+
21206
+ /**
21207
+ * 事件轴标题
21208
+ * 日期、手术天数、术后天数、时刻
21209
+ */
21210
+ class TimeTickTitleControl extends TimelineBaseControl {
21211
+ constructor() {
21212
+ super();
21213
+ this.bgColor = '#fff';
21214
+ }
21215
+ title;
21216
+ render(e) {
21217
+ }
21218
+ buildOverride(e) {
21219
+ const width = this.width;
21220
+ const height = this.height;
21221
+ const label = new LabelNode();
21222
+ label.text = this.title;
21223
+ label.fontSize = timelineConfig.fontSize;
21224
+ label.fontName = timelineConfig.fontName;
21225
+ const titleWidth = e.render.measureText2(label.text, label);
21226
+ label.x = (width - titleWidth) / 2;
21227
+ label.y = (height - label.fontSize) / 2;
21228
+ this.addChild(label);
21229
+ }
21230
+ }
21231
+ /**
21232
+ * 文本状态时刻控件,用于显示状态文本,例如:小便等
21233
+ */
21234
+ class TextStatusTickControl extends TimelineBaseControl {
21235
+ render(e) {
21236
+ }
21237
+ buildOverride(e) {
21238
+ const { timeTickHours, timeTickWidth } = timelineConfig;
21239
+ const height = this.height;
21240
+ const ticks = 24 / timeTickHours;
21241
+ for (let i = 0; i < this.showDays; i++) {
21242
+ const width = ticks * timeTickWidth;
21243
+ // const curr = moment(this.startTime).add(i, 'days').format('YYYY-MM-DD');
21244
+ //
21245
+ // const label = new LabelNode();
21246
+ // label.text = curr + '';
21247
+ // label.fontSize = timelineConfig.fontSize;
21248
+ // label.fontName = timelineConfig.fontName;
21249
+ //
21250
+ // const dateTitleWidth = e.render.measureText2(curr + '', label);
21251
+ //
21252
+ // label.x = i * width + (width - dateTitleWidth) / 2;
21253
+ // label.y = (height - label.fontSize) / 2;
21254
+ // this.addChild(label);
21255
+ const path = new TimeLinePath();
21256
+ path.startPos = { x: i * width, y: 0 };
21257
+ path.endPos = { x: i * width, y: height };
21258
+ path.lineColor = '#ffadd2';
21259
+ this.addChild(path);
21260
+ }
21261
+ }
21262
+ }
21263
+ /**
21264
+ * 呼吸状态容器
21265
+ */
21266
+ class TimelineHXStatusContainer extends TickContainer {
21267
+ tickTitleControl;
21268
+ constructor() {
21269
+ super();
21270
+ this.tickTitleControl = new TimeTickTitleControl();
21271
+ this.tickTitleControl.title = '呼吸';
21272
+ this.tickTitleControl.height = timelineConfig.tickHeaderHeight;
21273
+ this.tickControl = new TextStatusTickControl();
21274
+ this.tickControl.height = timelineConfig.tickHeaderHeight;
21275
+ this.addChild(this.tickControl);
21276
+ this.addChild(this.tickTitleControl);
21277
+ this.height = timelineConfig.tickHeaderHeight;
21278
+ }
21279
+ /**
21280
+ * 设置标题和刻度宽度
21281
+ * @param titleWidth
21282
+ * @param tickWidth
21283
+ */
21284
+ setLayout(titleWidth, tickWidth) {
21285
+ this.width = tickWidth + titleWidth;
21286
+ this.tickTitleControl.width = titleWidth;
21287
+ this.tickControl.width = tickWidth;
21288
+ this.tickControl.x = titleWidth;
21289
+ }
21290
+ render(e) {
21291
+ }
21292
+ }
21293
+ /**
21294
+ * 小便状态容器
21295
+ */
21296
+ class TimelineXBStatusContainer extends TickContainer {
21297
+ //statusControl: TextStatusTickControl;
21298
+ tickTitleControl;
21299
+ constructor() {
21300
+ super();
21301
+ this.tickTitleControl = new TimeTickTitleControl();
21302
+ this.tickTitleControl.title = '小便 ml';
21303
+ this.tickTitleControl.height = timelineConfig.tickHeaderHeight;
21304
+ this.tickControl = new TextStatusTickControl();
21305
+ this.tickControl.height = timelineConfig.tickHeaderHeight;
21306
+ this.addChild(this.tickControl);
21307
+ this.addChild(this.tickTitleControl);
21308
+ this.height = timelineConfig.tickHeaderHeight;
21309
+ }
21310
+ /**
21311
+ * 设置标题和刻度宽度
21312
+ * @param titleWidth
21313
+ * @param tickWidth
21314
+ */
21315
+ setLayout(titleWidth, tickWidth) {
21316
+ this.width = tickWidth + titleWidth;
21317
+ this.tickTitleControl.width = titleWidth;
21318
+ this.tickControl.width = tickWidth;
21319
+ this.tickControl.x = titleWidth;
21320
+ }
21321
+ render(e) {
21322
+ }
21323
+ }
21324
+ /**
21325
+ * 其他状态容器
21326
+ */
21327
+ class TimelineOtherStatusContainer extends TickContainer {
21328
+ //statusControl: TextStatusTickControl;
21329
+ tickTitleControl;
21330
+ constructor() {
21331
+ super();
21332
+ this.tickTitleControl = new TimeTickTitleControl();
21333
+ this.tickTitleControl.title = '其他';
21334
+ this.tickTitleControl.height = timelineConfig.tickHeaderHeight;
21335
+ this.tickControl = new TextStatusTickControl();
21336
+ this.tickControl.height = timelineConfig.tickHeaderHeight;
21337
+ this.addChild(this.tickControl);
21338
+ this.addChild(this.tickTitleControl);
21339
+ this.height = timelineConfig.tickHeaderHeight;
21340
+ }
21341
+ /**
21342
+ * 设置标题和刻度宽度
21343
+ * @param titleWidth
21344
+ * @param tickWidth
21345
+ */
21346
+ setLayout(titleWidth, tickWidth) {
21347
+ this.width = tickWidth + titleWidth;
21348
+ this.tickTitleControl.width = titleWidth;
21349
+ this.tickControl.width = tickWidth;
21350
+ this.tickControl.x = titleWidth;
21351
+ }
21352
+ render(e) {
21353
+ }
21354
+ }
21355
+
21356
+ /**
21357
+ * 时间刻度区域
21358
+ * 循环日期显示
21359
+ * 住院天数
21360
+ * 术后天数
21361
+ * 时刻等
21362
+ */
21363
+ /**
21364
+ * 日期时刻容器
21365
+ */
21366
+ class DateTickContainer extends TickContainer {
21367
+ tickTitleControl;
21368
+ constructor() {
21369
+ super();
21370
+ this.tickTitleControl = new TimeTickTitleControl();
21371
+ this.tickTitleControl.title = '日期';
21372
+ this.tickTitleControl.height = timelineConfig.tickHeaderHeight;
21373
+ this.tickControl = new DateTickControl();
21374
+ this.tickControl.height = timelineConfig.tickHeaderHeight;
21375
+ this.addChild(this.tickControl);
21376
+ this.addChild(this.tickTitleControl);
21377
+ this.height = timelineConfig.tickHeaderHeight;
21378
+ }
21379
+ /**
21380
+ * 设置标题和刻度宽度
21381
+ * @param titleWidth
21382
+ * @param tickWidth
21383
+ */
21384
+ setLayout(titleWidth, tickWidth) {
21385
+ this.width = tickWidth + titleWidth;
21386
+ this.tickTitleControl.width = titleWidth;
21387
+ this.tickControl.width = tickWidth;
21388
+ this.tickControl.x = titleWidth;
21389
+ }
21390
+ render(e) {
21391
+ }
21392
+ }
21393
+ /**
21394
+ * 日期刻度
21395
+ */
21396
+ class DateTickControl extends TimelineBaseControl {
21397
+ buildOverride(e) {
21398
+ const { timeTickHours, timeTickWidth } = timelineConfig;
21399
+ const height = this.height;
21400
+ const ticks = 24 / timeTickHours;
21401
+ for (let i = 0; i < this.showDays; i++) {
21402
+ const width = ticks * timeTickWidth;
21403
+ const curr = moment__default$1["default"](this.startTime).add(i, 'days').format('YYYY-MM-DD');
21404
+ const label = new LabelNode();
21405
+ label.text = curr + '';
21406
+ label.fontSize = timelineConfig.fontSize;
21407
+ label.fontName = timelineConfig.fontName;
21408
+ const dateTitleWidth = e.render.measureText2(curr + '', label);
21409
+ label.x = i * width + (width - dateTitleWidth) / 2;
21410
+ label.y = (height - label.fontSize) / 2;
21411
+ this.addChild(label);
21412
+ const path = new TimeLinePath();
21413
+ path.startPos = { x: i * width, y: 0 };
21414
+ path.endPos = { x: i * width, y: height };
21415
+ path.lineColor = '#ffadd2';
21416
+ this.addChild(path);
21417
+ }
21418
+ }
21419
+ render(e) {
21420
+ }
21421
+ }
21422
+ class TimeTickContainer extends TickContainer {
21423
+ tickTitleControl;
21424
+ constructor() {
21425
+ super();
21426
+ this.tickTitleControl = new TimeTickTitleControl();
21427
+ this.tickTitleControl.title = '时刻';
21428
+ this.tickTitleControl.height = timelineConfig.tickHeaderHeight;
21429
+ this.tickControl = new TimeTickControl();
21430
+ this.tickControl.height = timelineConfig.tickHeaderHeight;
21431
+ this.addChild(this.tickControl);
21432
+ this.addChild(this.tickTitleControl);
21433
+ this.height = timelineConfig.tickHeaderHeight;
21434
+ }
21435
+ /**
21436
+ * 设置标题和刻度宽度
21437
+ * @param titleWidth
21438
+ * @param tickWidth
21439
+ */
21440
+ setLayout(titleWidth, tickWidth) {
21441
+ this.width = tickWidth + titleWidth;
21442
+ this.tickTitleControl.width = titleWidth;
21443
+ this.tickControl.width = tickWidth;
21444
+ this.tickControl.x = titleWidth;
21445
+ }
21446
+ render(e) {
21447
+ }
21448
+ }
21449
+ class TimeTickControl extends TimelineBaseControl {
21450
+ constructor() {
21451
+ super();
21452
+ this.border = 1;
21453
+ this.borderColor = '#000';
21454
+ }
21455
+ showDays = 7;
21456
+ buildOverride(e) {
21457
+ const { timeTickHours, timeTickWidth } = timelineConfig;
21458
+ const ticks = 24 / timeTickHours;
21459
+ for (let i = 0; i < this.showDays; i++) {
21460
+ for (let j = 1; j <= ticks; j++) {
21461
+ const hourOffset = j * timeTickHours;
21462
+ const x = i * timeTickWidth * ticks + j * timeTickWidth;
21463
+ const text = hourOffset + '';
21464
+ const label = new LabelNode();
21465
+ label.text = text;
21466
+ label.fontSize = timelineConfig.fontSize;
21467
+ label.fontName = timelineConfig.fontName;
21468
+ const dateTitleWidth = e.render.measureText2(text, label);
21469
+ label.x = x - timeTickWidth + (timeTickWidth - dateTitleWidth) / 2;
21470
+ label.y = 0;
21471
+ this.addChild(label);
21472
+ }
21473
+ }
21474
+ }
21475
+ render(e) {
21476
+ const { timeTickHours, timeTickWidth } = timelineConfig;
21477
+ const ticks = 24 / timeTickHours;
21478
+ for (let i = 0; i < this.showDays; i++) {
21479
+ for (let j = 1; j <= ticks; j++) {
21480
+ const x = i * timeTickWidth * ticks + j * timeTickWidth;
21481
+ const color = j < ticks ? '#69c0ff' : '#ffadd2';
21482
+ e.render.strokeLines([{
21483
+ x,
21484
+ y: 0
21485
+ }, { x, y: this.finalRect.height }], 1, color);
21486
+ }
21487
+ }
21488
+ }
21489
+ }
21490
+ class InPatDaysTickContainer extends TickContainer {
21491
+ //inPatDaysControl: InPatDaysControl;
21492
+ tickTitleControl;
21493
+ constructor() {
21494
+ super();
21495
+ this.tickTitleControl = new TimeTickTitleControl();
21496
+ this.tickTitleControl.title = '住院天数';
21497
+ this.tickTitleControl.height = timelineConfig.tickHeaderHeight;
21498
+ this.tickControl = new InPatDaysControl();
21499
+ this.tickControl.height = timelineConfig.tickHeaderHeight;
21500
+ this.addChild(this.tickControl);
21501
+ this.addChild(this.tickTitleControl);
21502
+ this.height = timelineConfig.tickHeaderHeight;
21503
+ }
21504
+ /**
21505
+ * 设置标题和刻度宽度
21506
+ * @param titleWidth
21507
+ * @param tickWidth
21508
+ */
21509
+ setLayout(titleWidth, tickWidth) {
21510
+ this.width = tickWidth + titleWidth;
21511
+ this.tickTitleControl.width = titleWidth;
21512
+ this.tickControl.width = tickWidth;
21513
+ this.tickControl.x = titleWidth;
21514
+ }
21515
+ render(e) {
21516
+ }
21517
+ }
21518
+ class InPatDaysControl extends TimelineBaseControl {
21519
+ buildOverride(e) {
21520
+ const { timeTickHours, timeTickWidth } = timelineConfig;
21521
+ const height = this.height;
21522
+ const ticks = 24 / timeTickHours;
21523
+ for (let i = 0; i < this.showDays; i++) {
21524
+ const width = ticks * timeTickWidth;
21525
+ const text = (i + 1) + '';
21526
+ const label = new LabelNode();
21527
+ label.text = text;
21528
+ label.fontSize = timelineConfig.fontSize;
21529
+ label.fontName = timelineConfig.fontName;
21530
+ const dateTitleWidth = e.render.measureText2(text, label);
21531
+ label.x = i * width + (width - dateTitleWidth + label.fontSize) / 2;
21532
+ label.y = (height - label.fontSize) / 2;
21533
+ this.addChild(label);
21534
+ const path = new TimeLinePath();
21535
+ path.startPos = { x: i * width, y: 0 };
21536
+ path.endPos = { x: i * width, y: height };
21537
+ path.lineColor = '#ffadd2';
21538
+ this.addChild(path);
21539
+ }
21540
+ }
21541
+ render(e) {
21542
+ }
21543
+ }
21544
+
21545
+ class TimelineScrollBar extends NodeItems {
21546
+ //滚动条方向
21547
+ orientation = 'horizontal';
21548
+ thumb;
21549
+ thumbSize = 10;
21550
+ //按照百分比计算
21551
+ scrollChanged = new Subject();
21552
+ //总滚动宽度
21553
+ scrollSize = 0;
21554
+ //显示区域宽度
21555
+ viewSize = 0;
21556
+ scrollX = 0;
21557
+ scrollY = 0;
21558
+ constructor(orientation) {
21559
+ super();
21560
+ this.bgColor = '#fff';
21561
+ this.border = 1;
21562
+ this.borderColor = '#000';
21563
+ this.height = 16;
21564
+ this.orientation = orientation;
21565
+ this.thumb = new ScrollThumb();
21566
+ this.addChild(this.thumb);
21567
+ this.thumb.addEventListener('mousedown', evt => {
21568
+ const pos = { ...evt.pos };
21569
+ const { x, y } = this.thumb.finalRect;
21570
+ const mouseMoveListener = (evt2) => {
21571
+ //const scrollView = this.parent as ScrollView;
21572
+ const pos2 = evt2.pos;
21573
+ let moveX = pos2.x - pos.x;
21574
+ let moveY = pos2.y - pos.y;
21575
+ moveX += x;
21576
+ moveY += y;
21577
+ moveX = (moveX / this.finalRect.width) * this.scrollSize;
21578
+ moveY = (moveY / this.finalRect.height) * this.scrollSize;
21579
+ this.updateScroll(moveX, moveY);
21580
+ };
21581
+ const mouseUpListener = (evt3) => {
21582
+ this.thumb.removeEventListener('mousemove', mouseMoveListener);
21583
+ this.thumb.removeEventListener('mouseup', mouseUpListener);
21584
+ };
21585
+ this.thumb.addEventListener('mousemove', mouseMoveListener);
21586
+ this.thumb.addEventListener('mouseup', mouseUpListener);
21587
+ });
21588
+ }
21589
+ updateScroll(x, y) {
21590
+ //const scrollView = this.parent as ScrollView;
21591
+ if (this.orientation === 'horizontal') {
21592
+ if (this.finalRect.height === 0) {
21593
+ return;
21594
+ }
21595
+ if (x + this.viewSize > this.scrollSize) {
21596
+ x = this.scrollSize - this.viewSize;
21597
+ }
21598
+ x = x < 0 ? 0 : x;
21599
+ this.scrollChanged.next(x);
21600
+ this.scrollX = x;
21601
+ }
21602
+ }
21603
+ updateScrollByCurrent(increaseX, increaseY) {
21604
+ //const scrollView = this.parent as ScrollView;
21605
+ increaseX += this.scrollX;
21606
+ increaseY += this.scrollY;
21607
+ this.updateScroll(increaseX, increaseY);
21608
+ }
21609
+ measureOverride(e, availableSize) {
21610
+ if (this.orientation === 'horizontal') {
21611
+ return this.measureHorizontalBar(e, availableSize);
21612
+ }
21613
+ else {
21614
+ //return this.measureVerticalBar(e, availableSize);
21615
+ throw new Error('未实现');
21616
+ }
21617
+ }
21618
+ /**
21619
+ * 横向滚动条测量
21620
+ */
21621
+ measureHorizontalBar(e, availableSize) {
21622
+ if (this.scrollSize > this.viewSize) {
21623
+ //计算滚动按钮的长度
21624
+ const thumbWidth = (this.viewSize / this.scrollSize) * availableSize.width;
21625
+ this.thumb.measure(e, { width: thumbWidth, height: this.thumbSize });
21626
+ return { width: availableSize.width, height: ScrollBarSize };
21627
+ }
21628
+ else {
21629
+ this.thumb.measure(e, { width: 0, height: 0 });
21630
+ return { width: 0, height: 0 };
21631
+ }
21632
+ }
21633
+ arrangeOverride(e, finalSize) {
21634
+ //const scrollView = this.parent as ScrollView;
21635
+ const { width, height } = this.thumb.desiredSize;
21636
+ const x = this.orientation === 'horizontal' ? (this.scrollX / this.scrollSize) * finalSize.width : (ScrollBarSize - this.thumbSize) / 2;
21637
+ const y = this.orientation === 'horizontal' ? (ScrollBarSize - this.thumbSize) / 2 : (this.scrollY / this.scrollSize) * finalSize.height;
21638
+ this.thumb.arrange(e, { x, y, width, height });
21639
+ return super.arrangeOverride(e, finalSize);
21640
+ }
21641
+ render(e) {
21642
+ //e.render.contentContext.clearRect(0,0,this.finalRect.width,this.finalRect.height);
21643
+ //e.render.fillRect(0, 0, this.finalRect.width, this.finalRect.height, 'red')
21644
+ }
21645
+ }
21646
+
21647
+ function createTimeline() {
21648
+ const timeline = new TimelineControl();
21649
+ timeline.width = 940;
21650
+ const timeGridContainer = new TimeGridContainer();
21651
+ //timeGridContainer.y = 80;
21652
+ const timelineGridControl = timeGridContainer.timelineGridControl; //new TimeLineControl();
21653
+ timelineGridControl.showDays = 30;
21654
+ timelineGridControl.width = timelineGridControl.getLayoutWidth();
21655
+ timelineGridControl.height = 300;
21656
+ timelineGridControl.init();
21657
+ const tempValueRule = new TemperatureValueRuleControl();
21658
+ tempValueRule.temperatureTimeLineValueModel = timelineGridControl.temperatureTimeLineValueModel;
21659
+ tempValueRule.bgColor = '#fff';
21660
+ tempValueRule.height = timelineGridControl.height;
21661
+ timeGridContainer.timeValueRuleContainer.addChild(tempValueRule);
21662
+ tempValueRule.addEventListener('mouseenter', evt => {
21663
+ tempValueRule.bgColor = 'grey';
21664
+ const mousemoveHandler = () => {
21665
+ tempValueRule.bgColor = '#fff';
21666
+ tempValueRule.removeEventListener('mouseleave', mousemoveHandler);
21667
+ };
21668
+ tempValueRule.addEventListener('mouseleave', mousemoveHandler);
21669
+ });
21670
+ const heartRateValueRule = new HeartRateValueRuleControl();
21671
+ heartRateValueRule.heartRateTimeLineValueModel = timelineGridControl.heartRateTimeLineValueModel;
21672
+ heartRateValueRule.bgColor = '#fff';
21673
+ heartRateValueRule.height = timelineGridControl.height;
21674
+ timeGridContainer.timeValueRuleContainer.addChild(heartRateValueRule);
21675
+ heartRateValueRule.addEventListener('mouseenter', evt => {
21676
+ heartRateValueRule.bgColor = 'grey';
21677
+ const mousemoveHandler = () => {
21678
+ heartRateValueRule.bgColor = '#fff';
21679
+ heartRateValueRule.removeEventListener('mouseleave', mousemoveHandler);
21680
+ };
21681
+ heartRateValueRule.addEventListener('mouseleave', mousemoveHandler);
21682
+ });
21683
+ timeGridContainer.timeValueRuleContainer.init();
21684
+ const titleWidth = timeGridContainer.timeValueRuleContainer.getLayoutWidth();
21685
+ timeGridContainer.timeValueRuleContainer.width = titleWidth;
21686
+ timeGridContainer.timeValueRuleContainer.height = timelineGridControl.height;
21687
+ timeGridContainer.timelineGridControl.x = timeGridContainer.timeValueRuleContainer.width;
21688
+ const dateHeader = new DateTickContainer();
21689
+ dateHeader.showDays = timelineGridControl.showDays;
21690
+ dateHeader.setLayout(titleWidth, timelineGridControl.width);
21691
+ timeline.addChild(dateHeader);
21692
+ const inDaysHeader = new InPatDaysTickContainer();
21693
+ inDaysHeader.showDays = timelineGridControl.showDays;
21694
+ inDaysHeader.setLayout(titleWidth, timelineGridControl.width);
21695
+ timeline.addChild(inDaysHeader);
21696
+ const timeHeader = new TimeTickContainer();
21697
+ timeHeader.showDays = timelineGridControl.showDays;
21698
+ timeHeader.setLayout(titleWidth, timelineGridControl.width);
21699
+ timeline.addChild(timeHeader);
21700
+ timeline.addChild(timeGridContainer);
21701
+ const hxStatus = new TimelineHXStatusContainer();
21702
+ hxStatus.showDays = timelineGridControl.showDays;
21703
+ hxStatus.setLayout(titleWidth, timelineGridControl.width);
21704
+ timeline.addChild(hxStatus);
21705
+ const xbStatus = new TimelineXBStatusContainer();
21706
+ xbStatus.showDays = timelineGridControl.showDays;
21707
+ xbStatus.setLayout(titleWidth, timelineGridControl.width);
21708
+ timeline.addChild(xbStatus);
21709
+ const otStatus = new TimelineOtherStatusContainer();
21710
+ otStatus.showDays = timelineGridControl.showDays;
21711
+ otStatus.setLayout(titleWidth, timelineGridControl.width);
21712
+ timeline.addChild(otStatus);
21713
+ const timelineScrollbar = new TimelineScrollBar('horizontal');
21714
+ timelineScrollbar.scrollSize = timelineGridControl.width;
21715
+ timelineScrollbar.viewSize = 840;
21716
+ timelineScrollbar.width = timeline.width;
21717
+ timelineScrollbar.scrollChanged.subscribe(data => {
21718
+ dateHeader.scrollX = data;
21719
+ inDaysHeader.scrollX = data;
21720
+ timeHeader.scrollX = data;
21721
+ timeGridContainer.scrollX = data;
21722
+ xbStatus.scrollX = data;
21723
+ hxStatus.scrollX = data;
21724
+ otStatus.scrollX = data;
21725
+ });
21726
+ timeline.addChild(timelineScrollbar);
21727
+ return timeline;
21728
+ }
21729
+
21730
+ /**
21731
+ * Node宽度定义
21732
+ * 1.在单页模式下,文档最小宽度为单个文档宽度+合适的外边距
21733
+ * 2.在多页模式下,文档最小宽度为单个文档宽度+合适的外边距
21734
+ */
21735
+ class CanvasTextEditor extends AbsolutePanel {
21736
+ container;
21737
+ contentCtx;
21738
+ viewOptions;
21739
+ docCtx;
21740
+ docComment;
21741
+ renderContext;
21742
+ documentPaint;
21743
+ elementReader;
21744
+ documentEvent;
21745
+ documentSelection;
21746
+ documentInput;
21747
+ documentChange;
21748
+ selectionOverlays;
21749
+ //private docRule: DocRule;
21750
+ historyMange;
21751
+ selectionChanged = new Subject$1();
21752
+ beforeRenderSubject = new Subject$1();
21753
+ afterRenderSubject = new Subject$1();
21754
+ selectionState;
21755
+ //显示右键菜单
21756
+ onContextMenuItemChanged = new Subject$1();
21757
+ onDblClickEvent = new Subject$1();
21758
+ onClickEvent = new Subject$1();
21759
+ onScrollViewEvent = new Subject$1();
21760
+ //文档改变事件:内容及样式,业务模块需要根据此事件,来追踪当前文档是否改变的状态
21761
+ onDocChangedEvent = new Subject$1();
21762
+ //执行flushTask,refreshDoc之前,此时可以在文档计算排版之前改变内容
21763
+ onBeforeRefreshDocument = new Subject$1();
21764
+ editCanvas;
21765
+ editInput;
21766
+ constructor(container) {
21767
+ super();
21768
+ this.container = container;
21769
+ this.createDocDOM();
21770
+ this.viewOptions = new ViewOptions();
21771
+ this.documentSelection = new DocumentSelection();
21772
+ this.docCtx = new EditorContext(this.documentSelection.selectionState, this.viewOptions);
21773
+ this.viewOptions.copyRightInfo = '电子病历编辑器(XXX版权所有)';
21774
+ this.viewOptions.drawCharRectColor = 'green';
21775
+ this.viewOptions.showLineRect = true;
21776
+ this.viewOptions.docSpace = 20;
21777
+ this.viewOptions.reviewWindowWidth = 200;
21778
+ this.viewOptions.defaultFontName = '宋体';
21779
+ //this.viewOptions.scale = 2;
21780
+ //整个画布的尺寸
21781
+ this.viewOptions.viewSettings = {
21782
+ width: 1000,
21783
+ height: 200
21784
+ };
21785
+ this.viewOptions.editUser = {
21786
+ id: '6666',
21787
+ name: '管理员'
21788
+ };
21789
+ this.viewOptions.fullPageView = false;
21790
+ this.createDocViewer();
21791
+ this.docComment = new DocumentComment(this.docCtx);
21792
+ this.contentCtx = this.editCanvas.getContext('2d');
21793
+ this.renderContext = new RenderContext(new PaintContent(this.contentCtx));
21794
+ this.renderContext.init({ width: 500, height: 500, scale: 1 });
21795
+ this.selectionState = this.documentSelection.selectionState;
21796
+ this.selectionOverlays = new SelectionOverlays(this.documentSelection.selectionState);
21797
+ this.documentPaint = new DocumentPaint(this.renderContext, this.docCtx, this.selectionOverlays.selectedSets);
21798
+ this.elementReader = new ElementReader(this.docCtx);
21799
+ this.documentInput = new DocumentInput(this, this.docCtx);
21800
+ this.documentChange = new DocumentChange(this.elementReader, this.docCtx, this.docComment, this.documentInput);
21801
+ this.documentEvent = new DocumentEvent(this, this.documentPaint, this.docCtx, this.documentInput);
21802
+ this.historyMange = new ElementTrackManage(this.docCtx, this.elementReader);
21803
+ this.documentEvent.hitInfoChanged.subscribe((hitInfo) => {
21804
+ this.hitInfoChanged(hitInfo);
21805
+ });
21806
+ this.documentEvent.clickEvent.subscribe((evt) => {
21807
+ this.docClickHandle(evt);
21808
+ });
21809
+ this.documentEvent.dblClickEvent.subscribe((evt) => {
21810
+ this.docDblClickHandle(evt);
21811
+ });
21812
+ this.documentEvent.changeCursor.subscribe((cursor) => {
21813
+ this.changeCursor(cursor);
21814
+ });
21815
+ this.documentEvent.contextMenu.subscribe(evt => {
21816
+ this.onContextMenu(evt);
21817
+ });
21818
+ this.documentEvent.trackTipsChanged.subscribe(data => {
21819
+ });
21820
+ this.docCtx.docChange = this.documentChange;
21821
+ //this.listenContainerHeight();
21822
+ this.start();
21823
+ this.refreshDocRule();
21824
+ this.docCtx.syncRefresh = () => {
21825
+ this.flushToSchedule();
21826
+ };
21827
+ this.viewOptions.onChange.subscribe((type) => {
21828
+ this.resetViewer(type);
21829
+ });
21830
+ }
21831
+ createDocDOM() {
21832
+ const container = document.getElementById(this.container);
21833
+ const canvas = document.createElement('canvas');
21834
+ const input = document.createElement('input');
21835
+ container.style.overflow = 'hidden';
21836
+ container.style.position = 'relative';
21837
+ container.style.fontSize = '0';
21838
+ container.style.height = '100%';
21839
+ input.style.position = 'absolute';
21840
+ input.style.width = '1px';
21841
+ input.style.padding = '0';
21842
+ input.style.border = 'none';
21843
+ input.style.outline = 'none';
21844
+ input.style.background = 'black';
21845
+ input.style.pointerEvents = 'none';
21846
+ this.editCanvas = canvas;
21847
+ this.editInput = input;
21848
+ container.appendChild(canvas);
21849
+ container.appendChild(input);
21850
+ container.insertAdjacentElement('afterbegin', input);
21851
+ container.insertAdjacentElement('afterbegin', canvas);
21852
+ }
21853
+ destroyDOM() {
21854
+ this.editInput.remove();
21855
+ this.editCanvas.remove();
21856
+ }
21857
+ /**
21858
+ * 设置标尺
21859
+ */
21860
+ refreshDocRule() {
21861
+ let docLeft = 0; //CommonUtil.getOffsetX(this.editCanvas.parentElement as HTMLDivElement);
21862
+ let pagePL = 0, pagePR = 0;
21863
+ if (this.documentPaint.docContainer) {
21864
+ docLeft += this.documentPaint.docContainer.rect.x;
21865
+ }
21866
+ if (this.docCtx.document?.props?.padding) {
21867
+ const { left, right } = this.docCtx.document.props.padding;
21868
+ pagePL = left;
21869
+ pagePR = right;
21870
+ }
21871
+ this.rule.setRuleOptions({ width: this.viewOptions.docPageSettings.width, pagePL, pagePR, docLeft });
21872
+ }
21873
+ createDocViewer() {
21874
+ this.viewOptions.mmToPixelsRatio = this.measureMMToPixs();
21875
+ const width = Math.floor(210 * this.viewOptions.mmToPixelsRatio);
21876
+ const height = Math.floor(297 * this.viewOptions.mmToPixelsRatio);
21877
+ this.viewOptions.docPageSettings = new PageOptions(width, height);
21878
+ // this.docScroll.onscroll = (evt) => {
21879
+ // //this.onScrollViewHandler(evt);
21880
+ // };
20430
21881
  }
20431
21882
  measureMMToPixs() {
20432
21883
  const div = document.createElement('div');
@@ -20726,7 +22177,7 @@ class CanvasTextEditor extends AbsolutePanel {
20726
22177
  }
20727
22178
  const elementEvent = new ContextMenuElementEvent(this.docCtx);
20728
22179
  elementEvent.source = startControl;
20729
- DocumentEvent.invokeEvent('ElementContextMenu', startControl, elementEvent, 'All', this.docCtx);
22180
+ DocumentEvent.invokeEvent('ElementContextMenu', startControl, elementEvent, 'All');
20730
22181
  const position = { x: evt.offsetX + 10, y: evt.offsetY, translateY: this.viewOptions.pageOffset.y };
20731
22182
  this.onContextMenuItemChanged.next({ pos: position, menus: elementEvent.menus });
20732
22183
  }
@@ -20825,6 +22276,9 @@ class CanvasTextEditor extends AbsolutePanel {
20825
22276
  destroy() {
20826
22277
  this.docCtx.destroy();
20827
22278
  this.documentEvent.clearSubEvent();
22279
+ this.selectionState.destroy();
22280
+ this.surfaceView.destroy();
22281
+ this.destroyDOM();
20828
22282
  this.flushTask = null;
20829
22283
  }
20830
22284
  /**
@@ -20892,14 +22346,16 @@ class CanvasTextEditor extends AbsolutePanel {
20892
22346
  return null;
20893
22347
  }
20894
22348
  /**
20895
- * 设置段落对齐
20896
- * @param align
22349
+ * 设置段落样式
22350
+ * @param newProps
20897
22351
  */
20898
- switchParaAlign(align) {
22352
+ setParaStyle(newProps) {
20899
22353
  const setterFunc = (paraProps) => {
20900
- paraProps.textAlign = align;
22354
+ Object.keys(newProps).forEach(key => {
22355
+ paraProps[key] = newProps[key];
22356
+ });
20901
22357
  };
20902
- DocumentChange.setParaAlign(this.selectionState, setterFunc);
22358
+ DocumentChange.setParaStyle(this.selectionState, setterFunc);
20903
22359
  }
20904
22360
  combineCell() {
20905
22361
  TableUtil.mergeCells(this.selectionState);
@@ -21110,80 +22566,6 @@ class CanvasTextEditor extends AbsolutePanel {
21110
22566
  this.viewOptions.pageLayoutMode = mode;
21111
22567
  this.flushToSchedule();
21112
22568
  }
21113
- // test2(): void {
21114
- // //获取文档上下文
21115
- // const docEleCtx = this.docCtx.getCtx(this.docCtx.document);
21116
- // //获取年龄数据元
21117
- // const dataEle = docEleCtx.getControlById('1493477712134672386') as DataElementText;
21118
- // //获取要隐藏的数据组
21119
- // const dataGroup = docEleCtx.ctx.treeFind((item) => item instanceof DataElementGroupElement) as DataElementGroupElement;
21120
- // //侦听数据元更改时间
21121
- // dataEle.onChangeSubject.subscribe((e) => {
21122
- // //在文档重新排版、绘制前,获取最终的指定节点的内容
21123
- // const beforeRefreshSub = this.onBeforeRefreshDocument.subscribe((e2) => {
21124
- // console.log('内容发生改变,隐藏数据组');
21125
- // //获取年龄数据元输入的值
21126
- // const age = Number.parseInt(dataEle.getValue());
21127
- // //年龄大于20,隐藏数据元
21128
- // dataGroup.props.hidden = age > 20;
21129
- // //取消订阅事件
21130
- // beforeRefreshSub.unsubscribe();
21131
- // });
21132
- //
21133
- // });
21134
- // }
21135
- //
21136
- // //修改纸张尺寸,单位为毫米
21137
- // //editor.setPaperSize(200,150)
21138
- // test3(width: number, height: number): void {
21139
- // this.setPaperSize(200, 150);
21140
- // }
21141
- //
21142
- // //在当前段落后面插入新的段落,段落内容为当前时间
21143
- // test4(): void {
21144
- // const {startControl} = this.selectionState;
21145
- // if (!startControl) {
21146
- // return;
21147
- // }
21148
- // //1.获取当前段落
21149
- // const currentParagraph = ElementUtil.getParentByType(startControl, ParagraphElement) as ParagraphElement;
21150
- // //2.创建新段落对象
21151
- // const newPara = ParagraphElement.createElement();
21152
- //
21153
- // //3.创建文本对象
21154
- // const newText = new TextGroupElement();
21155
- // newText.text = '当前时间为' + new Date();
21156
- // newText.props.fontName = '楷体';
21157
- // newText.props.fontSize = 18;
21158
- // newText.props.color = '#5b8c00';
21159
- // //4.将文本对象追加到新段落中
21160
- // newPara.addChild(newText);
21161
- // //5.在当前段落后面追加新段落
21162
- // currentParagraph.parent.addChild(newPara, currentParagraph.getIndex() + 1);
21163
- // //6.定位光标到新段落末尾处
21164
- // this.selectionState.resetRange(newText,-1);
21165
- // }
21166
- //
21167
- // //在当前位置插入文本数据元
21168
- // test5():void{
21169
- // const {startControl} = this.selectionState;
21170
- // if (!startControl) {
21171
- // return;
21172
- // }
21173
- // const newDataTextElement=new DataElementText();
21174
- // newDataTextElement.props.nullText='请输入内容';
21175
- // newDataTextElement.props.nullTextProps=new TextProps();
21176
- // newDataTextElement.props.nullTextProps.fontSize=16;
21177
- // newDataTextElement.props.nullTextProps.fontName='宋体';
21178
- // newDataTextElement.props.nullTextProps.color='#ffc53d';
21179
- // newDataTextElement.props.valueTextProps=new TextProps();
21180
- // newDataTextElement.props.valueTextProps.fontSize=18;
21181
- // newDataTextElement.props.valueTextProps.fontName='楷体';
21182
- // newDataTextElement.props.valueTextProps.color='red';
21183
- // this.insertNewElement(newDataTextElement);
21184
- //
21185
- // }
21186
- //
21187
22569
  // //覆盖修改页眉
21188
22570
  // test6():void{
21189
22571
  // //1.获取页眉对象
@@ -21243,7 +22625,8 @@ class CanvasTextEditor extends AbsolutePanel {
21243
22625
  const win = new Window();
21244
22626
  win.width = 1000;
21245
22627
  win.height = 800;
21246
- //win.content.addChild(timelineScrollbar)
22628
+ const timeLineControl = createTimeline();
22629
+ win.content.addChild(timeLineControl);
21247
22630
  const rule2 = new RuleControl(this.docCtx);
21248
22631
  this.rule = rule2;
21249
22632
  rule2.width = 700;
@@ -21459,26 +22842,6 @@ class CanvasTextEditor extends AbsolutePanel {
21459
22842
  insertNewRow(tb, insertRowIndex) {
21460
22843
  return TableUtil.insertNewRow(tb, insertRowIndex);
21461
22844
  }
21462
- generatorDoc(data) {
21463
- //根据传入的参数,动态生成病情信息的结构化报告
21464
- const para = new ParagraphElement();
21465
- //创建患者姓名文本标签
21466
- const patNameLabel = new TextGroupElement();
21467
- patNameLabel.text = "患者姓名:";
21468
- //添加到段落中
21469
- para.addChild(patNameLabel);
21470
- //创建患者姓名数据元
21471
- const patNameDataEle = new DataElementText();
21472
- patNameDataEle.props.valueTextProps = new TextProps();
21473
- patNameDataEle.props.valueTextProps.fontName = '宋体';
21474
- patNameDataEle.props.valueTextProps.fontSize = 16;
21475
- //数据元赋值
21476
- patNameDataEle.setValue(data.patName);
21477
- //添加到段落中
21478
- para.addChild(patNameDataEle);
21479
- //添加到正文中
21480
- this.docCtx.document.bodyElement.addChild(para);
21481
- }
21482
22845
  }
21483
22846
 
21484
22847
  /**
@@ -21897,6 +23260,7 @@ exports.InlineGroupElement = InlineGroupElement;
21897
23260
  exports.InlineGroupInputElement = InlineGroupInputElement;
21898
23261
  exports.InlineGroupRenderObject = InlineGroupRenderObject;
21899
23262
  exports.InlineMuiltBlockLineRenderObject = InlineMuiltBlockLineRenderObject;
23263
+ exports.InputElementEvent = InputElementEvent;
21900
23264
  exports.IsInSideDataElement = IsInSideDataElement;
21901
23265
  exports.IsInSideInlineGroupInputElement = IsInSideInlineGroupInputElement;
21902
23266
  exports.KeyboradElementEvent = KeyboradElementEvent;
@@ -21971,6 +23335,7 @@ exports.deleteCurrentParagraph = deleteCurrentParagraph;
21971
23335
  exports.documentPrint = documentPrint;
21972
23336
  exports.drawDecorator = drawDecorator;
21973
23337
  exports.elementTypeEventHandler = elementTypeEventHandler;
23338
+ exports.falseChar = falseChar;
21974
23339
  exports.fontMapFunc = fontMapFunc;
21975
23340
  exports.fromEvent = fromEvent;
21976
23341
  exports.getCalleeName = getCalleeName;
@@ -21991,6 +23356,7 @@ exports.targetMaps = targetMaps;
21991
23356
  exports.textLineRenderMode = textLineRenderMode;
21992
23357
  exports.toRawType = toRawType;
21993
23358
  exports.toTypeString = toTypeString;
23359
+ exports.trueChar = trueChar;
21994
23360
  exports.validateDataEle = validateDataEle;
21995
23361
  exports.validateDataEleRenderObj = validateDataEleRenderObj;
21996
23362
  exports.validateInlineInputRenderObj = validateInlineInputRenderObj;