@hailin-zheng/editor-core 2.1.20 → 2.1.22

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
@@ -658,10 +658,60 @@ class CommonUtil {
658
658
  return reg.test(str);
659
659
  }
660
660
  static cloneValue(val) {
661
- if (typeof val === 'object' && val) {
662
- return JSON.parse(JSON.stringify(val));
661
+ return CommonUtil.cloneDeep(val);
662
+ }
663
+ static cloneDeep(source, visited = new WeakMap()) {
664
+ if (source === null || typeof source !== 'object') {
665
+ // 如果是基本类型或 null,则直接返回
666
+ return source;
667
+ }
668
+ // 处理循环引用
669
+ if (visited.has(source)) {
670
+ return visited.get(source);
671
+ }
672
+ if (Array.isArray(source)) {
673
+ // 如果是数组,则递归复制数组元素
674
+ const arrayClone = [];
675
+ visited.set(source, arrayClone);
676
+ source.forEach((item, index) => {
677
+ arrayClone[index] = CommonUtil.cloneDeep(item, visited);
678
+ });
679
+ return arrayClone;
680
+ }
681
+ if (source instanceof Date) {
682
+ // 如果是 Date 对象,则直接创建一个新的 Date 对象
683
+ return new Date(source.getTime());
684
+ }
685
+ if (source instanceof Map) {
686
+ // 如果是 Map 对象,则递归复制键值对
687
+ const mapClone = new Map();
688
+ visited.set(source, mapClone);
689
+ source.forEach((value, key) => {
690
+ mapClone.set(CommonUtil.cloneDeep(key, visited), CommonUtil.cloneDeep(value, visited));
691
+ });
692
+ return mapClone;
693
+ }
694
+ if (source instanceof Set) {
695
+ // 如果是 Set 对象,则递归复制元素
696
+ const setClone = new Set();
697
+ visited.set(source, setClone);
698
+ source.forEach(value => {
699
+ setClone.add(CommonUtil.cloneDeep(value, visited));
700
+ });
701
+ return setClone;
663
702
  }
664
- return val;
703
+ if (Object.prototype.toString.call(source) === '[object Object]') {
704
+ // 如果是普通对象,则递归复制对象属性
705
+ const objectClone = {};
706
+ visited.set(source, objectClone);
707
+ for (const key in source) {
708
+ if (source.hasOwnProperty(key)) {
709
+ objectClone[key] = CommonUtil.cloneDeep(source[key], visited);
710
+ }
711
+ }
712
+ return objectClone;
713
+ }
714
+ return source;
665
715
  }
666
716
  static isConstructor(f) {
667
717
  try {
@@ -741,6 +791,9 @@ class CommonUtil {
741
791
  return btoa(unescape(encodeURIComponent(str)));
742
792
  //return btoa(str.replace(/[\u00A0-\u2666]/g, c => `&#${c.charCodeAt(0)};`));
743
793
  }
794
+ static isEqual(a, b) {
795
+ return JSON.stringify(a) === JSON.stringify(b);
796
+ }
744
797
  }
745
798
 
746
799
  const docOpsMap = new Map();
@@ -1212,6 +1265,8 @@ class Element {
1212
1265
  disposed;
1213
1266
  //加载完毕
1214
1267
  loaded;
1268
+ visibleExpr;
1269
+ attribute;
1215
1270
  _parent;
1216
1271
  get parent() {
1217
1272
  return this._parent;
@@ -1284,7 +1339,6 @@ class Element {
1284
1339
  listeners.forEach(item => item(evt));
1285
1340
  }
1286
1341
  beginMeasure(data) {
1287
- this.paintRenders.length = 0;
1288
1342
  }
1289
1343
  endMeasure() {
1290
1344
  }
@@ -1700,6 +1754,7 @@ class ViewOptions {
1700
1754
  printHeaderFooterLine = false;
1701
1755
  //显示段落回车符号
1702
1756
  showEnterSymbol = false;
1757
+ enableVisibleExpression = false;
1703
1758
  get fullPageView() {
1704
1759
  return this._fullPageView;
1705
1760
  }
@@ -1813,6 +1868,30 @@ class BorderProps {
1813
1868
  return new BorderProps(this.width, this.color, this.style);
1814
1869
  }
1815
1870
  }
1871
+ /**
1872
+ * 克隆元素的基本属性
1873
+ * @param ele
1874
+ * @param target
1875
+ */
1876
+ function cloneElementBase(ele, target) {
1877
+ target.attribute = ele.attribute ? CommonUtil.cloneValue(ele.attribute) : undefined;
1878
+ }
1879
+ /**
1880
+ * 克隆元素的子元素
1881
+ * @param ele
1882
+ * @param target
1883
+ * @param data
1884
+ */
1885
+ function cloneChildren(ele, target, data) {
1886
+ if (!data) {
1887
+ return;
1888
+ }
1889
+ for (let i = 0; i < ele.length; i++) {
1890
+ const child = ele.getChild(i);
1891
+ const cloneChild = child.clone(true);
1892
+ target.addChild(cloneChild);
1893
+ }
1894
+ }
1816
1895
  class IDispose {
1817
1896
  }
1818
1897
  class ResizeLeafRenderObject extends LeafRenderObject {
@@ -2819,11 +2898,8 @@ class CommsContainerElement extends BlockContainerElement {
2819
2898
  }
2820
2899
  clone(data) {
2821
2900
  const clone = new CommsContainerElement();
2822
- if (data) {
2823
- for (let i = 0; i < this.length; i++) {
2824
- clone.addChild(this.getChild(i).clone(true));
2825
- }
2826
- }
2901
+ cloneElementBase(this, clone);
2902
+ cloneChildren(this, clone, data);
2827
2903
  return clone;
2828
2904
  }
2829
2905
  }
@@ -2906,7 +2982,7 @@ class DataDecorateElement extends LeafElement {
2906
2982
  clone() {
2907
2983
  const clone = new DataDecorateElement(this.dataEle, this.isPrefix);
2908
2984
  this.props.clone(clone.props);
2909
- //clone.renderCtx = this.renderCtx;
2985
+ cloneElementBase(this, clone);
2910
2986
  return clone;
2911
2987
  }
2912
2988
  }
@@ -2981,7 +3057,7 @@ class DataDecorateRenderObject extends LeafRenderObject {
2981
3057
  }
2982
3058
  }
2983
3059
 
2984
- function parser(code) {
3060
+ function parser(code, objects) {
2985
3061
  const node = acor__namespace.parse(code, { ecmaVersion: 'latest' });
2986
3062
  estraverse__default["default"].traverse(node, {
2987
3063
  enter: (child, parent) => {
@@ -2989,6 +3065,7 @@ function parser(code) {
2989
3065
  const identifierName = child['name'];
2990
3066
  if (identifierName.startsWith('$')) {
2991
3067
  child['name'] = `getObject('${identifierName.slice(1)}').value`;
3068
+ objects?.push(identifierName.slice(1));
2992
3069
  }
2993
3070
  }
2994
3071
  }
@@ -3015,6 +3092,28 @@ function parser(code) {
3015
3092
  });
3016
3093
  return astring.generate(node);
3017
3094
  }
3095
+ //判断代码的语句,如果最后一个语句不是return,那么加上return
3096
+ function addReturn(code) {
3097
+ const node = acor__namespace.parse(code, { ecmaVersion: 'latest' });
3098
+ estraverse__default["default"].replace(node, {
3099
+ leave: (child) => {
3100
+ //函数调用
3101
+ if (child.type == 'Program') {
3102
+ const body = child['body'];
3103
+ const lastNode = body[body.length - 1];
3104
+ if (lastNode.type !== 'ReturnStatement') {
3105
+ body[body.length - 1] = {
3106
+ type: 'ReturnStatement',
3107
+ start: -1, end: -1,
3108
+ argument: lastNode
3109
+ };
3110
+ }
3111
+ return child;
3112
+ }
3113
+ }
3114
+ });
3115
+ return astring.generate(node);
3116
+ }
3018
3117
  /**
3019
3118
  * 将参数转为函数调用arg => ()=>arg
3020
3119
  * @param nodes
@@ -3108,11 +3207,8 @@ class ParagraphElement extends BlockContentElement {
3108
3207
  clone(data) {
3109
3208
  const clone = new ParagraphElement();
3110
3209
  this.props.clone(clone.props);
3111
- if (data) {
3112
- for (let i = 0; i < this.length; i++) {
3113
- clone.addChild(this.getChild(i).clone(true));
3114
- }
3115
- }
3210
+ cloneElementBase(this, clone);
3211
+ cloneChildren(this, clone, data);
3116
3212
  return clone;
3117
3213
  }
3118
3214
  static createElement() {
@@ -3308,9 +3404,8 @@ class DocumentElement extends BlockContainerElement {
3308
3404
  clone() {
3309
3405
  const clone = new DocumentElement();
3310
3406
  this.props.clone(clone.props);
3311
- for (let i = 0; i < this.length; i++) {
3312
- clone.addChild(this.getChild(i).clone(true));
3313
- }
3407
+ cloneElementBase(this, clone);
3408
+ cloneChildren(this, clone, true);
3314
3409
  return clone;
3315
3410
  }
3316
3411
  /**
@@ -3687,6 +3782,7 @@ class InlineGroupInputElement extends InlineGroupElement {
3687
3782
  }
3688
3783
  cloneSelf(data, constr) {
3689
3784
  const clone = new constr();
3785
+ cloneElementBase(this, clone);
3690
3786
  this.props['clone'](clone.props);
3691
3787
  //cloneFunc.apply(this, clone.props);
3692
3788
  if (data) {
@@ -3809,7 +3905,7 @@ class DataElementInlineGroup extends InlineGroupInputElement {
3809
3905
  const code = parser(this.props.expression);
3810
3906
  this.expressFn = new Function(`with(this){ ${code} }`);
3811
3907
  }
3812
- this.expressFn.bind(data.parser)();
3908
+ this.expressFn.bind(data.execute)();
3813
3909
  //this.expressFn();
3814
3910
  }
3815
3911
  catch (e) {
@@ -4103,11 +4199,8 @@ class DocumentBodyElement extends BlockContainerElement {
4103
4199
  }
4104
4200
  clone(data) {
4105
4201
  const clone = new DocumentBodyElement();
4106
- if (data) {
4107
- for (let i = 0; i < this.length; i++) {
4108
- clone.addChild(this.getChild(i).clone(true));
4109
- }
4110
- }
4202
+ cloneElementBase(this, clone);
4203
+ cloneChildren(this, clone, data);
4111
4204
  return clone;
4112
4205
  }
4113
4206
  beginMeasure(data) {
@@ -4157,11 +4250,8 @@ class DocumentFooterElement extends BlockContainerElement {
4157
4250
  }
4158
4251
  clone(data) {
4159
4252
  const clone = new DocumentFooterElement();
4160
- if (data) {
4161
- for (let i = 0; i < this.length; i++) {
4162
- clone.addChild(this.getChild(i).clone(true));
4163
- }
4164
- }
4253
+ cloneElementBase(this, clone);
4254
+ cloneChildren(this, clone, data);
4165
4255
  return clone;
4166
4256
  }
4167
4257
  beginMeasure(data) {
@@ -4237,11 +4327,8 @@ class DocumentHeaderElement extends BlockContainerElement {
4237
4327
  }
4238
4328
  clone(data) {
4239
4329
  const clone = new DocumentHeaderElement();
4240
- if (data) {
4241
- for (let i = 0; i < this.length; i++) {
4242
- clone.addChild(this.getChild(i).clone(true));
4243
- }
4244
- }
4330
+ cloneElementBase(this, clone);
4331
+ cloneChildren(this, clone, data);
4245
4332
  return clone;
4246
4333
  }
4247
4334
  switchEditMode(evt) {
@@ -4339,6 +4426,7 @@ class PSymbolElement extends LeafElement {
4339
4426
  clone() {
4340
4427
  const clone = new PSymbolElement();
4341
4428
  clone.defaultHeight = this.defaultHeight;
4429
+ cloneElementBase(this, clone);
4342
4430
  return clone;
4343
4431
  }
4344
4432
  getSelfLength(pure) {
@@ -4420,11 +4508,8 @@ class TableCellElement extends BlockContainerElement {
4420
4508
  clone(data) {
4421
4509
  const clone = new TableCellElement();
4422
4510
  this.props.clone(clone.props);
4423
- if (data) {
4424
- for (let i = 0; i < this.length; i++) {
4425
- clone.addChild(this.getChild(i).clone(true));
4426
- }
4427
- }
4511
+ cloneElementBase(this, clone);
4512
+ cloneChildren(this, clone, data);
4428
4513
  return clone;
4429
4514
  }
4430
4515
  getCellWidth() {
@@ -4732,6 +4817,7 @@ class TextGroupElement extends LeafElement {
4732
4817
  const clone = new TextGroupElement();
4733
4818
  this.props.clone(clone.props);
4734
4819
  clone.text = this.text;
4820
+ cloneElementBase(this, clone);
4735
4821
  return clone;
4736
4822
  }
4737
4823
  destroy() {
@@ -4796,6 +4882,8 @@ class TextGroupRenderObject extends LeafRenderObject {
4796
4882
  return;
4797
4883
  }
4798
4884
  const props = this.element.props;
4885
+ //基线位置到top的距离
4886
+ const actualFontBoundingBoxAscent = event.renderCtx.mainContext.getActualFontBoundingBoxAscent(props.getFont());
4799
4887
  let { width, height } = this.rect;
4800
4888
  let vertHeight = 0; //baseLine;
4801
4889
  if (props.vertAlign === 'subscript') {
@@ -4814,10 +4902,11 @@ class TextGroupRenderObject extends LeafRenderObject {
4814
4902
  return curr.actualSize + prev;
4815
4903
  }, this.rect.x);
4816
4904
  const x = arr.join(' ');
4817
- const y = this.rect.y + vertHeight; //this.textMeasures.map(item => this.rect.y + vertHeight).join(' ');
4818
- // const text = this.textMeasures.map(item => {
4819
- // return item.char
4820
- // }).join('');
4905
+ let y = this.rect.y + vertHeight;
4906
+ //基线处理
4907
+ y += actualFontBoundingBoxAscent ?? 0;
4908
+ //行高处理
4909
+ y += (height - props.fontSize) / 2;
4821
4910
  const t = {
4822
4911
  sel: 'text',
4823
4912
  text: text,
@@ -4825,8 +4914,6 @@ class TextGroupRenderObject extends LeafRenderObject {
4825
4914
  ns: "http://www.w3.org/2000/svg",
4826
4915
  attrs: {
4827
4916
  //"transform": `translate(0,${(height - props.fontSize) / 2})`,
4828
- "translate": { x: 0, y: (height - props.fontSize) / 2 },
4829
- 'dominant-baseline': 'hanging',
4830
4917
  'font-family': this.element.props.fontName,
4831
4918
  'font-size': fontSize,
4832
4919
  x,
@@ -4834,6 +4921,9 @@ class TextGroupRenderObject extends LeafRenderObject {
4834
4921
  }
4835
4922
  },
4836
4923
  };
4924
+ if (actualFontBoundingBoxAscent === undefined) {
4925
+ t.data.attrs['dominant-baseline'] = 'hanging';
4926
+ }
4837
4927
  if (this.element.props.fontWeight !== 'normal') {
4838
4928
  t.data.attrs['font-weight'] = this.element.props.fontWeight;
4839
4929
  }
@@ -6457,11 +6547,8 @@ class TableElement extends BlockContainerElement {
6457
6547
  clone(data) {
6458
6548
  const clone = new TableElement();
6459
6549
  this.props.clone(clone.props);
6460
- if (data) {
6461
- for (let i = 0; i < this.length; i++) {
6462
- clone.addChild(this.getChild(i).clone(true));
6463
- }
6464
- }
6550
+ cloneElementBase(this, clone);
6551
+ cloneChildren(this, clone, data);
6465
6552
  return clone;
6466
6553
  }
6467
6554
  createRenderObject() {
@@ -6750,6 +6837,7 @@ class CheckBoxElement extends LeafElement {
6750
6837
  }
6751
6838
  clone() {
6752
6839
  const clone = new CheckBoxElement();
6840
+ cloneElementBase(this, clone);
6753
6841
  this.props.clone(clone.props);
6754
6842
  return clone;
6755
6843
  }
@@ -6853,11 +6941,8 @@ class CommContentElement extends CommContentBaseElement {
6853
6941
  clone(data) {
6854
6942
  const clone = new CommContentElement();
6855
6943
  this.props.clone(clone.props);
6856
- if (data) {
6857
- for (let i = 0; i < this.length; i++) {
6858
- clone.addChild(this.getChild(i).clone(true));
6859
- }
6860
- }
6944
+ cloneElementBase(this, clone);
6945
+ cloneChildren(this, clone, data);
6861
6946
  return clone;
6862
6947
  }
6863
6948
  beginMeasure(data) {
@@ -7134,6 +7219,7 @@ class CommentElement extends LeafElement {
7134
7219
  clone() {
7135
7220
  const clone = new CommentElement();
7136
7221
  this.props.clone(clone.props);
7222
+ cloneElementBase(this, clone);
7137
7223
  return clone;
7138
7224
  }
7139
7225
  }
@@ -7283,11 +7369,8 @@ class ValidateElement extends CommContentBaseElement {
7283
7369
  clone(data) {
7284
7370
  const clone = new ValidateElement();
7285
7371
  this.props.clone(clone.props);
7286
- if (data) {
7287
- for (let i = 0; i < this.length; i++) {
7288
- clone.addChild(this.getChild(i).clone(true));
7289
- }
7290
- }
7372
+ cloneElementBase(this, clone);
7373
+ cloneChildren(this, clone, data);
7291
7374
  return clone;
7292
7375
  }
7293
7376
  setContent(content) {
@@ -8215,6 +8298,7 @@ class DataElementBarcode extends DataElementLeaf {
8215
8298
  clone(data) {
8216
8299
  const clone = new DataElementBarcode();
8217
8300
  this.props.clone(clone.props);
8301
+ cloneElementBase(this, clone);
8218
8302
  return clone;
8219
8303
  }
8220
8304
  setValue(val) {
@@ -8368,6 +8452,7 @@ class DataElementCheck extends DataElementLeaf {
8368
8452
  clone(data) {
8369
8453
  const clone = new DataElementCheck();
8370
8454
  this.props.clone(clone.props);
8455
+ cloneElementBase(this, clone);
8371
8456
  return clone;
8372
8457
  }
8373
8458
  setValue(val) {
@@ -8738,6 +8823,7 @@ class DataElementImage extends DataElementLeaf {
8738
8823
  clone(data) {
8739
8824
  const clone = new DataElementImage();
8740
8825
  this.props.clone(clone.props);
8826
+ cloneElementBase(this, clone);
8741
8827
  return clone;
8742
8828
  }
8743
8829
  destroy() {
@@ -8989,7 +9075,7 @@ class BreakElement extends LeafElement {
8989
9075
  }
8990
9076
  clone() {
8991
9077
  const clone = new BreakElement();
8992
- //clone.renderCtx = this.renderCtx;
9078
+ cloneElementBase(this, clone);
8993
9079
  return clone;
8994
9080
  }
8995
9081
  }
@@ -9210,11 +9296,8 @@ class DocumentBodyPartElement extends BlockContainerElement {
9210
9296
  clone(data) {
9211
9297
  const clone = new DocumentBodyPartElement();
9212
9298
  clone.props.partId = this.props.partId;
9213
- if (data) {
9214
- for (let i = 0; i < this.length; i++) {
9215
- clone.addChild(this.getChild(i).clone(true));
9216
- }
9217
- }
9299
+ cloneElementBase(this, clone);
9300
+ cloneChildren(this, clone, data);
9218
9301
  return clone;
9219
9302
  }
9220
9303
  }
@@ -9312,6 +9395,7 @@ class DataElementMH extends DataElementLeaf {
9312
9395
  clone(data) {
9313
9396
  const element = new DataElementMH();
9314
9397
  this.props.clone(element.props);
9398
+ cloneElementBase(this, element);
9315
9399
  return element;
9316
9400
  }
9317
9401
  getCurrentLayoutItem() {
@@ -9557,6 +9641,152 @@ function renderMHHTML(event, element, isPaint, nodes = []) {
9557
9641
  }
9558
9642
  }
9559
9643
 
9644
+ const fontSize = 12;
9645
+ const verPadding = 2;
9646
+ /**
9647
+ * 恒牙牙位图
9648
+ */
9649
+ class PermanentTeethElement extends DataElementLeaf {
9650
+ constructor() {
9651
+ super('permanent-teeth');
9652
+ this.props = new PermanentTeethProps();
9653
+ this.props.topLeft = '';
9654
+ this.props.topRight = '';
9655
+ this.props.bottomLeft = '';
9656
+ this.props.bottomRight = '';
9657
+ }
9658
+ setValue(val) {
9659
+ if (typeof val === 'string' && val) {
9660
+ const items = val.split(';');
9661
+ if (items.length >= 4) {
9662
+ this.props.topLeft = items[0];
9663
+ this.props.topRight = items[1];
9664
+ this.props.bottomLeft = items[2];
9665
+ this.props.bottomRight = items[3];
9666
+ }
9667
+ }
9668
+ else if (typeof val === 'object') {
9669
+ this.props.topLeft = val?.topLeft ?? '';
9670
+ this.props.topRight = val?.topRight ?? '';
9671
+ this.props.bottomLeft = val?.bottomLeft ?? '';
9672
+ this.props.bottomRight = val?.bottomRight ?? '';
9673
+ }
9674
+ }
9675
+ getValue() {
9676
+ const { topLeft, topRight, bottomLeft, bottomRight } = this.props;
9677
+ return `${topLeft};${topRight};${bottomLeft};${bottomRight}`;
9678
+ }
9679
+ clone(data) {
9680
+ const clone = new PermanentTeethElement();
9681
+ clone.props = this.props.clone();
9682
+ cloneElementBase(this, clone);
9683
+ return clone;
9684
+ }
9685
+ createRenderObject(data) {
9686
+ const clone = new PermanentTeethRenderObject(this);
9687
+ clone.rect.width = 150;
9688
+ //字体大小*2+上下间距2*2
9689
+ clone.rect.height = fontSize * 2 + verPadding * 2;
9690
+ //clone.rect= ElementUtil.cloneRect(this.rect);
9691
+ return clone;
9692
+ }
9693
+ serialize(viewOptions) {
9694
+ return {
9695
+ type: this.type,
9696
+ props: this.props.getSerializeProps(viewOptions)
9697
+ };
9698
+ }
9699
+ }
9700
+ class PermanentTeethRenderObject extends LeafRenderObject {
9701
+ clone() {
9702
+ const clone = new PermanentTeethRenderObject(this.element);
9703
+ clone.rect = ElementUtil.cloneRect(this.rect);
9704
+ return clone;
9705
+ }
9706
+ // measure(): { width: number, height: number } {
9707
+ // const ele = this.element;
9708
+ //
9709
+ // }
9710
+ exportHTML(event) {
9711
+ const ele = this.element;
9712
+ const g = super.exportHTML(event);
9713
+ const contentHorPadding = 4;
9714
+ g.children = [];
9715
+ // g.children.push(ElementUtil.getFillSvgPath(`M 0 ${this.rect.height / 2} h${this.rect.width}`, '#000', 1));
9716
+ // g.children.push(ElementUtil.getFillSvgPath(`M ${this.rect.width / 2} 0 v${this.rect.height}`, '#000', 1));
9717
+ //
9718
+ g.children.push(ElementUtil.getFillSvgRect(0, this.rect.height / 2, this.rect.width, 1, '#000'));
9719
+ g.children.push(ElementUtil.getFillSvgRect(this.rect.width / 2, 0, 1, this.rect.height, '#000'));
9720
+ const getSvgText = (text, x, y) => {
9721
+ return {
9722
+ sel: 'text',
9723
+ text: text,
9724
+ data: {
9725
+ ns: "http://www.w3.org/2000/svg",
9726
+ attrs: {
9727
+ 'dominant-baseline': 'hanging',
9728
+ 'font-family': 'Arial',
9729
+ 'font-size': fontSize,
9730
+ x,
9731
+ y,
9732
+ }
9733
+ },
9734
+ };
9735
+ };
9736
+ const topLeftWidth = event.renderCtx.mainContext.measureTextWidth(ele.props.topLeft, {
9737
+ fontSize: fontSize,
9738
+ fontName: 'Arial'
9739
+ });
9740
+ const bottomLeftWidth = event.renderCtx.mainContext.measureTextWidth(ele.props.bottomLeft, {
9741
+ fontSize: fontSize,
9742
+ fontName: 'Arial'
9743
+ });
9744
+ g.children.push(getSvgText(ele.props.topLeft, this.rect.width / 2 - topLeftWidth - contentHorPadding, verPadding));
9745
+ g.children.push(getSvgText(ele.props.topRight, this.rect.width / 2 + contentHorPadding, verPadding));
9746
+ g.children.push(getSvgText(ele.props.bottomLeft, this.rect.width / 2 - bottomLeftWidth - contentHorPadding, this.rect.height - fontSize + verPadding));
9747
+ g.children.push(getSvgText(ele.props.bottomRight, this.rect.width / 2 + contentHorPadding, this.rect.height - fontSize + verPadding));
9748
+ return g;
9749
+ }
9750
+ }
9751
+ class PermanentTeethFactory extends ElementFactory {
9752
+ match(type) {
9753
+ return type === 'permanent-teeth';
9754
+ }
9755
+ createElement(data) {
9756
+ const ele = new PermanentTeethElement();
9757
+ ele.props.bottomLeft = data.props?.bottomLeft ?? '';
9758
+ ele.props.bottomRight = data.props?.bottomRight ?? '';
9759
+ ele.props.topLeft = data.props?.topLeft ?? '';
9760
+ ele.props.topRight = data.props?.topRight ?? '';
9761
+ return ele;
9762
+ }
9763
+ }
9764
+ /**
9765
+ * 恒牙牙位图属性
9766
+ */
9767
+ class PermanentTeethProps extends INotifyPropertyChanged {
9768
+ topLeft;
9769
+ topRight;
9770
+ bottomLeft;
9771
+ bottomRight;
9772
+ getSerializeProps(viewOptions) {
9773
+ return {
9774
+ topLeft: this.topLeft,
9775
+ topRight: this.topRight,
9776
+ bottomLeft: this.bottomLeft,
9777
+ bottomRight: this.bottomRight,
9778
+ };
9779
+ }
9780
+ clone(dest) {
9781
+ dest = dest || new PermanentTeethProps();
9782
+ dest.topLeft = this.topLeft;
9783
+ dest.topRight = this.topRight;
9784
+ dest.bottomLeft = this.bottomLeft;
9785
+ dest.bottomRight = this.bottomRight;
9786
+ return dest;
9787
+ }
9788
+ }
9789
+
9560
9790
  class PictureElement extends LeafElement {
9561
9791
  //props: PictureProps;
9562
9792
  status = 'no';
@@ -9585,6 +9815,7 @@ class PictureElement extends LeafElement {
9585
9815
  clone(data) {
9586
9816
  const clone = new PictureElement();
9587
9817
  this.props.clone(clone.props);
9818
+ cloneElementBase(this, clone);
9588
9819
  return clone;
9589
9820
  }
9590
9821
  destroy() {
@@ -9710,6 +9941,7 @@ class RadioBoxElement extends LeafElement {
9710
9941
  clone() {
9711
9942
  const clone = new RadioBoxElement();
9712
9943
  this.props.clone(clone.props);
9944
+ cloneElementBase(this, clone);
9713
9945
  return clone;
9714
9946
  }
9715
9947
  }
@@ -9761,7 +9993,7 @@ class PageBreakElement extends LeafElement {
9761
9993
  }
9762
9994
  clone() {
9763
9995
  const clone = new PageBreakElement();
9764
- //clone.renderCtx = this.renderCtx;
9996
+ cloneElementBase(this, clone);
9765
9997
  return clone;
9766
9998
  }
9767
9999
  }
@@ -9798,7 +10030,9 @@ class TabElement extends LeafElement {
9798
10030
  };
9799
10031
  }
9800
10032
  clone() {
9801
- return new TabElement();
10033
+ const clone = new TabElement();
10034
+ cloneElementBase(this, clone);
10035
+ return clone;
9802
10036
  }
9803
10037
  }
9804
10038
  class TabRenderObject extends LeafRenderObject {
@@ -10393,6 +10627,7 @@ class SVGElement extends LeafElement {
10393
10627
  clone(data) {
10394
10628
  const clone = new SVGElement();
10395
10629
  this.props.clone(clone.props);
10630
+ cloneElementBase(this, clone);
10396
10631
  return clone;
10397
10632
  }
10398
10633
  destroy() {
@@ -10519,6 +10754,9 @@ class ElementSerialize {
10519
10754
  if (element.props && element.props['__attachedProperty'] && !result.props['__attachedProperty']) {
10520
10755
  result.props['__attachedProperty'] = CommonUtil.cloneValue(element.props['__attachedProperty']);
10521
10756
  }
10757
+ if (element.attribute) {
10758
+ result['attribute'] = this.serializeAttribute(element);
10759
+ }
10522
10760
  return result;
10523
10761
  }
10524
10762
  static serializeString(element, options = { all: false }) {
@@ -10541,6 +10779,21 @@ class ElementSerialize {
10541
10779
  }
10542
10780
  return "";
10543
10781
  }
10782
+ static serializeAttribute(element) {
10783
+ if (element.attribute) {
10784
+ const result = {};
10785
+ for (const key in element.attribute) {
10786
+ if (element.attribute[key] !== undefined && element.attribute[key] !== null) {
10787
+ result[key] = element.attribute[key];
10788
+ }
10789
+ }
10790
+ if (Object.keys(result).length === 0) {
10791
+ return null;
10792
+ }
10793
+ return CommonUtil.cloneValue(result);
10794
+ }
10795
+ return null;
10796
+ }
10544
10797
  /**
10545
10798
  * 获取选中的结构
10546
10799
  * @param ss
@@ -10639,12 +10892,8 @@ class TrackRunElement extends InlineGroupElement {
10639
10892
  clone(data) {
10640
10893
  const clone = new TrackRunElement(this.type);
10641
10894
  this.props.clone(clone.props);
10642
- if (data) {
10643
- const length = this.length;
10644
- for (let i = 0; i < length; i++) {
10645
- clone.addChild(this.getChild(i).clone(true));
10646
- }
10647
- }
10895
+ cloneElementBase(this, clone);
10896
+ cloneChildren(this, clone, data);
10648
10897
  return clone;
10649
10898
  }
10650
10899
  createRenderObject(data) {
@@ -12528,6 +12777,26 @@ class ElementUtil {
12528
12777
  ss.resetRange(ele.getChild(ele.length - 2), -1);
12529
12778
  }
12530
12779
  }
12780
+ static setEleAttribute(ele, attr, value) {
12781
+ if (!ele.attribute) {
12782
+ ele.attribute = {};
12783
+ }
12784
+ if (ele.attribute[attr] === value) {
12785
+ return;
12786
+ }
12787
+ ele.attribute[attr] = value;
12788
+ }
12789
+ static getEleAttribute(ele, attr) {
12790
+ if (ele.attribute) {
12791
+ return ele.attribute[attr];
12792
+ }
12793
+ return undefined;
12794
+ }
12795
+ static removeEleAttribute(ele, attr) {
12796
+ if (ele.attribute) {
12797
+ delete ele.attribute[attr];
12798
+ }
12799
+ }
12531
12800
  }
12532
12801
 
12533
12802
  class RenderContext {
@@ -12602,7 +12871,18 @@ class PaintContent {
12602
12871
  this.init();
12603
12872
  }
12604
12873
  init() {
12605
- this.ctx.textBaseline = 'top';
12874
+ //this.ctx.textBaseline = 'top';
12875
+ }
12876
+ cacheFontBoundingBoxAscentMap = new Map();
12877
+ getActualFontBoundingBoxAscent(font) {
12878
+ if (this.cacheFontBoundingBoxAscentMap.has(font)) {
12879
+ return this.cacheFontBoundingBoxAscentMap.get(font);
12880
+ }
12881
+ this.ctx.font = font;
12882
+ const textMetrics = this.ctx.measureText('正');
12883
+ const value = textMetrics.actualBoundingBoxAscent;
12884
+ this.cacheFontBoundingBoxAscentMap.set(font, value);
12885
+ return value;
12606
12886
  }
12607
12887
  setGlobalAlpha(alpha) {
12608
12888
  this.ctx.globalAlpha = alpha;
@@ -13162,10 +13442,7 @@ class EditorContext {
13162
13442
  isDirty = false;
13163
13443
  cursorRect;
13164
13444
  _document;
13165
- //文档刷新的订阅事件
13166
- //refSub!: Subscription;
13167
13445
  syncRefresh;
13168
- //imageLoader: IImageLoader;
13169
13446
  dynamicFunc;
13170
13447
  docChange;
13171
13448
  clearPrevDocCb;
@@ -13219,6 +13496,7 @@ class EditorContext {
13219
13496
  //this.imageLoader.clear();
13220
13497
  this.dynamicFunc.destroyScripts();
13221
13498
  this.isDirty = false;
13499
+ //this.clearEleDepMaps();
13222
13500
  }
13223
13501
  get defaultCtx() {
13224
13502
  return new DocumentContext(this._document, this.selectionState);
@@ -13293,17 +13571,6 @@ class EditorContext {
13293
13571
  return this._document.modifyFlag === exports.ModifyFlag.None ? 'appearance' : 'content';
13294
13572
  }
13295
13573
  }
13296
- // export interface IImageLoader {
13297
- // clear(): void;
13298
- //
13299
- // loadImage(src: string, onCallback: (status: ImgLoadStatus) => void): void;
13300
- //
13301
- // getImage(src: string): HTMLImageElement | undefined;
13302
- //
13303
- // imagesLoadCompleted(): boolean;
13304
- //
13305
- // getLoadTasks(): Array<Promise<void>>;
13306
- // }
13307
13574
  /**
13308
13575
  * 文档上下文
13309
13576
  */
@@ -13566,13 +13833,23 @@ class DocumentContext {
13566
13833
  }
13567
13834
  }
13568
13835
 
13569
- class DynamicContextParser {
13836
+ class DynamicExecute {
13570
13837
  doc;
13571
13838
  ss;
13839
+ current;
13840
+ depItems;
13572
13841
  constructor(doc, ss) {
13573
13842
  this.doc = doc;
13574
13843
  this.ss = ss;
13575
13844
  }
13845
+ setCurrentCtx(ele, depItems) {
13846
+ this.current = ele;
13847
+ this.depItems = depItems;
13848
+ }
13849
+ clearCurrentCtx() {
13850
+ this.current = undefined;
13851
+ this.depItems = undefined;
13852
+ }
13576
13853
  cacheList;
13577
13854
  getControlById(id) {
13578
13855
  if (!this.cacheList) {
@@ -13584,6 +13861,10 @@ class DynamicContextParser {
13584
13861
  //return this.cacheList.find(item => item['props']['id'] === id);
13585
13862
  }
13586
13863
  getObject(id) {
13864
+ //如果当前存在编译缓存,则直接从缓存中获取
13865
+ if (this.depItems && this.depItems.has(id)) {
13866
+ return this.depItems.get(id);
13867
+ }
13587
13868
  new DocumentContext(this.doc, this.ss);
13588
13869
  if (id.startsWith('$')) {
13589
13870
  id = id.slice(1);
@@ -13602,6 +13883,9 @@ class DynamicContextParser {
13602
13883
  if (control) {
13603
13884
  control.setValue(val);
13604
13885
  }
13886
+ },
13887
+ get ref() {
13888
+ return control;
13605
13889
  }
13606
13890
  };
13607
13891
  }
@@ -13673,9 +13957,12 @@ class DynamicContextParser {
13673
13957
  class ParagraphMeasure {
13674
13958
  options;
13675
13959
  renderCtx;
13676
- constructor(options, renderCtx) {
13960
+ execute;
13961
+ constructor(options, renderCtx, execute) {
13677
13962
  this.options = options;
13678
13963
  this.renderCtx = renderCtx;
13964
+ this.execute = execute;
13965
+ this.execute = execute;
13679
13966
  }
13680
13967
  /**
13681
13968
  * 段落排版:
@@ -13771,7 +14058,10 @@ class ParagraphMeasure {
13771
14058
  const paraRenders = [];
13772
14059
  for (let i = 0; i < paraModels.length; i++) {
13773
14060
  const innerLineRects = paraModels[i].innerLine;
13774
- let render = p.createRenderObject();
14061
+ let render = this.createRenderObject(p);
14062
+ if (!render) {
14063
+ return [];
14064
+ }
13775
14065
  render.setRenderWidth(limitWidth);
13776
14066
  paraRenders.push(render);
13777
14067
  for (let j = 0; j < innerLineRects.length; j++) {
@@ -13912,7 +14202,7 @@ class ParagraphMeasure {
13912
14202
  }
13913
14203
  arrangeInlineGroupElement(parentLine, ele) {
13914
14204
  const { options, renderCtx } = this;
13915
- let render = ele.createRenderObject({ options, renderCtx });
14205
+ let render = this.createRenderObject(ele);
13916
14206
  //记录多行情况下的渲染对象,用于计算总长度,生成fill-null-space
13917
14207
  const inlineGroupRenders = [];
13918
14208
  ele.cacheRender = render;
@@ -13966,10 +14256,7 @@ class ParagraphMeasure {
13966
14256
  const baseTextProps = ele.props;
13967
14257
  nullText.text = baseTextProps.nullText;
13968
14258
  baseTextProps.nullTextProps.clone(nullText.props);
13969
- const nullTextRender = nullText.createRenderObject({
13970
- options: this.options,
13971
- renderCtx: this.renderCtx
13972
- });
14259
+ const nullTextRender = this.createRenderObject(nullText);
13973
14260
  //inlineGroupRender.insertChild(nullTextRender, 1);
13974
14261
  this.arrangeLeafRender(data, nullTextRender);
13975
14262
  }
@@ -13998,7 +14285,7 @@ class ParagraphMeasure {
13998
14285
  }
13999
14286
  }
14000
14287
  arrangeLeafElement(parentLine, ele) {
14001
- ele.cacheRender = ele.createRenderObject({ options: this.options, renderCtx: this.renderCtx });
14288
+ ele.cacheRender = this.createRenderObject(ele);
14002
14289
  if (ele.cacheRender) {
14003
14290
  this.arrangeLeafRender(parentLine, ele.cacheRender);
14004
14291
  }
@@ -14195,6 +14482,80 @@ class ParagraphMeasure {
14195
14482
  }
14196
14483
  throw new Error('未到达计算位置');
14197
14484
  }
14485
+ /**
14486
+ * 解析可见性表达式
14487
+ * @param ele
14488
+ * @param execute
14489
+ * @private
14490
+ */
14491
+ parseVisibleExpression(ele, execute) {
14492
+ if (ele.visibleExpr)
14493
+ return;
14494
+ if (!ele.attribute?.visibleExpr)
14495
+ return;
14496
+ const reactiveMode = this.renderCtx.drawMode !== 'print';
14497
+ try {
14498
+ const depIdItems = [];
14499
+ const depEleMap = new Map();
14500
+ let compliedCode = parser(ele.attribute?.visibleExpr, depIdItems);
14501
+ compliedCode = addReturn(compliedCode);
14502
+ if (depIdItems.length) {
14503
+ depIdItems.forEach(dep => {
14504
+ const refCtx = execute.getObject(dep);
14505
+ if (refCtx.ref) {
14506
+ const refEle = refCtx.ref.item;
14507
+ depEleMap.set(dep, refCtx);
14508
+ //当前有可能是checkbox数组
14509
+ const refEles = Array.isArray(refEle) ? refEle : [refEle];
14510
+ reactiveMode && refEles.forEach(item => {
14511
+ //求值依赖元素更改的时候,发布当前元素重新计算的指令
14512
+ item.onChangeSubject.subscribe(() => {
14513
+ ele.pubOnChange('self');
14514
+ });
14515
+ });
14516
+ }
14517
+ });
14518
+ }
14519
+ ele.visibleExpr = { compliedCode, func: new Function(`with(this){ ${compliedCode} }`), depItems: depEleMap };
14520
+ }
14521
+ catch (e) {
14522
+ console.error('解析表达式出错', ele.attribute?.visibleExpr);
14523
+ }
14524
+ }
14525
+ /**
14526
+ * 元素可见行求值
14527
+ * @param ele
14528
+ * @param executeCtx
14529
+ * @private
14530
+ */
14531
+ evalVisibleExpr(ele, executeCtx) {
14532
+ if (ele.visibleExpr && ele.visibleExpr.func) {
14533
+ try {
14534
+ executeCtx.setCurrentCtx(ele, ele.visibleExpr.depItems);
14535
+ const func = ele.visibleExpr.func.bind(executeCtx);
14536
+ return func() === true;
14537
+ }
14538
+ catch (e) {
14539
+ console.error(e, "表达式执行出错", ele.visibleExpr.compliedCode);
14540
+ }
14541
+ finally {
14542
+ executeCtx.clearCurrentCtx();
14543
+ }
14544
+ }
14545
+ return true;
14546
+ }
14547
+ createRenderObject(element) {
14548
+ if (this.options.enableVisibleExpression) {
14549
+ this.parseVisibleExpression(element, this.execute);
14550
+ if (!this.evalVisibleExpr(element, this.execute)) {
14551
+ return null;
14552
+ }
14553
+ }
14554
+ return element.createRenderObject({
14555
+ options: this.options,
14556
+ renderCtx: this.renderCtx
14557
+ });
14558
+ }
14198
14559
  }
14199
14560
 
14200
14561
  /**
@@ -14326,6 +14687,8 @@ class DocumentArrange {
14326
14687
  renderCtx;
14327
14688
  seo;
14328
14689
  options;
14690
+ execute;
14691
+ pMeasure;
14329
14692
  constructor(docCtx, renderCtx, seo) {
14330
14693
  this.docCtx = docCtx;
14331
14694
  this.renderCtx = renderCtx;
@@ -14345,10 +14708,12 @@ class DocumentArrange {
14345
14708
  //测量阶段,对于空段落会插入段落符号,新表格会插入空段落,此时不需要记录节点的更改,以最大的节点进行记录
14346
14709
  return suppressTracking(() => {
14347
14710
  const doc = this.docCtx.document;
14711
+ this.execute = new DynamicExecute(doc, this.docCtx.selectionState);
14712
+ this.pMeasure = new ParagraphMeasure(this.options, this.renderCtx, this.execute);
14348
14713
  const data = {
14349
14714
  doc,
14350
14715
  viewOptions: this.options,
14351
- parser: new DynamicContextParser(doc, this.docCtx.selectionState),
14716
+ execute: this.execute,
14352
14717
  createParaFn: () => this.createDefaultPara()
14353
14718
  };
14354
14719
  doc.clearMarkItems();
@@ -14464,15 +14829,6 @@ class DocumentArrange {
14464
14829
  cloneFooterRender.rect.x = limitRect.x;
14465
14830
  cloneFooterRender.rect.y = documentRender.rect.height - bodyMarginBottom;
14466
14831
  currColumn === 0 && documentRender.addChild(cloneFooterRender);
14467
- // //审阅模式,添加审阅窗口
14468
- // if (this.options.showReviewWindow && commentsRender) {
14469
- // const commentsContainer = this.createRenderObject(commentsRender.element) as CommsContainerRenderObject;
14470
- // commentsContainer.padding.top = bodyMarginTop;
14471
- // commentsContainer.rect.height = documentRender.rect.height;
14472
- // documentRender.addChild(commentsContainer);
14473
- // commentsContainer.rect.x = documentRender.rect.x + documentRender.rect.width;
14474
- // documentRender.rect.width += this.options.reviewWindowWidth;
14475
- // }
14476
14832
  currColumn++;
14477
14833
  if (currColumn === docColumns) {
14478
14834
  currColumn = 0;
@@ -14483,7 +14839,7 @@ class DocumentArrange {
14483
14839
  return docPages;
14484
14840
  }
14485
14841
  createEmptyBodyRender(bodyRender, limitRect) {
14486
- const pageBodyRender = this.createRenderObject(bodyRender.element);
14842
+ const pageBodyRender = this.pMeasure.createRenderObject(bodyRender.element);
14487
14843
  pageBodyRender.rect.width = limitRect.width;
14488
14844
  const bodyInnerLimitRect = pageBodyRender.getInnerRect();
14489
14845
  if (this.options.fullPageView) {
@@ -14499,12 +14855,11 @@ class DocumentArrange {
14499
14855
  return element.cacheRender;
14500
14856
  }
14501
14857
  if (element instanceof BlockContentElement) {
14502
- const pRange = new ParagraphMeasure(this.options, this.renderCtx);
14503
- return pRange.measureParagraph(element, maxWidth);
14858
+ return this.pMeasure.measureParagraph(element, maxWidth);
14504
14859
  }
14505
14860
  else if (element instanceof BlockContainerElement) {
14506
14861
  const renders = [];
14507
- let render = this.createRenderObject(element);
14862
+ let render = this.pMeasure.createRenderObject(element);
14508
14863
  if (!render) {
14509
14864
  element.cacheRender = null;
14510
14865
  return null;
@@ -14517,8 +14872,8 @@ class DocumentArrange {
14517
14872
  const innerMaxWidth = render.getInnerMaxWidth();
14518
14873
  for (let i = 0; i < element.length; i++) {
14519
14874
  const child = element.getChild(i);
14520
- const blockContentELement = child;
14521
- const childRender = this.measureControl(blockContentELement, innerMaxWidth);
14875
+ const blockContentElement = child;
14876
+ const childRender = this.measureControl(blockContentElement, innerMaxWidth);
14522
14877
  if (!childRender) {
14523
14878
  continue;
14524
14879
  }
@@ -14528,7 +14883,7 @@ class DocumentArrange {
14528
14883
  }
14529
14884
  for (let j = 0; j < childRender.length; j++) {
14530
14885
  if (j > 0) {
14531
- render = this.createRenderObject(element);
14886
+ render = this.pMeasure.createRenderObject(element);
14532
14887
  if (!render.rect.width) {
14533
14888
  render.setRenderWidth(maxWidth);
14534
14889
  }
@@ -14556,12 +14911,6 @@ class DocumentArrange {
14556
14911
  textLineRenderMode(cacheRender, { options: this.options, renderCtx: this.renderCtx });
14557
14912
  }
14558
14913
  }
14559
- createRenderObject(element) {
14560
- return element.createRenderObject({
14561
- options: this.options,
14562
- renderCtx: this.renderCtx
14563
- });
14564
- }
14565
14914
  getDocInnerRect(documentRender) {
14566
14915
  const render = documentRender.element.createRenderObject();
14567
14916
  render.padding = documentRender.padding;
@@ -14580,7 +14929,7 @@ class DocumentArrange {
14580
14929
  if (render instanceof TableRenderObject) {
14581
14930
  return this.cutTable(render, limitHeight);
14582
14931
  }
14583
- const cloneRender = this.createRenderObject(render.element);
14932
+ const cloneRender = this.pMeasure.createRenderObject(render.element);
14584
14933
  cloneRender.setRenderWidth(render.rect.width);
14585
14934
  if (render instanceof MuiltBlockLineRenderObject) {
14586
14935
  let sumHeight = 0;
@@ -14757,7 +15106,7 @@ class DocumentArrange {
14757
15106
  for (let i = 0; i < cutCellRenders.length; i++) {
14758
15107
  let cellRender = cutCellRenders[i];
14759
15108
  if (!cellRender) {
14760
- cellRender = this.createRenderObject(cellRenders[i].element);
15109
+ cellRender = this.pMeasure.createRenderObject(cellRenders[i].element);
14761
15110
  cellRender.rect = ElementUtil.cloneRect(cellRenders[i].rect);
14762
15111
  cellRender.rect.height = 0;
14763
15112
  ElementUtil.remeasure(cellRender);
@@ -14873,647 +15222,18 @@ class DocumentArrange {
14873
15222
  return -1;
14874
15223
  }
14875
15224
  getHeaderRows(tb) {
14876
- const rows = [];
14877
- for (let i = 0; i < tb.length; i++) {
14878
- const rowRender = tb.getChild(i);
14879
- const rowEle = rowRender.element;
14880
- if (rowEle.props.headerRow) {
14881
- rows.push(rowRender);
14882
- }
14883
- else {
14884
- break;
14885
- }
14886
- }
14887
- return rows;
14888
- }
14889
- /**
14890
- * 修改测量完毕后的元素状态
14891
- * @param ele
14892
- */
14893
- setMeasureCompletedModifyFlag(ele) {
14894
- if (ele instanceof BranchElement) {
14895
- for (let i = 0; i < ele.length; i++) {
14896
- this.setMeasureCompletedModifyFlag(ele.getChild(i));
14897
- }
14898
- }
14899
- ele.modifyFlag = exports.ModifyFlag.None;
14900
- if (!ele.loaded) {
14901
- ele.loaded = true;
14902
- }
14903
- }
14904
- clearPaintCache(ele, data) {
14905
- ele.beginMeasure(data);
14906
- this.identifyComment(ele);
14907
- if (ele instanceof BranchElement) {
14908
- for (let i = 0; i < ele.length; i++) {
14909
- this.clearPaintCache(ele.getChild(i), data);
14910
- }
14911
- }
14912
- }
14913
- identifyComment(ele) {
14914
- if (ele instanceof CommentElement) {
14915
- this.docCtx.document.identifyCommMark(ele);
14916
- }
14917
- }
14918
- cacheDoc;
14919
- cacheDocRenders(docs) {
14920
- docs.forEach(doc => {
14921
- this.cacheDoc = doc;
14922
- this.cacheRenders(doc);
14923
- });
14924
- this.cacheDoc = null;
14925
- }
14926
- /**
14927
- * 生成批注区间信息
14928
- * @param renderTree
14929
- */
14930
- generateCommRange() {
14931
- this.seo.commRangeSets.clear();
14932
- const commMarks = this.docCtx.document.markPairs;
14933
- for (let i = 0; i < commMarks.length; i++) {
14934
- const commMark = commMarks[i];
14935
- if (commMark.start && commMark.end) {
14936
- const ancestor = DocumentSelection.getAncestorCommonControl(commMark.start, commMark.end);
14937
- const range = RangeUtil.getSectionRange(commMark.start, 0, commMark.end, 1, ancestor);
14938
- SelectionOverlays.addToCommentSets(range, this.seo.commRangeSets, commMark.start.color);
14939
- }
14940
- }
14941
- }
14942
- cacheRenders(renderTree) {
14943
- if (renderTree.element) {
14944
- renderTree.element.paintRenders.push(renderTree);
14945
- }
14946
- for (let i = 0; i < renderTree.length; i++) {
14947
- const currRender = renderTree.getChild(i);
14948
- if (currRender.element) {
14949
- this.cacheCommsRender(currRender);
14950
- }
14951
- if (currRender instanceof BranchRenderObject) {
14952
- this.cacheRenders(currRender);
14953
- }
14954
- else {
14955
- currRender.element && currRender.element.paintRenders.push(currRender);
14956
- }
14957
- }
14958
- }
14959
- /**
14960
- * 缓存批注标志
14961
- * @private
14962
- */
14963
- cacheCommsRender(render) {
14964
- if (render.element && render.element.type === 'comm') {
14965
- const commElement = render.element;
14966
- if (commElement.props.markType === 'start') {
14967
- const currDocRender = this.cacheDoc;
14968
- const docCommContainer = currDocRender.getItems().find(item => item instanceof CommsContainerRenderObject);
14969
- if (docCommContainer) {
14970
- docCommContainer.commsMarks.push(render);
14971
- }
14972
- }
14973
- }
14974
- if (render.element && render.element.type === 'comm-list') {
14975
- const commContainer = render;
14976
- CommentsUtil.createCommentsImage(commContainer);
14977
- }
14978
- }
14979
- endMeasures(ele) {
14980
- ele.endMeasure();
14981
- if (ele instanceof BranchElement) {
14982
- for (let i = 0; i < ele.length; i++) {
14983
- this.endMeasures(ele.getChild(i));
14984
- }
14985
- }
14986
- }
14987
- createDefaultPara() {
14988
- const tmp = new ParagraphElement();
14989
- tmp.props.lineHeight = this.options.defaultLineHeight;
14990
- return tmp;
14991
- }
14992
- }
14993
-
14994
- /**
14995
- * 文字行渲染模式
14996
- 用于医嘱打印模式
14997
- */
14998
- function runTextLineRender(ele, data) {
14999
- if (!data.options.textRowLineMode) {
15000
- return;
15001
- }
15002
- if (ele instanceof TableElement) {
15003
- // textLineRenderMode(ele, data);
15004
- // remeasureParentRenders(ele.cacheRender)
15005
- return;
15006
- }
15007
- if (ele instanceof BranchElement) {
15008
- for (let i = 0; i < ele.length; i++) {
15009
- runTextLineRender(ele.getChild(i), data);
15010
- }
15011
- }
15012
- }
15013
-
15014
- /**
15015
- * 测量阶段,生成Render-UI
15016
- */
15017
- class ElementMeasure {
15018
- docCtx;
15019
- renderCtx;
15020
- options;
15021
- constructor(docCtx, renderCtx) {
15022
- this.docCtx = docCtx;
15023
- this.renderCtx = renderCtx;
15024
- this.options = docCtx.viewOptions;
15025
- }
15026
- measureDocument(document) {
15027
- //测量阶段,对于空段落会插入段落符号,新表格会插入空段落,此时不需要记录节点的更改,以最大的节点进行记录
15028
- return suppressTracking(() => {
15029
- this.clearPaintCache(document, {
15030
- doc: document,
15031
- viewOptions: this.options,
15032
- parser: new DynamicContextParser(document, this.docCtx.selectionState),
15033
- createParaFn: () => new ParagraphElement()
15034
- });
15035
- const docRender = this.measureControl(document, this.options.docPageSettings.width);
15036
- this.setMeasureCompletedModifyFlag(document);
15037
- runTextLineRender(document, { options: this.options, renderCtx: this.renderCtx });
15038
- return docRender;
15039
- });
15040
- }
15041
- measureControl(element, maxWidth) {
15042
- if (element.modifyFlag === exports.ModifyFlag.None) {
15043
- return element.cacheRender;
15044
- }
15045
- if (element instanceof BlockContentElement) {
15046
- const render = element.createRenderObject({ options: this.options, renderCtx: this.renderCtx });
15047
- element.cacheRender = render;
15048
- //测量阶段,只限制最大宽度即可
15049
- render.setRenderWidth(maxWidth);
15050
- if (element instanceof ParagraphElement) {
15051
- this.measureParagraph(element, render);
15052
- }
15053
- else {
15054
- throw new Error('未实现');
15055
- }
15056
- return render;
15057
- }
15058
- else if (element instanceof BlockContainerElement) {
15059
- //ElementUtil.fixBlockContainer(element);
15060
- let render = null;
15061
- if (element.modifyFlag === exports.ModifyFlag.Modify || element.modifyFlag === exports.ModifyFlag.Track) {
15062
- //ElementUtil.fixBlockContainer(element);
15063
- element.cacheRender = null;
15064
- render = element.createRenderObject({ options: this.options, renderCtx: this.renderCtx });
15065
- if (!render) {
15066
- element.cacheRender = null;
15067
- return null;
15068
- }
15069
- if (!render.rect.width) {
15070
- render.setRenderWidth(maxWidth);
15071
- }
15072
- }
15073
- if (!render) {
15074
- throw new Error('render is null');
15075
- }
15076
- element.cacheRender = render;
15077
- const innerMaxWidth = render.getInnerMaxWidth();
15078
- for (let i = 0; i < element.length; i++) {
15079
- const child = element.getChild(i);
15080
- const blockContentELement = child;
15081
- const childRender = this.measureControl(blockContentELement, innerMaxWidth);
15082
- if (!childRender) {
15083
- continue;
15084
- }
15085
- render.addChild(childRender);
15086
- }
15087
- ElementUtil.remeasure(render);
15088
- return render;
15089
- }
15090
- else {
15091
- throw new Error('未实现');
15092
- }
15093
- }
15094
- /**
15095
- * 生成段落 UI 树
15096
- * @param para
15097
- * @param render
15098
- */
15099
- measureParagraph(para, render) {
15100
- ElementUtil.fixParagraphContent(para);
15101
- const renderObjects = [];
15102
- for (let i = 0; i < para.length; i++) {
15103
- const child = para.getChild(i);
15104
- if (child instanceof InlineGroupElement) {
15105
- child.cacheRender = this.getInlineGroupRenderItem(child);
15106
- if (child.cacheRender) {
15107
- renderObjects.push(child.cacheRender);
15108
- }
15109
- }
15110
- else if (child instanceof LeafElement) {
15111
- child.cacheRender = child.createRenderObject({ options: this.options, renderCtx: this.renderCtx });
15112
- if (child.cacheRender) {
15113
- renderObjects.push(child.cacheRender);
15114
- }
15115
- }
15116
- }
15117
- this.measureInnerParagraph(render, para, renderObjects);
15118
- }
15119
- /**
15120
- * 根据段落UI元素,进行排列
15121
- * @param render
15122
- * @param paragraph
15123
- * @param renderObjects
15124
- */
15125
- measureInnerParagraph(render, paragraph, renderObjects) {
15126
- return;
15127
- // let lineRect = render.createLineRect();
15128
- // let maxLineWidth=render.rect.width;
15129
- // //行内框
15130
- // const innerLineRects: Array<ParagraphLineRectRenderObject> = [];
15131
- // const addInnerLineFunc = (lineRect: ParagraphLineRectRenderObject): void => {
15132
- // maxLineWidth=render.rect.width;
15133
- // innerLineRects.push(lineRect);
15134
- // if (innerLineRects.indexOf(lineRect) === 0) {
15135
- // if (paragraph.props.indent > 0) {
15136
- // maxLineWidth -= paragraph.props.indent;
15137
- // }
15138
- // } else {
15139
- // maxLineWidth -= paragraph.props.hanging;
15140
- // }
15141
- // };
15142
- // addInnerLineFunc(lineRect);
15143
- // let i = 0;
15144
- // let currItem = renderObjects[i++];
15145
- // const inCloseBody = paragraph.parent.type === 'body';
15146
- // while (currItem) {
15147
- // const maxWidth = maxLineWidth;
15148
- // const nextItem = renderObjects[i];
15149
- // const {
15150
- // firstItem,
15151
- // lastItem,
15152
- // br
15153
- // } = this.cutRenderItem(currItem, nextItem, maxWidth - lineRect.rect.width, lineRect.length === 0, inCloseBody);
15154
- // if (firstItem) {
15155
- // if (lastItem) {
15156
- // renderObjects.splice(i, 0, lastItem);
15157
- // }
15158
- // currItem = firstItem;
15159
- // } else {
15160
- // lineRect = render.createLineRect();
15161
- // addInnerLineFunc(lineRect);
15162
- // continue;
15163
- // }
15164
- // lineRect.addChild(currItem);
15165
- // currItem.rect.x = lineRect.rect.width;
15166
- // if (currItem.rect.height > lineRect.rect.height) {
15167
- // lineRect.rect.height = currItem.rect.height;
15168
- // }
15169
- // lineRect.rect.width += currItem.rect.width;
15170
- // if (br) {
15171
- // //lineRect.rect.maxWidth = lineRect.rect.width;
15172
- // lineRect = render.createLineRect();
15173
- // addInnerLineFunc(lineRect);
15174
- // }
15175
- // currItem = renderObjects[i++];
15176
- // }
15177
- // for (let i = 0; i < innerLineRects.length; i++) {
15178
- // const innerLineRect = innerLineRects[i] as ParagraphLineRectRenderObject;
15179
- // innerLineRect.rect.x = this.getParaLineRectStartX(innerLineRects.length, i, paragraph, render, innerLineRect);
15180
- // //限制最大行高
15181
- // const maxLineHeight = paragraph.props.lineHeight !== this.options.defaultLineHeight ? 100 : Math.floor(14 * 2);
15182
- // //fillLineHeight填充行高
15183
- // let fillLineHeight = Math.ceil(innerLineRect.rect.height * (paragraph.props.lineHeight - 1));
15184
- // fillLineHeight = fillLineHeight > maxLineHeight ? maxLineHeight : fillLineHeight;
15185
- // const lineHeight = innerLineRect.rect.height + fillLineHeight;
15186
- // const paddingBottom = Math.ceil(fillLineHeight / 2);
15187
- // innerLineRect.rect.height = lineHeight;
15188
- // for (let j = 0; j < innerLineRect.length; j++) {
15189
- // const leaf = innerLineRect.getChild(j);
15190
- // leaf.rect.y = innerLineRect.rect.height - paddingBottom - leaf.rect.height;
15191
- // }
15192
- // //render.rect.height += lineRect.rect.height;
15193
- // const outterLineRect = render.createLineRect();
15194
- // outterLineRect.rect.width = render.rect.width;
15195
- // outterLineRect.addChild(innerLineRect);
15196
- // ElementUtil.remeasure(outterLineRect, false);
15197
- // render.addChild(outterLineRect);
15198
- // }
15199
- // ElementUtil.remeasure(render);
15200
- }
15201
- /**
15202
- * 获取段落行布局横向坐标起始位置,被段落text-align影响
15203
- */
15204
- getParaLineRectStartX(counter, paraLineIndex, paraElement, paraRenderObject, paraLineRender) {
15205
- //左对齐,首行缩进
15206
- let indent = paraElement.props.indent;
15207
- //存在项目符号
15208
- if (paraLineIndex > 0) {
15209
- indent = paraElement.props.hanging;
15210
- }
15211
- if (paraElement.props.textAlign === 'center') {
15212
- const remainSpace = paraRenderObject.rect.width - paraLineRender.rect.width;
15213
- return Math.ceil(remainSpace / 2) + indent;
15214
- }
15215
- else if (paraElement.props.textAlign === 'right') {
15216
- const remainSpace = paraRenderObject.rect.width - paraLineRender.rect.width;
15217
- return remainSpace + indent;
15218
- }
15219
- else if (paraElement.props.textAlign === 'justify') {
15220
- const renderUnitCount = this.getRenderUnitLength(paraLineRender);
15221
- if (paraLineIndex === counter - 1 || renderUnitCount === 1) {
15222
- return indent;
15223
- }
15224
- const spaceWidth = (paraRenderObject.rect.width - paraLineRender.rect.width) / (renderUnitCount - 1);
15225
- this.setAlignJustify(paraLineRender, 0, spaceWidth);
15226
- return indent;
15227
- }
15228
- else {
15229
- return indent;
15230
- }
15231
- }
15232
- /**
15233
- * 设置两端对齐
15234
- * @param render
15235
- * @param count
15236
- * @param spaceWidth
15237
- */
15238
- setAlignJustify(render, count, spaceWidth) {
15239
- if (render instanceof BranchRenderObject) {
15240
- let width = 0;
15241
- for (let i = 0; i < render.length; i++) {
15242
- const currRender = render.getChild(i);
15243
- count += this.setAlignJustify(currRender, count, spaceWidth);
15244
- currRender.rect.x = width;
15245
- width += currRender.rect.width;
15246
- }
15247
- render.rect.width = width;
15248
- }
15249
- else if (render instanceof LeafRenderObject) {
15250
- if (render instanceof TextGroupRenderObject) {
15251
- let i = count === 0 ? 1 : 0;
15252
- for (; i < render.textMeasures.length; i++) {
15253
- render.textMeasures[i].actualSize = render.textMeasures[i].actualSize + spaceWidth;
15254
- }
15255
- render.measure();
15256
- count += render.textMeasures.length;
15257
- }
15258
- else {
15259
- if (count !== 0) {
15260
- render.rect.width += spaceWidth;
15261
- }
15262
- count += 1;
15263
- }
15264
- }
15265
- return count;
15266
- }
15267
- /**
15268
- * 获取段落行渲染单位个数,字符需要计算为字符长度
15269
- */
15270
- getRenderUnitLength(paraLine) {
15271
- if (paraLine instanceof LeafRenderObject) {
15272
- if (paraLine instanceof TextGroupRenderObject) {
15273
- return paraLine.textMeasures.length;
15274
- }
15275
- else {
15276
- return 1;
15277
- }
15278
- }
15279
- else if (paraLine instanceof BranchRenderObject) {
15280
- let count = 0;
15281
- for (let i = 0; i < paraLine.length; i++) {
15282
- count += this.getRenderUnitLength(paraLine.getChild(i));
15283
- }
15284
- return count;
15285
- }
15286
- throw new Error('未到达计算位置');
15287
- }
15288
- getInlineGroupRenderItem(item) {
15289
- const inlineGroupRender = item.createRenderObject({ options: this.options, renderCtx: this.renderCtx });
15290
- if (!inlineGroupRender) {
15291
- return null;
15292
- }
15293
- for (let i = 0; i < item.length; i++) {
15294
- const child = item.getChild(i);
15295
- if (child instanceof LeafElement) {
15296
- child.cacheRender = child.createRenderObject({ options: this.options, renderCtx: this.renderCtx });
15297
- if (child.cacheRender) {
15298
- inlineGroupRender.addChild(child.cacheRender);
15299
- }
15300
- }
15301
- else if (child instanceof InlineGroupElement) {
15302
- item.cacheRender = this.getInlineGroupRenderItem(child);
15303
- if (item.cacheRender) {
15304
- inlineGroupRender.addChild(item.cacheRender);
15305
- }
15306
- }
15307
- else {
15308
- throw new Error('未实现');
15309
- }
15310
- }
15311
- ElementUtil.remeasureInlineGroupRender(inlineGroupRender);
15312
- //限制最小长度
15313
- if (item instanceof DataElementInlineGroup) {
15314
- //需要填充null-text
15315
- if (item.length === 2) {
15316
- const nullText = new TextGroupElement();
15317
- nullText.isDecorate = true;
15318
- nullText.disableClick = true;
15319
- const baseTextProps = item.props;
15320
- nullText.text = baseTextProps.nullText;
15321
- baseTextProps.nullTextProps.clone(nullText.props);
15322
- const nullTextRender = nullText.createRenderObject({ options: this.options, renderCtx: this.renderCtx });
15323
- inlineGroupRender.insertChild(nullTextRender, 1);
15324
- ElementUtil.remeasureInlineGroupRender(inlineGroupRender);
15325
- }
15326
- const props = item.props;
15327
- let minLength = props.minLength ?? 14;
15328
- minLength = minLength < 14 ? 14 : minLength;
15329
- if (item instanceof DataElementInlineGroup && inlineGroupRender.rect.width < minLength) {
15330
- const fillNullSpace = new FillNullSpaceRenderObject();
15331
- fillNullSpace.rect.width = minLength - inlineGroupRender.rect.width;
15332
- fillNullSpace.rect.height = inlineGroupRender.rect.height;
15333
- inlineGroupRender.insertChild(fillNullSpace, inlineGroupRender.length - 1);
15334
- }
15335
- ElementUtil.remeasureInlineGroupRender(inlineGroupRender);
15336
- }
15337
- return inlineGroupRender;
15338
- }
15339
- cutRenderItem(render, nextRender, limitWidth, lineEmpty, inCloseBody) {
15340
- if (render instanceof LeafRenderObject) {
15341
- if (render.rect.width > limitWidth && render instanceof TextGroupRenderObject) {
15342
- return this.cutTextRender(render, nextRender, limitWidth, lineEmpty, inCloseBody);
15343
- }
15344
- if (render instanceof FillNullSpaceRenderObject) {
15345
- return this.cutFillNullRender(render, limitWidth);
15346
- }
15347
- if (render.rect.width < limitWidth || lineEmpty || render.element.type === 'br' || render.element.type === 'psym') {
15348
- return { firstItem: render, lastItem: null, br: render.element.type === 'br' };
15349
- }
15350
- return { firstItem: null, lastItem: null };
15351
- }
15352
- else if (render instanceof InlineGroupRenderObject) {
15353
- return this.cutInlineGroupRenderItem(render, limitWidth, lineEmpty, inCloseBody);
15354
- }
15355
- throw new Error('到达计算边界');
15356
- }
15357
- cutTextRender(render, nextRender, limitWidth, lineEmpty, inCloseBody) {
15358
- let sumWidth = 0;
15359
- const cutRender = render.clone();
15360
- cutRender.textMeasures.length = 0;
15361
- let i = 0;
15362
- for (; i < render.textMeasures.length; i++) {
15363
- sumWidth += render.textMeasures[i].actualSize;
15364
- if (sumWidth > limitWidth) {
15365
- if (lineEmpty && i === 0) {
15366
- i = 1;
15367
- }
15368
- break;
15369
- }
15370
- }
15371
- //后置标点处理
15372
- i = this.patchHandlePostPunctuation(render, nextRender, i, inCloseBody, lineEmpty);
15373
- //前置标点处理
15374
- i = this.patchHandleLeadingPunctuation(render, i, lineEmpty);
15375
- if (i <= 0) {
15376
- return { firstItem: null, lastItem: null };
15377
- }
15378
- cutRender.textMeasures = render.textMeasures.splice(0, i);
15379
- render.measure();
15380
- cutRender.measure();
15381
- return { firstItem: cutRender, lastItem: render, br: true };
15382
- }
15383
- /**
15384
- * 处理前置标点,前置标点不能出现在末尾
15385
- * @param render
15386
- * @param i
15387
- */
15388
- patchHandleLeadingPunctuation(render, i, lineEmpty) {
15389
- if (i === 1 && lineEmpty) {
15390
- return i;
15391
- }
15392
- if (this.containLeadingPunctuation(render.textMeasures[i]?.char)) {
15393
- return i--;
15394
- }
15395
- return i;
15396
- }
15397
- /**
15398
- * 处理后置标点,后置标点不能出现在行首
15399
- * @param render
15400
- * @param i
15401
- * @param lineEmpty
15402
- */
15403
- patchHandlePostPunctuation(render, nextRender, i, inCloseBody, lineEmpty) {
15404
- if (i === render.textMeasures.length - 1) {
15405
- //紧跟着的字符包含后置标点
15406
- if (this.containerStartSymbolInTextStart(nextRender)) {
15407
- i--;
15408
- }
15409
- }
15410
- if (inCloseBody && this.containPostPunctuation(render.textMeasures[i]?.char)) {
15411
- if (this.containPostPunctuation(render.textMeasures[i + 1]?.char)) {
15412
- i--;
15413
- }
15414
- else {
15415
- i++;
15416
- }
15417
- }
15418
- else {
15419
- if (i > 1 && this.containPostPunctuation(render.textMeasures[i]?.char)) {
15420
- i--;
15421
- }
15422
- }
15423
- return i;
15424
- }
15425
- /**
15426
- * 是否包含后置标点
15427
- * @param str
15428
- * @returns
15429
- */
15430
- containPostPunctuation(str) {
15431
- return '!),.:;?]}¨·ˇˉ―‖’”…∶、。〃々〉》」』】〕〗!"'),.:;?]`|}~¢'.indexOf(str) > -1;
15432
- }
15433
- //是否包含前置标点
15434
- containLeadingPunctuation(str) {
15435
- return '‘“〈《「『【〔〖([{£'.indexOf(str) > -1;
15436
- }
15437
- /**
15438
- * 文本开头是否包含后置标点
15439
- * @param render
15440
- * @returns
15441
- */
15442
- containerStartSymbolInTextStart(render) {
15443
- //return false;
15444
- if (render instanceof TextGroupRenderObject) {
15445
- if (render.textMeasures.length > 0) {
15446
- return this.containPostPunctuation(render.textMeasures[0].char);
15447
- }
15448
- }
15449
- return false;
15450
- }
15451
- cutFillNullRender(render, limitWidth) {
15452
- if (limitWidth === 0) {
15453
- return { firstItem: null, lastItem: null };
15454
- }
15455
- if (render.rect.width > limitWidth) {
15456
- const cutRender = new FillNullSpaceRenderObject();
15457
- cutRender.rect.width = limitWidth;
15458
- cutRender.rect.height = render.rect.height;
15459
- render.rect.width = render.rect.width - limitWidth;
15460
- return { firstItem: cutRender, lastItem: render };
15461
- }
15462
- else {
15463
- return { firstItem: render, lastItem: null };
15464
- }
15465
- }
15466
- /**
15467
- * 行内编组元素超出行内可用空间,需要根据剩余空间长度进行截断
15468
- */
15469
- cutInlineGroupRenderItem(render, limitWidth, emptyLine, inCloseBody) {
15470
- const cutRender = render.element.createRenderObject({ options: this.options, renderCtx: this.renderCtx });
15471
- let x = 0;
15472
- let br = false;
15473
- const items = [...render.getItems()];
15474
- for (let i = 0; i < items.length; i++) {
15475
- const child = items[i];
15476
- if (child instanceof LeafRenderObject) {
15477
- if (x + child.rect.width > limitWidth) {
15478
- const { firstItem, lastItem, br: childBr } = this.cutRenderItem(child, items[i + 1], limitWidth - x, emptyLine && cutRender.length === 0, inCloseBody);
15479
- if (firstItem) {
15480
- cutRender.addChild(firstItem);
15481
- }
15482
- br = childBr || br;
15483
- break;
15484
- }
15485
- else {
15486
- render.removeChild(child);
15487
- cutRender.addChild(child);
15488
- }
15489
- //软换行符
15490
- if (child.element && child.element.type === 'br') {
15491
- br = true;
15492
- break;
15493
- }
15225
+ const rows = [];
15226
+ for (let i = 0; i < tb.length; i++) {
15227
+ const rowRender = tb.getChild(i);
15228
+ const rowEle = rowRender.element;
15229
+ if (rowEle.props.headerRow) {
15230
+ rows.push(rowRender);
15494
15231
  }
15495
- else if (child instanceof InlineGroupRenderObject) {
15496
- if (x + child.rect.width > limitWidth) {
15497
- const { firstItem, br: childBr } = this.cutInlineGroupRenderItem(child, limitWidth - x, emptyLine && cutRender.length === 0, inCloseBody);
15498
- if (firstItem) {
15499
- cutRender.addChild(firstItem);
15500
- }
15501
- br = childBr || br;
15502
- break;
15503
- }
15504
- else {
15505
- render.removeChild(child);
15506
- cutRender.addChild(child);
15507
- }
15232
+ else {
15233
+ break;
15508
15234
  }
15509
- x += child.rect.width;
15510
- }
15511
- if (!cutRender.length) {
15512
- return { firstItem: null, lastItem: null };
15513
15235
  }
15514
- ElementUtil.remeasureInlineGroupRender(cutRender);
15515
- ElementUtil.remeasureInlineGroupRender(render);
15516
- return { firstItem: cutRender, lastItem: render.length ? render : null, br };
15236
+ return rows;
15517
15237
  }
15518
15238
  /**
15519
15239
  * 修改测量完毕后的元素状态
@@ -15526,29 +15246,105 @@ class ElementMeasure {
15526
15246
  }
15527
15247
  }
15528
15248
  ele.modifyFlag = exports.ModifyFlag.None;
15249
+ if (!ele.loaded) {
15250
+ ele.loaded = true;
15251
+ }
15529
15252
  }
15530
15253
  clearPaintCache(ele, data) {
15254
+ ele.paintRenders.length = 0;
15531
15255
  ele.beginMeasure(data);
15256
+ this.identifyComment(ele);
15532
15257
  if (ele instanceof BranchElement) {
15533
15258
  for (let i = 0; i < ele.length; i++) {
15534
15259
  this.clearPaintCache(ele.getChild(i), data);
15535
15260
  }
15536
15261
  }
15537
15262
  }
15263
+ identifyComment(ele) {
15264
+ if (ele instanceof CommentElement) {
15265
+ this.docCtx.document.identifyCommMark(ele);
15266
+ }
15267
+ }
15268
+ cacheDoc;
15269
+ cacheDocRenders(docs) {
15270
+ docs.forEach(doc => {
15271
+ this.cacheDoc = doc;
15272
+ this.cacheRenders(doc);
15273
+ });
15274
+ this.cacheDoc = null;
15275
+ }
15276
+ /**
15277
+ * 生成批注区间信息
15278
+ * @param renderTree
15279
+ */
15280
+ generateCommRange() {
15281
+ this.seo.commRangeSets.clear();
15282
+ const commMarks = this.docCtx.document.markPairs;
15283
+ for (let i = 0; i < commMarks.length; i++) {
15284
+ const commMark = commMarks[i];
15285
+ if (commMark.start && commMark.end) {
15286
+ const ancestor = DocumentSelection.getAncestorCommonControl(commMark.start, commMark.end);
15287
+ const range = RangeUtil.getSectionRange(commMark.start, 0, commMark.end, 1, ancestor);
15288
+ SelectionOverlays.addToCommentSets(range, this.seo.commRangeSets, commMark.start.color);
15289
+ }
15290
+ }
15291
+ }
15292
+ cacheRenders(renderTree) {
15293
+ if (renderTree.element) {
15294
+ renderTree.element.paintRenders.push(renderTree);
15295
+ }
15296
+ for (let i = 0; i < renderTree.length; i++) {
15297
+ const currRender = renderTree.getChild(i);
15298
+ if (currRender.element) {
15299
+ this.cacheCommsRender(currRender);
15300
+ }
15301
+ if (currRender instanceof BranchRenderObject) {
15302
+ this.cacheRenders(currRender);
15303
+ }
15304
+ else {
15305
+ currRender.element && currRender.element.paintRenders.push(currRender);
15306
+ }
15307
+ }
15308
+ }
15309
+ /**
15310
+ * 缓存批注标志
15311
+ * @private
15312
+ */
15313
+ cacheCommsRender(render) {
15314
+ if (render.element && render.element.type === 'comm') {
15315
+ const commElement = render.element;
15316
+ if (commElement.props.markType === 'start') {
15317
+ const currDocRender = this.cacheDoc;
15318
+ const docCommContainer = currDocRender.getItems().find(item => item instanceof CommsContainerRenderObject);
15319
+ if (docCommContainer) {
15320
+ docCommContainer.commsMarks.push(render);
15321
+ }
15322
+ }
15323
+ }
15324
+ if (render.element && render.element.type === 'comm-list') {
15325
+ const commContainer = render;
15326
+ CommentsUtil.createCommentsImage(commContainer);
15327
+ }
15328
+ }
15538
15329
  endMeasures(ele) {
15330
+ ele.endMeasure();
15539
15331
  if (ele instanceof BranchElement) {
15540
15332
  for (let i = 0; i < ele.length; i++) {
15541
15333
  this.endMeasures(ele.getChild(i));
15542
15334
  }
15543
15335
  }
15544
15336
  }
15337
+ createDefaultPara() {
15338
+ const tmp = new ParagraphElement();
15339
+ tmp.props.lineHeight = this.options.defaultLineHeight;
15340
+ return tmp;
15341
+ }
15545
15342
  }
15546
15343
 
15547
15344
  class DocumentPaint {
15548
15345
  renderContext;
15549
15346
  docCtx;
15550
15347
  seo;
15551
- elementMeasure;
15552
15348
  //elementRenderCut: ElementRenderCut;
15553
15349
  elementPaint;
15554
15350
  docPages;
@@ -15560,7 +15356,6 @@ class DocumentPaint {
15560
15356
  this.docCtx = docCtx;
15561
15357
  this.seo = seo;
15562
15358
  this.viewOptions = this.docCtx.viewOptions;
15563
- this.elementMeasure = new ElementMeasure(this.docCtx, this.renderContext);
15564
15359
  //this.elementRenderCut = new ElementRenderCut(this.viewOptions, this.renderContext);
15565
15360
  this.elementPaint = new ElementPaint(this.renderContext, this.docCtx);
15566
15361
  }
@@ -15720,130 +15515,6 @@ class DocumentPaint {
15720
15515
  }
15721
15516
  }
15722
15517
 
15723
- const fontSize = 12;
15724
- const verPadding = 2;
15725
- /**
15726
- * 恒牙牙位图
15727
- */
15728
- class PermanentTeethElement extends LeafElement {
15729
- constructor() {
15730
- super('permanent-teeth');
15731
- this.props = new PermanentTeethProps();
15732
- this.props.topLeft = '';
15733
- this.props.topRight = '';
15734
- this.props.bottomLeft = '';
15735
- this.props.bottomRight = '';
15736
- }
15737
- clone(data) {
15738
- const clone = new PermanentTeethElement();
15739
- clone.props = this.props.clone();
15740
- return clone;
15741
- }
15742
- createRenderObject(data) {
15743
- const clone = new PermanentTeethRenderObject(this);
15744
- clone.rect.width = 150;
15745
- //字体大小*2+上下间距2*2
15746
- clone.rect.height = fontSize * 2 + verPadding * 2;
15747
- //clone.rect= ElementUtil.cloneRect(this.rect);
15748
- return clone;
15749
- }
15750
- serialize(viewOptions) {
15751
- return {
15752
- type: this.type,
15753
- props: this.props.getSerializeProps(viewOptions)
15754
- };
15755
- }
15756
- }
15757
- class PermanentTeethRenderObject extends LeafRenderObject {
15758
- clone() {
15759
- const clone = new PermanentTeethRenderObject(this.element);
15760
- clone.rect = ElementUtil.cloneRect(this.rect);
15761
- return clone;
15762
- }
15763
- // measure(): { width: number, height: number } {
15764
- // const ele = this.element;
15765
- //
15766
- // }
15767
- exportHTML(event) {
15768
- const ele = this.element;
15769
- const g = super.exportHTML(event);
15770
- const contentHorPadding = 4;
15771
- g.children = [];
15772
- // g.children.push(ElementUtil.getFillSvgPath(`M 0 ${this.rect.height / 2} h${this.rect.width}`, '#000', 1));
15773
- // g.children.push(ElementUtil.getFillSvgPath(`M ${this.rect.width / 2} 0 v${this.rect.height}`, '#000', 1));
15774
- //
15775
- g.children.push(ElementUtil.getFillSvgRect(0, this.rect.height / 2, this.rect.width, 1, '#000'));
15776
- g.children.push(ElementUtil.getFillSvgRect(this.rect.width / 2, 0, 1, this.rect.height, '#000'));
15777
- const getSvgText = (text, x, y) => {
15778
- return {
15779
- sel: 'text',
15780
- text: text,
15781
- data: {
15782
- ns: "http://www.w3.org/2000/svg",
15783
- attrs: {
15784
- 'dominant-baseline': 'hanging',
15785
- 'font-family': 'Arial',
15786
- 'font-size': fontSize,
15787
- x,
15788
- y,
15789
- }
15790
- },
15791
- };
15792
- };
15793
- const topLeftWidth = event.renderCtx.mainContext.measureTextWidth(ele.props.topLeft, {
15794
- fontSize: fontSize,
15795
- fontName: 'Arial'
15796
- });
15797
- const bottomLeftWidth = event.renderCtx.mainContext.measureTextWidth(ele.props.bottomLeft, {
15798
- fontSize: fontSize,
15799
- fontName: 'Arial'
15800
- });
15801
- g.children.push(getSvgText(ele.props.topLeft, this.rect.width / 2 - topLeftWidth - contentHorPadding, verPadding));
15802
- g.children.push(getSvgText(ele.props.topRight, this.rect.width / 2 + contentHorPadding, verPadding));
15803
- g.children.push(getSvgText(ele.props.bottomLeft, this.rect.width / 2 - bottomLeftWidth - contentHorPadding, this.rect.height - fontSize + verPadding));
15804
- g.children.push(getSvgText(ele.props.bottomRight, this.rect.width / 2 + contentHorPadding, this.rect.height - fontSize + verPadding));
15805
- return g;
15806
- }
15807
- }
15808
- class PermanentTeethFactory extends ElementFactory {
15809
- match(type) {
15810
- return type === 'permanent-teeth';
15811
- }
15812
- createElement(data) {
15813
- const ele = new PermanentTeethElement();
15814
- ele.props.bottomLeft = data.props?.bottomLeft ?? '';
15815
- ele.props.bottomRight = data.props?.bottomRight ?? '';
15816
- ele.props.topLeft = data.props?.topLeft ?? '';
15817
- ele.props.topRight = data.props?.topRight ?? '';
15818
- return ele;
15819
- }
15820
- }
15821
- /**
15822
- * 恒牙牙位图属性
15823
- */
15824
- class PermanentTeethProps extends INotifyPropertyChanged {
15825
- topLeft;
15826
- topRight;
15827
- bottomLeft;
15828
- bottomRight;
15829
- getSerializeProps(viewOptions) {
15830
- return {
15831
- topLeft: this.topLeft,
15832
- topRight: this.topRight,
15833
- bottomLeft: this.bottomLeft,
15834
- bottomRight: this.bottomRight,
15835
- };
15836
- }
15837
- clone(dest) {
15838
- dest = dest || new PermanentTeethProps();
15839
- dest.topLeft = this.topLeft;
15840
- dest.topRight = this.topRight;
15841
- dest.bottomLeft = this.bottomLeft;
15842
- dest.bottomRight = this.bottomRight;
15843
- return dest;
15844
- }
15845
- }
15846
-
15847
15518
  class ElementReader {
15848
15519
  docCtx;
15849
15520
  constructor(docCtx) {
@@ -15907,29 +15578,18 @@ class ElementReader {
15907
15578
  this.setDocument(document);
15908
15579
  }
15909
15580
  setDocument(document) {
15910
- // if (this.docCtx.document) {
15911
- // this.docCtx.document.destroy();
15912
- // }
15913
- // this.document?.clearItems();
15914
- // document.docProps.clone(this.document.docProps);
15915
15581
  document.bodyElement = document.find((item) => item instanceof DocumentBodyElement);
15916
15582
  document.headerElement = document.find((item) => item instanceof DocumentHeaderElement);
15917
15583
  document.footerElement = document.find((item) => item instanceof DocumentFooterElement);
15918
- // document.commentsContainerElement = document.find((item) => item instanceof CommsContainerElement) as CommsContainerElement;
15919
- // if (!document.commentsContainerElement) {
15920
- // document.commentsContainerElement = new CommsContainerElement();
15921
- // }
15922
15584
  document.clearItems();
15923
15585
  document.addChild(document.headerElement);
15924
15586
  document.addChild(document.bodyElement);
15925
15587
  document.addChild(document.footerElement);
15926
- //document.addChild(document.commentsContainerElement);
15927
15588
  this.docCtx.document = document;
15928
15589
  document.viewOptions = this.docCtx.viewOptions;
15929
15590
  const width = Math.floor(document.props.width * this.docCtx.viewOptions.mmToPixelsRatio);
15930
15591
  const height = Math.floor(document.props.height * this.docCtx.viewOptions.mmToPixelsRatio);
15931
15592
  this.docCtx.viewOptions.docPageSettings = new PageOptions(width, height, document.props.orient);
15932
- //this.viewOptions.viewSettings.width = this.viewOptions.docPageSettings.width + 10;
15933
15593
  }
15934
15594
  readElement(data, strictMode = false) {
15935
15595
  if (typeof data === 'string') {
@@ -15951,6 +15611,7 @@ class ElementReader {
15951
15611
  }
15952
15612
  }
15953
15613
  factory.readCompleted(element, childArr);
15614
+ this.readAttribute(data, element);
15954
15615
  return element;
15955
15616
  }
15956
15617
  }
@@ -15962,6 +15623,11 @@ class ElementReader {
15962
15623
  return null;
15963
15624
  }
15964
15625
  }
15626
+ readAttribute(data, ele) {
15627
+ if (data.attribute) {
15628
+ ele.attribute = data.attribute;
15629
+ }
15630
+ }
15965
15631
  /**
15966
15632
  * 读取扩展属性
15967
15633
  * @param data
@@ -17215,7 +16881,6 @@ class DocumentEvent {
17215
16881
  startHitInfo: this.startHitInfo,
17216
16882
  endHitInfo: this.endHitInfo
17217
16883
  });
17218
- console.log(this.endHitInfo);
17219
16884
  }
17220
16885
  /**
17221
16886
  * 获取鼠标所在的渲染元素对象
@@ -20185,7 +19850,8 @@ class ElementTrackManage {
20185
19850
  * @private
20186
19851
  */
20187
19852
  mergeOps(ops) {
20188
- return false;
19853
+ return this.mergeFormatOps(ops);
19854
+ //return false;
20189
19855
  //问题在于:
20190
19856
  //1.新输入的字符串,selectState的startOffset、endOffset=1,后输入的字符串的endOffset进行累加
20191
19857
  //2.撤销后重做,选区范围在1-2,英国是0-2,因为之前在创建文本对象后,选区的结束位为1
@@ -20236,6 +19902,41 @@ class ElementTrackManage {
20236
19902
  // }
20237
19903
  // return false;
20238
19904
  }
19905
+ /**
19906
+ * 将对某个元素的最近两次的属性修改合并为一次,ops为当前记录的修改,比较上次的修改,如果为对同一个元素的修改,则合并
19907
+ * @private
19908
+ */
19909
+ mergeFormatOps(ops) {
19910
+ if (ops.length > 1) {
19911
+ return false;
19912
+ }
19913
+ const lastOps = this.actions[this.actions.length - 1];
19914
+ if (!lastOps || lastOps.ops.length > 1) {
19915
+ return false;
19916
+ }
19917
+ const prevOp = lastOps.ops[lastOps.ops.length - 1];
19918
+ const currOp = ops[0];
19919
+ //操作类型相同
19920
+ if ('format' in currOp.ops && 'format' in prevOp.ops && currOp.index === prevOp.index) {
19921
+ // const prevAfterSelection = lastOps.afterSelection;
19922
+ // if (!prevAfterSelection) {
19923
+ // return false;
19924
+ // }
19925
+ //前后是连续的操作
19926
+ const { format: currFormat } = currOp.ops;
19927
+ const { format: prevFormat } = prevOp.ops;
19928
+ Object.keys(currFormat).forEach(key => {
19929
+ const currValue = currFormat[key].newValue;
19930
+ const prevValue = prevFormat[key].newValue;
19931
+ if (CommonUtil.isEqual(currValue, prevValue)) {
19932
+ return;
19933
+ }
19934
+ prevFormat[key].newValue = currValue;
19935
+ });
19936
+ return true;
19937
+ }
19938
+ return false;
19939
+ }
20239
19940
  getSelection() {
20240
19941
  const { startControl, startOffset, endControl, endOffset, editable } = this.docCtx.selectionState;
20241
19942
  if (!startControl) {
@@ -28148,7 +27849,7 @@ class DocEditor {
28148
27849
  rule.setRuleOptions({ width: this.viewOptions.docPageSettings.width, pagePL, pagePR, docLeft });
28149
27850
  }
28150
27851
  version() {
28151
- return "2.1.20";
27852
+ return "2.1.22";
28152
27853
  }
28153
27854
  switchPageHeaderEditor() {
28154
27855
  this.docCtx.document.switchPageHeaderEditor(this.selectionState, null);
@@ -28201,6 +27902,26 @@ class DocumentCombine {
28201
27902
  }
28202
27903
  }
28203
27904
 
27905
+ /**
27906
+ * 文字行渲染模式
27907
+ 用于医嘱打印模式
27908
+ */
27909
+ function runTextLineRender(ele, data) {
27910
+ if (!data.options.textRowLineMode) {
27911
+ return;
27912
+ }
27913
+ if (ele instanceof TableElement) {
27914
+ // textLineRenderMode(ele, data);
27915
+ // remeasureParentRenders(ele.cacheRender)
27916
+ return;
27917
+ }
27918
+ if (ele instanceof BranchElement) {
27919
+ for (let i = 0; i < ele.length; i++) {
27920
+ runTextLineRender(ele.getChild(i), data);
27921
+ }
27922
+ }
27923
+ }
27924
+
28204
27925
  /**
28205
27926
  * 删除当前段落
28206
27927
  * @param evt
@@ -28489,6 +28210,10 @@ exports.ParagraphLineRectRenderObject = ParagraphLineRectRenderObject;
28489
28210
  exports.ParagraphProps = ParagraphProps;
28490
28211
  exports.ParagraphRenderObject = ParagraphRenderObject;
28491
28212
  exports.PasteElementEvent = PasteElementEvent;
28213
+ exports.PermanentTeethElement = PermanentTeethElement;
28214
+ exports.PermanentTeethFactory = PermanentTeethFactory;
28215
+ exports.PermanentTeethProps = PermanentTeethProps;
28216
+ exports.PermanentTeethRenderObject = PermanentTeethRenderObject;
28492
28217
  exports.PictureElement = PictureElement;
28493
28218
  exports.PictureFactory = PictureFactory;
28494
28219
  exports.PictureProps = PictureProps;
@@ -28542,8 +28267,11 @@ exports.ValidateElement = ValidateElement;
28542
28267
  exports.ValidateProps = ValidateProps;
28543
28268
  exports.ValidateRenderObject = ValidateRenderObject;
28544
28269
  exports.ViewOptions = ViewOptions;
28270
+ exports.addReturn = addReturn;
28545
28271
  exports.clearChildrenRenderCache = clearChildrenRenderCache;
28546
28272
  exports.clearTraces = clearTraces;
28273
+ exports.cloneChildren = cloneChildren;
28274
+ exports.cloneElementBase = cloneElementBase;
28547
28275
  exports.createPrintTemplate = createPrintTemplate;
28548
28276
  exports.defaultParaHanging = defaultParaHanging;
28549
28277
  exports.deleteCurrentParagraph = deleteCurrentParagraph;