@ebuilding/base 2.3.2 → 2.3.4

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.
@@ -1,27 +1,28 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, EventEmitter, forwardRef, ViewChild, Output, Input, ChangeDetectionStrategy, Component, NgModule } from '@angular/core';
3
- import * as i4 from '@angular/common';
2
+ import { EventEmitter, forwardRef, HostListener, Output, Input, ViewChild, Component, NgModule } from '@angular/core';
3
+ import * as i3 from '@angular/common';
4
4
  import { CommonModule } from '@angular/common';
5
- import * as i5 from '@angular/forms';
5
+ import * as i4 from '@angular/forms';
6
6
  import { ReactiveFormsModule, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
7
- import * as i6 from 'ng-zorro-antd/input';
7
+ import * as i5 from 'ng-zorro-antd/input';
8
8
  import { NzInputModule } from 'ng-zorro-antd/input';
9
- import * as i7 from 'ng-zorro-antd/collapse';
9
+ import * as i6 from 'ng-zorro-antd/collapse';
10
10
  import { NzCollapseModule } from 'ng-zorro-antd/collapse';
11
11
  import { NzIconModule } from 'ng-zorro-antd/icon';
12
- import * as i8 from 'ng-zorro-antd/button';
12
+ import * as i7 from 'ng-zorro-antd/button';
13
13
  import { NzButtonModule } from 'ng-zorro-antd/button';
14
14
  import { NzToolTipModule } from 'ng-zorro-antd/tooltip';
15
- import CodeMirror from 'codemirror';
16
- import * as i11 from '@ebuilding/base/shared.pipe';
17
- import { GramPipeModule } from '@ebuilding/base/shared.pipe';
15
+ import * as CodeMirror from 'codemirror';
16
+ import CodeMirror__default from 'codemirror';
17
+ import 'codemirror/mode/javascript/javascript';
18
+ import 'codemirror/addon/edit/matchbrackets';
18
19
  import _ from 'lodash';
20
+ import * as i10 from '@ebuilding/base/shared.pipe';
21
+ import { GramPipeModule } from '@ebuilding/base/shared.pipe';
19
22
  import * as i1 from 'ng-zorro-antd/message';
20
- import * as i2 from 'ng-zorro-antd/core/config';
21
- import * as i9 from 'ng-zorro-antd/core/transition-patch';
22
- import * as i10 from 'ng-zorro-antd/core/wave';
23
+ import * as i8 from 'ng-zorro-antd/core/transition-patch';
24
+ import * as i9 from 'ng-zorro-antd/core/wave';
23
25
 
24
- const KRE_CODEMIRROR_TOKEN = new InjectionToken("KRE_CODEMIRROR_TOKEN");
25
26
  class Formula {
26
27
  FormulaUsage = [
27
28
  {
@@ -452,580 +453,83 @@ class Formula {
452
453
  Utils = {};
453
454
  Formula = {};
454
455
  constructor() {
455
- let that = this;
456
- that.Utils = {
456
+ this.initUtils();
457
+ this.initFormula();
458
+ }
459
+ initUtils() {
460
+ this.Utils = {
457
461
  isString: function (a) {
458
- return "string" == typeof a;
462
+ return typeof a === "string";
459
463
  },
460
464
  isNumber: function (b) {
461
- return this.isNumeric(b);
465
+ return !isNaN(parseFloat(b)) && isFinite(b);
462
466
  },
463
467
  isFunction: function (b) {
464
- return this.isFunction(b);
468
+ return typeof b === "function";
465
469
  },
466
470
  isDate: function (a) {
467
471
  return a instanceof Date;
468
472
  },
469
473
  isArray: function (b) {
470
- return this.isArray(b);
474
+ return Array.isArray(b);
471
475
  },
472
476
  isEmpty: function (a) {
473
- return "" === a || this.Utils.isNull(a);
477
+ return a === "" || this.isNull(a);
474
478
  },
475
479
  isBlank: function (a) {
476
- return this.Utils.isNull(a) || "" === a.trim();
480
+ return this.isNull(a) || (typeof a === "string" && a.trim() === "");
477
481
  },
478
482
  isNull: function (a) {
479
- return null == a;
483
+ return a == null;
480
484
  },
481
485
  isObjectEmpty: function (a) {
482
486
  if (null == a)
483
- return !0;
487
+ return true;
484
488
  if (a.length > 0)
485
- return !1;
486
- if (0 === a.length)
487
- return !0;
488
- for (var b in a) {
489
- if (this.hasOwnProperty.call(a, b)) {
490
- return !1;
489
+ return false;
490
+ if (a.length === 0)
491
+ return true;
492
+ for (var key in a) {
493
+ if (Object.prototype.hasOwnProperty.call(a, key)) {
494
+ return false;
491
495
  }
492
- return isNaN(a);
493
496
  }
494
- return null;
497
+ return true;
495
498
  },
496
499
  isValueWidget: function (a) {
497
- return !!this.ValueWidgets[a];
498
- },
499
- address2Str: function (a, b, c) {
500
- if (c && a) {
501
- b = "";
502
- var d = !0;
503
- /p/.test(c) &&
504
- a.province &&
505
- ((b += a.province), a.province === a.city && (d = !1)),
506
- /c/.test(c) && a.city && d && (b += a.city),
507
- /d/.test(c) && a.district && (b += a.district),
508
- /a/.test(c) && a.detail && (b += a.detail);
509
- }
510
- return b;
500
+ return !!a;
511
501
  },
512
- num2Str: function (a, b) {
513
- if (this.Utils.isEmpty(a))
514
- return "";
515
- var c = a + "";
516
- if (this.Utils.isEmpty(b))
517
- return c;
518
- var d = /\[Num0\]/;
519
- if (d.test(b))
520
- return b.replace(d, c);
521
- if (((d = /\[Num1\]/), d.test(b)))
522
- return b.replace(d, this.Utils._num2CN(c, !1));
523
- if (((d = /\[Num2\]/), d.test(b)))
524
- return b.replace(d, this.Utils._num2CN(c, !0));
525
- d = /[#0]+,?[#0]*\.?[#0]*%?/;
526
- var e = b.match(d);
527
- if (e && e.length > 0) {
528
- var f = e[0];
529
- return (c = this.Utils._numberFormat(a, f)), b.replace(d, c);
530
- }
531
- return b;
532
- },
533
- _numberFormat: function (a, b) {
534
- var c = "", d = a + "";
535
- if (/%$/.test(b)) {
536
- (c = "%"), (a = 100 * a), (b = b.replace("%", ""));
537
- var e = d.indexOf(".");
538
- if (e > -1) {
539
- var f = d.length - 3 - e;
540
- (f = f < 0 ? 0 : f > 8 ? 8 : f), (a = parseFloat(a.toFixed(f)));
541
- }
542
- d = a + "";
543
- }
544
- var g = b.split("."), h = g[0], i = g[1];
545
- if ("" !== i) {
546
- var j = i ? i.length : 0;
547
- d = parseFloat(a).toFixed(j);
548
- for (var k = d.split(""), l = j; l > 0 && "#" === i.charAt(l - 1); l--) {
549
- var m = k.pop();
550
- if ("0" !== m) {
551
- k.push(m);
502
+ forEach: function (a, b) {
503
+ if (Array.isArray(a)) {
504
+ for (var c = 0, d = a.length; c < d; c++) {
505
+ if (b(a[c], c, a) === false)
552
506
  break;
553
- }
554
- }
555
- var n = k.pop();
556
- "." === n && (n = ""), (d = k.join("") + n);
557
- }
558
- var o = d.split("."), p = o[0];
559
- if (/,/.test(h))
560
- o[0] = p.replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g, "$1,");
561
- else {
562
- var q = h.match(/[0]+[0#]*$/);
563
- q && q.length > 0 && (o[0] = this.Utils.leftPad(p, q[0].length, "0"));
564
- }
565
- return o.join(".") + c;
566
- },
567
- _num2CN: function (a, b) {
568
- var c = "〇一二三四五六七八九", d = "个十百千万亿";
569
- b && ((c = "零壹贰叁肆伍陆柒捌玖"), (d = "个拾佰仟万亿"));
570
- var e = Math.floor(Math.abs(a)), f = Math.abs(a).toString(), g = f.replace(/\..*$/, ""), h = f.split("."), i = c, j = d, k = "-.", l = i[0], m = new RegExp(i[0] + "*$"), n = new RegExp(i[0] + "+", "g"), o = "", p = "";
571
- if (((o = a < 0 ? k[0] : ""), h.length >= 2)) {
572
- var q = h[1];
573
- if (q) {
574
- p = k[1];
575
- for (var r = 0; r < q.length; r++)
576
- p += i[+q[r]];
577
- }
578
- }
579
- if (1 == g.length)
580
- return o + i[e] + p;
581
- if (g.length <= 5) {
582
- for (var s = "", t = 0, e = g.length; e--;) {
583
- var u = +g[t];
584
- (s += this._num2CN(g[t], b) + (u && e ? j[e] : "")), t++;
585
507
  }
586
- return (s = s.replace(n, l)), (s = s.replace(m, "")), o + s + p;
587
- }
588
- for (var v = (g.length / 4) >> 0, w = g.length % 4, s = ""; 0 == w || !j[3 + v];)
589
- (w += 4), v--;
590
- if (+g.substr(0, w)) {
591
- s = this._num2CN(g.substr(0, w), b) + j[3 + v];
592
- var x = g.substr(w);
593
- "0" === x[0] && (s += i[0]), (s += this._num2CN(x, b));
594
508
  }
595
- else
596
- s = this._num2CN(g.substr(0, w), b) + this._num2CN(g.substr(w), b);
597
- return (s = s.replace(n, l)), (s = s.replace(m, "")), o + s + p;
598
- },
599
- date2Str: function (a, b) {
600
- if (!a)
601
- return "";
602
- var c = b.length, d = "";
603
- if (c > 0) {
604
- for (var e = b.charAt(0), f = 0, g = e, h = 1; h < c; h++) {
605
- var i = b.charAt(h);
606
- e !== i
607
- ? ((d += this.Utils._compileDateFormat({
608
- char: e,
609
- str: g,
610
- len: h - f,
611
- }, a)),
612
- (e = i),
613
- (f = h),
614
- (g = e))
615
- : (g += i);
509
+ else if (a && typeof a === "object") {
510
+ for (var e in a) {
511
+ if (Object.prototype.hasOwnProperty.call(a, e)) {
512
+ if (b(a[e], e, a) === false)
513
+ break;
514
+ }
616
515
  }
617
- d += this.Utils._compileDateFormat({
618
- char: e,
619
- str: g,
620
- len: c - f,
621
- }, a);
622
516
  }
623
- return d;
624
- },
625
- _compileDateFormat: function (a, b) {
626
- var c = a.str, d = a.len, e = a.char;
627
- switch (e) {
628
- case "E":
629
- // c =
630
- // d > 2
631
- // ? Date._DN[b.getDay()]
632
- // : d > 1
633
- // ? Date._SDN[b.getDay()]
634
- // : b.getDay() + "";
635
- break;
636
- case "y":
637
- c = d <= 3 ? (b.getFullYear() + "").slice(2, 4) : b.getFullYear();
638
- break;
639
- case "M":
640
- // c =
641
- // d > 2
642
- // ? Date._MN[b.getMonth()]
643
- // : d < 2
644
- // ? b.getMonth() + 1
645
- // : this.Utils.leftPad(b.getMonth() + 1 + "", 2, "0");
646
- break;
647
- case "d":
648
- c =
649
- d > 1 ? this.Utils.leftPad(b.getDate() + "", 2, "0") : b.getDate();
650
- break;
651
- case "h":
652
- var f = b.getHours() % 12;
653
- 0 === f && (f = 12),
654
- (c = d > 1 ? this.Utils.leftPad(f + "", 2, "0") : f);
655
- break;
656
- case "H":
657
- c =
658
- d > 1
659
- ? this.Utils.leftPad(b.getHours() + "", 2, "0")
660
- : b.getHours();
661
- break;
662
- case "m":
663
- c =
664
- d > 1
665
- ? this.Utils.leftPad(b.getMinutes() + "", 2, "0")
666
- : b.getMinutes();
667
- break;
668
- case "s":
669
- c =
670
- d > 1
671
- ? this.Utils.leftPad(b.getSeconds() + "", 2, "0")
672
- : b.getSeconds();
673
- break;
674
- case "a":
675
- c = b.getHours() < 12 ? "am" : "pm";
676
- break;
677
- default:
678
- c = a.str;
679
- }
680
- return c;
681
- },
682
- pick: function (a, b) {
683
- var c = {};
684
- return (this.Utils.forEach(b, function (b, d) {
685
- d in a && (c[d] = a[d]);
686
- }),
687
- c);
688
- },
689
- applyFunc: function (a, b, c, d) {
690
- return this.Utils.isFunction(b) ? b.apply(a, c ? c : []) : d;
691
- },
692
- forEach(a, b) {
693
- if (Array.isArray(a))
694
- for (var c = 0, d = a.length; c < d && b.apply(a[c], [c, a[c]]) !== !1; c++)
695
- ;
696
- else if (a && 'object' == typeof a)
697
- for (var e in a)
698
- if (a.hasOwnProperty(e) && b.apply(a[e], [e, a[e]]) === !1)
699
- break;
700
517
  },
701
518
  flatten: function (a, b, c) {
702
- if ((c || (c = []), a))
519
+ if (!c)
520
+ c = [];
521
+ if (a) {
703
522
  for (var d = 0, e = a.length; d < e; d++) {
704
523
  var f = a[d];
705
524
  Array.isArray(f)
706
- ? this.Utils.flatten(f, b, c)
525
+ ? this.flatten(f, b, c)
707
526
  : (b && !b(f)) || c.push(f);
708
527
  }
709
- return c;
710
- },
711
- applyCss: function (a, b) {
712
- this.Utils.isEmpty(b) ||
713
- (this.Utils.isString(b) ? a.addClass(b) : a.css(b));
714
- },
715
- getServerDate: function (a) {
716
- if (a && a.getResponseHeader) {
717
- var b = a.getResponseHeader("date");
718
- b &&
719
- ((this.STATIC._st = new Date(b).getTime()),
720
- (this.STATIC._ct = new Date().getTime()));
721
- }
722
- },
723
- getUrlParameter: function (a) {
724
- for (var b = window.location.search.substring(1), c = b.split("&"), d = 0; d < c.length; d++) {
725
- var e = c[d].split("=");
726
- if (e[0] == a)
727
- return e[1];
728
- }
729
- return null;
730
- },
731
- validateEmail: function (a) {
732
- return /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(a);
733
- },
734
- redirectTo: function (a) {
735
- window.location.href = a;
736
- },
737
- isCanvasSupported: function () {
738
- var a = document.createElement("canvas");
739
- return !(!a.getContext || !a.getContext("2d"));
740
- },
741
- isFormDataSupported: function () {
742
- return void 0 !== window.FormData;
743
- },
744
- getFileDownloadURL: function (a, b, c) {
745
- switch (a.bucket) {
746
- case this.CONST.QN_BUCKET.PUBLIC_IMAGE:
747
- var d = "", e = a.thumb;
748
- return (e &&
749
- (d =
750
- "?imageView2/" + e.mode + "/w/" + e.width + "/h/" + e.height),
751
- b(this.CONFIG.HOST.IMAGE_HOST + "/" + a.qnKey + d));
752
- case this.CONST.OSS_BUCKET.PUBLIC_IMAGE:
753
- return b(this.CONFIG.HOST.OSS_IMAGE_HOST + "/" + a.ossKey);
754
- case this.CONST.QN_BUCKET.PRIVATE_FILE:
755
- default:
756
- return c();
757
- }
758
- },
759
- evalFormula: function (a) {
760
- var b = [];
761
- this.Utils.forEach(Object.keys(this.Formula), function (a, c) {
762
- b.push(`var ${c}=fml.Formula.${c}`);
763
- });
764
- var it = b.join(";") + ";";
765
- var c = new Function(it + "return " + a)();
766
- return c;
767
- },
768
- createEntryAttributeField: function (b, c) {
769
- var d = {
770
- id: c.entryId,
771
- };
772
- switch (b) {
773
- case "ext":
774
- this.extend(d, {
775
- name: "ext",
776
- type: "text",
777
- text: "扩展字段",
778
- items: c.extParams,
779
- });
780
- break;
781
- case "createTime":
782
- this.extend(d, {
783
- name: "createTime",
784
- type: "datetime",
785
- format: "yyyy-MM-dd HH:mm:ss",
786
- text: "提交时间",
787
- });
788
- break;
789
- case "updateTime":
790
- this.extend(d, {
791
- name: "updateTime",
792
- type: "datetime",
793
- format: "yyyy-MM-dd HH:mm:ss",
794
- text: "更新时间",
795
- });
796
- break;
797
- case "creator":
798
- this.extend(d, {
799
- name: "creator",
800
- type: "text",
801
- text: "提交人",
802
- });
803
- break;
804
- case "flowState":
805
- this.extend(d, {
806
- name: "flowState",
807
- type: "flowState",
808
- text: "流程状态",
809
- });
810
- break;
811
- case "chargers":
812
- this.extend(d, {
813
- name: "chargers",
814
- type: "chargers",
815
- text: "当前节点/负责人",
816
- });
817
- break;
818
- case "deleter":
819
- this.extend(d, {
820
- name: "deleter",
821
- type: "text",
822
- text: "删除人",
823
- });
824
- break;
825
- case "deleteTime":
826
- this.extend(d, {
827
- name: "deleteTime",
828
- type: "datetime",
829
- format: "yyyy-MM-dd HH:mm:ss",
830
- text: "删除时间",
831
- });
832
- break;
833
- default:
834
- return null;
835
- }
836
- return d;
837
- },
838
- createWidgetName: function () {
839
- return "{" + this.STATIC.IDBase++;
840
- },
841
- formatFileSize: function (a) {
842
- return this.Utils.isNumber(a)
843
- ? a >= 1e9
844
- ? (a / 1e9).toFixed(2) + " GB"
845
- : a >= 1e6
846
- ? (a / 1e6).toFixed(2) + " MB"
847
- : (a / 1e3).toFixed(2) + " KB"
848
- : "未知";
849
- },
850
- chunkArray: function (a, b) {
851
- var c = [];
852
- if (!b || !a.length)
853
- return c;
854
- for (var d = 0, e = a.length; d < e; d += b) {
855
- var f = a.slice(d, d + b);
856
- c.push(f);
857
- }
858
- return c;
859
- },
860
- UUID: function (a) {
861
- return null;
862
- },
863
- GCD: function (a, b) {
864
- return b ? this.GCD(b, a % b) : a;
865
- },
866
- LCM: function (a, b) {
867
- return (a * b) / this.GCD(a, b);
868
- },
869
- fixDecimalPrecision: function (a, b) {
870
- let c = null;
871
- if ((b || (b = 8), !this.isEmpty(a))) {
872
- let d = parseFloat(a);
873
- if (!isNaN(d)) {
874
- let e = (d + "").split(".")[1];
875
- c == e && e.length > b ? parseFloat(d.toFixed(b)) : d,
876
- b > 6 &&
877
- Math.abs(c) < 1 &&
878
- /e-/.test(c + "") &&
879
- (c = parseFloat(d.toFixed(6)));
880
- }
881
528
  }
882
529
  return c;
883
530
  },
884
- getSelectionText: function () {
885
- // return window.getSelection
886
- // ? window.getSelection().toString()
887
- // : document.selection && document.selection.createRange
888
- // ? document.selection.createRange().text
889
- // : "";
890
- return null;
891
- },
892
- getCorpType: function (a) {
893
- return a
894
- ? ((a = a.toLowerCase()),
895
- /^ding/.test(a) ? "dingtalk" : /^w/.test(a) ? "wechat" : "internal")
896
- : null;
897
- },
898
- isCorpSuiteAdmin: function (a) {
899
- return a && ("dingtalk" === a || "wechat" === a);
900
- },
901
- getWeekStartDate: function (a) {
902
- var b = a.getDay();
903
- return (0 === b && (b = 7),
904
- new Date(a.getFullYear(), a.getMonth(), a.getDate() - (b - 1)));
905
- },
906
- getWeekEndDate: function (a) {
907
- var b = a.getDay();
908
- return (0 === b && (b = 7),
909
- new Date(a.getFullYear(), a.getMonth(), a.getDate() + (7 - b)));
910
- },
911
- getMonthStartDate: function (a) {
912
- return new Date(a.getFullYear(), a.getMonth(), 1);
913
- },
914
- getMonthEndDate: function (a) {
915
- return new Date(a.getFullYear(), a.getMonth() + 1, 0);
916
- },
917
- setPageTitle: function (a) {
918
- this.Utils.isEmpty(a) || (document.title = a);
919
- },
920
- createMask: function (b, c) {
921
- var d = this('<div class="x-window-mask"/>'), e = c || {};
922
- if ((e.isModal && d.addClass("modal"),
923
- e.isLight ? d.addClass("light") : e.isDark && d.addClass("dark"),
924
- e.hasLoader)) {
925
- var f = !e.isDark;
926
- this.createLoadIcon(d, f);
927
- }
928
- return (b &&
929
- d
930
- .css({
931
- "z-index": this.STATIC.zIndex++,
932
- })
933
- .appendTo(b),
934
- d);
935
- },
936
- createLoadIcon: function (b, c) {
937
- var d = this('<div class="x-loader-icon"/>').appendTo(b);
938
- return c && d.addClass("colorful"), this("<div/>").appendTo(d), d;
939
- },
940
- doPrint: function (b, c) {
941
- this("body").children("div").addClass("x-ui-notprint");
942
- var d = this("#x-printer").removeClass().empty();
943
- 0 === d.length && (d = this('<div id="x-printer"/>').appendTo("body")),
944
- b && d.append(b),
945
- (c = this.Utils.isNull(c) ? 0 : c),
946
- setTimeout(function () {
947
- window.print();
948
- }, c);
949
- },
950
- cancelPrint: function () {
951
- this("body").children(".x-ui-notprint").removeClass("x-ui-notprint"),
952
- this("#x-printer").remove();
953
- },
954
- copyToClipboard: function (a, b) {
955
- if (a && a.length) {
956
- var c = document.createElement("textarea");
957
- (c.style.background = "transparent"),
958
- (c.style.color = "transparent"),
959
- (c.value = a),
960
- document.body.appendChild(c),
961
- c.select();
962
- var d;
963
- try {
964
- d = document.execCommand("copy");
965
- }
966
- catch (a) {
967
- d = !1;
968
- }
969
- document.body.removeChild(c),
970
- d && this.Utils.applyFunc(this, b, [], !1);
971
- }
972
- },
973
- getColorNumber: function (a) {
974
- return this.Utils.isEmpty(a)
975
- ? 1
976
- : (parseInt(a.toString().substring(0, 8), 16) % 6) + 1;
977
- },
978
- getFieldAttr: function (b, c) {
979
- if (!this.Utils.isValueWidget(b.widget.type))
980
- return null;
981
- if (c && c.indexOf(b.widget.type) < 0)
982
- return null;
983
- var d = {
984
- id: b.formId,
985
- text: b.label,
986
- name: b.widget.widgetName,
987
- type: b.widget.type,
988
- };
989
- switch (b.widget.type) {
990
- case "subform":
991
- var e = [];
992
- this.Utils.forEach(b.widget.items, function (d, f) {
993
- this.extend(f, {
994
- formId: b.formId,
995
- });
996
- var g = this.Utils.getFieldAttr(f, c);
997
- g &&
998
- (this.extend(g, {
999
- subform: b.widget.widgetName,
1000
- }),
1001
- e.push(g));
1002
- }),
1003
- this.extend(d, {
1004
- items: e,
1005
- });
1006
- break;
1007
- case "linkdata":
1008
- this.extend(d, {
1009
- linkForm: b.widget.linkForm,
1010
- linkFields: b.widget.linkFields,
1011
- refAppId: b.widget.refAppId,
1012
- });
1013
- break;
1014
- case "combo":
1015
- case "combocheck":
1016
- case "radiogroup":
1017
- case "checkboxgroup":
1018
- this.extend(d, {
1019
- async: b.widget.async,
1020
- items: b.widget.items,
1021
- });
1022
- break;
1023
- case "datetime":
1024
- this.extend(d, {
1025
- format: b.widget.format,
1026
- });
1027
- }
1028
- return d;
531
+ applyFunc: function (a, b, c, d) {
532
+ return this.isFunction(b) ? b.apply(a, c || []) : d;
1029
533
  },
1030
534
  leftPad: function (a, b, c) {
1031
535
  var d = String(a);
@@ -1035,117 +539,65 @@ class Formula {
1035
539
  },
1036
540
  startWith: function (a, b) {
1037
541
  var c = a.length;
1038
- return (!(null == b || "" == b || 0 === c || b.length > c) &&
1039
- a.substr(0, b.length) == b);
1040
- },
1041
- getFieldInfoByFormula: function (a) {
1042
- var b = {}, c = a + "", d = c.match(/(\$[0-9a-zA-Z\._]+)(#[0-9a-f]+)?(@[0-9a-f]+)?/), e = ["", "field", "entryId", "appId"];
1043
- return (this.Utils.forEach(d, function (a, c) {
1044
- 0 !== a && c && (b[e[a]] = c.substr(1));
1045
- }),
1046
- b);
1047
- },
1048
- getFieldInfoById: function (a) {
1049
- var b = {};
1050
- a = "#" + a;
1051
- var c = a.match(/(#[0-9a-f]+)(@[0-9a-f]+)?/), d = ["", "entryId", "appId"];
1052
- return (this.Utils.forEach(c, function (a, c) {
1053
- 0 !== a && c && (b[d[a]] = c.substr(1));
1054
- }),
1055
- b);
1056
- },
1057
- isWpsWebView: function () {
1058
- return /wpscloudform/.test(navigator.userAgent);
1059
- },
1060
- callWPSAPI: function (a) {
1061
- // var b = "jsAsynCall(" + JSON.stringify(a) + ")";
1062
- // window.cefQuery &&
1063
- // window.cefQuery({
1064
- // request: b,
1065
- // });
542
+ return !(null == b || "" == b || 0 === c || b.length > c) && a.substr(0, b.length) == b;
1066
543
  },
1067
- onWPSPageUnload: function (a, b) {
1068
- a
1069
- ? this.Msg.alert({
1070
- type: "warning",
1071
- msg: "当前页面未保存,是否确定离开?",
1072
- text4Ok: "离开",
1073
- text4Cancel: "取消",
1074
- onOk: function () {
1075
- this.Utils.applyFunc(this, b, [], !1);
1076
- },
1077
- })
1078
- : this.Utils.applyFunc(this, b, [], !1);
1079
- },
1080
- fileDownload: function (a, b) {
1081
- // if (this.Utils.isWpsWebView()) {
1082
- // var c = {
1083
- // method: "downloadUrl",
1084
- // url: a,
1085
- // filename: b,
1086
- // },
1087
- // d = b && b.split(".").pop();
1088
- // (c.filter = "(*." + (d || "*") + ")"), fml.Utils.callWPSAPI(c);
1089
- // } else fml.Utils.redirectTo(a);
1090
- },
1091
- isSupportPdf: function () {
1092
- return "undefined" != typeof navigator.mimeTypes["application/pdf"];
1093
- },
1094
- dt: function (a, b) {
1095
- if (a) {
1096
- var c = ["e=" + a, "t=" + new Date().getTime()];
1097
- this.Utils.isEmpty(b) || c.push("ext=" + b),
1098
- this.STATIC.user &&
1099
- this.STATIC.user.username &&
1100
- c.push("u=" + this.STATIC.user.username);
1101
- var d = new Image();
1102
- d.src = this.CONFIG.HOST.TRACK_HOST + "/log?" + c.join("&");
544
+ extend: function (target, source) {
545
+ for (var key in source) {
546
+ if (source.hasOwnProperty(key)) {
547
+ target[key] = source[key];
548
+ }
1103
549
  }
550
+ return target;
1104
551
  },
552
+ fakeLabel: function (t) {
553
+ return t ? t.replace(/[\[\]()'"]/g, " ") : "";
554
+ }
1105
555
  };
556
+ }
557
+ initFormula() {
1106
558
  this.Formula = {
1107
559
  AND: function () {
1108
560
  for (var a = this.Utils.flatten(arguments), b = 0, c = a.length; b < c; b++)
1109
561
  if (!a[b])
1110
562
  return !1;
1111
563
  return !0;
1112
- },
564
+ }.bind(this),
1113
565
  OR: function () {
1114
566
  for (var a = this.Utils.flatten(arguments), b = 0, c = a.length; b < c; b++)
1115
567
  if (a[b])
1116
568
  return !0;
1117
569
  return !1;
1118
- },
570
+ }.bind(this),
1119
571
  FALSE: function () {
1120
572
  return !1;
1121
- },
573
+ }.bind(this),
1122
574
  TRUE: function () {
1123
575
  return !0;
1124
- },
576
+ }.bind(this),
1125
577
  IF: function (a, b, c) {
1126
578
  return a ? b : c;
1127
- },
579
+ }.bind(this),
1128
580
  NOT: function (a) {
1129
581
  return !a;
1130
- },
582
+ }.bind(this),
1131
583
  XOR: function () {
1132
584
  for (var a = 0, b = this.Utils.flatten(arguments), c = 0, d = b.length; c < d; c++)
1133
585
  b[c] && a++;
1134
586
  return !!(1 & Math.floor(Math.abs(a)));
1135
- },
587
+ }.bind(this),
1136
588
  CONCATENATE: function () {
1137
589
  for (var a = this.Utils.flatten(arguments), b = 0; (b = a.indexOf(!0)) > -1;)
1138
590
  a[b] = "TRUE";
1139
591
  for (var c = 0; (c = a.indexOf(!1)) > -1;)
1140
592
  a[c] = "FALSE";
1141
593
  return a.join("");
1142
- },
594
+ }.bind(this),
1143
595
  EXACT: function (a, b) {
1144
596
  return a === b;
1145
- },
597
+ }.bind(this),
1146
598
  LEFT: function (a, b) {
1147
599
  return (b = this.Utils.isEmpty(b) ? 1 : b), a ? a.substring(0, b) : "";
1148
- },
600
+ }.bind(this),
1149
601
  LEN: function (a) {
1150
602
  return this.Utils.isString(a)
1151
603
  ? a
@@ -1154,63 +606,62 @@ class Formula {
1154
606
  : a && a.length
1155
607
  ? a.length
1156
608
  : 0;
1157
- },
609
+ }.bind(this),
1158
610
  SUBSTRING: function (a, b, c) {
1159
611
  return ((a = a || ""),
1160
612
  this.Utils.isNumber(b) && this.Utils.isNumber(c)
1161
- ? a.substr(b - 1, c)
613
+ ? a.substr(b - 1, c - b + 1)
1162
614
  : a);
1163
- },
615
+ }.bind(this),
1164
616
  LOWER: function (a) {
1165
617
  return this.Utils.isString(a) ? (a ? a.toLowerCase() : a) : "";
1166
- },
618
+ }.bind(this),
1167
619
  REPLACE: function (a, b, c, d) {
1168
620
  return this.Utils.isNumber(b) && this.Utils.isNumber(c)
1169
621
  ? ((a = a || ""),
1170
622
  (d = d || ""),
1171
623
  a.substr(0, b - 1) + d + a.substr(b - 1 + c))
1172
624
  : a;
1173
- },
625
+ }.bind(this),
1174
626
  REPT: function (a, b) {
1175
627
  return (b = b || 0), new Array(b + 1).join(a);
1176
- },
628
+ }.bind(this),
1177
629
  RIGHT: function (a, b) {
1178
630
  return (b = void 0 === b ? 1 : b), a ? a.substring(a.length - b) : "";
1179
- },
631
+ }.bind(this),
1180
632
  SEARCH: function (a, b, c) {
1181
633
  var d;
1182
634
  return this.Utils.isString(a) && this.Utils.isString(b)
1183
635
  ? ((c = this.Utils.isNull(c) ? 0 : c),
1184
636
  (d = b.toLowerCase().indexOf(a.toLowerCase(), c - 1) + 1))
1185
637
  : 0;
1186
- },
638
+ }.bind(this),
1187
639
  SPLIT: function (a, b) {
1188
640
  return this.Utils.isString(a) ? a.split(b) : [];
1189
- },
641
+ }.bind(this),
1190
642
  TRIM: function (a) {
1191
643
  return this.Utils.isString(a) ? a.replace(/ +/g, " ").trim() : "";
1192
- },
644
+ }.bind(this),
1193
645
  UPPER: function (a) {
1194
646
  return this.Utils.isString(a) ? a.toUpperCase() : "";
1195
- },
647
+ }.bind(this),
1196
648
  MID: function (a, b, c) {
1197
649
  return ((a = a || ""),
1198
650
  this.Utils.isNumber(b) && this.Utils.isNumber(c)
1199
651
  ? a.substr(b - 1, c)
1200
652
  : a);
1201
- },
653
+ }.bind(this),
1202
654
  AVERAGE: function () {
1203
655
  for (var a = this.Utils.flatten(arguments, function (a) {
1204
656
  return this.Utils.isNumber(a);
1205
- }), b = a.length, c = 0, d = 0, e = 0; e < b; e++)
657
+ }.bind(this)), b = a.length, c = 0, d = 0, e = 0; e < b; e++)
1206
658
  (c += a[e]), (d += 1);
1207
- return c / d;
1208
- },
659
+ return d > 0 ? c / d : 0;
660
+ }.bind(this),
1209
661
  COUNT: function () {
1210
662
  return this.Utils.flatten(arguments).length;
1211
- },
1212
- COUNTIF: function () {
1213
- var arr = arguments[0], condition = arguments[1];
663
+ }.bind(this),
664
+ COUNTIF: function (arr, condition) {
1214
665
  var len = 0;
1215
666
  if (condition.indexOf(">") == -1 &&
1216
667
  condition.indexOf("=") == -1 &&
@@ -1233,41 +684,33 @@ class Formula {
1233
684
  }
1234
685
  return len;
1235
686
  }
1236
- },
687
+ }.bind(this),
1237
688
  LARGE: function (a, b) {
1238
689
  return ((a = this.Utils.flatten(a, function (a) {
1239
690
  return this.Utils.isNumber(a);
1240
- })),
691
+ }.bind(this))),
1241
692
  a.sort(function (a, b) {
1242
693
  return b - a;
1243
694
  })[b - 1]);
1244
- },
695
+ }.bind(this),
1245
696
  MAX: function () {
1246
697
  var a = this.Utils.flatten(arguments, function (a) {
1247
698
  return this.Utils.isNumber(a);
1248
- });
699
+ }.bind(this));
1249
700
  return 0 === a.length ? 0 : Math.max.apply(Math, a);
1250
- },
701
+ }.bind(this),
1251
702
  MIN: function () {
1252
703
  var a = this.Utils.flatten(arguments, function (a) {
1253
704
  return this.Utils.isNumber(a);
1254
- });
705
+ }.bind(this));
1255
706
  return 0 === a.length ? 0 : Math.min.apply(Math, a);
1256
- },
1257
- SMALL: function (a, b) {
1258
- return ((a = this.Utils.flatten(a, function (a) {
1259
- return this.Utils.isNumber(a);
1260
- })),
1261
- a.sort(function (a, b) {
1262
- return a - b;
1263
- })[b - 1]);
1264
- },
707
+ }.bind(this),
1265
708
  ABS: function (a) {
1266
709
  return this.Utils.isNumber(a) ? Math.abs(a) : 0;
1267
- },
710
+ }.bind(this),
1268
711
  ROUND: function (a, b) {
1269
712
  return Math.round(a * Math.pow(10, b)) / Math.pow(10, b);
1270
- },
713
+ }.bind(this),
1271
714
  CEILING: function (a, b) {
1272
715
  if (0 === b)
1273
716
  return 0;
@@ -1280,7 +723,7 @@ class Formula {
1280
723
  : 0 === c
1281
724
  ? -this.Formula.ROUND(Math.floor(Math.abs(a) / b) * b, e)
1282
725
  : -this.Formula.ROUND(Math.ceil(Math.abs(a) / b) * b, e));
1283
- },
726
+ }.bind(this),
1284
727
  FLOOR: function (a, b) {
1285
728
  if (0 === b)
1286
729
  return 0;
@@ -1292,41 +735,41 @@ class Formula {
1292
735
  a >= 0
1293
736
  ? this.Formula.ROUND(Math.floor(a / b) * b, d)
1294
737
  : -this.Formula.ROUND(Math.floor(Math.abs(a) / b) * b, d));
1295
- },
738
+ }.bind(this),
1296
739
  INT: function (a) {
1297
740
  return this.Utils.isNumber(a) ? Math.floor(a) : 0;
1298
- },
741
+ }.bind(this),
1299
742
  LOG: function (a, b) {
1300
743
  return ((b = void 0 === b ? 10 : b),
1301
744
  this.Utils.isNumber(b) ? Math.log(a) / Math.log(b) : 0);
1302
- },
745
+ }.bind(this),
1303
746
  MOD: function (a, b) {
1304
747
  if (0 === b)
1305
748
  return 0;
1306
749
  var c = Math.abs(a % b);
1307
750
  return b > 0 ? c : -c;
1308
- },
751
+ }.bind(this),
1309
752
  POWER: function (a, b) {
1310
753
  var c = Math.pow(a, b);
1311
754
  return isNaN(c) ? 0 : c;
1312
- },
755
+ }.bind(this),
1313
756
  PRODUCT: function () {
1314
757
  for (var a = this.Utils.flatten(arguments, function (a) {
1315
758
  return this.Utils.isNumber(a);
1316
- }), b = 1, c = 0; c < a.length; c++)
759
+ }.bind(this)), b = 1, c = 0; c < a.length; c++)
1317
760
  b *= a[c];
1318
761
  return b;
1319
- },
762
+ }.bind(this),
1320
763
  SQRT: function (a) {
1321
764
  return a < 0 ? 0 : Math.sqrt(a);
1322
- },
765
+ }.bind(this),
1323
766
  SUM: function () {
1324
767
  for (var a = 0, b = this.Utils.flatten(arguments, function (a) {
1325
768
  return this.Utils.isNumber(a);
1326
- }), c = 0, d = b.length; c < d; ++c)
769
+ }.bind(this)), c = 0, d = b.length; c < d; ++c)
1327
770
  a += b[c];
1328
771
  return a;
1329
- },
772
+ }.bind(this),
1330
773
  SUMPRODUCT: function () {
1331
774
  for (var a = 0, b = [], c = -1, d = 0; d < arguments.length; d++)
1332
775
  arguments[d] instanceof Array &&
@@ -1338,969 +781,1126 @@ class Formula {
1338
781
  a += e;
1339
782
  }
1340
783
  return a;
1341
- },
784
+ }.bind(this),
1342
785
  FIXED: function (a, b) {
1343
786
  return ((b = void 0 === b ? 0 : b),
1344
787
  this.Utils.isNumber(b) && b >= 0 ? Number(a).toFixed(b) : "");
1345
- },
1346
- DATE: function () {
1347
- return 6 === arguments.length
1348
- ? new Date(parseInt(arguments[0], 10), parseInt(arguments[1], 10) - 1, parseInt(arguments[2], 10), parseInt(arguments[3], 10), parseInt(arguments[4], 10), parseInt(arguments[5], 10))
1349
- : 3 === arguments.length
1350
- ? new Date(parseInt(arguments[0], 10), parseInt(arguments[1], 10) - 1, parseInt(arguments[2], 10))
1351
- : new Date(arguments[0]);
1352
- },
788
+ }.bind(this),
789
+ DATE: function (year, month, day, hour, minute, second) {
790
+ if (arguments.length === 6) {
791
+ return new Date(year, month - 1, day, hour || 0, minute || 0, second || 0);
792
+ }
793
+ else if (arguments.length === 3) {
794
+ return new Date(year, month - 1, day);
795
+ }
796
+ else if (arguments.length === 1) {
797
+ return new Date(year);
798
+ }
799
+ return new Date();
800
+ }.bind(this),
1353
801
  TIME: function (a, b, c) {
1354
802
  return (3600 * a + 60 * b + c) / 86400;
1355
- },
803
+ }.bind(this),
1356
804
  TIMESTAMP: function (a) {
1357
805
  return this.Utils.isDate(a) ? a.getTime() : 0;
1358
- },
806
+ }.bind(this),
1359
807
  TODAY: function () {
1360
808
  return new Date();
1361
- },
809
+ }.bind(this),
1362
810
  NOW: function () {
1363
811
  return new Date();
1364
- },
1365
- SYSTIME: function () {
1366
- var a = this.STATIC._st, b = new Date().getTime() - this.STATIC._ct;
1367
- return b > 0 && b < 36e5 && (a += b), new Date(a);
1368
- },
812
+ }.bind(this),
1369
813
  DAY: function (a) {
1370
814
  return a.getDate();
1371
- },
815
+ }.bind(this),
1372
816
  MONTH: function (a) {
1373
817
  return a.getMonth() + 1;
1374
- },
818
+ }.bind(this),
1375
819
  YEAR: function (a) {
1376
820
  return a.getFullYear();
1377
- },
821
+ }.bind(this),
1378
822
  HOUR: function (a) {
1379
823
  return a.getHours();
1380
- },
824
+ }.bind(this),
1381
825
  MINUTE: function (a) {
1382
826
  return a.getMinutes();
1383
- },
827
+ }.bind(this),
1384
828
  SECOND: function (a) {
1385
829
  return a.getSeconds();
1386
- },
830
+ }.bind(this),
1387
831
  DAYS: function (a, b) {
1388
- var c = new Date(a.getFullYear(), a.getMonth(), a.getDate()), d = new Date(b.getFullYear(), b.getMonth(), b.getDate());
1389
- return null; //(c - d) / 864e5
1390
- },
1391
- DATEMINUS: function (a, b, c) {
1392
- var d, e, f = b.getMonth(), g = a.getMonth();
1393
- if (c)
1394
- (d = 31 === b.getDate() ? 30 : b.getDate()),
1395
- (e = 31 === a.getDate() ? 30 : a.getDate());
1396
- else {
1397
- var h = new Date(b.getFullYear(), f + 1, 0).getDate(), i = new Date(a.getFullYear(), g + 1, 0).getDate();
1398
- (d = b.getDate() === h ? 30 : b.getDate()),
1399
- a.getDate() === i
1400
- ? d < 30
1401
- ? (g++, (e = 1))
1402
- : (e = 30)
1403
- : (e = a.getDate());
1404
- }
1405
- return 360 * (a.getFullYear() - b.getFullYear()) + 30 * (g - f) + (e - d);
1406
- },
832
+ const c = new Date(a.getFullYear(), a.getMonth(), a.getDate());
833
+ const d = new Date(b.getFullYear(), b.getMonth(), b.getDate());
834
+ return Math.round((c.getTime() - d.getTime()) / (1000 * 60 * 60 * 24));
835
+ }.bind(this),
1407
836
  DATEDELTA: function (a, b) {
1408
837
  return (this.Utils.isNumber(b) || (b = 0), new Date(a.getTime() + 864e5 * b));
1409
- },
1410
- ISOWEEKNUM: function (a) {
1411
- a.setHours(0, 0, 0), a.setDate(a.getDate() + 4 - (a.getDay() || 7));
1412
- var b = new Date(a.getFullYear(), 0, 1);
1413
- //return Math.ceil(((a - b) / 864e5 + 1) / 7);
1414
- return null;
1415
- },
1416
- WEEKNUM: function (a, b) {
1417
- var c = 2 === b ? 1 : 0, d = new Date(a.getFullYear(), 0, 1), e = (c + 7 - d.getDay()) % 7, f = e > 0 ? 1 : 0, g = d.getTime() + 24 * e * 60 * 60 * 1e3;
1418
- return Math.floor((a.getTime() - g) / 864e5 / 7 + 1) + f;
1419
- },
1420
- STRDATE: function (a) {
1421
- return a.getFullYear() + "-" + a.getMonth() + 1 + '-' + a.getDate();
1422
- },
838
+ }.bind(this),
1423
839
  TEXT: function (a, b) {
1424
840
  return this.Utils.isNull(a)
1425
841
  ? ""
1426
842
  : this.Utils.isDate(a) && !this.Utils.isEmpty(b)
1427
- ? this.Utils.date2Str(a, b)
1428
- : this.Utils.num2Str(a, b);
1429
- },
843
+ ? a.toLocaleString()
844
+ : String(a);
845
+ }.bind(this),
1430
846
  VALUE: function (a) {
1431
847
  return this.Utils.isEmpty(a) ? 0 : isNaN(a) ? 0 : parseFloat(a);
1432
- },
848
+ }.bind(this),
1433
849
  UUID: function () {
1434
- return this.Utils.UUID();
1435
- },
1436
- RECNO: function () {
1437
- //需修改
1438
- // return this.Utils.isNull(this.STATIC.EntryRecNo) ? this.STATIC.APPID && this.STATIC.ENTRYID ? (this.Utils.dataAjax({
1439
- // url: "/data/formula/recno",
1440
- // async: !1,
1441
- // data: {
1442
- // appId: fml.STATIC.APPID,
1443
- // formId: fml.STATIC.ENTRYID,
1444
- // hasIncLock: fml.STATIC.RecnoLock
1445
- // }
1446
- // }, function (a) {
1447
- // fml.STATIC.EntryRecNo = a.incId
1448
- // }), fml.STATIC.EntryRecNo) : "" : fml.STATIC.EntryRecNo
1449
- return null;
1450
- },
850
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
851
+ var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
852
+ return v.toString(16);
853
+ });
854
+ }.bind(this),
1451
855
  ISEMPTY: function (a) {
1452
856
  return this.Utils.isObjectEmpty(a);
1453
- },
1454
- MAPX: function (a, b, c, d) {
1455
- var e = null;
1456
- if (this.Utils.isEmpty(a) || this.Utils.isObjectEmpty(b))
1457
- return e;
1458
- // a = a.toLowerCase();
1459
- // var f = this.Utils.getFieldInfoByFormula(c),
1460
- // g = this.Utils.getFieldInfoByFormula(d);
1461
- // if (/^sum|avg|max|min|count|first|last$/.test(a) && f.entryId && f.entryId === g.entryId) {
1462
- // var h = this.Utils.isDate(b),
1463
- // i = h ? b.getTime() : b;
1464
- // fml.Utils.dataAjax({
1465
- // url: "/data/formula/aggregate",
1466
- // async: !1,
1467
- // data: {
1468
- // op: a,
1469
- // formId: f.entryId,
1470
- // lookup_value: i,
1471
- // lookup_field: f.field,
1472
- // result_field: g.field,
1473
- // date_type: h,
1474
- // refAppId: f.appId
1475
- // }
1476
- // }, function (a) {
1477
- // a.result && a.result[0] && (e = a.result[0].result)
1478
- // })
1479
- // }
1480
- return e;
1481
- },
1482
- MAP: function (a, b, c) {
1483
- // var d = [];
1484
- // if (fml.Utils.isObjectEmpty(a))
1485
- // return d;
1486
- // var e = fml.Utils.getFieldInfoByFormula(b),
1487
- // f = fml.Utils.getFieldInfoByFormula(c);
1488
- // return e.entryId && e.entryId === f.entryId && fml.Utils.dataAjax({
1489
- // url: "/data/formula/map",
1490
- // async: !1,
1491
- // data: {
1492
- // formId: e.entryId,
1493
- // lookup_value: a,
1494
- // lookup_field: e.field,
1495
- // result_field: f.field,
1496
- // refAppId: e.appId
1497
- // }
1498
- // }, function (a) {
1499
- // fml.Utils.forEach(a.result, function (a, b) {
1500
- // d.push(b[f.field])
1501
- // })
1502
- // }, function () {}),
1503
- // d
1504
- return [];
1505
- },
857
+ }.bind(this),
1506
858
  GETUSERNAME: function () {
1507
- //需修改
1508
- return this.STATIC.user ? this.STATIC.user.nickname : "";
1509
- },
859
+ return "当前用户";
860
+ }.bind(this),
1510
861
  };
1511
862
  }
1512
863
  }
1513
864
 
1514
865
  /**
1515
- * 根据关键字匹配变量
1516
- * @param key
1517
- * @param fieldVariable
866
+ * 公式增强器 - 通过组合而不是继承来扩展 Formula 类
1518
867
  */
1519
- function searchVariable(key, fieldVariable) {
1520
- let result = [];
1521
- if (key != null && key !== "") {
1522
- if (fieldVariable.formFields &&
1523
- fieldVariable.formFields !== null &&
1524
- fieldVariable.formFields.length > 0) {
1525
- fieldVariable.formFields.forEach((item) => {
1526
- if (item.label.indexOf(key) > -1) {
1527
- result.push(item);
868
+ class FormulaEnhancer {
869
+ formulaInstance;
870
+ validationCache = new Map();
871
+ functionNamesCache = null;
872
+ constructor(formulaInstance) {
873
+ this.formulaInstance = formulaInstance;
874
+ }
875
+ /**
876
+ * 获取底层 Formula 实例(用于访问原有功能)
877
+ */
878
+ get formula() {
879
+ return this.formulaInstance;
880
+ }
881
+ /**
882
+ * 验证公式
883
+ */
884
+ validate(formula) {
885
+ // 检查缓存
886
+ const cacheKey = formula;
887
+ if (this.validationCache.has(cacheKey)) {
888
+ return this.validationCache.get(cacheKey);
889
+ }
890
+ const availableFunctions = this.getAllFunctionNames();
891
+ const result = {
892
+ isValid: true,
893
+ errors: [],
894
+ warnings: []
895
+ };
896
+ // 基础验证
897
+ if (!formula || formula.trim() === '') {
898
+ result.errors.push({
899
+ message: '公式不能为空',
900
+ severity: 'error',
901
+ type: 'syntax'
902
+ });
903
+ result.isValid = false;
904
+ return result;
905
+ }
906
+ // 检查未闭合的括号
907
+ const openParen = (formula.match(/\(/g) || []).length;
908
+ const closeParen = (formula.match(/\)/g) || []).length;
909
+ if (openParen !== closeParen) {
910
+ result.errors.push({
911
+ message: `括号不匹配: 有 ${openParen} 个左括号,${closeParen} 个右括号`,
912
+ severity: 'error',
913
+ type: 'syntax'
914
+ });
915
+ result.isValid = false;
916
+ }
917
+ // 检查引号匹配
918
+ let inString = false;
919
+ let quoteChar = '';
920
+ for (let i = 0; i < formula.length; i++) {
921
+ const char = formula[i];
922
+ if ((char === '"' || char === "'") && (i === 0 || formula[i - 1] !== '\\')) {
923
+ if (!inString) {
924
+ inString = true;
925
+ quoteChar = char;
1528
926
  }
927
+ else if (char === quoteChar) {
928
+ inString = false;
929
+ }
930
+ }
931
+ }
932
+ if (inString) {
933
+ result.errors.push({
934
+ message: '字符串未闭合',
935
+ severity: 'error',
936
+ type: 'syntax'
1529
937
  });
938
+ result.isValid = false;
1530
939
  }
1531
- if (fieldVariable.tableList &&
1532
- fieldVariable.tableList !== null &&
1533
- fieldVariable.tableList.length > 0) {
1534
- fieldVariable.tableList.forEach((table) => {
1535
- table.fields.forEach((item) => {
1536
- if (item.label.indexOf(key) > -1) {
1537
- result.push(item);
1538
- }
940
+ // 检查未知函数
941
+ const functionMatches = formula.match(/\b([A-Z][A-Z0-9_]*)\s*\(/gi) || [];
942
+ functionMatches.forEach(match => {
943
+ const funcName = match.replace(/\s*\(/, '').toUpperCase();
944
+ if (!availableFunctions.includes(funcName)) {
945
+ result.errors.push({
946
+ message: `未知函数: ${funcName}`,
947
+ severity: 'error',
948
+ type: 'semantic'
1539
949
  });
950
+ result.isValid = false;
951
+ }
952
+ });
953
+ // 检查函数调用格式
954
+ const invalidCalls = formula.match(/\b[A-Z][A-Z0-9_]*\s*\(\s*,/g);
955
+ if (invalidCalls) {
956
+ result.warnings.push({
957
+ message: '函数参数格式可能有误',
958
+ severity: 'warning',
959
+ type: 'syntax'
960
+ });
961
+ }
962
+ // 检查连续逗号
963
+ if (formula.includes(',,')) {
964
+ result.warnings.push({
965
+ message: '参数之间不应有连续的逗号',
966
+ severity: 'warning',
967
+ type: 'syntax'
1540
968
  });
1541
969
  }
970
+ // 缓存结果
971
+ this.validationCache.set(cacheKey, result);
972
+ return result;
1542
973
  }
1543
- return result;
1544
- }
1545
- /**
1546
- * 根据关键字匹配变量 fieldVariable 为数组
1547
- * @param key
1548
- * @param fieldVariable
1549
- */
1550
- function searchArrayVariable(key, groupArray) {
1551
- let result = [];
1552
- groupArray.map((group) => {
1553
- const tableList = searchVariable(key, group);
1554
- if (tableList.length > 0) {
1555
- result = [...result, ...tableList];
974
+ /**
975
+ * 获取所有可用函数名
976
+ */
977
+ getAllFunctionNames() {
978
+ if (this.functionNamesCache) {
979
+ return this.functionNamesCache;
1556
980
  }
1557
- });
1558
- return result;
1559
- }
1560
- /**
1561
- * 根据关键字匹配函数
1562
- * @param key
1563
- */
1564
- function searchUsageFun(key, formulaUsage) {
1565
- let result = [];
1566
- if (key != null && key !== "") {
1567
- let fml = new Formula();
1568
- formulaUsage.forEach((usage) => {
1569
- usage.contains.forEach((item) => {
1570
- if (item.name.toUpperCase().indexOf(key.toUpperCase()) > -1) {
1571
- result.push(item);
981
+ const functionNames = [];
982
+ // 从 FormulaUsage 获取函数名
983
+ if (this.formulaInstance.FormulaUsage) {
984
+ this.formulaInstance.FormulaUsage.forEach((category) => {
985
+ if (category.contains) {
986
+ category.contains.forEach((func) => {
987
+ if (func.name) {
988
+ functionNames.push(func.name.toUpperCase());
989
+ }
990
+ });
1572
991
  }
1573
992
  });
1574
- });
1575
- }
1576
- return result;
1577
- }
1578
-
1579
- class GramCodemirrorComponent {
1580
- _differs;
1581
- _ngZone;
1582
- el;
1583
- message;
1584
- nzConfigService;
1585
- fmlService;
1586
- itemTitle = {};
1587
- set options(value) {
1588
- if (value) {
1589
- this._options = value;
1590
- if (!this._differ && value) {
1591
- this._differ = this._differs.find(value).create();
1592
- }
1593
993
  }
994
+ // 从 Formula 对象获取函数名
995
+ if (this.formulaInstance.Formula) {
996
+ Object.keys(this.formulaInstance.Formula).forEach(funcName => {
997
+ functionNames.push(funcName.toUpperCase());
998
+ });
999
+ }
1000
+ // 去重并缓存
1001
+ this.functionNamesCache = [...new Set(functionNames)];
1002
+ return this.functionNamesCache;
1594
1003
  }
1595
1004
  /**
1596
- * 可用变量对象
1597
- * {
1598
- * formFields:[],tableList:[]
1599
- * }
1005
+ * 获取函数详情
1600
1006
  */
1601
- set fieldData(value) {
1602
- this._fieldData = value;
1603
- if (Array.isArray(value) && value.length > 0) {
1604
- value.forEach((t) => {
1605
- if (Array.isArray(t.listField) && t.listField.length > 0) {
1606
- t.listField.forEach((f) => {
1607
- this.labelMap['$' + `{${f.key}}`] = f.label;
1608
- });
1007
+ getFunctionDetails(name) {
1008
+ const upperName = name.toUpperCase();
1009
+ // FormulaUsage 中查找
1010
+ if (this.formulaInstance.FormulaUsage) {
1011
+ for (const category of this.formulaInstance.FormulaUsage) {
1012
+ if (category.contains) {
1013
+ const func = category.contains.find((f) => f.name && f.name.toUpperCase() === upperName);
1014
+ if (func) {
1015
+ return {
1016
+ ...func,
1017
+ category: category.category
1018
+ };
1019
+ }
1609
1020
  }
1610
- });
1021
+ }
1022
+ }
1023
+ // 从 Formula 对象中查找
1024
+ if (this.formulaInstance.Formula && this.formulaInstance.Formula[upperName]) {
1025
+ return {
1026
+ name: upperName,
1027
+ intro: '内置函数',
1028
+ usage: `${upperName}(...)`,
1029
+ example: '请参考文档',
1030
+ category: '内置函数'
1031
+ };
1611
1032
  }
1033
+ return null;
1612
1034
  }
1613
- get fieldData() {
1614
- return this._fieldData;
1035
+ /**
1036
+ * 获取函数签名
1037
+ */
1038
+ getFunctionSignature(name) {
1039
+ const func = this.getFunctionDetails(name);
1040
+ if (func && func.usage) {
1041
+ return func.usage;
1042
+ }
1043
+ return `${name}(...)`;
1615
1044
  }
1616
1045
  /**
1617
- * 黑名单 值为函数名数组
1046
+ * 清理验证缓存
1618
1047
  */
1619
- blacklist;
1048
+ clearValidationCache() {
1049
+ this.validationCache.clear();
1050
+ this.functionNamesCache = null;
1051
+ }
1620
1052
  /**
1621
- * 启用默认黑名单
1622
- * 默认黑名单与blackList合并
1053
+ * 获取公式中使用的所有变量
1623
1054
  */
1624
- enableDefaultBlack = true;
1055
+ extractVariables(formula) {
1056
+ const variableRegex = /\${([^}]+)}/g;
1057
+ const variables = [];
1058
+ let match;
1059
+ while ((match = variableRegex.exec(formula)) !== null) {
1060
+ variables.push(match[1]);
1061
+ }
1062
+ return [...new Set(variables)];
1063
+ }
1625
1064
  /**
1626
- * 显示的公式 值显示列表内指定公式
1065
+ * 获取公式中使用的所有函数
1627
1066
  */
1628
- showList;
1629
- get dateType() {
1630
- const t = Array.isArray(this.fieldData);
1631
- return t ? "array" : "object";
1632
- }
1633
- set variableSearch(value) {
1634
- let variableSearchList;
1635
- if ("array" === this.dateType) {
1636
- variableSearchList = searchArrayVariable(value, this.fieldData);
1637
- }
1638
- else {
1639
- variableSearchList = searchVariable(value, this.fieldData);
1640
- }
1641
- this.variableSearchList = variableSearchList;
1642
- this._variableSearch = value;
1643
- }
1644
- get variableSearch() {
1645
- return this._variableSearch;
1646
- }
1647
- set usageFunSearch(value) {
1648
- // TODO 只显示当前公式编辑器支持的函数
1649
- this.usageFunSearchList = searchUsageFun(value, this.FormulaUsage);
1650
- this._usageFunSearch = value;
1651
- }
1652
- get usageFunSearch() {
1653
- return this._usageFunSearch;
1067
+ extractFunctions(formula) {
1068
+ const functionRegex = /\b([A-Z][A-Z0-9_]*)\s*\(/gi;
1069
+ const functions = [];
1070
+ let match;
1071
+ while ((match = functionRegex.exec(formula)) !== null) {
1072
+ functions.push(match[1].toUpperCase());
1073
+ }
1074
+ return [...new Set(functions)];
1654
1075
  }
1655
1076
  /**
1656
- * 所有支持函数分组信息
1657
- * name 分组名称 string
1658
- * code 分组code string
1659
- * items 函数名集合 string[]
1077
+ * 格式化公式
1660
1078
  */
1661
- get globalCategorys() {
1662
- var info = [];
1663
- _.forEach(this.fml.FormulaUsage, function (item) {
1664
- info.push({
1665
- // name 分组名称 string
1666
- name: item.category,
1667
- // code 分组code string
1668
- code: item.categoryCode,
1669
- // items 函数名集合 string[]
1670
- items: _.flatMap(item.contains, function (c) {
1671
- return c.name;
1672
- }),
1673
- });
1674
- });
1675
- return info;
1079
+ format(formula) {
1080
+ if (!formula)
1081
+ return '';
1082
+ // 简单的格式化逻辑
1083
+ return formula
1084
+ .replace(/\s+/g, ' ')
1085
+ .replace(/\s*\(\s*/g, '(')
1086
+ .replace(/\s*\)\s*/g, ')')
1087
+ .replace(/\s*,\s*/g, ', ')
1088
+ .replace(/\s*=\s*/g, ' = ')
1089
+ .replace(/\s*\+\s*/g, ' + ')
1090
+ .replace(/\s*-\s*/g, ' - ')
1091
+ .replace(/\s*\*\s*/g, ' * ')
1092
+ .replace(/\s*\/\s*/g, ' / ')
1093
+ .trim();
1676
1094
  }
1677
1095
  /**
1678
- * 获取全局CodeMirror
1096
+ * 获取智能建议
1679
1097
  */
1680
- get codeMirrorGlobal() {
1681
- if (this._codeMirror) {
1682
- return this._codeMirror;
1098
+ getSuggestions(text, cursorPos, availableVariables = []) {
1099
+ const suggestions = [];
1100
+ const lineText = this.getLineText(text, cursorPos);
1101
+ // 获取函数建议
1102
+ suggestions.push(...this.getFunctionSuggestions(lineText));
1103
+ // 获取变量建议
1104
+ if (availableVariables.length > 0) {
1105
+ suggestions.push(...this.getVariableSuggestions(lineText, availableVariables));
1683
1106
  }
1684
- this._codeMirror =
1685
- typeof CodeMirror !== "undefined" ? CodeMirror : require("codemirror");
1686
- return this._codeMirror;
1687
- }
1688
- // fml = new Formula();
1689
- name = "codemirror";
1690
- title = "";
1691
- autoFocus = false;
1692
- /**
1693
- * 函数显示类型
1694
- * 班次 attendance 所有 // attendance-items 精度 进位规则
1695
- *
1696
- * 与categorys互斥,有type时使用type
1697
- */
1698
- type = "";
1699
- /**
1700
- * 显示的函数组
1701
- * 与type 互斥,如果type有值,当前参数无效。
1702
- */
1703
- categorys;
1704
- /**
1705
- * 自定义公式
1706
- */
1707
- formulaClass;
1708
- typeList = {
1709
- "attendance-items": [
1710
- "MANHOURS",
1711
- "CalendarDay",
1712
- "PRECISION",
1713
- "DepartmentScope",
1714
- "AND",
1715
- "OR",
1716
- "IF",
1717
- "IN",
1718
- "AttendanceType",
1719
- "MinusSupport",
1720
- ],
1721
- Daycalculation: [
1722
- "Daycalculation",
1723
- "Hourcalculation",
1724
- "SUM",
1725
- "Daycompute",
1726
- "PositionHeadcount",
1727
- ],
1728
- };
1729
- preserveScrollPosition = false;
1730
- labelMap = {};
1731
- _fieldData = null;
1732
- cursorActivity = new EventEmitter();
1733
- focusChange = new EventEmitter();
1734
- scroll = new EventEmitter();
1735
- drop = new EventEmitter();
1736
- textChange = new EventEmitter();
1737
- ref;
1738
- fml;
1739
- value = "";
1740
- disabled = false;
1741
- isFocused = false;
1742
- codeMirror;
1743
- /**
1744
- * 存放匹配的变量集合
1745
- */
1746
- variableSearchList = [];
1747
- /**
1748
- * 存放匹配的函数集合
1749
- */
1750
- usageFunSearchList = [];
1751
- FormulaUsage = [];
1752
- /**
1753
- * 查询可用变量
1754
- */
1755
- _variableSearch = null;
1756
- /**
1757
- * 查询可用函数
1758
- */
1759
- _usageFunSearch = null;
1760
- /**
1761
- * 函数描述
1762
- */
1763
- usageDescription = `
1764
- <ul class="intro-wrapper default">
1765
- <li>从左侧面板选择字段名和函数,或输入函数</li>
1766
- <li>公式编辑举例:
1767
- <span class="formula-name">AVERAGE</span>
1768
- (
1769
- <span class="formula-field">语文成绩</span>
1770
- ,
1771
- <span class="formula-field">数学成绩</span>
1772
- )
1773
- </li>
1774
- </ul>
1775
- `;
1776
- _codeMirror;
1777
- _differ;
1778
- _options = {
1779
- autoCloseBrackets: true,
1780
- keywords: [],
1781
- textWrapping: true,
1782
- lineWrapping: true,
1783
- lineNumbers: false,
1784
- matchBrackets: true,
1785
- specialChars: /[\u0000-\u001f\u007f\u00ad\u200c-\u200f\u2028\u2029\ufeff]/,
1786
- mode: "text/fx-formula",
1787
- labelMap: null,
1788
- };
1789
- _fomulaContext;
1790
- /**
1791
- * 默认公式
1792
- */
1793
- defaultFml;
1794
- constructor(_differs, _ngZone, el, message, nzConfigService, fmlService) {
1795
- this._differs = _differs;
1796
- this._ngZone = _ngZone;
1797
- this.el = el;
1798
- this.message = message;
1799
- this.nzConfigService = nzConfigService;
1800
- this.fmlService = fmlService;
1801
- this.defaultFml = _.cloneDeep({
1802
- FormulaUsage: fmlService.FormulaUsage,
1803
- Formula: fmlService.Formula,
1804
- });
1805
- this.fml = fmlService;
1107
+ return this.sortSuggestions(suggestions, lineText);
1806
1108
  }
1807
- ngOnInit() {
1808
- this.nzConfigService.set("message", {
1809
- nzMaxStack: 1,
1810
- nzAnimate: false,
1811
- });
1109
+ getLineText(text, cursorPos) {
1110
+ const lines = text.substring(0, cursorPos).split('\n');
1111
+ return lines[lines.length - 1];
1812
1112
  }
1813
- /**
1814
- * 根据黑名单过滤公式
1815
- */
1816
- filterUsageByBlackList(formulaUsage) {
1817
- let FormulaUsageList = [];
1818
- formulaUsage.forEach((el) => {
1819
- el.contains.forEach((formula) => {
1820
- // 黑名单列表内的Index。
1821
- const blackIndex = _.indexOf(this.blacklist, formula.name);
1822
- if (blackIndex < 0) {
1823
- if (FormulaUsageList.findIndex((ele) => ele.category === el.category) >
1824
- -1) {
1825
- let index = FormulaUsageList.findIndex((ele) => ele.category === el.category);
1826
- FormulaUsageList[index].contains.push(formula);
1827
- }
1828
- else {
1829
- let item = {
1830
- category: el.category,
1831
- contains: [],
1832
- };
1833
- item.contains.push(formula);
1834
- FormulaUsageList.push(item);
1835
- }
1113
+ getFunctionSuggestions(lineText) {
1114
+ const suggestions = [];
1115
+ const functionMatch = lineText.match(/\b([A-Z][A-Z0-9_]*)$/i);
1116
+ const prefix = functionMatch ? functionMatch[1].toUpperCase() : '';
1117
+ if (this.formulaInstance.FormulaUsage) {
1118
+ this.formulaInstance.FormulaUsage.forEach((category) => {
1119
+ if (category.contains) {
1120
+ category.contains.forEach((func) => {
1121
+ if (!prefix || func.name.toUpperCase().startsWith(prefix)) {
1122
+ suggestions.push({
1123
+ text: func.name,
1124
+ displayText: `${func.name}()`,
1125
+ className: 'cm-function',
1126
+ type: 'function',
1127
+ description: func.intro,
1128
+ usage: func.usage,
1129
+ category: category.category
1130
+ });
1131
+ }
1132
+ });
1836
1133
  }
1837
1134
  });
1838
- });
1839
- return FormulaUsageList;
1840
- }
1841
- /**
1842
- * 组装显示的函数
1843
- */
1844
- resolveDisplayFormula() {
1845
- let displayFormula = [];
1846
- if (this.showList) {
1847
- return _.cloneDeep(this.showList);
1848
1135
  }
1849
- if (this.type && !_.isEmpty(this.type)) {
1850
- displayFormula = this.typeList[this.type];
1851
- return displayFormula || [];
1852
- }
1853
- /**
1854
- * this.categorys 显示的函数组
1855
- * 与this.type 互斥,this.type优先级最高。
1856
- */
1857
- if (this.categorys && Array.isArray(this.categorys)) {
1858
- // 显示函数组数组转对象
1859
- const displayCategory = _.keyBy(this.categorys, function (o) {
1860
- return o;
1861
- });
1862
- // 过滤出需显示的函数
1863
- this.globalCategorys.map((c) => {
1864
- if (c.items && displayCategory[c.code]) {
1865
- displayFormula = displayFormula.concat(c.items);
1136
+ return suggestions;
1137
+ }
1138
+ getVariableSuggestions(lineText, availableVariables) {
1139
+ const suggestions = [];
1140
+ // 检测是否在输入变量
1141
+ if (lineText.includes('$') || lineText.includes('{')) {
1142
+ availableVariables.forEach(variable => {
1143
+ if (variable.key && variable.label) {
1144
+ suggestions.push({
1145
+ text: variable.key,
1146
+ displayText: variable.label,
1147
+ className: 'cm-variable',
1148
+ type: 'variable',
1149
+ description: variable.description || ''
1150
+ });
1866
1151
  }
1867
1152
  });
1868
1153
  }
1869
- return displayFormula || [];
1154
+ return suggestions;
1870
1155
  }
1871
- /**
1872
- * 组装FomulaContext
1873
- */
1874
- resolveFomulaContext() {
1875
- const fomlaArray = [];
1876
- if (!this.FormulaUsage) {
1877
- return fomlaArray;
1878
- }
1879
- this.FormulaUsage.map((usage) => {
1880
- const contains = _.flatMap(usage.contains, function (c) {
1881
- return c.name;
1882
- });
1883
- fomlaArray.push(...contains);
1156
+ sortSuggestions(suggestions, currentText) {
1157
+ return suggestions.sort((a, b) => {
1158
+ const currentLower = currentText.toLowerCase();
1159
+ const aLower = a.text.toLowerCase();
1160
+ const bLower = b.text.toLowerCase();
1161
+ // 精确匹配优先
1162
+ if (aLower === currentLower)
1163
+ return -1;
1164
+ if (bLower === currentLower)
1165
+ return 1;
1166
+ // 开头匹配优先
1167
+ const aStartsWith = aLower.startsWith(currentLower);
1168
+ const bStartsWith = bLower.startsWith(currentLower);
1169
+ if (aStartsWith && !bStartsWith)
1170
+ return -1;
1171
+ if (!aStartsWith && bStartsWith)
1172
+ return 1;
1173
+ // 包含匹配
1174
+ const aContains = aLower.includes(currentLower);
1175
+ const bContains = bLower.includes(currentLower);
1176
+ if (aContains && !bContains)
1177
+ return -1;
1178
+ if (!aContains && bContains)
1179
+ return 1;
1180
+ // 按字母顺序
1181
+ return a.text.localeCompare(b.text);
1884
1182
  });
1885
- this._fomulaContext = fomlaArray;
1886
- return fomlaArray;
1887
1183
  }
1888
- /**
1889
- * 组装 this.FormulaUsage
1890
- */
1891
- setFormulaUsage() {
1892
- var FormulaUsage = _.cloneDeep(this.fml.FormulaUsage);
1893
- this.FormulaUsage = FormulaUsage;
1894
- }
1895
- ngAfterViewInit() {
1896
- this.setFormulaUsage();
1897
- if (!this.ref) {
1184
+ }
1185
+ /**
1186
+ * 公式高亮器
1187
+ */
1188
+ let FormulaHighlighter$1 = class FormulaHighlighter {
1189
+ static highlightErrors(codeMirror, errors) {
1190
+ if (!codeMirror)
1898
1191
  return;
1899
- }
1900
- this._ngZone.runOutsideAngular(() => {
1901
- this.codeMirror = this.codeMirrorGlobal.fromTextArea(this.ref.nativeElement, this._options);
1902
- this.codeMirror.on("cursorActivity", (cm) => this._ngZone.run(() => this.cursorActive(cm)));
1903
- this.codeMirror.on("scroll", this.scrollChanged.bind(this));
1904
- this.codeMirror.on("blur", () => this._ngZone.run(() => this.focusChanged(false)));
1905
- this.codeMirror.on("focus", () => this._ngZone.run(() => this.focusChanged(true)));
1906
- this.codeMirror.on("change", (cm, change) => {
1907
- this._ngZone.run(() => this.codemirrorValueChanged(cm, change));
1908
- });
1909
- this.codeMirror.on("drop", (cm, e) => {
1910
- this._ngZone.run(() => this.dropFiles(cm, e));
1911
- });
1912
- this.codeMirror.setValue(this.value);
1913
- CodeMirror.fomulaContext = Object.keys(this.fml.Formula);
1914
- this.codeMirror.setOption("mode", "text/fx-formula");
1192
+ // 清除之前的高亮
1193
+ this.clearHighlights(codeMirror);
1194
+ errors.forEach((error) => {
1195
+ if (error.line !== undefined && error.column !== undefined) {
1196
+ const from = CodeMirror__default.Pos(error.line, error.column);
1197
+ const to = CodeMirror__default.Pos(error.endLine || error.line, error.endColumn || error.column + 1);
1198
+ // 添加错误高亮
1199
+ codeMirror.markText(from, to, {
1200
+ className: 'formula-error-highlight',
1201
+ title: error.message
1202
+ });
1203
+ // 添加错误线标记
1204
+ const lineHandle = codeMirror.getLineHandle(error.line);
1205
+ if (lineHandle) {
1206
+ codeMirror.addLineClass(lineHandle, 'wrap', 'formula-error-line');
1207
+ }
1208
+ }
1915
1209
  });
1916
1210
  }
1917
- ngOnChanges(changes) {
1918
- if (changes && changes["formulaClass"]) {
1919
- const change = changes["formulaClass"];
1920
- if (change && (change.currentValue || change.previousValue)) {
1921
- this.setFormulaClass(change.currentValue);
1922
- this.setFormulaUsage();
1211
+ static clearHighlights(codeMirror) {
1212
+ if (!codeMirror)
1213
+ return;
1214
+ // 清除所有标记
1215
+ codeMirror.getAllMarks().forEach((mark) => mark.clear());
1216
+ // 清除所有行类
1217
+ for (let i = 0; i < codeMirror.lineCount(); i++) {
1218
+ const lineHandle = codeMirror.getLineHandle(i);
1219
+ if (lineHandle) {
1220
+ codeMirror.removeLineClass(lineHandle, 'wrap', 'formula-error-line');
1923
1221
  }
1924
1222
  }
1925
1223
  }
1926
- ngDoCheck() {
1927
- if (!this._differ) {
1224
+ static highlightVariable(codeMirror, variable, label) {
1225
+ if (!codeMirror)
1928
1226
  return;
1929
- }
1930
- const changes = this._differ.diff(this._options);
1931
- if (changes) {
1932
- changes.forEachChangedItem((option) => this.setOptionIfChanged(option.key, option.currentValue));
1933
- changes.forEachAddedItem((option) => this.setOptionIfChanged(option.key, option.currentValue));
1934
- changes.forEachRemovedItem((option) => this.setOptionIfChanged(option.key, option.currentValue));
1227
+ const content = codeMirror.getValue();
1228
+ const escapedVariable = variable.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1229
+ const regex = new RegExp(`\\$\\{${escapedVariable}\\}`, 'g');
1230
+ let match;
1231
+ while ((match = regex.exec(content)) !== null) {
1232
+ const from = codeMirror.posFromIndex(match.index);
1233
+ const to = codeMirror.posFromIndex(match.index + match[0].length);
1234
+ codeMirror.markText(from, to, {
1235
+ className: 'formula-variable-highlight',
1236
+ title: label
1237
+ });
1935
1238
  }
1936
1239
  }
1937
- ngOnDestroy() {
1938
- if (this.codeMirror) {
1939
- this.codeMirror.toTextArea();
1240
+ };
1241
+
1242
+ // 原有的搜索函数(保持不变)
1243
+ function searchUsageFun(value, formulaList) {
1244
+ let result = [];
1245
+ if (!value || value.trim() === '' || !formulaList || formulaList.length === 0) {
1246
+ return result;
1247
+ }
1248
+ const searchText = value.toLowerCase();
1249
+ formulaList.forEach(category => {
1250
+ if (category && category.contains) {
1251
+ category.contains.forEach((fun) => {
1252
+ if (fun.name.toLowerCase().includes(searchText) ||
1253
+ fun.intro.toLowerCase().includes(searchText)) {
1254
+ result.push(fun);
1255
+ }
1256
+ });
1940
1257
  }
1258
+ });
1259
+ return result;
1260
+ }
1261
+ // 原有的搜索变量函数(保持不变)
1262
+ function searchVariable(value, fieldData) {
1263
+ let result = [];
1264
+ if (!value || value.trim() === '' || !fieldData) {
1265
+ return result;
1941
1266
  }
1942
- /**
1943
- * set FormulaClass
1944
- * @param formulaCalss
1945
- */
1946
- setFormulaClass(formulaCalss) {
1947
- const fml = new formulaCalss(this.fml);
1948
- const { FormulaUsage, Formula } = fml;
1949
- if (Formula) {
1950
- this._ngZone.runOutsideAngular(() => {
1951
- Object.keys(Formula).forEach((key) => {
1952
- this.fml.Formula[key] = Formula[key].bind(this.fml);
1267
+ const searchText = value.toLowerCase();
1268
+ function searchFields(fields, prefix = '') {
1269
+ if (!fields || !Array.isArray(fields))
1270
+ return;
1271
+ fields.forEach(field => {
1272
+ const fullPath = prefix ? `${prefix}.${field.name || field.label}` : (field.name || field.label);
1273
+ if (field.label && field.label.toLowerCase().includes(searchText)) {
1274
+ result.push({
1275
+ ...field,
1276
+ fullPath
1953
1277
  });
1954
- // CodeMirror.fomulaContext = this.resolveFomulaContext();
1955
- CodeMirror.fomulaContext = Object.keys(this.fml.Formula);
1278
+ }
1279
+ if (field.items && Array.isArray(field.items)) {
1280
+ searchFields(field.items, fullPath);
1281
+ }
1282
+ if (field.subform && field.subform.items) {
1283
+ searchFields(field.subform.items, fullPath);
1284
+ }
1285
+ });
1286
+ }
1287
+ if (Array.isArray(fieldData)) {
1288
+ searchFields(fieldData);
1289
+ }
1290
+ else if (typeof fieldData === 'object') {
1291
+ const fieldsArray = Object.keys(fieldData).map(key => ({
1292
+ ...fieldData[key],
1293
+ name: key
1294
+ }));
1295
+ searchFields(fieldsArray);
1296
+ }
1297
+ return result;
1298
+ }
1299
+ // 原有的搜索数组变量函数(保持不变)
1300
+ function searchArrayVariable(value, fieldDataArray) {
1301
+ let result = [];
1302
+ if (!value || value.trim() === '' || !fieldDataArray || !Array.isArray(fieldDataArray)) {
1303
+ return result;
1304
+ }
1305
+ const searchText = value.toLowerCase();
1306
+ fieldDataArray.forEach(item => {
1307
+ if (item && item.listField && Array.isArray(item.listField)) {
1308
+ item.listField.forEach((field) => {
1309
+ if (field.label && field.label.toLowerCase().includes(searchText)) {
1310
+ result.push({
1311
+ ...field,
1312
+ group: item.label
1313
+ });
1314
+ }
1956
1315
  });
1957
1316
  }
1958
- if (FormulaUsage) {
1959
- const oldIndexs = {};
1960
- this.fml.FormulaUsage.forEach((category, index) => {
1961
- oldIndexs[category.categoryCode] = index;
1962
- });
1963
- const newCategorys = {};
1964
- FormulaUsage.forEach((category) => {
1965
- newCategorys[category.categoryCode] = category;
1966
- });
1967
- Object.keys(newCategorys).forEach((categoryCode) => {
1968
- const oldIndex = _.get(oldIndexs, categoryCode, undefined);
1969
- const newCategory = newCategorys[categoryCode];
1970
- if (undefined === oldIndex) {
1971
- // 新增分类
1972
- this.fml.FormulaUsage.push(newCategorys[categoryCode]);
1317
+ });
1318
+ return result;
1319
+ }
1320
+ /**
1321
+ * 增强的公式验证器
1322
+ */
1323
+ class FormulaValidator {
1324
+ static validateSyntax(formula) {
1325
+ const errors = [];
1326
+ // 检查括号匹配
1327
+ const stack = [];
1328
+ for (let i = 0; i < formula.length; i++) {
1329
+ if (formula[i] === '(') {
1330
+ stack.push(i);
1331
+ }
1332
+ else if (formula[i] === ')') {
1333
+ if (stack.length === 0) {
1334
+ errors.push({
1335
+ message: '多余的右括号',
1336
+ severity: 'error',
1337
+ column: i,
1338
+ type: 'syntax'
1339
+ });
1973
1340
  }
1974
1341
  else {
1975
- // 已有分类 添加新函数
1976
- let oldContains = this.fml.FormulaUsage[oldIndex].contains;
1977
- oldContains = oldContains.concat(newCategory.contains);
1978
- oldContains.reverse();
1979
- _.uniqWith(oldContains, (a, b) => {
1980
- return a.name === b.name;
1981
- });
1982
- this.fml.FormulaUsage[oldIndex].contains = oldContains.reverse();
1342
+ stack.pop();
1983
1343
  }
1984
- });
1344
+ }
1985
1345
  }
1986
- }
1987
- codemirrorValueChanged(cm, change) {
1988
- if (change.origin !== "complete") {
1989
- cm.showHint({
1990
- hint: CodeMirror.hint.formula,
1991
- completeSingle: false,
1992
- shown: function () { },
1993
- select: function (cpt, ele) { },
1994
- pick: function (item) { },
1346
+ stack.forEach(pos => {
1347
+ errors.push({
1348
+ message: '缺少右括号',
1349
+ severity: 'error',
1350
+ column: pos,
1351
+ type: 'syntax'
1995
1352
  });
1353
+ });
1354
+ // 检查引号匹配
1355
+ let inString = false;
1356
+ let quoteChar = '';
1357
+ for (let i = 0; i < formula.length; i++) {
1358
+ const char = formula[i];
1359
+ if ((char === '"' || char === "'") && (i === 0 || formula[i - 1] !== '\\')) {
1360
+ if (!inString) {
1361
+ inString = true;
1362
+ quoteChar = char;
1363
+ }
1364
+ else if (char === quoteChar) {
1365
+ inString = false;
1366
+ }
1367
+ }
1996
1368
  }
1997
- else {
1998
- this.insertBarcket();
1369
+ if (inString) {
1370
+ errors.push({
1371
+ message: '字符串未闭合',
1372
+ severity: 'error',
1373
+ type: 'syntax'
1374
+ });
1999
1375
  }
2000
- setTimeout(() => {
2001
- this.getValue();
2002
- }, 0);
1376
+ return errors;
2003
1377
  }
2004
- setOptionIfChanged(optionName, newValue) {
2005
- if (!this.codeMirror) {
2006
- return;
1378
+ static validateSemantics(formula, availableFunctions) {
1379
+ const errors = [];
1380
+ const warnings = [];
1381
+ // 提取所有函数名
1382
+ const functionRegex = /\b([A-Z][A-Z0-9_]*)\s*\(/gi;
1383
+ let match;
1384
+ const foundFunctions = new Set();
1385
+ while ((match = functionRegex.exec(formula)) !== null) {
1386
+ const funcName = match[1].toUpperCase();
1387
+ foundFunctions.add(funcName);
1388
+ // 检查函数是否存在
1389
+ if (!availableFunctions.includes(funcName)) {
1390
+ errors.push({
1391
+ message: `未知函数: ${funcName}`,
1392
+ severity: 'error',
1393
+ type: 'semantic'
1394
+ });
1395
+ }
2007
1396
  }
2008
- this.codeMirror.setOption(optionName, newValue);
2009
- }
2010
- focusChanged(focused) {
2011
- this.onTouched();
2012
- this.isFocused = focused;
2013
- // CodeMirror.fomulaContext = this._fomulaContext;
2014
- this.focusChange.emit(focused);
1397
+ // 检查函数参数
1398
+ const paramRegex = /,\s*,/g;
1399
+ if (paramRegex.test(formula)) {
1400
+ warnings.push({
1401
+ message: '函数参数格式可能有误',
1402
+ severity: 'warning',
1403
+ type: 'semantic'
1404
+ });
1405
+ }
1406
+ return [...errors, ...warnings];
2015
1407
  }
2016
- scrollChanged(cm) {
2017
- this.scroll.emit(cm.getScrollInfo());
1408
+ static validateFormula(formula, availableFunctions) {
1409
+ const syntaxErrors = this.validateSyntax(formula);
1410
+ const semanticErrors = this.validateSemantics(formula, availableFunctions);
1411
+ const errors = [...syntaxErrors, ...semanticErrors].filter(e => e.severity === 'error');
1412
+ const warnings = [...syntaxErrors, ...semanticErrors].filter(e => e.severity === 'warning');
1413
+ return {
1414
+ isValid: errors.length === 0,
1415
+ errors,
1416
+ warnings
1417
+ };
2018
1418
  }
2019
- cursorActive(cm) {
2020
- this.cursorActivity.emit(cm);
1419
+ }
1420
+ /**
1421
+ * 增强的智能提示服务
1422
+ */
1423
+ class SmartSuggestionService {
1424
+ static getSuggestions(text, cursorPos, formulaList, fieldData, searchType = 'all') {
1425
+ const suggestions = [];
1426
+ const lineText = this.getLineText(text, cursorPos);
1427
+ if (searchType === 'variable' || searchType === 'all') {
1428
+ suggestions.push(...this.getVariableSuggestions(lineText, fieldData));
1429
+ }
1430
+ if (searchType === 'function' || searchType === 'all') {
1431
+ suggestions.push(...this.getFunctionSuggestions(lineText, formulaList));
1432
+ }
1433
+ return this.sortSuggestions(suggestions, lineText);
2021
1434
  }
2022
- dropFiles(cm, e) {
2023
- this.drop.emit([cm, e]);
1435
+ static getLineText(text, cursorPos) {
1436
+ const lines = text.substring(0, cursorPos).split('\n');
1437
+ return lines[lines.length - 1];
2024
1438
  }
2025
- writeValue(value) {
2026
- if (value === null || value === undefined) {
2027
- if (this.codeMirror) {
2028
- this.codeMirror.setValue("");
2029
- }
2030
- return;
1439
+ static getVariableSuggestions(lineText, fieldData) {
1440
+ const suggestions = [];
1441
+ // 检测是否在输入变量
1442
+ if (lineText.includes('$') || lineText.includes('{')) {
1443
+ // 使用原有的搜索函数
1444
+ const variableResults = searchVariable('', fieldData);
1445
+ variableResults.forEach(variable => {
1446
+ suggestions.push({
1447
+ text: `\${${variable.key}}`,
1448
+ displayText: variable.label,
1449
+ className: 'cm-variable',
1450
+ type: 'variable',
1451
+ description: variable.description || ''
1452
+ });
1453
+ });
2031
1454
  }
2032
- this.value = value;
2033
- this.setValue();
1455
+ return suggestions;
2034
1456
  }
2035
- registerOnChange(fn) {
2036
- this.onChange = fn;
2037
- }
2038
- registerOnTouched(fn) {
2039
- this.onTouched = fn;
1457
+ static getFunctionSuggestions(lineText, formulaList) {
1458
+ const suggestions = [];
1459
+ // 提取当前输入的函数前缀
1460
+ const functionMatch = lineText.match(/\b([A-Z][A-Z0-9_]*)$/i);
1461
+ const prefix = functionMatch ? functionMatch[1].toUpperCase() : '';
1462
+ formulaList.forEach(category => {
1463
+ if (category && category.contains) {
1464
+ category.contains.forEach((func) => {
1465
+ if (!prefix || func.name.toUpperCase().startsWith(prefix)) {
1466
+ suggestions.push({
1467
+ text: func.name,
1468
+ displayText: `${func.name}()`,
1469
+ className: 'cm-function',
1470
+ type: 'function',
1471
+ description: func.intro,
1472
+ usage: func.usage,
1473
+ category: category.category
1474
+ });
1475
+ }
1476
+ });
1477
+ }
1478
+ });
1479
+ return suggestions;
2040
1480
  }
2041
- setDisabledState(isDisabled) {
2042
- this.disabled = isDisabled;
2043
- this.setOptionIfChanged("readOnly", this.disabled);
1481
+ static sortSuggestions(suggestions, currentText) {
1482
+ return suggestions.sort((a, b) => {
1483
+ // 精确匹配优先
1484
+ if (a.text.toLowerCase() === currentText.toLowerCase())
1485
+ return -1;
1486
+ if (b.text.toLowerCase() === currentText.toLowerCase())
1487
+ return 1;
1488
+ // 开头匹配优先
1489
+ const aStartsWith = a.text.toLowerCase().startsWith(currentText.toLowerCase());
1490
+ const bStartsWith = b.text.toLowerCase().startsWith(currentText.toLowerCase());
1491
+ if (aStartsWith && !bStartsWith)
1492
+ return -1;
1493
+ if (!aStartsWith && bStartsWith)
1494
+ return 1;
1495
+ // 包含匹配
1496
+ const aContains = a.text.toLowerCase().includes(currentText.toLowerCase());
1497
+ const bContains = b.text.toLowerCase().includes(currentText.toLowerCase());
1498
+ if (aContains && !bContains)
1499
+ return -1;
1500
+ if (!aContains && bContains)
1501
+ return 1;
1502
+ // 按字母顺序
1503
+ return a.text.localeCompare(b.text);
1504
+ });
2044
1505
  }
2045
- /**
2046
- * 函数鼠标滑动时事件
2047
- * @param e
2048
- */
2049
- usageMouseover(e) {
2050
- let usage = e.usage ? `<li class="usage"> 用法:${e.usage} </li>` : "";
2051
- this.usageDescription = `
2052
- <div class="formula-title">${e.name}</div>
2053
- <ul class="intro-wrapper">
2054
- <li class="intro">
2055
- ${e.intro}
2056
- </li>
2057
- ${usage}
2058
- <li class="example">示例:${e.example}</li>
2059
- </ul>
2060
- `;
1506
+ }
1507
+ /**
1508
+ * 公式高亮服务
1509
+ */
1510
+ class FormulaHighlighter {
1511
+ static highlightErrors(codeMirror, errors) {
1512
+ // 清除之前的高亮
1513
+ this.clearHighlights(codeMirror);
1514
+ errors.forEach((error) => {
1515
+ if (error.line !== undefined && error.column !== undefined) {
1516
+ const from = { line: error.line, ch: error.column };
1517
+ const to = {
1518
+ line: error.endLine || error.line,
1519
+ ch: error.endColumn || error.column + 1
1520
+ };
1521
+ // 添加错误高亮
1522
+ codeMirror.markText(from, to, {
1523
+ className: 'formula-error-highlight',
1524
+ title: error.message
1525
+ });
1526
+ // 添加错误线标记
1527
+ const lineHandle = codeMirror.getLineHandle(error.line);
1528
+ if (lineHandle) {
1529
+ codeMirror.addLineClass(lineHandle, 'wrap', 'formula-error-line');
1530
+ }
1531
+ }
1532
+ });
2061
1533
  }
2062
- /**
2063
- * 插入函数
2064
- * @param e
2065
- */
2066
- insertUsageFun(e) {
2067
- if (this.codeMirror && this.codeMirror !== null) {
2068
- let c = this.codeMirror.getCursor();
2069
- this.codeMirror.replaceSelection(`${e.name}`);
2070
- let d = this.codeMirror.getCursor();
2071
- this.insertBarcket();
2072
- this.getValue();
1534
+ static clearHighlights(codeMirror) {
1535
+ // 清除所有标记
1536
+ codeMirror.getAllMarks().forEach((mark) => mark.clear());
1537
+ // 清除所有行类
1538
+ for (let i = 0; i < codeMirror.lineCount(); i++) {
1539
+ const lineHandle = codeMirror.getLineHandle(i);
1540
+ if (lineHandle) {
1541
+ codeMirror.removeLineClass(lineHandle, 'wrap', 'formula-error-line');
1542
+ }
2073
1543
  }
2074
1544
  }
2075
- /**
2076
- * 插入可用变量
2077
- * @param event
2078
- */
2079
- insertField(event) {
2080
- if (this.codeMirror && this.codeMirror !== null) {
2081
- let c = this.codeMirror.getCursor();
2082
- this.codeMirror.replaceSelection("" + event.label + "");
2083
- let d = this.codeMirror.getCursor();
2084
- let e = {
2085
- from: c,
2086
- to: d,
2087
- key: '$' + `{${event.key}}`, // 工作项ID
2088
- label: event.label,
2089
- };
2090
- this.markField(e);
2091
- this.codeMirror.focus();
2092
- this.getValue();
1545
+ static highlightVariable(codeMirror, variable, label) {
1546
+ const content = codeMirror.getValue();
1547
+ const regex = new RegExp(`\\$\\{${variable}\\}`, 'g');
1548
+ let match;
1549
+ while ((match = regex.exec(content)) !== null) {
1550
+ const from = codeMirror.posFromIndex(match.index);
1551
+ const to = codeMirror.posFromIndex(match.index + match[0].length);
1552
+ codeMirror.markText(from, to, {
1553
+ className: 'formula-variable-highlight',
1554
+ title: label
1555
+ });
2093
1556
  }
2094
1557
  }
2095
- /**
2096
- * 复制
2097
- */
2098
- btnCopy() {
2099
- if (!!`${this.value}`) {
2100
- let value = _.cloneDeep(this.value).replace("↵", "");
2101
- localStorage.setItem("codemirror", value);
2102
- this.message.success(`复制成功`);
1558
+ }
1559
+
1560
+ class GramCodemirrorComponent {
1561
+ el;
1562
+ msg;
1563
+ cdr;
1564
+ formula;
1565
+ ref;
1566
+ title = '';
1567
+ name = 'formula';
1568
+ autoFocus = false;
1569
+ fieldData = [];
1570
+ options = {};
1571
+ validationResult = new EventEmitter();
1572
+ codeMirror;
1573
+ value = '';
1574
+ disabled = false;
1575
+ FormulaUsage = [];
1576
+ usageDescription = '';
1577
+ suggestions = [];
1578
+ showSuggestionBox = false;
1579
+ selectedSuggestionIndex = 0;
1580
+ fieldLabelMap = new Map();
1581
+ labelKeyMap = new Map();
1582
+ showVariableLabels = true;
1583
+ variableMarkers = [];
1584
+ // ===== 查询 =====
1585
+ _variableSearch = null;
1586
+ variableSearchList = [];
1587
+ _usageFunSearch = null;
1588
+ usageFunSearchList = [];
1589
+ set variableSearch(value) {
1590
+ if ("array" === this.dateType) {
1591
+ this.variableSearchList = searchArrayVariable(value, this.fieldData);
2103
1592
  }
2104
1593
  else {
2105
- this.message.warning(`公式为空,请配置公式后复制`);
1594
+ this.variableSearchList = searchVariable(value, this.fieldData);
2106
1595
  }
1596
+ this._variableSearch = value;
2107
1597
  }
2108
- /**
2109
- * 粘贴
2110
- */
2111
- btnPaste() {
2112
- if (!!localStorage.getItem("codemirror")) {
2113
- if (!this.value) {
2114
- this.value = localStorage.getItem("codemirror");
2115
- }
2116
- else {
2117
- this.value = `${this.value}${localStorage.getItem("codemirror")}`;
2118
- }
2119
- this.setValue();
2120
- this.message.success(`粘贴成功`);
2121
- }
2122
- else {
2123
- this.message.warning(`没有需要粘贴的数据,请先复制`);
2124
- }
1598
+ get variableSearch() { return this._variableSearch; }
1599
+ set usageFunSearch(value) {
1600
+ this.usageFunSearchList = searchUsageFun(value, this.FormulaUsage);
1601
+ this._usageFunSearch = value;
2125
1602
  }
2126
- /**
2127
- * 清空
2128
- */
2129
- btnClear() {
2130
- this.value = null;
2131
- if (this.codeMirror) {
2132
- this.codeMirror.setValue("");
2133
- }
2134
- this.message.success(`清空成功`);
1603
+ get usageFunSearch() { return this._usageFunSearch; }
1604
+ get dateType() {
1605
+ return Array.isArray(this.fieldData) ? "array" : "object";
2135
1606
  }
2136
- onChange = (_) => { };
2137
- onTouched = () => { };
2138
- markField(e) {
2139
- if (this.codeMirror && this.codeMirror !== null) {
2140
- let node = document.createElement("span");
2141
- node.innerHTML = e.label;
2142
- node.className = "cm-field cm-field-value";
2143
- node.setAttribute("field-key", e.key);
2144
- this.codeMirror.markText(e.from, e.to, {
2145
- handleMouseEvents: !0,
2146
- atomic: !0,
2147
- replacedWith: node,
2148
- });
2149
- let d = this.codeMirror.getCursor();
2150
- }
1607
+ constructor(el, msg, cdr, formula) {
1608
+ this.el = el;
1609
+ this.msg = msg;
1610
+ this.cdr = cdr;
1611
+ this.formula = formula;
2151
1612
  }
2152
- insertBarcket() {
2153
- if (this.codeMirror && this.codeMirror !== null) {
2154
- let c = this.codeMirror.getCursor();
2155
- this.codeMirror.replaceSelection("(");
2156
- let d = this.codeMirror.getCursor();
2157
- let c1 = this.codeMirror.getCursor();
2158
- this.codeMirror.replaceSelection(")");
2159
- let d1 = this.codeMirror.getCursor();
2160
- this.codeMirror.setCursor(d);
2161
- this.codeMirror.focus();
2162
- }
1613
+ ngOnInit() {
1614
+ this.FormulaUsage = _.cloneDeep(this.formula.FormulaUsage);
1615
+ this.buildVariableMap();
2163
1616
  }
2164
- getValue() {
2165
- let result = [];
2166
- let codeContent = this.el.nativeElement.querySelectorAll(".CodeMirror-line");
2167
- this.fml.Utils.forEach(codeContent, (t, e) => {
2168
- this.fml.Utils.forEach(e.children, (t1, e1) => {
2169
- this.fml.Utils.forEach(e1.children, (t2, e2) => {
2170
- if (e2.getAttribute("cm-text") !== undefined &&
2171
- e2.getAttribute("cm-text") !== null) {
2172
- result.push("↵");
1617
+ ngAfterViewInit() {
1618
+ this.defineMode();
1619
+ this.initEditor();
1620
+ }
1621
+ ngOnDestroy() {
1622
+ this.codeMirror?.toTextArea();
1623
+ }
1624
+ // ===== 工具方法 =====
1625
+ escapeRegExp(str) {
1626
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1627
+ }
1628
+ // ===== Variable Map =====
1629
+ buildVariableMap() {
1630
+ this.fieldData?.forEach(g => g.listField?.forEach((f) => {
1631
+ const key = `\${${f.key}}`;
1632
+ this.fieldLabelMap.set(key, f.label);
1633
+ this.labelKeyMap.set(f.label, key);
1634
+ }));
1635
+ }
1636
+ displayToFormula(text) {
1637
+ let result = text;
1638
+ this.labelKeyMap.forEach((key, label) => {
1639
+ const escapedLabel = this.escapeRegExp(label);
1640
+ result = result.replace(new RegExp(escapedLabel, 'g'), key);
1641
+ });
1642
+ return result;
1643
+ }
1644
+ formulaToDisplay(text) {
1645
+ let result = text;
1646
+ this.fieldLabelMap.forEach((label, key) => {
1647
+ const escapedKey = this.escapeRegExp(key);
1648
+ result = result.replace(new RegExp(escapedKey, 'g'), label);
1649
+ });
1650
+ return result;
1651
+ }
1652
+ // ===== CodeMirror =====
1653
+ defineMode() {
1654
+ const self = this; // 保留 this 引用
1655
+ CodeMirror.defineMode('fx-formula', () => ({
1656
+ token: (stream) => {
1657
+ if (stream.eatSpace())
1658
+ return null;
1659
+ // 1. 匹配 ${xxx} 变量
1660
+ if (stream.match(/\$\{[^}]+\}/))
1661
+ return 'variable';
1662
+ // 2. 匹配标签变量(中文/字母/数字/下划线)
1663
+ if (stream.match(/[^\s\(\)\+\-\*\/%,]+/)) {
1664
+ const word = stream.current();
1665
+ if (self.labelKeyMap.has(word) || Array.from(self.labelKeyMap.values()).includes(word)) {
1666
+ return 'variable'; // 标签变量高亮
2173
1667
  }
2174
1668
  else {
2175
- if (e2.className === "CodeMirror-widget") {
2176
- this.fml.Utils.forEach(e2.children, (t3, e3) => {
2177
- if (e3.getAttribute("field-key") !== undefined &&
2178
- e3.getAttribute("field-key") !== null) {
2179
- result.push(e3.getAttribute("field-key"));
2180
- }
2181
- else {
2182
- result.push(e3.innerText);
2183
- }
2184
- });
2185
- }
2186
- else {
2187
- result.push(e2.innerText);
2188
- }
1669
+ return 'function'; // 函数名
2189
1670
  }
2190
- });
2191
- });
2192
- });
2193
- if (result[0] === "↵") {
2194
- result.splice(0, 1);
2195
- }
2196
- this.value = result.join("");
2197
- if (this.codeMirror) {
2198
- this.textChange.emit(this.codeMirror.getValue());
1671
+ }
1672
+ // 3. 括号或运算符
1673
+ if (stream.match(/[\(\)\+\-\*\/%,]/))
1674
+ return 'operator';
1675
+ // 4. 跳过一个字符
1676
+ stream.next();
1677
+ return null;
1678
+ }
1679
+ }));
1680
+ }
1681
+ // private initEditor() {
1682
+ // this.codeMirror = CodeMirror.fromTextArea(this.ref.nativeElement, {
1683
+ // mode: 'fx-formula',
1684
+ // lineWrapping: true,
1685
+ // matchBrackets: true,
1686
+ // extraKeys: {
1687
+ // 'Ctrl-Space': () => this.updateSuggestions(),
1688
+ // Enter: () => this.applySuggestion()
1689
+ // }
1690
+ // });
1691
+ // this.codeMirror.on('change', () => this.onEditorChange());
1692
+ // if (this.autoFocus) setTimeout(() => this.codeMirror.focus(), 100);
1693
+ // }
1694
+ initEditor() {
1695
+ const defaultOptions = {
1696
+ mode: 'fx-formula', // 始终使用自定义公式 mode
1697
+ lineWrapping: true,
1698
+ matchBrackets: true,
1699
+ lineNumbers: false,
1700
+ extraKeys: {
1701
+ 'Ctrl-Space': () => this.updateSuggestions(),
1702
+ Enter: () => this.applySuggestion()
1703
+ }
1704
+ };
1705
+ const finalOptions = {
1706
+ ...defaultOptions,
1707
+ ...this.options,
1708
+ mode: 'fx-formula'
1709
+ };
1710
+ this.codeMirror = CodeMirror.fromTextArea(this.ref.nativeElement, finalOptions);
1711
+ this.codeMirror.on('change', () => this.onEditorChange());
1712
+ if (this.autoFocus) {
1713
+ setTimeout(() => this.codeMirror.focus(), 100);
2199
1714
  }
1715
+ }
1716
+ onEditorChange() {
1717
+ const display = this.codeMirror.getValue();
1718
+ this.value = this.showVariableLabels
1719
+ ? this.displayToFormula(display)
1720
+ : display;
2200
1721
  this.onChange(this.value);
1722
+ this.updateSuggestions();
1723
+ this.highlightVariables();
1724
+ }
1725
+ highlightVariables() {
1726
+ if (!this.codeMirror)
1727
+ return;
1728
+ // 清除原来的标记
1729
+ this.variableMarkers.forEach(m => m.clear());
1730
+ this.variableMarkers = [];
1731
+ const text = this.codeMirror.getValue();
1732
+ this.fieldLabelMap.forEach((label, key) => {
1733
+ const escapedKey = this.escapeRegExp(this.showVariableLabels ? label : key);
1734
+ const regex = new RegExp(escapedKey, 'g');
1735
+ let match;
1736
+ while ((match = regex.exec(text)) !== null) {
1737
+ const from = this.codeMirror.posFromIndex(match.index);
1738
+ const to = this.codeMirror.posFromIndex(match.index + match[0].length);
1739
+ const marker = this.codeMirror.markText(from, to, {
1740
+ className: 'formula-variable-highlight',
1741
+ title: `${label} (${key})`
1742
+ });
1743
+ this.variableMarkers.push(marker);
1744
+ }
1745
+ });
1746
+ }
1747
+ // ===== Insert =====
1748
+ insertField(f) {
1749
+ const text = this.showVariableLabels ? f.label : `\${${f.key}}`;
1750
+ const cursor = this.codeMirror.getCursor();
1751
+ const prevChar = this.codeMirror.getRange({ line: cursor.line, ch: cursor.ch - 1 }, cursor);
1752
+ const nextChar = this.codeMirror.getRange(cursor, { line: cursor.line, ch: cursor.ch + 1 });
1753
+ let insertText = text;
1754
+ if (prevChar && !/\s|[\(\)\+\-\*\/%,]/.test(prevChar))
1755
+ insertText = ' ' + insertText;
1756
+ if (nextChar && !/\s|[\(\)\+\-\*\/%,]/.test(nextChar))
1757
+ insertText += ' ';
1758
+ this.codeMirror.replaceSelection(insertText);
1759
+ }
1760
+ insertUsageFun(f) {
1761
+ const text = `${f.name}()`;
1762
+ const cursor = this.codeMirror.getCursor();
1763
+ const prevChar = this.codeMirror.getRange({ line: cursor.line, ch: cursor.ch - 1 }, cursor);
1764
+ const nextChar = this.codeMirror.getRange(cursor, { line: cursor.line, ch: cursor.ch + 1 });
1765
+ let insertText = text;
1766
+ if (prevChar && !/\s|[\(\)\+\-\*\/%,]/.test(prevChar))
1767
+ insertText = ' ' + insertText;
1768
+ if (nextChar && !/\s|[\(\)\+\-\*\/%,]/.test(nextChar))
1769
+ insertText += ' ';
1770
+ this.codeMirror.replaceSelection(insertText);
1771
+ const c = this.codeMirror.getCursor();
1772
+ this.codeMirror.setCursor({ line: c.line, ch: c.ch - 1 }); // 光标放在括号里面
2201
1773
  }
2202
- fakeLabel(t) {
2203
- return t ? t.replace(/[\[\]()'"]/g, " ") : "";
1774
+ // ===== Suggestions =====
1775
+ updateSuggestions() {
1776
+ const cursor = this.codeMirror.getCursor();
1777
+ const idx = this.codeMirror.indexFromPos(cursor);
1778
+ const enhancer = new FormulaEnhancer(this.formula);
1779
+ this.suggestions = enhancer.getSuggestions(this.value, idx, []);
1780
+ this.showSuggestionBox = this.suggestions.length > 0;
1781
+ this.selectedSuggestionIndex = 0;
1782
+ this.cdr.detectChanges();
2204
1783
  }
2205
- setValue() {
2206
- if (this.value === undefined || this.value === null || this.value === "") {
1784
+ applySuggestion() {
1785
+ if (!this.showSuggestionBox)
2207
1786
  return;
1787
+ this.insertSuggestion(this.suggestions[this.selectedSuggestionIndex]);
1788
+ }
1789
+ insertSuggestion(s) {
1790
+ this.codeMirror.replaceSelection(this.showVariableLabels && s.type === 'variable'
1791
+ ? this.fieldLabelMap.get(s.text) || s.text
1792
+ : s.text);
1793
+ this.showSuggestionBox = false;
1794
+ }
1795
+ btnValidate() {
1796
+ let res = this.validateFormula();
1797
+ if (res && res?.isValid && res?.isValid == true) {
1798
+ this.msg.success("校验成功");
2208
1799
  }
2209
- let e = [];
2210
- let p = [];
2211
- let t = this.value.split("\n");
2212
- this.fml.Utils.forEach(t, (c, t1) => {
2213
- let d = "", t = t1.split(new RegExp(this.fml.FormulaEditor.COMMON_REG.FORM_FORMULA, "g"));
2214
- this.fml.Utils.forEach(t, (t, e) => {
2215
- let i, a, n, s, o, r, l;
2216
- this.fml.FormulaEditor.CONST.FIELD_REG.test(e)
2217
- ? ((a = !1),
2218
- this.labelMap &&
2219
- (i = this.labelMap[e] ? this.labelMap[e] : " ") &&
2220
- ((i = this.fakeLabel(i)), (a = !0)),
2221
- (n = !1),
2222
- this.fml.Utils.isNull(i) && ((i = 1), (n = !0)),
2223
- (s = (l = e.replace("$", "").split("}"))[0]),
2224
- (o = l[1]),
2225
- (r = CodeMirror.Pos(c, d.length)),
2226
- (d += i),
2227
- (l = CodeMirror.Pos(c, d.length)),
2228
- p.push({
2229
- from: r,
2230
- to: l,
2231
- key: `$${s}}`,
2232
- label: a ? (this.labelMap[e] ? this.labelMap[e] : "") : null,
2233
- }))
2234
- : (d += e);
2235
- });
2236
- e.push(d);
1800
+ else {
1801
+ this.msg.error("校验失败");
1802
+ }
1803
+ }
1804
+ // ===== Validation =====
1805
+ validateFormula() {
1806
+ const enhancer = new FormulaEnhancer(this.formula);
1807
+ const res = enhancer.validate(this.value);
1808
+ FormulaHighlighter$1.highlightErrors(this.codeMirror, res.errors);
1809
+ this.validationResult.emit(res);
1810
+ return res;
1811
+ }
1812
+ // ===== Buttons =====
1813
+ toggleVariableDisplay() {
1814
+ this.showVariableLabels = !this.showVariableLabels;
1815
+ const text = this.showVariableLabels
1816
+ ? this.formulaToDisplay(this.value)
1817
+ : this.value;
1818
+ this.codeMirror.setValue(text);
1819
+ this.highlightVariables();
1820
+ }
1821
+ btnCopy() {
1822
+ navigator.clipboard.writeText(this.value);
1823
+ this.msg.success('复制成功');
1824
+ }
1825
+ btnPaste() {
1826
+ navigator.clipboard.readText().then(v => {
1827
+ this.value += v;
1828
+ this.codeMirror.setValue(this.showVariableLabels ? this.formulaToDisplay(this.value) : this.value);
1829
+ this.highlightVariables();
2237
1830
  });
1831
+ }
1832
+ btnClear() {
1833
+ this.value = '';
1834
+ this.codeMirror.setValue('');
1835
+ }
1836
+ // ===== CVA =====
1837
+ writeValue(v) {
1838
+ this.value = v || '';
2238
1839
  if (this.codeMirror) {
2239
- this.codeMirror.setValue(e.join("\n"));
2240
- this.fml.Utils.forEach(p, (t, e) => {
2241
- this.markField(e);
2242
- });
1840
+ this.codeMirror.setValue(this.showVariableLabels ? this.formulaToDisplay(this.value) : this.value);
1841
+ this.highlightVariables();
1842
+ }
1843
+ }
1844
+ onChange = (_) => { };
1845
+ registerOnChange(fn) { this.onChange = fn; }
1846
+ registerOnTouched() { }
1847
+ setDisabledState(d) {
1848
+ this.disabled = d;
1849
+ this.codeMirror?.setOption('readOnly', d);
1850
+ }
1851
+ closeSuggest(e) {
1852
+ if (!this.el.nativeElement.contains(e.target)) {
1853
+ this.showSuggestionBox = false;
2243
1854
  }
2244
1855
  }
2245
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: GramCodemirrorComponent, deps: [{ token: i0.KeyValueDiffers }, { token: i0.NgZone }, { token: i0.ElementRef }, { token: i1.NzMessageService }, { token: i2.NzConfigService }, { token: Formula }], target: i0.ɵɵFactoryTarget.Component });
2246
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.15", type: GramCodemirrorComponent, isStandalone: true, selector: "deon-codemirror", inputs: { itemTitle: "itemTitle", options: "options", fieldData: "fieldData", blacklist: "blacklist", enableDefaultBlack: "enableDefaultBlack", showList: "showList", name: "name", title: "title", autoFocus: "autoFocus", type: "type", categorys: "categorys", formulaClass: "formulaClass", preserveScrollPosition: "preserveScrollPosition" }, outputs: { cursorActivity: "cursorActivity", focusChange: "focusChange", scroll: "scroll", drop: "drop", textChange: "textChange" }, providers: [
1856
+ usageMouseover(e) {
1857
+ let usage = e.usage ? `<li class="usage"> 用法:${e.usage} </li>` : "";
1858
+ this.usageDescription = `
1859
+ <div class="formula-title">${e.name}</div>
1860
+ <ul class="intro-wrapper">
1861
+ <li class="intro">${e.intro}</li>
1862
+ ${usage}
1863
+ <li class="example">示例:${e.example}</li>
1864
+ </ul>`;
1865
+ }
1866
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: GramCodemirrorComponent, deps: [{ token: i0.ElementRef }, { token: i1.NzMessageService }, { token: i0.ChangeDetectorRef }, { token: Formula }], target: i0.ɵɵFactoryTarget.Component });
1867
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.15", type: GramCodemirrorComponent, isStandalone: true, selector: "deon-codemirror", inputs: { title: "title", name: "name", autoFocus: "autoFocus", fieldData: "fieldData", options: "options" }, outputs: { validationResult: "validationResult" }, host: { listeners: { "document:click": "closeSuggest($event)" } }, providers: [
2247
1868
  {
2248
1869
  provide: NG_VALUE_ACCESSOR,
2249
1870
  useExisting: forwardRef(() => GramCodemirrorComponent),
2250
- multi: true,
1871
+ multi: true
2251
1872
  },
2252
1873
  Formula
2253
- ], viewQueries: [{ propertyName: "ref", first: true, predicate: ["ref"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"formula-head\">\r\n <div class=\"formula-title\">\r\n <span class=\"formula-name\">{{ title }}</span><span class=\"formula-equal\">=</span>\r\n </div>\r\n <div class=\"formula-body\">\r\n <textarea [name]=\"name\" autocomplete=\"off\" [autofocus]=\"autoFocus\" #ref>\r\n </textarea>\r\n <div class=\"button-body\">\r\n <button nz-button type=\"button\" nzSize=\"small\" (click)=\"btnCopy()\">\u590D\u5236</button>\r\n <button nz-button type=\"button\" nzSize=\"small\" (click)=\"btnPaste()\">\u7C98\u8D34</button>\r\n <button nz-button type=\"button\" nzSize=\"small\" (click)=\"btnClear()\">\u6E05\u7A7A</button>\r\n </div>\r\n </div>\r\n</div>\r\n<div class=\"formula-wrapper\">\r\n <div class=\"field-list\">\r\n <div class=\"title\">\u53EF\u7528\u53D8\u91CF</div>\r\n <div class=\"field-wrapper\">\r\n <div class=\"search\">\r\n <input type=\"text\" nz-input placeholder=\"\u641C\u7D22\u53EF\u7528\u53D8\u91CF\" [(ngModel)]=\"variableSearch\" />\r\n </div>\r\n <div class=\"collapse-wrapper\">\r\n <ng-container *ngIf=\"fieldData!! && fieldData.length>0\">\r\n <nz-collapse [nzBordered]=\"false\">\r\n <ng-container *ngFor=\"let item of fieldData\">\r\n <nz-collapse-panel [nzHeader]=\"item.label\">\r\n <div class=\"item\" *ngFor=\"let field of item.listField\" (click)=\"insertField(field)\">\r\n {{ field.label }}\r\n </div>\r\n </nz-collapse-panel>\r\n </ng-container>\r\n </nz-collapse>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"field-list\">\r\n <div class=\"title\">\u51FD\u6570</div>\r\n <div class=\"field-wrapper\">\r\n <div class=\"search\">\r\n <input type=\"text\" nz-input placeholder=\"\u641C\u7D22\u51FD\u6570\" [(ngModel)]=\"usageFunSearch\" />\r\n </div>\r\n <div class=\"collapse-wrapper\">\r\n\r\n <ng-container *ngIf=\"FormulaUsage!! && FormulaUsage.length>0\">\r\n <nz-collapse [nzBordered]=\"false\">\r\n <ng-container *ngFor=\"let item of FormulaUsage\">\r\n <nz-collapse-panel [nzHeader]=\"item.category\">\r\n <div class=\"item\" *ngFor=\"let field of item.contains\" (mouseover)=\"usageMouseover(field)\"\r\n (click)=\"insertUsageFun(field)\">\r\n {{ field.name }}\r\n </div>\r\n </nz-collapse-panel>\r\n </ng-container>\r\n </nz-collapse>\r\n </ng-container>\r\n\r\n\r\n <ng-template #searchPanel>\r\n <ul>\r\n <li *ngFor=\"let item of usageFunSearchList\" (mouseover)=\"usageMouseover(item)\"\r\n (click)=\"insertUsageFun(item)\">\r\n {{ item.name }}\r\n </li>\r\n </ul>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"formula-intro\" [innerHtml]=\"usageDescription | safeHtml\"></div>\r\n</div>", styles: [":host ::ng-deep{display:flex;flex-direction:column;width:100%}:host ::ng-deep .CodeMirror{height:200px}:host ::ng-deep input::placeholder{font-size:12px!important}:host ::ng-deep .ant-input{font-size:12px!important;border:0!important}:host ::ng-deep .ant-input:focus{box-shadow:none!important}:host ::ng-deep .formula-head{display:flex;flex-direction:column;width:100%;overflow:hidden;font-size:12px;border:1px solid #eaeaea;border-radius:4px}:host ::ng-deep .formula-head .formula-title{display:inline-block;width:100%;padding:8px 12px;background:#f3f8fb}:host ::ng-deep .formula-head .formula-body{padding:12px 12px 0}:host ::ng-deep .formula-head .formula-body .button-body{display:inline-block;width:100%;padding:0 0 10px;text-align:right}:host ::ng-deep .formula-head .formula-body .button-body button{font-size:12px!important}:host ::ng-deep .formula-wrapper{display:flex;flex-direction:row;height:280px;margin-top:10px;font-size:12px}:host ::ng-deep .formula-wrapper .search{border-bottom:1px solid #eaeaea}:host ::ng-deep .formula-wrapper .field-list+.field-list{padding-left:15px}:host ::ng-deep .formula-wrapper .field-list{display:flex;flex-direction:column;width:230px;height:100%}:host ::ng-deep .formula-wrapper .field-list .title{display:inline-block;height:20px}:host ::ng-deep .formula-wrapper .field-list .field-wrapper{display:flex;flex:1;flex-direction:column;width:100%;overflow:auto;border:1px solid #eaeaea;border-radius:2px}:host ::ng-deep .formula-wrapper .field-list .item{padding:3px 0 0;cursor:pointer}:host ::ng-deep .formula-wrapper .collapse-wrapper{flex:1;overflow-x:overlay;overflow-y:overlay}:host ::ng-deep .formula-wrapper .collapse-wrapper::-webkit-scrollbar{width:8px}:host ::ng-deep .formula-wrapper .collapse-wrapper::-webkit-scrollbar-thumb{background-color:#94949475;border-radius:7px}:host ::ng-deep .formula-wrapper .collapse-wrapper::-webkit-scrollbar-track{background-color:#fff}:host ::ng-deep .formula-intro{flex:1;margin:20px 0 0 15px;border:1px solid #eaeaea}:host ::ng-deep .formula-intro ul{margin:0;padding:0}:host ::ng-deep .formula-intro .intro-wrapper{height:240px;margin:0;padding:10px 0 0;color:#5e6d82;overflow-x:overlay;overflow-y:overlay}:host ::ng-deep .formula-intro .intro-wrapper::-webkit-scrollbar{width:8px}:host ::ng-deep .formula-intro .intro-wrapper::-webkit-scrollbar-thumb{background-color:#94949475;border-radius:7px}:host ::ng-deep .formula-intro .intro-wrapper::-webkit-scrollbar-track{background-color:#fff}:host ::ng-deep .formula-intro .intro-wrapper>li{padding:2px 10px;word-wrap:break-word;word-break:break-all;list-style-type:none}:host ::ng-deep .formula-intro .default>li{margin-left:25px;padding:5px 0;list-style-type:disc}:host ::ng-deep .formula-intro .formula-title{height:35px;padding-left:10px;line-height:35px;border-bottom:solid 1px #e0e0e0}:host ::ng-deep .ant-collapse-borderless{background-color:#fff}:host ::ng-deep .ant-collapse-borderless .ant-collapse-item{border-bottom:0}:host ::ng-deep .ant-collapse-header{padding:10px 15px 0 19px!important;font-size:12px}:host ::ng-deep .ant-collapse-header i{top:3px!important;left:5px!important;padding:10px 15px 10px 0!important}:host ::ng-deep .ant-collapse-content-box{padding:0 16px!important;font-size:12px!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: NzInputModule }, { kind: "directive", type: i6.NzInputDirective, selector: "input[nz-input],textarea[nz-input]", inputs: ["nzBorderless", "nzSize", "nzStepperless", "nzStatus", "disabled"], exportAs: ["nzInput"] }, { kind: "ngmodule", type: NzCollapseModule }, { kind: "component", type: i7.NzCollapsePanelComponent, selector: "nz-collapse-panel", inputs: ["nzActive", "nzDisabled", "nzShowArrow", "nzExtra", "nzHeader", "nzExpandedIcon"], outputs: ["nzActiveChange"], exportAs: ["nzCollapsePanel"] }, { kind: "component", type: i7.NzCollapseComponent, selector: "nz-collapse", inputs: ["nzAccordion", "nzBordered", "nzGhost", "nzExpandIconPosition"], exportAs: ["nzCollapse"] }, { kind: "ngmodule", type: NzIconModule }, { kind: "ngmodule", type: NzButtonModule }, { kind: "component", type: i8.NzButtonComponent, selector: "button[nz-button], a[nz-button]", inputs: ["nzBlock", "nzGhost", "nzSearch", "nzLoading", "nzDanger", "disabled", "tabIndex", "nzType", "nzShape", "nzSize"], exportAs: ["nzButton"] }, { kind: "directive", type: i9.ɵNzTransitionPatchDirective, selector: "[nz-button], nz-button-group, [nz-icon], nz-icon, [nz-menu-item], [nz-submenu], nz-select-top-control, nz-select-placeholder, nz-input-group", inputs: ["hidden"] }, { kind: "directive", type: i10.NzWaveDirective, selector: "[nz-wave],button[nz-button]:not([nzType=\"link\"]):not([nzType=\"text\"])", inputs: ["nzWaveExtraNode"], exportAs: ["nzWave"] }, { kind: "ngmodule", type: NzToolTipModule }, { kind: "ngmodule", type: GramPipeModule }, { kind: "pipe", type: i11.SafeHtmlPipe, name: "safeHtml" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1874
+ ], viewQueries: [{ propertyName: "ref", first: true, predicate: ["ref"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"formula-head\">\r\n <div class=\"formula-title\">\r\n <span class=\"formula-name\">{{ title }}</span>\r\n <span class=\"formula-equal\">=</span>\r\n </div>\r\n\r\n <div class=\"formula-body\">\r\n <textarea #ref [name]=\"name\" autocomplete=\"off\" [autofocus]=\"autoFocus\"></textarea>\r\n\r\n <div class=\"button-body\">\r\n <button nz-button nzSize=\"small\" (click)=\"toggleVariableDisplay()\">\u5207\u6362\u663E\u793A</button>\r\n <button nz-button nzSize=\"small\" (click)=\"btnValidate()\">\u57FA\u7840\u6821\u9A8C</button>\r\n <button nz-button nzSize=\"small\" (click)=\"btnCopy()\">\u590D\u5236</button>\r\n <button nz-button nzSize=\"small\" (click)=\"btnPaste()\">\u7C98\u8D34</button>\r\n <button nz-button nzSize=\"small\" (click)=\"btnClear()\">\u6E05\u7A7A</button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"formula-wrapper\">\r\n <!-- \u53D8\u91CF -->\r\n <div class=\"field-list\">\r\n <div class=\"title\">\u53EF\u7528\u53D8\u91CF</div>\r\n <div class=\"field-wrapper\">\r\n <input nz-input placeholder=\"\u641C\u7D22\u53D8\u91CF\" [(ngModel)]=\"variableSearch\" />\r\n <div class=\"field-data\">\r\n <ng-container\r\n *ngIf=\"variableSearch && variableSearchList && variableSearchList.length>0;else tmpFieldPanel\">\r\n <ul>\r\n <li *ngFor=\"let item of variableSearchList\" (click)=\"insertField(item)\">\r\n {{ item.label }}\r\n </li>\r\n </ul>\r\n </ng-container>\r\n <ng-template #tmpFieldPanel>\r\n <nz-collapse nzBordered=\"false\">\r\n <nz-collapse-panel *ngFor=\"let g of fieldData\" [nzHeader]=\"g.label\">\r\n <div class=\"item\" *ngFor=\"let f of g.listField\" (click)=\"insertField(f)\">\r\n {{ f.label }}\r\n </div>\r\n </nz-collapse-panel>\r\n </nz-collapse>\r\n </ng-template>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- \u51FD\u6570 -->\r\n <div class=\"field-list\">\r\n <div class=\"title\">\u51FD\u6570</div>\r\n <div class=\"field-wrapper\">\r\n <input nz-input placeholder=\"\u641C\u7D22\u51FD\u6570\" [(ngModel)]=\"usageFunSearch\" />\r\n <div class=\"field-data\">\r\n <ng-container\r\n *ngIf=\"usageFunSearch && usageFunSearchList && usageFunSearchList.length>0;else tmpFunPanel\">\r\n <ul>\r\n <li *ngFor=\"let item of usageFunSearchList\" (click)=\"insertUsageFun(item)\">\r\n {{ item.name }}\r\n </li>\r\n </ul>\r\n </ng-container>\r\n\r\n <ng-template #tmpFunPanel>\r\n <nz-collapse nzBordered=\"false\">\r\n <nz-collapse-panel *ngFor=\"let g of FormulaUsage\" [nzHeader]=\"g.category\">\r\n <div class=\"item\" *ngFor=\"let f of g.contains\" (click)=\"insertUsageFun(f)\"\r\n (mouseover)=\"usageMouseover(f)\">\r\n {{ f.name }}\r\n </div>\r\n </nz-collapse-panel>\r\n </nz-collapse>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- \u63D0\u793A -->\r\n <div class=\"formula-intro\" [innerHTML]=\"usageDescription | safeHtml\"></div>\r\n</div>", styles: [":host ::ng-deep{display:flex;flex-direction:column;width:100%}:host ::ng-deep .CodeMirror{height:200px}:host ::ng-deep input::placeholder{font-size:12px!important}:host ::ng-deep .ant-input{font-size:12px!important;border:0!important}:host ::ng-deep .ant-input:focus{box-shadow:none!important}:host ::ng-deep .formula-head{display:flex;flex-direction:column;width:100%;overflow:hidden;font-size:12px;border:1px solid #eaeaea;border-radius:4px}:host ::ng-deep .formula-head .formula-title{display:inline-block;width:100%;padding:8px 12px;background:#f3f8fb}:host ::ng-deep .formula-head .formula-body{padding:12px 12px 0}:host ::ng-deep .formula-head .formula-body .button-body{display:inline-block;width:100%;padding:0 0 10px;text-align:right}:host ::ng-deep .formula-head .formula-body .button-body button{font-size:12px!important}:host ::ng-deep .formula-wrapper{display:flex;flex-direction:row;height:280px;margin-top:10px;font-size:12px}:host ::ng-deep .formula-wrapper .search{border-bottom:1px solid #eaeaea}:host ::ng-deep .formula-wrapper .field-list+.field-list{padding-left:15px}:host ::ng-deep .formula-wrapper .field-list{display:flex;flex-direction:column;width:230px;height:100%}:host ::ng-deep .formula-wrapper .field-list .title{display:inline-block;height:20px}:host ::ng-deep .formula-wrapper .field-list .field-wrapper{display:flex;flex:1;flex-direction:column;width:100%;overflow:auto;border:1px solid #eaeaea;border-radius:2px}:host ::ng-deep .formula-wrapper .field-list .item{padding:3px 0 0;cursor:pointer}:host ::ng-deep .formula-wrapper .collapse-wrapper{flex:1;overflow-x:overlay;overflow-y:overlay}:host ::ng-deep .formula-wrapper .collapse-wrapper::-webkit-scrollbar{width:8px}:host ::ng-deep .formula-wrapper .collapse-wrapper::-webkit-scrollbar-thumb{background-color:#94949475;border-radius:7px}:host ::ng-deep .formula-wrapper .collapse-wrapper::-webkit-scrollbar-track{background-color:#fff}:host ::ng-deep .formula-intro{flex:1;margin:20px 0 0 15px;border:1px solid #eaeaea}:host ::ng-deep .formula-intro ul{margin:0;padding:0}:host ::ng-deep .formula-intro .intro-wrapper{height:240px;margin:0;padding:10px 0 0;color:#5e6d82;overflow-x:overlay;overflow-y:overlay}:host ::ng-deep .formula-intro .intro-wrapper::-webkit-scrollbar{width:8px}:host ::ng-deep .formula-intro .intro-wrapper::-webkit-scrollbar-thumb{background-color:#94949475;border-radius:7px}:host ::ng-deep .formula-intro .intro-wrapper::-webkit-scrollbar-track{background-color:#fff}:host ::ng-deep .formula-intro .intro-wrapper>li{padding:2px 10px;word-wrap:break-word;word-break:break-all;list-style-type:none}:host ::ng-deep .formula-intro .default>li{margin-left:25px;padding:5px 0;list-style-type:disc}:host ::ng-deep .formula-intro .formula-title{height:35px;padding-left:10px;line-height:35px;border-bottom:solid 1px #e0e0e0}:host ::ng-deep .ant-collapse{padding:0 5px}:host ::ng-deep .ant-collapse-borderless{background-color:#fff}:host ::ng-deep .ant-collapse-borderless .ant-collapse-item{border-bottom:0}:host ::ng-deep .ant-collapse-header{padding:10px 15px 0 0!important;font-size:12px}:host ::ng-deep .ant-collapse-header i{top:3px!important;left:5px!important;padding:10px 15px 10px 0!important}:host ::ng-deep .ant-collapse-content-box{padding:0 8px!important;font-size:12px!important}:host ::ng-deep .field-data{display:flex;flex:1;flex-direction:column;border-top:1px solid #eaeaea;padding:0;overflow-x:overlay;overflow-y:overlay}:host ::ng-deep .field-data::-webkit-scrollbar{width:8px}:host ::ng-deep .field-data::-webkit-scrollbar-thumb{background-color:#94949475;border-radius:7px}:host ::ng-deep .field-data::-webkit-scrollbar-track{background-color:#fff}:host ::ng-deep .field-data ul li{padding:5px 0 5px 10px}:host ::ng-deep .cm-variable{color:#008dcd;background:#ebf5ff;display:inline-block;margin:0 2px}:host ::ng-deep .cm-function{color:#708;margin:0 4px}:host ::ng-deep .cm-operator{color:#555;margin:0 2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: NzInputModule }, { kind: "directive", type: i5.NzInputDirective, selector: "input[nz-input],textarea[nz-input]", inputs: ["nzBorderless", "nzSize", "nzStepperless", "nzStatus", "disabled"], exportAs: ["nzInput"] }, { kind: "ngmodule", type: NzCollapseModule }, { kind: "component", type: i6.NzCollapsePanelComponent, selector: "nz-collapse-panel", inputs: ["nzActive", "nzDisabled", "nzShowArrow", "nzExtra", "nzHeader", "nzExpandedIcon"], outputs: ["nzActiveChange"], exportAs: ["nzCollapsePanel"] }, { kind: "component", type: i6.NzCollapseComponent, selector: "nz-collapse", inputs: ["nzAccordion", "nzBordered", "nzGhost", "nzExpandIconPosition"], exportAs: ["nzCollapse"] }, { kind: "ngmodule", type: NzIconModule }, { kind: "ngmodule", type: NzButtonModule }, { kind: "component", type: i7.NzButtonComponent, selector: "button[nz-button], a[nz-button]", inputs: ["nzBlock", "nzGhost", "nzSearch", "nzLoading", "nzDanger", "disabled", "tabIndex", "nzType", "nzShape", "nzSize"], exportAs: ["nzButton"] }, { kind: "directive", type: i8.ɵNzTransitionPatchDirective, selector: "[nz-button], nz-button-group, [nz-icon], nz-icon, [nz-menu-item], [nz-submenu], nz-select-top-control, nz-select-placeholder, nz-input-group", inputs: ["hidden"] }, { kind: "directive", type: i9.NzWaveDirective, selector: "[nz-wave],button[nz-button]:not([nzType=\"link\"]):not([nzType=\"text\"])", inputs: ["nzWaveExtraNode"], exportAs: ["nzWave"] }, { kind: "ngmodule", type: NzToolTipModule }, { kind: "ngmodule", type: GramPipeModule }, { kind: "pipe", type: i10.SafeHtmlPipe, name: "safeHtml" }] });
2254
1875
  }
2255
1876
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: GramCodemirrorComponent, decorators: [{
2256
1877
  type: Component,
2257
- args: [{ selector: "deon-codemirror", providers: [
1878
+ args: [{ selector: 'deon-codemirror', providers: [
2258
1879
  {
2259
1880
  provide: NG_VALUE_ACCESSOR,
2260
1881
  useExisting: forwardRef(() => GramCodemirrorComponent),
2261
- multi: true,
1882
+ multi: true
2262
1883
  },
2263
1884
  Formula
2264
- ], preserveWhitespaces: false, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, ReactiveFormsModule, FormsModule, NzInputModule, NzCollapseModule, NzIconModule, NzButtonModule, NzToolTipModule, GramPipeModule], template: "<div class=\"formula-head\">\r\n <div class=\"formula-title\">\r\n <span class=\"formula-name\">{{ title }}</span><span class=\"formula-equal\">=</span>\r\n </div>\r\n <div class=\"formula-body\">\r\n <textarea [name]=\"name\" autocomplete=\"off\" [autofocus]=\"autoFocus\" #ref>\r\n </textarea>\r\n <div class=\"button-body\">\r\n <button nz-button type=\"button\" nzSize=\"small\" (click)=\"btnCopy()\">\u590D\u5236</button>\r\n <button nz-button type=\"button\" nzSize=\"small\" (click)=\"btnPaste()\">\u7C98\u8D34</button>\r\n <button nz-button type=\"button\" nzSize=\"small\" (click)=\"btnClear()\">\u6E05\u7A7A</button>\r\n </div>\r\n </div>\r\n</div>\r\n<div class=\"formula-wrapper\">\r\n <div class=\"field-list\">\r\n <div class=\"title\">\u53EF\u7528\u53D8\u91CF</div>\r\n <div class=\"field-wrapper\">\r\n <div class=\"search\">\r\n <input type=\"text\" nz-input placeholder=\"\u641C\u7D22\u53EF\u7528\u53D8\u91CF\" [(ngModel)]=\"variableSearch\" />\r\n </div>\r\n <div class=\"collapse-wrapper\">\r\n <ng-container *ngIf=\"fieldData!! && fieldData.length>0\">\r\n <nz-collapse [nzBordered]=\"false\">\r\n <ng-container *ngFor=\"let item of fieldData\">\r\n <nz-collapse-panel [nzHeader]=\"item.label\">\r\n <div class=\"item\" *ngFor=\"let field of item.listField\" (click)=\"insertField(field)\">\r\n {{ field.label }}\r\n </div>\r\n </nz-collapse-panel>\r\n </ng-container>\r\n </nz-collapse>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"field-list\">\r\n <div class=\"title\">\u51FD\u6570</div>\r\n <div class=\"field-wrapper\">\r\n <div class=\"search\">\r\n <input type=\"text\" nz-input placeholder=\"\u641C\u7D22\u51FD\u6570\" [(ngModel)]=\"usageFunSearch\" />\r\n </div>\r\n <div class=\"collapse-wrapper\">\r\n\r\n <ng-container *ngIf=\"FormulaUsage!! && FormulaUsage.length>0\">\r\n <nz-collapse [nzBordered]=\"false\">\r\n <ng-container *ngFor=\"let item of FormulaUsage\">\r\n <nz-collapse-panel [nzHeader]=\"item.category\">\r\n <div class=\"item\" *ngFor=\"let field of item.contains\" (mouseover)=\"usageMouseover(field)\"\r\n (click)=\"insertUsageFun(field)\">\r\n {{ field.name }}\r\n </div>\r\n </nz-collapse-panel>\r\n </ng-container>\r\n </nz-collapse>\r\n </ng-container>\r\n\r\n\r\n <ng-template #searchPanel>\r\n <ul>\r\n <li *ngFor=\"let item of usageFunSearchList\" (mouseover)=\"usageMouseover(item)\"\r\n (click)=\"insertUsageFun(item)\">\r\n {{ item.name }}\r\n </li>\r\n </ul>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"formula-intro\" [innerHtml]=\"usageDescription | safeHtml\"></div>\r\n</div>", styles: [":host ::ng-deep{display:flex;flex-direction:column;width:100%}:host ::ng-deep .CodeMirror{height:200px}:host ::ng-deep input::placeholder{font-size:12px!important}:host ::ng-deep .ant-input{font-size:12px!important;border:0!important}:host ::ng-deep .ant-input:focus{box-shadow:none!important}:host ::ng-deep .formula-head{display:flex;flex-direction:column;width:100%;overflow:hidden;font-size:12px;border:1px solid #eaeaea;border-radius:4px}:host ::ng-deep .formula-head .formula-title{display:inline-block;width:100%;padding:8px 12px;background:#f3f8fb}:host ::ng-deep .formula-head .formula-body{padding:12px 12px 0}:host ::ng-deep .formula-head .formula-body .button-body{display:inline-block;width:100%;padding:0 0 10px;text-align:right}:host ::ng-deep .formula-head .formula-body .button-body button{font-size:12px!important}:host ::ng-deep .formula-wrapper{display:flex;flex-direction:row;height:280px;margin-top:10px;font-size:12px}:host ::ng-deep .formula-wrapper .search{border-bottom:1px solid #eaeaea}:host ::ng-deep .formula-wrapper .field-list+.field-list{padding-left:15px}:host ::ng-deep .formula-wrapper .field-list{display:flex;flex-direction:column;width:230px;height:100%}:host ::ng-deep .formula-wrapper .field-list .title{display:inline-block;height:20px}:host ::ng-deep .formula-wrapper .field-list .field-wrapper{display:flex;flex:1;flex-direction:column;width:100%;overflow:auto;border:1px solid #eaeaea;border-radius:2px}:host ::ng-deep .formula-wrapper .field-list .item{padding:3px 0 0;cursor:pointer}:host ::ng-deep .formula-wrapper .collapse-wrapper{flex:1;overflow-x:overlay;overflow-y:overlay}:host ::ng-deep .formula-wrapper .collapse-wrapper::-webkit-scrollbar{width:8px}:host ::ng-deep .formula-wrapper .collapse-wrapper::-webkit-scrollbar-thumb{background-color:#94949475;border-radius:7px}:host ::ng-deep .formula-wrapper .collapse-wrapper::-webkit-scrollbar-track{background-color:#fff}:host ::ng-deep .formula-intro{flex:1;margin:20px 0 0 15px;border:1px solid #eaeaea}:host ::ng-deep .formula-intro ul{margin:0;padding:0}:host ::ng-deep .formula-intro .intro-wrapper{height:240px;margin:0;padding:10px 0 0;color:#5e6d82;overflow-x:overlay;overflow-y:overlay}:host ::ng-deep .formula-intro .intro-wrapper::-webkit-scrollbar{width:8px}:host ::ng-deep .formula-intro .intro-wrapper::-webkit-scrollbar-thumb{background-color:#94949475;border-radius:7px}:host ::ng-deep .formula-intro .intro-wrapper::-webkit-scrollbar-track{background-color:#fff}:host ::ng-deep .formula-intro .intro-wrapper>li{padding:2px 10px;word-wrap:break-word;word-break:break-all;list-style-type:none}:host ::ng-deep .formula-intro .default>li{margin-left:25px;padding:5px 0;list-style-type:disc}:host ::ng-deep .formula-intro .formula-title{height:35px;padding-left:10px;line-height:35px;border-bottom:solid 1px #e0e0e0}:host ::ng-deep .ant-collapse-borderless{background-color:#fff}:host ::ng-deep .ant-collapse-borderless .ant-collapse-item{border-bottom:0}:host ::ng-deep .ant-collapse-header{padding:10px 15px 0 19px!important;font-size:12px}:host ::ng-deep .ant-collapse-header i{top:3px!important;left:5px!important;padding:10px 15px 10px 0!important}:host ::ng-deep .ant-collapse-content-box{padding:0 16px!important;font-size:12px!important}\n"] }]
2265
- }], ctorParameters: () => [{ type: i0.KeyValueDiffers }, { type: i0.NgZone }, { type: i0.ElementRef }, { type: i1.NzMessageService }, { type: i2.NzConfigService }, { type: Formula }], propDecorators: { itemTitle: [{
2266
- type: Input
2267
- }], options: [{
2268
- type: Input
2269
- }], fieldData: [{
2270
- type: Input
2271
- }], blacklist: [{
2272
- type: Input
2273
- }], enableDefaultBlack: [{
2274
- type: Input
2275
- }], showList: [{
1885
+ ], imports: [CommonModule, ReactiveFormsModule, FormsModule, NzInputModule, NzCollapseModule, NzIconModule, NzButtonModule, NzToolTipModule, GramPipeModule], template: "<div class=\"formula-head\">\r\n <div class=\"formula-title\">\r\n <span class=\"formula-name\">{{ title }}</span>\r\n <span class=\"formula-equal\">=</span>\r\n </div>\r\n\r\n <div class=\"formula-body\">\r\n <textarea #ref [name]=\"name\" autocomplete=\"off\" [autofocus]=\"autoFocus\"></textarea>\r\n\r\n <div class=\"button-body\">\r\n <button nz-button nzSize=\"small\" (click)=\"toggleVariableDisplay()\">\u5207\u6362\u663E\u793A</button>\r\n <button nz-button nzSize=\"small\" (click)=\"btnValidate()\">\u57FA\u7840\u6821\u9A8C</button>\r\n <button nz-button nzSize=\"small\" (click)=\"btnCopy()\">\u590D\u5236</button>\r\n <button nz-button nzSize=\"small\" (click)=\"btnPaste()\">\u7C98\u8D34</button>\r\n <button nz-button nzSize=\"small\" (click)=\"btnClear()\">\u6E05\u7A7A</button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"formula-wrapper\">\r\n <!-- \u53D8\u91CF -->\r\n <div class=\"field-list\">\r\n <div class=\"title\">\u53EF\u7528\u53D8\u91CF</div>\r\n <div class=\"field-wrapper\">\r\n <input nz-input placeholder=\"\u641C\u7D22\u53D8\u91CF\" [(ngModel)]=\"variableSearch\" />\r\n <div class=\"field-data\">\r\n <ng-container\r\n *ngIf=\"variableSearch && variableSearchList && variableSearchList.length>0;else tmpFieldPanel\">\r\n <ul>\r\n <li *ngFor=\"let item of variableSearchList\" (click)=\"insertField(item)\">\r\n {{ item.label }}\r\n </li>\r\n </ul>\r\n </ng-container>\r\n <ng-template #tmpFieldPanel>\r\n <nz-collapse nzBordered=\"false\">\r\n <nz-collapse-panel *ngFor=\"let g of fieldData\" [nzHeader]=\"g.label\">\r\n <div class=\"item\" *ngFor=\"let f of g.listField\" (click)=\"insertField(f)\">\r\n {{ f.label }}\r\n </div>\r\n </nz-collapse-panel>\r\n </nz-collapse>\r\n </ng-template>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- \u51FD\u6570 -->\r\n <div class=\"field-list\">\r\n <div class=\"title\">\u51FD\u6570</div>\r\n <div class=\"field-wrapper\">\r\n <input nz-input placeholder=\"\u641C\u7D22\u51FD\u6570\" [(ngModel)]=\"usageFunSearch\" />\r\n <div class=\"field-data\">\r\n <ng-container\r\n *ngIf=\"usageFunSearch && usageFunSearchList && usageFunSearchList.length>0;else tmpFunPanel\">\r\n <ul>\r\n <li *ngFor=\"let item of usageFunSearchList\" (click)=\"insertUsageFun(item)\">\r\n {{ item.name }}\r\n </li>\r\n </ul>\r\n </ng-container>\r\n\r\n <ng-template #tmpFunPanel>\r\n <nz-collapse nzBordered=\"false\">\r\n <nz-collapse-panel *ngFor=\"let g of FormulaUsage\" [nzHeader]=\"g.category\">\r\n <div class=\"item\" *ngFor=\"let f of g.contains\" (click)=\"insertUsageFun(f)\"\r\n (mouseover)=\"usageMouseover(f)\">\r\n {{ f.name }}\r\n </div>\r\n </nz-collapse-panel>\r\n </nz-collapse>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- \u63D0\u793A -->\r\n <div class=\"formula-intro\" [innerHTML]=\"usageDescription | safeHtml\"></div>\r\n</div>", styles: [":host ::ng-deep{display:flex;flex-direction:column;width:100%}:host ::ng-deep .CodeMirror{height:200px}:host ::ng-deep input::placeholder{font-size:12px!important}:host ::ng-deep .ant-input{font-size:12px!important;border:0!important}:host ::ng-deep .ant-input:focus{box-shadow:none!important}:host ::ng-deep .formula-head{display:flex;flex-direction:column;width:100%;overflow:hidden;font-size:12px;border:1px solid #eaeaea;border-radius:4px}:host ::ng-deep .formula-head .formula-title{display:inline-block;width:100%;padding:8px 12px;background:#f3f8fb}:host ::ng-deep .formula-head .formula-body{padding:12px 12px 0}:host ::ng-deep .formula-head .formula-body .button-body{display:inline-block;width:100%;padding:0 0 10px;text-align:right}:host ::ng-deep .formula-head .formula-body .button-body button{font-size:12px!important}:host ::ng-deep .formula-wrapper{display:flex;flex-direction:row;height:280px;margin-top:10px;font-size:12px}:host ::ng-deep .formula-wrapper .search{border-bottom:1px solid #eaeaea}:host ::ng-deep .formula-wrapper .field-list+.field-list{padding-left:15px}:host ::ng-deep .formula-wrapper .field-list{display:flex;flex-direction:column;width:230px;height:100%}:host ::ng-deep .formula-wrapper .field-list .title{display:inline-block;height:20px}:host ::ng-deep .formula-wrapper .field-list .field-wrapper{display:flex;flex:1;flex-direction:column;width:100%;overflow:auto;border:1px solid #eaeaea;border-radius:2px}:host ::ng-deep .formula-wrapper .field-list .item{padding:3px 0 0;cursor:pointer}:host ::ng-deep .formula-wrapper .collapse-wrapper{flex:1;overflow-x:overlay;overflow-y:overlay}:host ::ng-deep .formula-wrapper .collapse-wrapper::-webkit-scrollbar{width:8px}:host ::ng-deep .formula-wrapper .collapse-wrapper::-webkit-scrollbar-thumb{background-color:#94949475;border-radius:7px}:host ::ng-deep .formula-wrapper .collapse-wrapper::-webkit-scrollbar-track{background-color:#fff}:host ::ng-deep .formula-intro{flex:1;margin:20px 0 0 15px;border:1px solid #eaeaea}:host ::ng-deep .formula-intro ul{margin:0;padding:0}:host ::ng-deep .formula-intro .intro-wrapper{height:240px;margin:0;padding:10px 0 0;color:#5e6d82;overflow-x:overlay;overflow-y:overlay}:host ::ng-deep .formula-intro .intro-wrapper::-webkit-scrollbar{width:8px}:host ::ng-deep .formula-intro .intro-wrapper::-webkit-scrollbar-thumb{background-color:#94949475;border-radius:7px}:host ::ng-deep .formula-intro .intro-wrapper::-webkit-scrollbar-track{background-color:#fff}:host ::ng-deep .formula-intro .intro-wrapper>li{padding:2px 10px;word-wrap:break-word;word-break:break-all;list-style-type:none}:host ::ng-deep .formula-intro .default>li{margin-left:25px;padding:5px 0;list-style-type:disc}:host ::ng-deep .formula-intro .formula-title{height:35px;padding-left:10px;line-height:35px;border-bottom:solid 1px #e0e0e0}:host ::ng-deep .ant-collapse{padding:0 5px}:host ::ng-deep .ant-collapse-borderless{background-color:#fff}:host ::ng-deep .ant-collapse-borderless .ant-collapse-item{border-bottom:0}:host ::ng-deep .ant-collapse-header{padding:10px 15px 0 0!important;font-size:12px}:host ::ng-deep .ant-collapse-header i{top:3px!important;left:5px!important;padding:10px 15px 10px 0!important}:host ::ng-deep .ant-collapse-content-box{padding:0 8px!important;font-size:12px!important}:host ::ng-deep .field-data{display:flex;flex:1;flex-direction:column;border-top:1px solid #eaeaea;padding:0;overflow-x:overlay;overflow-y:overlay}:host ::ng-deep .field-data::-webkit-scrollbar{width:8px}:host ::ng-deep .field-data::-webkit-scrollbar-thumb{background-color:#94949475;border-radius:7px}:host ::ng-deep .field-data::-webkit-scrollbar-track{background-color:#fff}:host ::ng-deep .field-data ul li{padding:5px 0 5px 10px}:host ::ng-deep .cm-variable{color:#008dcd;background:#ebf5ff;display:inline-block;margin:0 2px}:host ::ng-deep .cm-function{color:#708;margin:0 4px}:host ::ng-deep .cm-operator{color:#555;margin:0 2px}\n"] }]
1886
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1.NzMessageService }, { type: i0.ChangeDetectorRef }, { type: Formula }], propDecorators: { ref: [{
1887
+ type: ViewChild,
1888
+ args: ['ref', { static: true }]
1889
+ }], title: [{
2276
1890
  type: Input
2277
1891
  }], name: [{
2278
1892
  type: Input
2279
- }], title: [{
2280
- type: Input
2281
1893
  }], autoFocus: [{
2282
1894
  type: Input
2283
- }], type: [{
2284
- type: Input
2285
- }], categorys: [{
2286
- type: Input
2287
- }], formulaClass: [{
1895
+ }], fieldData: [{
2288
1896
  type: Input
2289
- }], preserveScrollPosition: [{
1897
+ }], options: [{
2290
1898
  type: Input
2291
- }], cursorActivity: [{
2292
- type: Output
2293
- }], focusChange: [{
2294
- type: Output
2295
- }], scroll: [{
1899
+ }], validationResult: [{
2296
1900
  type: Output
2297
- }], drop: [{
2298
- type: Output
2299
- }], textChange: [{
2300
- type: Output
2301
- }], ref: [{
2302
- type: ViewChild,
2303
- args: ["ref", { static: true }]
1901
+ }], closeSuggest: [{
1902
+ type: HostListener,
1903
+ args: ['document:click', ['$event']]
2304
1904
  }] } });
2305
1905
 
2306
1906
  const components = [GramCodemirrorComponent];
@@ -2317,16 +1917,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
2317
1917
  }]
2318
1918
  }] });
2319
1919
 
2320
- // /**
2321
- // * Public API surface of GramCodemirror
2322
- // */
2323
- // // Components
2324
- // export * from './default/index';
2325
- // // Module
2326
- // export * from './index.module';
2327
- // // Types
2328
- // export * from './tools/formula'; // Assuming this exists
2329
-
2330
1920
  /**
2331
1921
  * Generated bundle index. Do not edit.
2332
1922
  */