@hailin-zheng/editor-core 1.1.18 → 1.1.20

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
  * 元素事件
@@ -4440,6 +4442,10 @@ class SelectionState {
4440
4442
  constructor() {
4441
4443
  this.clear();
4442
4444
  }
4445
+ destroy() {
4446
+ this.onChangedEvent.unsubscribe();
4447
+ this.clear();
4448
+ }
4443
4449
  clear() {
4444
4450
  this.range = null;
4445
4451
  this.startOffset = -1;
@@ -7718,6 +7724,19 @@ class ElementUtil {
7718
7724
  static getDataElement(ele) {
7719
7725
  return this.getParent(ele, item => item instanceof DataElementInlineGroup);
7720
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
+ }
7721
7740
  }
7722
7741
 
7723
7742
  class RenderContext {
@@ -11684,19 +11703,24 @@ class ParagraphMeasure {
11684
11703
  render.rect.width = parentLine.limitWidth - parentLine.lineWidth();
11685
11704
  parentLine.add(render);
11686
11705
  parentLine.applyNewLine();
11706
+ return;
11687
11707
  }
11688
- if (render.element && render.element.type === 'br') {
11708
+ else if (render.element && render.element.type === 'br') {
11689
11709
  parentLine.add(render);
11690
11710
  parentLine.applyNewLine();
11691
11711
  return;
11692
11712
  }
11693
- if (render.element && render.element.type === 'page-br') {
11713
+ else if (render.element && render.element.type === 'page-br') {
11694
11714
  parentLine.applyNewPara();
11695
11715
  }
11696
- if (render.element && render.element.type === 'psym') {
11716
+ else if (render.element && render.element.type === 'psym') {
11697
11717
  parentLine.add(render);
11698
11718
  return;
11699
11719
  }
11720
+ else {
11721
+ parentLine.add(render);
11722
+ parentLine.applyNewLine();
11723
+ }
11700
11724
  }
11701
11725
  else {
11702
11726
  parentLine.add(render);
@@ -14971,7 +14995,7 @@ class DocumentEvent {
14971
14995
  });
14972
14996
  document.execCommand('copy');
14973
14997
  };
14974
- if (navigator.appVersion.indexOf('Mac') >= 0) {
14998
+ if (ElementUtil.getOSPlatform() === 'Mac') {
14975
14999
  if (evt.metaKey && evt.keyCode === 67) {
14976
15000
  copy();
14977
15001
  }
@@ -15020,6 +15044,7 @@ class DocumentInput {
15020
15044
  onTabKeyEvent = new Subject$1();
15021
15045
  constructor(node, docCtx) {
15022
15046
  this.docCtx = docCtx;
15047
+ const os = ElementUtil.getOSPlatform();
15023
15048
  node.addEventListener('input', evt => {
15024
15049
  const { startControl, startOffset } = this.docCtx.selectionState;
15025
15050
  this.onInputEvent.next({
@@ -15067,7 +15092,11 @@ class DocumentInput {
15067
15092
  else if (evt.keyCode === 46) {
15068
15093
  this.onDeleteEvent.next(evt);
15069
15094
  }
15070
- else if (evt.ctrlKey && evt.keyCode === 65) {
15095
+ else if (evt.ctrlKey && evt.keyCode === 65 && os !== 'Mac') {
15096
+ evt.preventDefault();
15097
+ this.onSelectAllEvent.next();
15098
+ }
15099
+ else if (evt.metaKey && evt.keyCode === 65 && os === 'Mac') {
15071
15100
  evt.preventDefault();
15072
15101
  this.onSelectAllEvent.next();
15073
15102
  }
@@ -17817,7 +17846,6 @@ function setCurrentActiveAppContext(ctx) {
17817
17846
  currentActiveAppContext = ctx;
17818
17847
  }
17819
17848
  function renderApp(root, renderCtx, nodeEvent) {
17820
- window['root'] = root;
17821
17849
  // const nodeEvent = new NodeEvent(root, renderCtx.mainContext.ctx.canvas);
17822
17850
  let delayTask = false;
17823
17851
  const flushTask = () => {
@@ -17836,8 +17864,10 @@ function renderApp(root, renderCtx, nodeEvent) {
17836
17864
  };
17837
17865
  flushTask();
17838
17866
  root.onChangedEvent.subscribe(() => {
17867
+ if (root.isDisposed) {
17868
+ return;
17869
+ }
17839
17870
  flushTask();
17840
- //console.log('准备创建任务'+taskId)
17841
17871
  });
17842
17872
  nodeEvent.onSignal.subscribe(() => {
17843
17873
  flushTask();
@@ -19102,6 +19132,7 @@ class SurfaceView extends NodeItems {
19102
19132
  renderSchedule;
19103
19133
  nodeEvent;
19104
19134
  renderCtx;
19135
+ isDisposed = false;
19105
19136
  onSizeChanged = new Subject();
19106
19137
  constructor(canvas, input) {
19107
19138
  super();
@@ -19184,6 +19215,10 @@ class SurfaceView extends NodeItems {
19184
19215
  clearPopNodes() {
19185
19216
  this.popNodes = [];
19186
19217
  }
19218
+ destroy() {
19219
+ this.clearChildren();
19220
+ this.isDisposed = true;
19221
+ }
19187
19222
  initInputEvent() {
19188
19223
  let composition = false;
19189
19224
  this.input.addEventListener('input', evt => {
@@ -20393,14 +20428,1317 @@ function pointInPoly(pt, poly) {
20393
20428
  return c;
20394
20429
  }
20395
20430
 
20431
+ const timelineConfig = {
20432
+ fontSize: 12,
20433
+ fontName: '宋体',
20434
+ /**
20435
+ * 单个时刻的宽度,像素
20436
+ */
20437
+ timeTickWidth: 14,
20438
+ /**
20439
+ * 纵轴一个单位的高度
20440
+ */
20441
+ timeValueHeight: 20,
20442
+ /**
20443
+ * 单个时刻宽度代表的小时数
20444
+ */
20445
+ timeTickHours: 4,
20446
+ /**
20447
+ * 体温点的大小
20448
+ */
20449
+ temperaturePointSize: 4,
20450
+ /**
20451
+ * 心率点的大小
20452
+ */
20453
+ heartRatePointSize: 4,
20454
+ temperatureModels: [42, 41, 40, 39, 38, 37, 36, 35],
20455
+ heartRateModels: [180, 160, 140, 120, 100, 80, 40, 20],
20456
+ valueRuleCounts: 8,
20457
+ /**
20458
+ * 时刻头部高度
20459
+ */
20460
+ tickHeaderHeight: 20,
20461
+ /**
20462
+ * 体温符号
20463
+ */
20464
+ temperatureSymbol: '℃',
20465
+ heartRateSymbol: 'BPM'
20466
+ };
20467
+ class TimelineBaseControl extends AbsolutePanel {
20468
+ startTime;
20469
+ showDays = 0;
20470
+ constructor() {
20471
+ super();
20472
+ this.border = 1;
20473
+ this.borderColor = '#000';
20474
+ this.bgColor = '#fff';
20475
+ }
20476
+ measureOverride(e, availableSize) {
20477
+ this.build(e);
20478
+ return super.measureOverride(e, availableSize);
20479
+ }
20480
+ isBuild = false;
20481
+ build(e) {
20482
+ if (this.isBuild) {
20483
+ return;
20484
+ }
20485
+ this.clearChildren();
20486
+ this.buildOverride(e);
20487
+ this.isBuild = true;
20488
+ }
20489
+ reBuild() {
20490
+ this.isBuild = false;
20491
+ }
20492
+ buildOverride(e) {
20493
+ }
20494
+ }
20495
+ class TickContainer extends AbsolutePanel {
20496
+ tickControl;
20497
+ _startTime;
20498
+ _showDays = 0;
20499
+ scrollX = 0;
20500
+ get startTime() {
20501
+ return this._startTime;
20502
+ }
20503
+ set startTime(value) {
20504
+ this._startTime = value;
20505
+ this.tickControl.startTime = value;
20506
+ }
20507
+ get showDays() {
20508
+ return this._showDays;
20509
+ }
20510
+ set showDays(value) {
20511
+ this._showDays = value;
20512
+ this.tickControl.showDays = value;
20513
+ }
20514
+ arrangeOverride(e, finalSize) {
20515
+ this.controls.filter(item => item !== this.tickControl).forEach(item => {
20516
+ const itemRect = {
20517
+ x: item.x,
20518
+ y: item.y,
20519
+ width: item.desiredSize.width,
20520
+ height: item.desiredSize.height
20521
+ };
20522
+ item.arrange(e, itemRect);
20523
+ });
20524
+ this.tickControl.arrange(e, { x: this.tickControl.x - this.scrollX,
20525
+ y: this.tickControl.y,
20526
+ width: this.tickControl.desiredSize.width,
20527
+ height: this.tickControl.desiredSize.height });
20528
+ return finalSize;
20529
+ }
20530
+ }
20531
+
20532
+ class TemperaturePoint extends NodeCore {
20533
+ type;
20534
+ value;
20535
+ constructor(type = 'axillary', value) {
20536
+ super();
20537
+ this.type = type;
20538
+ this.value = value;
20539
+ this.bgColor = 'blue';
20540
+ this.width = timelineConfig.temperaturePointSize;
20541
+ this.height = timelineConfig.temperaturePointSize;
20542
+ this.addEventListener('mouseenter', evt => {
20543
+ this.bgColor = 'red';
20544
+ const onMouseLeave = () => {
20545
+ this.bgColor = 'blue';
20546
+ this.removeEventListener('mouseleave', onMouseLeave);
20547
+ };
20548
+ this.addEventListener('mouseleave', onMouseLeave);
20549
+ });
20550
+ }
20551
+ renderOutline(renderCtx) {
20552
+ translate(renderCtx, this.finalRect.x, this.finalRect.y);
20553
+ translate(renderCtx, this.border + this.padding, this.border + this.padding);
20554
+ }
20555
+ render(e) {
20556
+ if (this.type === 'axillary') {
20557
+ this.renderAxillary(e);
20558
+ }
20559
+ else if (this.type === 'oral') {
20560
+ this.renderOral(e);
20561
+ }
20562
+ else if (this.type === 'anal') {
20563
+ this.renderAnal(e);
20564
+ }
20565
+ }
20566
+ /**
20567
+ * 绘制腋下温度 X
20568
+ * @private
20569
+ */
20570
+ renderAxillary(e) {
20571
+ const { width, height } = this.finalRect;
20572
+ const x = 0, y = 0;
20573
+ e.render.strokeLines([{ x, y }, { x: x + width, y: y + height }], 3, this.bgColor);
20574
+ e.render.strokeLines([{ x: x + width, y }, { x, y: y + height }], 3, this.bgColor);
20575
+ }
20576
+ /**
20577
+ * 绘制肛下温度 ○
20578
+ * @private
20579
+ */
20580
+ renderAnal(e) {
20581
+ const width = this.finalRect.width;
20582
+ const ctx = e.render.ctx;
20583
+ ctx.save();
20584
+ ctx.beginPath();
20585
+ ctx.strokeStyle = this.bgColor;
20586
+ ctx.lineWidth = 2;
20587
+ ctx.arc(width / 2, width / 2, width, 0, 2 * Math.PI);
20588
+ ctx.stroke();
20589
+ ctx.restore();
20590
+ }
20591
+ /**
20592
+ * 绘制口腔温度 ●
20593
+ * @private
20594
+ */
20595
+ renderOral(e) {
20596
+ const width = this.finalRect.width;
20597
+ e.render.fillCircular(width / 2, width / 2, width, this.bgColor);
20598
+ }
20599
+ }
20600
+ class HeartRatePoint extends NodeCore {
20601
+ value;
20602
+ constructor() {
20603
+ super();
20604
+ this.bgColor = 'red';
20605
+ this.width = timelineConfig.heartRatePointSize * 2;
20606
+ this.height = timelineConfig.heartRatePointSize * 2;
20607
+ this.addEventListener('mouseenter', evt => {
20608
+ this.bgColor = 'green';
20609
+ const tipLabel = new LabelNode();
20610
+ tipLabel.text = this.value;
20611
+ tipLabel.fontSize = timelineConfig.fontSize;
20612
+ tipLabel.shadowBlur = 5;
20613
+ tipLabel.shadowColor = '#000';
20614
+ tipLabel.bgColor = '#fff';
20615
+ tipLabel.x = this.x;
20616
+ tipLabel.y = this.y - tipLabel.fontSize - 2;
20617
+ this.parent?.addChild(tipLabel);
20618
+ const onMouseLeave = () => {
20619
+ this.bgColor = 'red';
20620
+ this.parent?.removeChild(tipLabel);
20621
+ this.removeEventListener('mouseleave', onMouseLeave);
20622
+ };
20623
+ this.addEventListener('mouseleave', onMouseLeave);
20624
+ });
20625
+ }
20626
+ renderOutline(renderCtx) {
20627
+ translate(renderCtx, this.finalRect.x, this.finalRect.y);
20628
+ translate(renderCtx, this.border + this.padding, this.border + this.padding);
20629
+ }
20630
+ render(e) {
20631
+ const heartRatePointSize = this.finalRect.width / 2;
20632
+ e.render.fillCircular(heartRatePointSize, heartRatePointSize, heartRatePointSize, this.bgColor);
20633
+ }
20634
+ }
20635
+ class TimeLinePath extends NodeCore {
20636
+ startPos;
20637
+ endPos;
20638
+ lineColor = '#000';
20639
+ lineWidth = 1;
20640
+ constructor() {
20641
+ super();
20642
+ this.allowHitTest = true;
20643
+ this.enableClip = false;
20644
+ }
20645
+ renderOutline(renderCtx) {
20646
+ translate(renderCtx, this.finalRect.x, this.finalRect.y);
20647
+ translate(renderCtx, this.border + this.padding, this.border + this.padding);
20648
+ }
20649
+ render(e) {
20650
+ e.render.strokeLines([this.startPos, this.endPos], this.lineWidth, this.lineColor);
20651
+ }
20652
+ }
20653
+
20654
+ class TimelineControl extends AbsolutePanel {
20655
+ render(e) {
20656
+ }
20657
+ constructor() {
20658
+ super();
20659
+ this.border = 1;
20660
+ this.borderColor = '#000';
20661
+ }
20662
+ measureOverride(e, availableSize) {
20663
+ const height = this.controls.reduce((prev, curr) => {
20664
+ curr.measure(e, availableSize);
20665
+ return prev + curr.desiredSize.height;
20666
+ }, 0);
20667
+ return {
20668
+ height, width: availableSize.width
20669
+ };
20670
+ }
20671
+ arrangeOverride(e, finalSize) {
20672
+ this.controls.reduce((prev, curr) => {
20673
+ const itemRect = {
20674
+ x: 0,
20675
+ y: prev,
20676
+ width: curr.desiredSize.width,
20677
+ height: curr.desiredSize.height
20678
+ };
20679
+ curr.arrange(e, itemRect);
20680
+ return prev + curr.desiredSize.height;
20681
+ }, 0);
20682
+ return finalSize;
20683
+ }
20684
+ rebuild() {
20685
+ treeForEach(this, item => {
20686
+ if (item instanceof NodeItems) {
20687
+ return item.controls;
20688
+ }
20689
+ else {
20690
+ return [];
20691
+ }
20692
+ }, (item) => {
20693
+ if (item instanceof TimelineBaseControl) {
20694
+ item.reBuild();
20695
+ }
20696
+ });
20697
+ }
20698
+ }
20699
+ function treeForEach(root, children, callback) {
20700
+ callback(root);
20701
+ children(root).forEach(node => {
20702
+ treeForEach(node, children, callback);
20703
+ });
20704
+ }
20705
+ /**
20706
+ * 中间网格数据绘制区域
20707
+ */
20708
+ class TimeGridContainer extends AbsolutePanel {
20709
+ get gridHeight() {
20710
+ return this._gridHeight;
20711
+ }
20712
+ set gridHeight(value) {
20713
+ this._gridHeight = value;
20714
+ this.timelineGridControl.height = value;
20715
+ this.timeValueRuleContainer.height = value;
20716
+ }
20717
+ _startTime;
20718
+ _showDays = 7;
20719
+ get startTime() {
20720
+ return this._startTime;
20721
+ }
20722
+ set startTime(value) {
20723
+ this._startTime = value;
20724
+ this.timelineGridControl.startTime = value;
20725
+ }
20726
+ get showDays() {
20727
+ return this._showDays;
20728
+ }
20729
+ set showDays(value) {
20730
+ this._showDays = value;
20731
+ this.timelineGridControl.showDays = value;
20732
+ }
20733
+ /**
20734
+ * 网格区域高度
20735
+ */
20736
+ _gridHeight = 0;
20737
+ scrollX = 0;
20738
+ timelineGridControl;
20739
+ timeValueRuleContainer;
20740
+ constructor() {
20741
+ super();
20742
+ this.timelineGridControl = new TimelineGridControl();
20743
+ this.addChild(this.timelineGridControl);
20744
+ this.timeValueRuleContainer = new TimeValueRuleContainer();
20745
+ this.addChild(this.timeValueRuleContainer);
20746
+ }
20747
+ init() {
20748
+ this.timelineGridControl.init();
20749
+ }
20750
+ measureOverride(e, availableSize) {
20751
+ this.timelineGridControl.measure(e, availableSize);
20752
+ const height = this.timelineGridControl.desiredSize.height;
20753
+ this.timeValueRuleContainer.measure(e, { height, width: availableSize.width });
20754
+ return { height, width: availableSize.width };
20755
+ }
20756
+ arrangeOverride(e, finalSize) {
20757
+ this.controls.filter(item => item !== this.timelineGridControl).forEach(item => {
20758
+ const itemRect = {
20759
+ x: item.x,
20760
+ y: item.y,
20761
+ width: item.desiredSize.width,
20762
+ height: item.desiredSize.height
20763
+ };
20764
+ item.arrange(e, itemRect);
20765
+ });
20766
+ this.timelineGridControl.arrange(e, {
20767
+ x: this.timelineGridControl.x - this.scrollX,
20768
+ y: this.timelineGridControl.y,
20769
+ width: this.timelineGridControl.desiredSize.width,
20770
+ height: this.timelineGridControl.desiredSize.height
20771
+ });
20772
+ return finalSize;
20773
+ }
20774
+ render(e) {
20775
+ }
20776
+ }
20777
+ class TimeValueRuleContainer extends AbsolutePanel {
20778
+ getLayoutWidth() {
20779
+ return this.controls.reduce((prev, curr) => prev + curr.width, 0);
20780
+ }
20781
+ init() {
20782
+ this.controls.reduce((prev, curr) => {
20783
+ curr.x = prev;
20784
+ return prev + curr.width;
20785
+ }, 0);
20786
+ }
20787
+ renderOutline(renderCtx) {
20788
+ translate(renderCtx, this.finalRect.x, this.finalRect.y);
20789
+ translate(renderCtx, this.border + this.padding, this.border + this.padding);
20790
+ }
20791
+ render(e) {
20792
+ }
20793
+ }
20794
+ /**
20795
+ * 标题区域
20796
+ * 时间刻度:日期、住院天数、手术天数、时刻
20797
+ * 数值标尺区域、数据网格区域
20798
+ * 文本时间轴区域
20799
+ */
20800
+ class TimelineGridControl extends TimelineBaseControl {
20801
+ get isShowTemperature() {
20802
+ return this._isShowTemperature;
20803
+ }
20804
+ set isShowTemperature(value) {
20805
+ this.propertyChanged('isShowTemperature', this._isShowTemperature, value);
20806
+ this._isShowTemperature = value;
20807
+ }
20808
+ get isShowHeartRate() {
20809
+ return this._isShowHeartRate;
20810
+ }
20811
+ set isShowHeartRate(value) {
20812
+ this.propertyChanged('isShowHeartRate', this._isShowHeartRate, value);
20813
+ this._isShowHeartRate = value;
20814
+ }
20815
+ //体温数据
20816
+ temperatureData = [];
20817
+ //心率数据
20818
+ heartRateData = [];
20819
+ //体温时间轴值模型
20820
+ temperatureTimeLineValueModel = [];
20821
+ //心率时间轴值模型
20822
+ heartRateTimeLineValueModel = [];
20823
+ //图章数据
20824
+ eventData = [];
20825
+ _isShowTemperature = true;
20826
+ _isShowHeartRate = true;
20827
+ mousePos = null;
20828
+ constructor() {
20829
+ super();
20830
+ this.startTime = moment__default$1["default"](moment__default$1["default"]().format("YYYY-MM-DD")).toDate();
20831
+ this.addEventListener('mousemove', evt => {
20832
+ const pos = evt.pos;
20833
+ const nodePos = getNodePosition(this, { x: 0, y: 0 });
20834
+ this.mousePos = { x: pos.x - nodePos.x, y: pos.y - nodePos.y };
20835
+ });
20836
+ this.addEventListener('mouseleave', evt => {
20837
+ this.mousePos = null;
20838
+ });
20839
+ }
20840
+ randomNum = (start, end) => {
20841
+ return Math.floor(Math.random() * (end - start) + start);
20842
+ };
20843
+ getLayoutWidth() {
20844
+ return this.showDays * (24 / timelineConfig.timeTickHours) * timelineConfig.timeTickWidth;
20845
+ }
20846
+ init() {
20847
+ this.temperatureTimeLineValueModel = timelineConfig.temperatureModels.map((item, index, arr) => ({
20848
+ value: item,
20849
+ offset: (index + 1) / (arr.length + 1)
20850
+ }));
20851
+ this.heartRateTimeLineValueModel = timelineConfig.heartRateModels.map((item, index, arr) => ({
20852
+ value: item,
20853
+ offset: (index + 1) / (arr.length + 1)
20854
+ }));
20855
+ const { timeTickHours } = timelineConfig;
20856
+ for (let i = 0; i < this.showDays; i++) {
20857
+ for (let j = 0; j < 24; j += timeTickHours) {
20858
+ this.temperatureData.push({
20859
+ date: moment__default$1["default"](this.startTime).add(i, 'days').add(j, 'hours').toDate(),
20860
+ value: this.randomNum(33, 43) + this.randomNum(0, 10) / 10
20861
+ //value: 43
20862
+ });
20863
+ this.heartRateData.push({
20864
+ date: moment__default$1["default"](this.startTime).add(i, 'days').add(j, 'hours').toDate(),
20865
+ value: this.randomNum(70, 150)
20866
+ });
20867
+ }
20868
+ this.eventData.push({ date: moment__default$1["default"](this.startTime).add(i, 'days').toDate(), value: '入\r\n院' });
20869
+ }
20870
+ this.temperatureData.sort((prev, curr) => {
20871
+ return curr.date > prev.date ? 1 : -1;
20872
+ });
20873
+ this.heartRateData.sort((prev, curr) => curr.date > prev.date ? 1 : -1);
20874
+ }
20875
+ buildOverride(e) {
20876
+ this.buildTemperature(e);
20877
+ this.buildHearRate(e);
20878
+ this.buildStampUnit(e);
20879
+ const tipLabel = new LabelNode();
20880
+ tipLabel.text = '外\r\n科\r\n手\r\n术';
20881
+ tipLabel.borderColor = '#000';
20882
+ tipLabel.border = 1;
20883
+ tipLabel.shadowBlur = 5;
20884
+ tipLabel.shadowColor = 'red';
20885
+ tipLabel.fontSize = 12;
20886
+ tipLabel.bgColor = '#fff';
20887
+ tipLabel.color = 'red';
20888
+ tipLabel.textWrapping = 'wrap';
20889
+ //tipLabel.width = 14;
20890
+ tipLabel.x = 100;
20891
+ tipLabel.y = 30;
20892
+ this.addChild(tipLabel);
20893
+ }
20894
+ render(e) {
20895
+ const { timeValueHeight, timeTickHours, timeTickWidth } = timelineConfig;
20896
+ const ticks = 24 / timeTickHours;
20897
+ for (let i = 0; i < this.showDays; i++) {
20898
+ for (let j = 1; j <= ticks; j++) {
20899
+ const x = i * timeTickWidth * ticks + j * timeTickWidth;
20900
+ const color = j < ticks ? '#69c0ff' : '#ffadd2';
20901
+ e.render.strokeLines([{
20902
+ x,
20903
+ y: 0
20904
+ }, { x, y: this.finalRect.height }], 0.5, color);
20905
+ }
20906
+ }
20907
+ for (let i = timeValueHeight; i < this.finalRect.height; i += timeValueHeight) {
20908
+ e.render.strokeLines([{
20909
+ x: 0,
20910
+ y: i
20911
+ }, { x: this.finalRect.width, y: i }], 0.5, '#69c0ff');
20912
+ }
20913
+ this.renderTemperatureGuideLine(e);
20914
+ if (this.mousePos) {
20915
+ e.render.strokeLines([{ x: 0, y: this.mousePos.y }, { x: this.finalRect.width, y: this.mousePos.y }]);
20916
+ e.render.strokeLines([{ x: this.mousePos.x, y: 0 }, { x: this.mousePos.x, y: this.finalRect.height }]);
20917
+ }
20918
+ }
20919
+ renderTemperatureGuideLine(e) {
20920
+ const timelineValue = this.temperatureTimeLineValueModel.map(item => ({
20921
+ value: item.value,
20922
+ offset: this.height * item.offset
20923
+ }));
20924
+ //绘制正常36-37度,辅助线
20925
+ const startPoint = 36.5;
20926
+ const endPoint = 37.3;
20927
+ const startFilter = timelineValue.filter(item => item.value >= startPoint);
20928
+ const endFilter = timelineValue.filter(item => item.value >= endPoint);
20929
+ let startY = 0;
20930
+ let endY = 0;
20931
+ if (startFilter.length > 1) {
20932
+ const curr = startFilter[startFilter.length - 1];
20933
+ const next = startFilter[startFilter.length - 2];
20934
+ startY = curr.offset + (curr.value - startPoint) * (next.offset - curr.offset) / (curr.value - next.value);
20935
+ }
20936
+ if (endFilter.length > 1) {
20937
+ const curr = endFilter[endFilter.length - 1];
20938
+ const next = endFilter[endFilter.length - 2];
20939
+ endY = curr.offset + (curr.value - endPoint) * (next.offset - curr.offset) / (curr.value - next.value);
20940
+ }
20941
+ e.render.strokeLines([{ x: 0, y: startY }, { x: this.finalRect.width, y: startY }], 1, 'red');
20942
+ e.render.strokeLines([{ x: 0, y: endY }, { x: this.finalRect.width, y: endY }], 1, 'red');
20943
+ }
20944
+ buildTemperature(e) {
20945
+ if (this.temperatureData.length === 0) {
20946
+ return;
20947
+ }
20948
+ const height = this.height;
20949
+ const { timeValueHeight, timeTickHours, timeTickWidth, temperaturePointSize } = timelineConfig;
20950
+ const timelineValue = this.temperatureTimeLineValueModel.map(item => ({
20951
+ value: item.value,
20952
+ offset: height * item.offset
20953
+ }));
20954
+ //获取体温点纵向坐标
20955
+ const getTimelineVerValue = (val) => {
20956
+ const filter = timelineValue.filter(item => item.value >= val);
20957
+ if (filter.length) {
20958
+ if (filter.length > 1) {
20959
+ const curr = filter[filter.length - 1];
20960
+ const next = filter[filter.length - 2];
20961
+ return curr.offset + (curr.value - val) * (next.offset - curr.offset) / (curr.value - next.value);
20962
+ }
20963
+ else {
20964
+ return filter[0].offset;
20965
+ }
20966
+ }
20967
+ return -1;
20968
+ };
20969
+ let prevPos = null;
20970
+ for (let i = 0; i < this.showDays; i++) {
20971
+ const ticks = 24 / timeTickHours;
20972
+ for (let j = 0; j < ticks; j++) {
20973
+ const hourOffset = j * timeTickHours;
20974
+ const x = i * timeTickWidth * ticks + j * timeTickWidth;
20975
+ const startTime = moment__default$1["default"](this.startTime).add(i, 'days').add(hourOffset, 'hours');
20976
+ const endTime = moment__default$1["default"](this.startTime).add(i, 'days').add(hourOffset + timeTickHours, 'hours');
20977
+ const predicate = (item) => {
20978
+ return moment__default$1["default"](item).isBetween(startTime, endTime, null, '(]');
20979
+ };
20980
+ const currTimePoints = this.temperatureData.filter(item => predicate(item.date));
20981
+ currTimePoints.forEach(item => {
20982
+ let currX = x;
20983
+ const diffMinutes = moment__default$1["default"](item.date).diff(startTime, 'minutes');
20984
+ const offsetMinutes = diffMinutes * timeTickWidth / (timeTickHours * 60);
20985
+ currX += offsetMinutes;
20986
+ let currY = getTimelineVerValue(item.value);
20987
+ //超出显示范围
20988
+ if (currY > height) {
20989
+ currY = height;
20990
+ this.setExceededValueTip(e, item.value + '℃', currX, currY - 20);
20991
+ }
20992
+ if (currY < 0) {
20993
+ currY = 0;
20994
+ this.setExceededValueTip(e, item.value + '℃', currX, currY + 5);
20995
+ }
20996
+ const point = new TemperaturePoint('axillary', item.value);
20997
+ point.x = currX - point.width / 2;
20998
+ point.y = currY - point.width / 2;
20999
+ this.addChild(point);
21000
+ if (prevPos) {
21001
+ const linePath = new TimeLinePath();
21002
+ linePath.lineColor = 'blue';
21003
+ linePath.startPos = prevPos;
21004
+ linePath.endPos = { x: currX, y: currY };
21005
+ this.addChild(linePath);
21006
+ }
21007
+ prevPos = { x: currX, y: currY };
21008
+ });
21009
+ }
21010
+ }
21011
+ }
21012
+ setExceededValueTip(e, tip, x, y) {
21013
+ const tipLabel = new LabelNode();
21014
+ tipLabel.text = tip;
21015
+ tipLabel.borderColor = '#000';
21016
+ tipLabel.border = 1;
21017
+ tipLabel.shadowBlur = 5;
21018
+ tipLabel.shadowColor = '#000';
21019
+ tipLabel.fontSize = 10;
21020
+ tipLabel.bgColor = '#fff';
21021
+ const tipLabelWidth = e.render.measureText2(tipLabel.text, tipLabel);
21022
+ tipLabel.x = x -= tipLabelWidth / 2;
21023
+ tipLabel.y = y;
21024
+ this.addChild(tipLabel);
21025
+ }
21026
+ buildHearRate(e) {
21027
+ const height = this.height;
21028
+ const { timeTickHours, timeTickWidth, heartRateSymbol } = timelineConfig;
21029
+ const timelineValue = this.heartRateTimeLineValueModel.map(item => ({
21030
+ value: item.value,
21031
+ offset: height * item.offset
21032
+ }));
21033
+ //获取心率纵向坐标
21034
+ const getTimelineVerValue = (val) => {
21035
+ const filter = timelineValue.filter(item => item.value >= val);
21036
+ if (filter.length) {
21037
+ if (filter.length > 1) {
21038
+ const curr = filter[filter.length - 1];
21039
+ const next = filter[filter.length - 2];
21040
+ return curr.offset + (curr.value - val) * (next.offset - curr.offset) / (curr.value - next.value);
21041
+ }
21042
+ else {
21043
+ return filter[0].offset;
21044
+ }
21045
+ }
21046
+ return -1;
21047
+ };
21048
+ //const getTimelineHorValue=()
21049
+ let prevPos = null;
21050
+ for (let i = 0; i < this.showDays; i++) {
21051
+ const ticks = 24 / timeTickHours;
21052
+ for (let j = 0; j < ticks; j++) {
21053
+ const hourOffset = j * timeTickHours;
21054
+ const x = i * timeTickWidth * ticks + j * timeTickWidth;
21055
+ const startTime = moment__default$1["default"](this.startTime).add(i, 'days').add(hourOffset, 'hours');
21056
+ const endTime = moment__default$1["default"](this.startTime).add(i, 'days').add(hourOffset + timeTickHours, 'hours');
21057
+ const predicate = (item) => {
21058
+ return moment__default$1["default"](item).isBetween(startTime, endTime, null, '(]');
21059
+ };
21060
+ const currTimePoints = this.heartRateData.filter(item => predicate(item.date));
21061
+ currTimePoints.forEach(item => {
21062
+ let currX = x;
21063
+ const diffMinutes = moment__default$1["default"](item.date).diff(startTime, 'minutes');
21064
+ const offsetMinutes = diffMinutes * timeTickWidth / (timeTickHours * 60);
21065
+ currX += offsetMinutes;
21066
+ let currY = getTimelineVerValue(item.value);
21067
+ //超出显示范围
21068
+ if (currY > height) {
21069
+ currY = height;
21070
+ this.setExceededValueTip(e, item.value + heartRateSymbol, currX, currY - 20);
21071
+ }
21072
+ if (currY < 0) {
21073
+ currY = 0;
21074
+ this.setExceededValueTip(e, item.value + heartRateSymbol, currX, currY + 5);
21075
+ }
21076
+ const point = new HeartRatePoint();
21077
+ point.value = item.value + '次/分';
21078
+ point.x = currX - point.width / 2;
21079
+ point.y = currY - point.width / 2;
21080
+ this.addChild(point);
21081
+ if (prevPos) {
21082
+ const linePath = new TimeLinePath();
21083
+ linePath.lineColor = 'red';
21084
+ linePath.startPos = prevPos;
21085
+ linePath.endPos = { x: currX, y: currY };
21086
+ this.addChild(linePath);
21087
+ }
21088
+ prevPos = { x: currX, y: currY };
21089
+ });
21090
+ }
21091
+ }
21092
+ }
21093
+ buildStampUnit(e) {
21094
+ if (!this.eventData.length) {
21095
+ return;
21096
+ }
21097
+ const { timeTickHours, timeTickWidth, heartRateSymbol } = timelineConfig;
21098
+ for (let i = 0; i < this.showDays; i++) {
21099
+ const ticks = 24 / timeTickHours;
21100
+ for (let j = 0; j < ticks; j++) {
21101
+ const hourOffset = j * timeTickHours;
21102
+ const x = i * timeTickWidth * ticks + j * timeTickWidth;
21103
+ const startTime = moment__default$1["default"](this.startTime).add(i, 'days').add(hourOffset, 'hours');
21104
+ const endTime = moment__default$1["default"](this.startTime).add(i, 'days').add(hourOffset + timeTickHours, 'hours');
21105
+ const predicate = (item) => {
21106
+ return moment__default$1["default"](item).isBetween(startTime, endTime, null, '(]');
21107
+ };
21108
+ const currTimePoints = this.eventData.filter(item => predicate(item.date));
21109
+ currTimePoints.forEach(item => {
21110
+ let currX = x;
21111
+ const diffMinutes = moment__default$1["default"](item.date).diff(startTime, 'minutes');
21112
+ const offsetMinutes = diffMinutes * timeTickWidth / (timeTickHours * 60);
21113
+ currX += offsetMinutes;
21114
+ const tipLabel = new LabelNode();
21115
+ tipLabel.text = item.value;
21116
+ tipLabel.borderColor = '#000';
21117
+ tipLabel.border = 1;
21118
+ tipLabel.shadowBlur = 5;
21119
+ tipLabel.shadowColor = 'red';
21120
+ tipLabel.fontSize = 12;
21121
+ tipLabel.bgColor = '#fff';
21122
+ tipLabel.color = 'red';
21123
+ tipLabel.textWrapping = 'wrap';
21124
+ //tipLabel.width = 14;
21125
+ tipLabel.x = currX;
21126
+ tipLabel.y = 30;
21127
+ this.addChild(tipLabel);
21128
+ });
21129
+ }
21130
+ }
21131
+ }
21132
+ }
21133
+ /**
21134
+ * 心率数值标尺控件
21135
+ */
21136
+ class HeartRateValueRuleControl extends TimelineBaseControl {
21137
+ constructor() {
21138
+ super();
21139
+ this.width = 50;
21140
+ }
21141
+ //体温时间轴值模型
21142
+ heartRateTimeLineValueModel = [];
21143
+ buildOverride(e) {
21144
+ const width = this.width;
21145
+ const height = this.height;
21146
+ const label = new LabelNode();
21147
+ label.text = '心率';
21148
+ label.fontSize = timelineConfig.fontSize;
21149
+ label.fontName = timelineConfig.fontName;
21150
+ label.y = 5;
21151
+ this.addChild(label);
21152
+ const textProps = new TextProps();
21153
+ textProps.fontSize = timelineConfig.fontSize;
21154
+ textProps.fontName = timelineConfig.fontName;
21155
+ label.x = (width - e.render.measureText(label.text, textProps).width) / 2;
21156
+ const timelineValue = this.heartRateTimeLineValueModel.map(item => ({
21157
+ value: item.value,
21158
+ offset: (height) * item.offset
21159
+ }));
21160
+ timelineValue.forEach(item => {
21161
+ const valueLabel = new LabelNode();
21162
+ valueLabel.fontName = timelineConfig.fontName;
21163
+ valueLabel.fontSize = timelineConfig.fontSize;
21164
+ valueLabel.text = item.value + '';
21165
+ valueLabel.x = (width - e.render.measureText(valueLabel.text, textProps).width) / 2;
21166
+ valueLabel.y = item.offset;
21167
+ this.addChild(valueLabel);
21168
+ });
21169
+ }
21170
+ render(e) {
21171
+ }
21172
+ }
21173
+ /**
21174
+ * 体温数值标尺控件
21175
+ */
21176
+ class TemperatureValueRuleControl extends TimelineBaseControl {
21177
+ constructor() {
21178
+ super();
21179
+ this.width = 50;
21180
+ }
21181
+ //体温时间轴值模型
21182
+ temperatureTimeLineValueModel = [];
21183
+ buildOverride(e) {
21184
+ const width = this.width;
21185
+ const height = this.height;
21186
+ const label = new LabelNode();
21187
+ label.text = '体温';
21188
+ label.fontSize = timelineConfig.fontSize;
21189
+ label.fontName = timelineConfig.fontName;
21190
+ label.y = 5;
21191
+ this.addChild(label);
21192
+ label.x = (width - e.render.measureText2(label.text, label)) / 2;
21193
+ const timelineValue = this.temperatureTimeLineValueModel.map(item => ({
21194
+ value: item.value,
21195
+ offset: (height) * item.offset
21196
+ }));
21197
+ timelineValue.forEach(item => {
21198
+ const valueLabel = new LabelNode();
21199
+ valueLabel.fontName = timelineConfig.fontName;
21200
+ valueLabel.fontSize = timelineConfig.fontSize;
21201
+ valueLabel.text = item.value + '';
21202
+ valueLabel.x = (width - e.render.measureText2(valueLabel.text, valueLabel)) / 2;
21203
+ valueLabel.y = item.offset;
21204
+ this.addChild(valueLabel);
21205
+ });
21206
+ }
21207
+ render(e) {
21208
+ }
21209
+ }
21210
+
21211
+ /**
21212
+ * 事件轴标题
21213
+ * 日期、手术天数、术后天数、时刻
21214
+ */
21215
+ class TimeTickTitleControl extends TimelineBaseControl {
21216
+ constructor() {
21217
+ super();
21218
+ this.bgColor = '#fff';
21219
+ }
21220
+ title;
21221
+ render(e) {
21222
+ }
21223
+ buildOverride(e) {
21224
+ const width = this.width;
21225
+ const height = this.height;
21226
+ const label = new LabelNode();
21227
+ label.text = this.title;
21228
+ label.fontSize = timelineConfig.fontSize;
21229
+ label.fontName = timelineConfig.fontName;
21230
+ const titleWidth = e.render.measureText2(label.text, label);
21231
+ label.x = (width - titleWidth) / 2;
21232
+ label.y = (height - label.fontSize) / 2;
21233
+ this.addChild(label);
21234
+ }
21235
+ }
21236
+ /**
21237
+ * 文本状态时刻控件,用于显示状态文本,例如:小便等
21238
+ */
21239
+ class TextStatusTickControl extends TimelineBaseControl {
21240
+ render(e) {
21241
+ }
21242
+ buildOverride(e) {
21243
+ const { timeTickHours, timeTickWidth } = timelineConfig;
21244
+ const height = this.height;
21245
+ const ticks = 24 / timeTickHours;
21246
+ for (let i = 0; i < this.showDays; i++) {
21247
+ const width = ticks * timeTickWidth;
21248
+ // const curr = moment(this.startTime).add(i, 'days').format('YYYY-MM-DD');
21249
+ //
21250
+ // const label = new LabelNode();
21251
+ // label.text = curr + '';
21252
+ // label.fontSize = timelineConfig.fontSize;
21253
+ // label.fontName = timelineConfig.fontName;
21254
+ //
21255
+ // const dateTitleWidth = e.render.measureText2(curr + '', label);
21256
+ //
21257
+ // label.x = i * width + (width - dateTitleWidth) / 2;
21258
+ // label.y = (height - label.fontSize) / 2;
21259
+ // this.addChild(label);
21260
+ const path = new TimeLinePath();
21261
+ path.startPos = { x: i * width, y: 0 };
21262
+ path.endPos = { x: i * width, y: height };
21263
+ path.lineColor = '#ffadd2';
21264
+ this.addChild(path);
21265
+ }
21266
+ }
21267
+ }
21268
+ /**
21269
+ * 呼吸状态容器
21270
+ */
21271
+ class TimelineHXStatusContainer extends TickContainer {
21272
+ tickTitleControl;
21273
+ constructor() {
21274
+ super();
21275
+ this.tickTitleControl = new TimeTickTitleControl();
21276
+ this.tickTitleControl.title = '呼吸';
21277
+ this.tickTitleControl.height = timelineConfig.tickHeaderHeight;
21278
+ this.tickControl = new TextStatusTickControl();
21279
+ this.tickControl.height = timelineConfig.tickHeaderHeight;
21280
+ this.addChild(this.tickControl);
21281
+ this.addChild(this.tickTitleControl);
21282
+ this.height = timelineConfig.tickHeaderHeight;
21283
+ }
21284
+ /**
21285
+ * 设置标题和刻度宽度
21286
+ * @param titleWidth
21287
+ * @param tickWidth
21288
+ */
21289
+ setLayout(titleWidth, tickWidth) {
21290
+ this.width = tickWidth + titleWidth;
21291
+ this.tickTitleControl.width = titleWidth;
21292
+ this.tickControl.width = tickWidth;
21293
+ this.tickControl.x = titleWidth;
21294
+ }
21295
+ render(e) {
21296
+ }
21297
+ }
21298
+ /**
21299
+ * 小便状态容器
21300
+ */
21301
+ class TimelineXBStatusContainer extends TickContainer {
21302
+ //statusControl: TextStatusTickControl;
21303
+ tickTitleControl;
21304
+ constructor() {
21305
+ super();
21306
+ this.tickTitleControl = new TimeTickTitleControl();
21307
+ this.tickTitleControl.title = '小便 ml';
21308
+ this.tickTitleControl.height = timelineConfig.tickHeaderHeight;
21309
+ this.tickControl = new TextStatusTickControl();
21310
+ this.tickControl.height = timelineConfig.tickHeaderHeight;
21311
+ this.addChild(this.tickControl);
21312
+ this.addChild(this.tickTitleControl);
21313
+ this.height = timelineConfig.tickHeaderHeight;
21314
+ }
21315
+ /**
21316
+ * 设置标题和刻度宽度
21317
+ * @param titleWidth
21318
+ * @param tickWidth
21319
+ */
21320
+ setLayout(titleWidth, tickWidth) {
21321
+ this.width = tickWidth + titleWidth;
21322
+ this.tickTitleControl.width = titleWidth;
21323
+ this.tickControl.width = tickWidth;
21324
+ this.tickControl.x = titleWidth;
21325
+ }
21326
+ render(e) {
21327
+ }
21328
+ }
21329
+ /**
21330
+ * 其他状态容器
21331
+ */
21332
+ class TimelineOtherStatusContainer extends TickContainer {
21333
+ //statusControl: TextStatusTickControl;
21334
+ tickTitleControl;
21335
+ constructor() {
21336
+ super();
21337
+ this.tickTitleControl = new TimeTickTitleControl();
21338
+ this.tickTitleControl.title = '其他';
21339
+ this.tickTitleControl.height = timelineConfig.tickHeaderHeight;
21340
+ this.tickControl = new TextStatusTickControl();
21341
+ this.tickControl.height = timelineConfig.tickHeaderHeight;
21342
+ this.addChild(this.tickControl);
21343
+ this.addChild(this.tickTitleControl);
21344
+ this.height = timelineConfig.tickHeaderHeight;
21345
+ }
21346
+ /**
21347
+ * 设置标题和刻度宽度
21348
+ * @param titleWidth
21349
+ * @param tickWidth
21350
+ */
21351
+ setLayout(titleWidth, tickWidth) {
21352
+ this.width = tickWidth + titleWidth;
21353
+ this.tickTitleControl.width = titleWidth;
21354
+ this.tickControl.width = tickWidth;
21355
+ this.tickControl.x = titleWidth;
21356
+ }
21357
+ render(e) {
21358
+ }
21359
+ }
21360
+
21361
+ /**
21362
+ * 时间刻度区域
21363
+ * 循环日期显示
21364
+ * 住院天数
21365
+ * 术后天数
21366
+ * 时刻等
21367
+ */
21368
+ /**
21369
+ * 日期时刻容器
21370
+ */
21371
+ class DateTickContainer extends TickContainer {
21372
+ tickTitleControl;
21373
+ constructor() {
21374
+ super();
21375
+ this.tickTitleControl = new TimeTickTitleControl();
21376
+ this.tickTitleControl.title = '日期';
21377
+ this.tickTitleControl.height = timelineConfig.tickHeaderHeight;
21378
+ this.tickControl = new DateTickControl();
21379
+ this.tickControl.height = timelineConfig.tickHeaderHeight;
21380
+ this.addChild(this.tickControl);
21381
+ this.addChild(this.tickTitleControl);
21382
+ this.height = timelineConfig.tickHeaderHeight;
21383
+ }
21384
+ /**
21385
+ * 设置标题和刻度宽度
21386
+ * @param titleWidth
21387
+ * @param tickWidth
21388
+ */
21389
+ setLayout(titleWidth, tickWidth) {
21390
+ this.width = tickWidth + titleWidth;
21391
+ this.tickTitleControl.width = titleWidth;
21392
+ this.tickControl.width = tickWidth;
21393
+ this.tickControl.x = titleWidth;
21394
+ }
21395
+ render(e) {
21396
+ }
21397
+ }
21398
+ /**
21399
+ * 日期刻度
21400
+ */
21401
+ class DateTickControl extends TimelineBaseControl {
21402
+ buildOverride(e) {
21403
+ const { timeTickHours, timeTickWidth } = timelineConfig;
21404
+ const height = this.height;
21405
+ const ticks = 24 / timeTickHours;
21406
+ for (let i = 0; i < this.showDays; i++) {
21407
+ const width = ticks * timeTickWidth;
21408
+ const curr = moment__default$1["default"](this.startTime).add(i, 'days').format('YYYY-MM-DD');
21409
+ const label = new LabelNode();
21410
+ label.text = curr + '';
21411
+ label.fontSize = timelineConfig.fontSize;
21412
+ label.fontName = timelineConfig.fontName;
21413
+ const dateTitleWidth = e.render.measureText2(curr + '', label);
21414
+ label.x = i * width + (width - dateTitleWidth) / 2;
21415
+ label.y = (height - label.fontSize) / 2;
21416
+ this.addChild(label);
21417
+ const path = new TimeLinePath();
21418
+ path.startPos = { x: i * width, y: 0 };
21419
+ path.endPos = { x: i * width, y: height };
21420
+ path.lineColor = '#ffadd2';
21421
+ this.addChild(path);
21422
+ }
21423
+ }
21424
+ render(e) {
21425
+ }
21426
+ }
21427
+ class TimeTickContainer extends TickContainer {
21428
+ tickTitleControl;
21429
+ constructor() {
21430
+ super();
21431
+ this.tickTitleControl = new TimeTickTitleControl();
21432
+ this.tickTitleControl.title = '时刻';
21433
+ this.tickTitleControl.height = timelineConfig.tickHeaderHeight;
21434
+ this.tickControl = new TimeTickControl();
21435
+ this.tickControl.height = timelineConfig.tickHeaderHeight;
21436
+ this.addChild(this.tickControl);
21437
+ this.addChild(this.tickTitleControl);
21438
+ this.height = timelineConfig.tickHeaderHeight;
21439
+ }
21440
+ /**
21441
+ * 设置标题和刻度宽度
21442
+ * @param titleWidth
21443
+ * @param tickWidth
21444
+ */
21445
+ setLayout(titleWidth, tickWidth) {
21446
+ this.width = tickWidth + titleWidth;
21447
+ this.tickTitleControl.width = titleWidth;
21448
+ this.tickControl.width = tickWidth;
21449
+ this.tickControl.x = titleWidth;
21450
+ }
21451
+ render(e) {
21452
+ }
21453
+ }
21454
+ class TimeTickControl extends TimelineBaseControl {
21455
+ constructor() {
21456
+ super();
21457
+ this.border = 1;
21458
+ this.borderColor = '#000';
21459
+ }
21460
+ showDays = 7;
21461
+ buildOverride(e) {
21462
+ const { timeTickHours, timeTickWidth } = timelineConfig;
21463
+ const ticks = 24 / timeTickHours;
21464
+ for (let i = 0; i < this.showDays; i++) {
21465
+ for (let j = 1; j <= ticks; j++) {
21466
+ const hourOffset = j * timeTickHours;
21467
+ const x = i * timeTickWidth * ticks + j * timeTickWidth;
21468
+ const text = hourOffset + '';
21469
+ const label = new LabelNode();
21470
+ label.text = text;
21471
+ label.fontSize = timelineConfig.fontSize;
21472
+ label.fontName = timelineConfig.fontName;
21473
+ const dateTitleWidth = e.render.measureText2(text, label);
21474
+ label.x = x - timeTickWidth + (timeTickWidth - dateTitleWidth) / 2;
21475
+ label.y = 0;
21476
+ this.addChild(label);
21477
+ }
21478
+ }
21479
+ }
21480
+ render(e) {
21481
+ const { timeTickHours, timeTickWidth } = timelineConfig;
21482
+ const ticks = 24 / timeTickHours;
21483
+ for (let i = 0; i < this.showDays; i++) {
21484
+ for (let j = 1; j <= ticks; j++) {
21485
+ const x = i * timeTickWidth * ticks + j * timeTickWidth;
21486
+ const color = j < ticks ? '#69c0ff' : '#ffadd2';
21487
+ e.render.strokeLines([{
21488
+ x,
21489
+ y: 0
21490
+ }, { x, y: this.finalRect.height }], 1, color);
21491
+ }
21492
+ }
21493
+ }
21494
+ }
21495
+ class InPatDaysTickContainer extends TickContainer {
21496
+ //inPatDaysControl: InPatDaysControl;
21497
+ tickTitleControl;
21498
+ constructor() {
21499
+ super();
21500
+ this.tickTitleControl = new TimeTickTitleControl();
21501
+ this.tickTitleControl.title = '住院天数';
21502
+ this.tickTitleControl.height = timelineConfig.tickHeaderHeight;
21503
+ this.tickControl = new InPatDaysControl();
21504
+ this.tickControl.height = timelineConfig.tickHeaderHeight;
21505
+ this.addChild(this.tickControl);
21506
+ this.addChild(this.tickTitleControl);
21507
+ this.height = timelineConfig.tickHeaderHeight;
21508
+ }
21509
+ /**
21510
+ * 设置标题和刻度宽度
21511
+ * @param titleWidth
21512
+ * @param tickWidth
21513
+ */
21514
+ setLayout(titleWidth, tickWidth) {
21515
+ this.width = tickWidth + titleWidth;
21516
+ this.tickTitleControl.width = titleWidth;
21517
+ this.tickControl.width = tickWidth;
21518
+ this.tickControl.x = titleWidth;
21519
+ }
21520
+ render(e) {
21521
+ }
21522
+ }
21523
+ class InPatDaysControl extends TimelineBaseControl {
21524
+ buildOverride(e) {
21525
+ const { timeTickHours, timeTickWidth } = timelineConfig;
21526
+ const height = this.height;
21527
+ const ticks = 24 / timeTickHours;
21528
+ for (let i = 0; i < this.showDays; i++) {
21529
+ const width = ticks * timeTickWidth;
21530
+ const text = (i + 1) + '';
21531
+ const label = new LabelNode();
21532
+ label.text = text;
21533
+ label.fontSize = timelineConfig.fontSize;
21534
+ label.fontName = timelineConfig.fontName;
21535
+ const dateTitleWidth = e.render.measureText2(text, label);
21536
+ label.x = i * width + (width - dateTitleWidth + label.fontSize) / 2;
21537
+ label.y = (height - label.fontSize) / 2;
21538
+ this.addChild(label);
21539
+ const path = new TimeLinePath();
21540
+ path.startPos = { x: i * width, y: 0 };
21541
+ path.endPos = { x: i * width, y: height };
21542
+ path.lineColor = '#ffadd2';
21543
+ this.addChild(path);
21544
+ }
21545
+ }
21546
+ render(e) {
21547
+ }
21548
+ }
21549
+
21550
+ class TimelineScrollBar extends NodeItems {
21551
+ //滚动条方向
21552
+ orientation = 'horizontal';
21553
+ thumb;
21554
+ thumbSize = 10;
21555
+ //按照百分比计算
21556
+ scrollChanged = new Subject();
21557
+ //总滚动宽度
21558
+ scrollSize = 0;
21559
+ //显示区域宽度
21560
+ viewSize = 0;
21561
+ scrollX = 0;
21562
+ scrollY = 0;
21563
+ constructor(orientation) {
21564
+ super();
21565
+ this.bgColor = '#fff';
21566
+ this.border = 1;
21567
+ this.borderColor = '#000';
21568
+ this.height = 16;
21569
+ this.orientation = orientation;
21570
+ this.thumb = new ScrollThumb();
21571
+ this.addChild(this.thumb);
21572
+ this.thumb.addEventListener('mousedown', evt => {
21573
+ const pos = { ...evt.pos };
21574
+ const { x, y } = this.thumb.finalRect;
21575
+ const mouseMoveListener = (evt2) => {
21576
+ //const scrollView = this.parent as ScrollView;
21577
+ const pos2 = evt2.pos;
21578
+ let moveX = pos2.x - pos.x;
21579
+ let moveY = pos2.y - pos.y;
21580
+ moveX += x;
21581
+ moveY += y;
21582
+ moveX = (moveX / this.finalRect.width) * this.scrollSize;
21583
+ moveY = (moveY / this.finalRect.height) * this.scrollSize;
21584
+ this.updateScroll(moveX, moveY);
21585
+ };
21586
+ const mouseUpListener = (evt3) => {
21587
+ this.thumb.removeEventListener('mousemove', mouseMoveListener);
21588
+ this.thumb.removeEventListener('mouseup', mouseUpListener);
21589
+ };
21590
+ this.thumb.addEventListener('mousemove', mouseMoveListener);
21591
+ this.thumb.addEventListener('mouseup', mouseUpListener);
21592
+ });
21593
+ }
21594
+ updateScroll(x, y) {
21595
+ //const scrollView = this.parent as ScrollView;
21596
+ if (this.orientation === 'horizontal') {
21597
+ if (this.finalRect.height === 0) {
21598
+ return;
21599
+ }
21600
+ if (x + this.viewSize > this.scrollSize) {
21601
+ x = this.scrollSize - this.viewSize;
21602
+ }
21603
+ x = x < 0 ? 0 : x;
21604
+ this.scrollChanged.next(x);
21605
+ this.scrollX = x;
21606
+ }
21607
+ }
21608
+ updateScrollByCurrent(increaseX, increaseY) {
21609
+ //const scrollView = this.parent as ScrollView;
21610
+ increaseX += this.scrollX;
21611
+ increaseY += this.scrollY;
21612
+ this.updateScroll(increaseX, increaseY);
21613
+ }
21614
+ measureOverride(e, availableSize) {
21615
+ if (this.orientation === 'horizontal') {
21616
+ return this.measureHorizontalBar(e, availableSize);
21617
+ }
21618
+ else {
21619
+ //return this.measureVerticalBar(e, availableSize);
21620
+ throw new Error('未实现');
21621
+ }
21622
+ }
21623
+ /**
21624
+ * 横向滚动条测量
21625
+ */
21626
+ measureHorizontalBar(e, availableSize) {
21627
+ if (this.scrollSize > this.viewSize) {
21628
+ //计算滚动按钮的长度
21629
+ const thumbWidth = (this.viewSize / this.scrollSize) * availableSize.width;
21630
+ this.thumb.measure(e, { width: thumbWidth, height: this.thumbSize });
21631
+ return { width: availableSize.width, height: ScrollBarSize };
21632
+ }
21633
+ else {
21634
+ this.thumb.measure(e, { width: 0, height: 0 });
21635
+ return { width: 0, height: 0 };
21636
+ }
21637
+ }
21638
+ arrangeOverride(e, finalSize) {
21639
+ //const scrollView = this.parent as ScrollView;
21640
+ const { width, height } = this.thumb.desiredSize;
21641
+ const x = this.orientation === 'horizontal' ? (this.scrollX / this.scrollSize) * finalSize.width : (ScrollBarSize - this.thumbSize) / 2;
21642
+ const y = this.orientation === 'horizontal' ? (ScrollBarSize - this.thumbSize) / 2 : (this.scrollY / this.scrollSize) * finalSize.height;
21643
+ this.thumb.arrange(e, { x, y, width, height });
21644
+ return super.arrangeOverride(e, finalSize);
21645
+ }
21646
+ render(e) {
21647
+ //e.render.contentContext.clearRect(0,0,this.finalRect.width,this.finalRect.height);
21648
+ //e.render.fillRect(0, 0, this.finalRect.width, this.finalRect.height, 'red')
21649
+ }
21650
+ }
21651
+
21652
+ function createTimeline() {
21653
+ const timeline = new TimelineControl();
21654
+ timeline.width = 940;
21655
+ const timeGridContainer = new TimeGridContainer();
21656
+ //timeGridContainer.y = 80;
21657
+ const timelineGridControl = timeGridContainer.timelineGridControl; //new TimeLineControl();
21658
+ timelineGridControl.showDays = 30;
21659
+ timelineGridControl.width = timelineGridControl.getLayoutWidth();
21660
+ timelineGridControl.height = 300;
21661
+ timelineGridControl.init();
21662
+ const tempValueRule = new TemperatureValueRuleControl();
21663
+ tempValueRule.temperatureTimeLineValueModel = timelineGridControl.temperatureTimeLineValueModel;
21664
+ tempValueRule.bgColor = '#fff';
21665
+ tempValueRule.height = timelineGridControl.height;
21666
+ timeGridContainer.timeValueRuleContainer.addChild(tempValueRule);
21667
+ tempValueRule.addEventListener('mouseenter', evt => {
21668
+ tempValueRule.bgColor = 'grey';
21669
+ const mousemoveHandler = () => {
21670
+ tempValueRule.bgColor = '#fff';
21671
+ tempValueRule.removeEventListener('mouseleave', mousemoveHandler);
21672
+ };
21673
+ tempValueRule.addEventListener('mouseleave', mousemoveHandler);
21674
+ });
21675
+ const heartRateValueRule = new HeartRateValueRuleControl();
21676
+ heartRateValueRule.heartRateTimeLineValueModel = timelineGridControl.heartRateTimeLineValueModel;
21677
+ heartRateValueRule.bgColor = '#fff';
21678
+ heartRateValueRule.height = timelineGridControl.height;
21679
+ timeGridContainer.timeValueRuleContainer.addChild(heartRateValueRule);
21680
+ heartRateValueRule.addEventListener('mouseenter', evt => {
21681
+ heartRateValueRule.bgColor = 'grey';
21682
+ const mousemoveHandler = () => {
21683
+ heartRateValueRule.bgColor = '#fff';
21684
+ heartRateValueRule.removeEventListener('mouseleave', mousemoveHandler);
21685
+ };
21686
+ heartRateValueRule.addEventListener('mouseleave', mousemoveHandler);
21687
+ });
21688
+ timeGridContainer.timeValueRuleContainer.init();
21689
+ const titleWidth = timeGridContainer.timeValueRuleContainer.getLayoutWidth();
21690
+ timeGridContainer.timeValueRuleContainer.width = titleWidth;
21691
+ timeGridContainer.timeValueRuleContainer.height = timelineGridControl.height;
21692
+ timeGridContainer.timelineGridControl.x = timeGridContainer.timeValueRuleContainer.width;
21693
+ const dateHeader = new DateTickContainer();
21694
+ dateHeader.showDays = timelineGridControl.showDays;
21695
+ dateHeader.setLayout(titleWidth, timelineGridControl.width);
21696
+ timeline.addChild(dateHeader);
21697
+ const inDaysHeader = new InPatDaysTickContainer();
21698
+ inDaysHeader.showDays = timelineGridControl.showDays;
21699
+ inDaysHeader.setLayout(titleWidth, timelineGridControl.width);
21700
+ timeline.addChild(inDaysHeader);
21701
+ const timeHeader = new TimeTickContainer();
21702
+ timeHeader.showDays = timelineGridControl.showDays;
21703
+ timeHeader.setLayout(titleWidth, timelineGridControl.width);
21704
+ timeline.addChild(timeHeader);
21705
+ timeline.addChild(timeGridContainer);
21706
+ const hxStatus = new TimelineHXStatusContainer();
21707
+ hxStatus.showDays = timelineGridControl.showDays;
21708
+ hxStatus.setLayout(titleWidth, timelineGridControl.width);
21709
+ timeline.addChild(hxStatus);
21710
+ const xbStatus = new TimelineXBStatusContainer();
21711
+ xbStatus.showDays = timelineGridControl.showDays;
21712
+ xbStatus.setLayout(titleWidth, timelineGridControl.width);
21713
+ timeline.addChild(xbStatus);
21714
+ const otStatus = new TimelineOtherStatusContainer();
21715
+ otStatus.showDays = timelineGridControl.showDays;
21716
+ otStatus.setLayout(titleWidth, timelineGridControl.width);
21717
+ timeline.addChild(otStatus);
21718
+ const timelineScrollbar = new TimelineScrollBar('horizontal');
21719
+ timelineScrollbar.scrollSize = timelineGridControl.width;
21720
+ timelineScrollbar.viewSize = 840;
21721
+ timelineScrollbar.width = timeline.width;
21722
+ timelineScrollbar.scrollChanged.subscribe(data => {
21723
+ dateHeader.scrollX = data;
21724
+ inDaysHeader.scrollX = data;
21725
+ timeHeader.scrollX = data;
21726
+ timeGridContainer.scrollX = data;
21727
+ xbStatus.scrollX = data;
21728
+ hxStatus.scrollX = data;
21729
+ otStatus.scrollX = data;
21730
+ });
21731
+ timeline.addChild(timelineScrollbar);
21732
+ return timeline;
21733
+ }
21734
+
20396
21735
  /**
20397
21736
  * Node宽度定义
20398
21737
  * 1.在单页模式下,文档最小宽度为单个文档宽度+合适的外边距
20399
21738
  * 2.在多页模式下,文档最小宽度为单个文档宽度+合适的外边距
20400
21739
  */
20401
21740
  class CanvasTextEditor extends AbsolutePanel {
20402
- editCanvas;
20403
- editInput;
21741
+ container;
20404
21742
  contentCtx;
20405
21743
  viewOptions;
20406
21744
  docCtx;
@@ -20428,10 +21766,12 @@ class CanvasTextEditor extends AbsolutePanel {
20428
21766
  onDocChangedEvent = new Subject$1();
20429
21767
  //执行flushTask,refreshDoc之前,此时可以在文档计算排版之前改变内容
20430
21768
  onBeforeRefreshDocument = new Subject$1();
20431
- constructor(editCanvas, editInput) {
21769
+ editCanvas;
21770
+ editInput;
21771
+ constructor(container) {
20432
21772
  super();
20433
- this.editCanvas = editCanvas;
20434
- this.editInput = editInput;
21773
+ this.container = container;
21774
+ this.createDocDOM();
20435
21775
  this.viewOptions = new ViewOptions();
20436
21776
  this.documentSelection = new DocumentSelection();
20437
21777
  this.docCtx = new EditorContext(this.documentSelection.selectionState, this.viewOptions);
@@ -20454,14 +21794,13 @@ class CanvasTextEditor extends AbsolutePanel {
20454
21794
  this.viewOptions.fullPageView = false;
20455
21795
  this.createDocViewer();
20456
21796
  this.docComment = new DocumentComment(this.docCtx);
20457
- this.contentCtx = editCanvas.getContext('2d');
21797
+ this.contentCtx = this.editCanvas.getContext('2d');
20458
21798
  this.renderContext = new RenderContext(new PaintContent(this.contentCtx));
20459
21799
  this.renderContext.init({ width: 500, height: 500, scale: 1 });
20460
21800
  this.selectionState = this.documentSelection.selectionState;
20461
21801
  this.selectionOverlays = new SelectionOverlays(this.documentSelection.selectionState);
20462
21802
  this.documentPaint = new DocumentPaint(this.renderContext, this.docCtx, this.selectionOverlays.selectedSets);
20463
21803
  this.elementReader = new ElementReader(this.docCtx);
20464
- //this.docRule = new DocRule(this.ruleCanvas, this.docCtx);
20465
21804
  this.documentInput = new DocumentInput(this, this.docCtx);
20466
21805
  this.documentChange = new DocumentChange(this.elementReader, this.docCtx, this.docComment, this.documentInput);
20467
21806
  this.documentEvent = new DocumentEvent(this, this.documentPaint, this.docCtx, this.documentInput);
@@ -20494,6 +21833,32 @@ class CanvasTextEditor extends AbsolutePanel {
20494
21833
  this.resetViewer(type);
20495
21834
  });
20496
21835
  }
21836
+ createDocDOM() {
21837
+ const container = document.getElementById(this.container);
21838
+ const canvas = document.createElement('canvas');
21839
+ const input = document.createElement('input');
21840
+ container.style.overflow = 'hidden';
21841
+ container.style.position = 'relative';
21842
+ container.style.fontSize = '0';
21843
+ container.style.height = '100%';
21844
+ input.style.position = 'absolute';
21845
+ input.style.width = '1px';
21846
+ input.style.padding = '0';
21847
+ input.style.border = 'none';
21848
+ input.style.outline = 'none';
21849
+ input.style.background = 'black';
21850
+ input.style.pointerEvents = 'none';
21851
+ this.editCanvas = canvas;
21852
+ this.editInput = input;
21853
+ container.appendChild(canvas);
21854
+ container.appendChild(input);
21855
+ container.insertAdjacentElement('afterbegin', input);
21856
+ container.insertAdjacentElement('afterbegin', canvas);
21857
+ }
21858
+ destroyDOM() {
21859
+ this.editInput.remove();
21860
+ this.editCanvas.remove();
21861
+ }
20497
21862
  /**
20498
21863
  * 设置标尺
20499
21864
  */
@@ -20916,6 +22281,9 @@ class CanvasTextEditor extends AbsolutePanel {
20916
22281
  destroy() {
20917
22282
  this.docCtx.destroy();
20918
22283
  this.documentEvent.clearSubEvent();
22284
+ this.selectionState.destroy();
22285
+ this.surfaceView.destroy();
22286
+ this.destroyDOM();
20919
22287
  this.flushTask = null;
20920
22288
  }
20921
22289
  /**
@@ -21193,90 +22561,10 @@ class CanvasTextEditor extends AbsolutePanel {
21193
22561
  const { startControl, startOffset } = this.selectionState;
21194
22562
  this.insertElement(startControl, startOffset, [ele]);
21195
22563
  }
21196
- getControlById(index) {
21197
- return ElementUtil.getControlByIndex(this.docCtx.document, { currIndex: -1, index });
21198
- }
21199
- getControlId(ele) {
21200
- return ElementUtil.getControlIndex(ele);
21201
- }
21202
22564
  switchPageLayout(mode) {
21203
22565
  this.viewOptions.pageLayoutMode = mode;
21204
22566
  this.flushToSchedule();
21205
22567
  }
21206
- // test2(): void {
21207
- // //获取文档上下文
21208
- // const docEleCtx = this.docCtx.getCtx(this.docCtx.document);
21209
- // //获取年龄数据元
21210
- // const dataEle = docEleCtx.getControlById('1493477712134672386') as DataElementText;
21211
- // //获取要隐藏的数据组
21212
- // const dataGroup = docEleCtx.ctx.treeFind((item) => item instanceof DataElementGroupElement) as DataElementGroupElement;
21213
- // //侦听数据元更改时间
21214
- // dataEle.onChangeSubject.subscribe((e) => {
21215
- // //在文档重新排版、绘制前,获取最终的指定节点的内容
21216
- // const beforeRefreshSub = this.onBeforeRefreshDocument.subscribe((e2) => {
21217
- // console.log('内容发生改变,隐藏数据组');
21218
- // //获取年龄数据元输入的值
21219
- // const age = Number.parseInt(dataEle.getValue());
21220
- // //年龄大于20,隐藏数据元
21221
- // dataGroup.props.hidden = age > 20;
21222
- // //取消订阅事件
21223
- // beforeRefreshSub.unsubscribe();
21224
- // });
21225
- //
21226
- // });
21227
- // }
21228
- //
21229
- // //修改纸张尺寸,单位为毫米
21230
- // //editor.setPaperSize(200,150)
21231
- // test3(width: number, height: number): void {
21232
- // this.setPaperSize(200, 150);
21233
- // }
21234
- //
21235
- // //在当前段落后面插入新的段落,段落内容为当前时间
21236
- // test4(): void {
21237
- // const {startControl} = this.selectionState;
21238
- // if (!startControl) {
21239
- // return;
21240
- // }
21241
- // //1.获取当前段落
21242
- // const currentParagraph = ElementUtil.getParentByType(startControl, ParagraphElement) as ParagraphElement;
21243
- // //2.创建新段落对象
21244
- // const newPara = ParagraphElement.createElement();
21245
- //
21246
- // //3.创建文本对象
21247
- // const newText = new TextGroupElement();
21248
- // newText.text = '当前时间为' + new Date();
21249
- // newText.props.fontName = '楷体';
21250
- // newText.props.fontSize = 18;
21251
- // newText.props.color = '#5b8c00';
21252
- // //4.将文本对象追加到新段落中
21253
- // newPara.addChild(newText);
21254
- // //5.在当前段落后面追加新段落
21255
- // currentParagraph.parent.addChild(newPara, currentParagraph.getIndex() + 1);
21256
- // //6.定位光标到新段落末尾处
21257
- // this.selectionState.resetRange(newText,-1);
21258
- // }
21259
- //
21260
- // //在当前位置插入文本数据元
21261
- // test5():void{
21262
- // const {startControl} = this.selectionState;
21263
- // if (!startControl) {
21264
- // return;
21265
- // }
21266
- // const newDataTextElement=new DataElementText();
21267
- // newDataTextElement.props.nullText='请输入内容';
21268
- // newDataTextElement.props.nullTextProps=new TextProps();
21269
- // newDataTextElement.props.nullTextProps.fontSize=16;
21270
- // newDataTextElement.props.nullTextProps.fontName='宋体';
21271
- // newDataTextElement.props.nullTextProps.color='#ffc53d';
21272
- // newDataTextElement.props.valueTextProps=new TextProps();
21273
- // newDataTextElement.props.valueTextProps.fontSize=18;
21274
- // newDataTextElement.props.valueTextProps.fontName='楷体';
21275
- // newDataTextElement.props.valueTextProps.color='red';
21276
- // this.insertNewElement(newDataTextElement);
21277
- //
21278
- // }
21279
- //
21280
22568
  // //覆盖修改页眉
21281
22569
  // test6():void{
21282
22570
  // //1.获取页眉对象
@@ -21336,7 +22624,8 @@ class CanvasTextEditor extends AbsolutePanel {
21336
22624
  const win = new Window();
21337
22625
  win.width = 1000;
21338
22626
  win.height = 800;
21339
- //win.content.addChild(timelineScrollbar)
22627
+ const timeLineControl = createTimeline();
22628
+ win.content.addChild(timeLineControl);
21340
22629
  const rule2 = new RuleControl(this.docCtx);
21341
22630
  this.rule = rule2;
21342
22631
  rule2.width = 700;