@flexem/fc-gui 3.0.0-alpha.182 → 3.0.0-alpha.183

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.
@@ -31,9 +31,17 @@ export declare class AlarmElement extends ConditionalDisplayElement {
31
31
  private getAlarmDataId;
32
32
  private readonly maxVisibleRows;
33
33
  private scrollIntervalId;
34
- private scrollContainer;
34
+ private scrollContent;
35
+ private scrollWindowStart;
35
36
  private hoverTarget;
36
37
  private rowHeight;
38
+ private touchStartY;
39
+ private touchScrollAccumulator;
40
+ private scrollTrack;
41
+ private scrollThumb;
42
+ private thumbDragStartY;
43
+ private thumbDragStartWindow;
44
+ private thumbDragging;
37
45
  private isDisposed;
38
46
  constructor(element: HTMLElement, injector: Injector, permissionChecker: PermissionChecker, variableCommunicator: VariableCommunicator, variableStore: VariableStore, alarmsStore: AlarmsStore, signalRAppId: string, systemTextLibraryService?: SystemTextLibraryService, languageService?: LanguageService, guiContext?: GuiContext);
39
47
  dispose(): void;
@@ -62,6 +70,8 @@ export declare class AlarmElement extends ConditionalDisplayElement {
62
70
  private getAlarmData;
63
71
  private refreshCurrentPageData;
64
72
  private updateTableContent;
73
+ private renderScrollWindow;
74
+ private updateScrollThumb;
65
75
  private getIconScale;
66
76
  private renderElement;
67
77
  private buildHeaderRow;
@@ -70,8 +80,19 @@ export declare class AlarmElement extends ConditionalDisplayElement {
70
80
  private renderScrollableTable;
71
81
  private bindScrollHoverEvents;
72
82
  private unbindScrollHoverEvents;
83
+ private moveScrollWindowBy;
84
+ private readonly handleScrollWheel;
85
+ private readonly handleScrollTouchStart;
86
+ private readonly handleScrollTouchMove;
73
87
  private readonly handleScrollMouseEnter;
74
88
  private readonly handleScrollMouseLeave;
89
+ private bindScrollbarEvents;
90
+ private unbindScrollbarEvents;
91
+ private getClientY;
92
+ private readonly handleThumbDragStart;
93
+ private readonly handleThumbDragMove;
94
+ private readonly handleThumbDragEnd;
95
+ private readonly handleTrackClick;
75
96
  private startAutoScroll;
76
97
  private scrollOneRow;
77
98
  private autoNextPage;
@@ -38,14 +38,102 @@ export class AlarmElement extends ConditionalDisplayElement {
38
38
  this.totalCount = 0;
39
39
  this.pageSize = 5;
40
40
  this.maxVisibleRows = 15;
41
+ this.scrollWindowStart = 0;
41
42
  this.rowHeight = 0;
43
+ this.touchStartY = 0;
44
+ this.touchScrollAccumulator = 0;
45
+ this.thumbDragStartY = 0;
46
+ this.thumbDragStartWindow = 0;
47
+ this.thumbDragging = false;
42
48
  this.isDisposed = false;
49
+ this.handleScrollWheel = (event) => {
50
+ if (!this.rowHeight)
51
+ return;
52
+ event.preventDefault();
53
+ this.touchScrollAccumulator += event.deltaY;
54
+ const rowDelta = Math.trunc(this.touchScrollAccumulator / this.rowHeight);
55
+ if (rowDelta !== 0) {
56
+ this.touchScrollAccumulator -= rowDelta * this.rowHeight;
57
+ this.moveScrollWindowBy(rowDelta);
58
+ }
59
+ };
60
+ this.handleScrollTouchStart = (event) => {
61
+ this.touchStartY = event.touches[0].clientY;
62
+ this.touchScrollAccumulator = 0;
63
+ };
64
+ this.handleScrollTouchMove = (event) => {
65
+ if (!this.rowHeight)
66
+ return;
67
+ event.preventDefault();
68
+ const currentY = event.touches[0].clientY;
69
+ const deltaY = this.touchStartY - currentY;
70
+ this.touchStartY = currentY;
71
+ this.touchScrollAccumulator += deltaY;
72
+ const rowDelta = Math.trunc(this.touchScrollAccumulator / this.rowHeight);
73
+ if (rowDelta !== 0) {
74
+ this.touchScrollAccumulator -= rowDelta * this.rowHeight;
75
+ this.moveScrollWindowBy(rowDelta);
76
+ }
77
+ };
43
78
  this.handleScrollMouseEnter = () => {
44
79
  clearInterval(this.scrollIntervalId);
45
80
  };
46
81
  this.handleScrollMouseLeave = () => {
82
+ if (!this.thumbDragging)
83
+ this.startAutoScroll();
84
+ };
85
+ // 拖拽滑块时挂全局 mousemove/mouseup,允许拖出滚动条区域也能继续跟手,松开时才解绑
86
+ this.handleThumbDragStart = (event) => {
87
+ event.preventDefault();
88
+ event.stopPropagation();
89
+ this.thumbDragging = true;
90
+ clearInterval(this.scrollIntervalId);
91
+ this.thumbDragStartY = this.getClientY(event);
92
+ this.thumbDragStartWindow = this.scrollWindowStart;
93
+ document.addEventListener('mousemove', this.handleThumbDragMove);
94
+ document.addEventListener('mouseup', this.handleThumbDragEnd);
95
+ document.addEventListener('touchmove', this.handleThumbDragMove, { passive: false });
96
+ document.addEventListener('touchend', this.handleThumbDragEnd);
97
+ };
98
+ this.handleThumbDragMove = (event) => {
99
+ if (!this.thumbDragging || !this.scrollTrack)
100
+ return;
101
+ event.preventDefault();
102
+ const maxWindowStart = Math.max(0, this.pageSize - this.maxVisibleRows);
103
+ if (maxWindowStart <= 0)
104
+ return;
105
+ const trackHeight = this.scrollTrack.clientHeight;
106
+ const thumbHeightRatio = Math.min(1, this.maxVisibleRows / this.pageSize);
107
+ const thumbHeight = Math.max(20, trackHeight * thumbHeightRatio);
108
+ const maxThumbTop = trackHeight - thumbHeight;
109
+ if (maxThumbTop <= 0)
110
+ return;
111
+ const deltaY = this.getClientY(event) - this.thumbDragStartY;
112
+ const deltaWindow = Math.round((deltaY / maxThumbTop) * maxWindowStart);
113
+ const nextStart = Math.min(maxWindowStart, Math.max(0, this.thumbDragStartWindow + deltaWindow));
114
+ if (nextStart === this.scrollWindowStart)
115
+ return;
116
+ this.scrollWindowStart = nextStart;
117
+ this.renderScrollWindow(this.scrollWindowStart);
118
+ };
119
+ this.handleThumbDragEnd = () => {
120
+ this.thumbDragging = false;
121
+ document.removeEventListener('mousemove', this.handleThumbDragMove);
122
+ document.removeEventListener('mouseup', this.handleThumbDragEnd);
123
+ document.removeEventListener('touchmove', this.handleThumbDragMove);
124
+ document.removeEventListener('touchend', this.handleThumbDragEnd);
47
125
  this.startAutoScroll();
48
126
  };
127
+ // 点击轨道空白处(非滑块)时整页跳转,方向取决于点击位置在滑块上方还是下方
128
+ this.handleTrackClick = (event) => {
129
+ if (event.target !== this.scrollTrack || !this.scrollTrack)
130
+ return;
131
+ const trackRect = this.scrollTrack.getBoundingClientRect();
132
+ const clickTop = event.clientY - trackRect.top;
133
+ const thumbTop = parseFloat(this.scrollThumb.style.top) || 0;
134
+ const rowDelta = clickTop < thumbTop ? -this.maxVisibleRows : this.maxVisibleRows;
135
+ this.moveScrollWindowBy(rowDelta);
136
+ };
49
137
  this.rootElement.selectAll('*').remove();
50
138
  this.setStatusAsLoading();
51
139
  this.logger = injector.get(LOGGER_SERVICE_TOKEN);
@@ -276,10 +364,8 @@ export class AlarmElement extends ConditionalDisplayElement {
276
364
  }, 500);
277
365
  }
278
366
  refreshCurrentPageData() {
279
- var _a;
280
367
  if (this.isDisposed)
281
368
  return;
282
- const currentScrollTop = ((_a = this.scrollContainer) === null || _a === void 0 ? void 0 : _a.scrollTop) || 0;
283
369
  if (this.model.filterSetting.alarmType) {
284
370
  this.updateQueryTimeRange();
285
371
  const input = new GetAlarmsArgs(this.alarmNames, this.startTime, this.endTime, this.pageSize, this.page * this.pageSize);
@@ -295,9 +381,6 @@ export class AlarmElement extends ConditionalDisplayElement {
295
381
  item.triggeredTime.format('YYYY-MM-DD HH:mm:ss')
296
382
  ]);
297
383
  this.updateTableContent();
298
- if (this.scrollContainer) {
299
- this.scrollContainer.scrollTop = currentScrollTop;
300
- }
301
384
  }
302
385
  });
303
386
  }
@@ -321,9 +404,6 @@ export class AlarmElement extends ConditionalDisplayElement {
321
404
  item.triggeredTime.format('YYYY-MM-DD HH:mm:ss')
322
405
  ]);
323
406
  this.updateTableContent();
324
- if (this.scrollContainer) {
325
- this.scrollContainer.scrollTop = currentScrollTop;
326
- }
327
407
  }
328
408
  });
329
409
  }
@@ -332,36 +412,62 @@ export class AlarmElement extends ConditionalDisplayElement {
332
412
  if (!this.element)
333
413
  return;
334
414
  const useScroll = this.pageSize > this.maxVisibleRows;
335
- const dataRowHeight = this.model.heights[1] || this.model.heights[0];
336
- // 查找表格主体
337
- let tbody;
338
415
  if (useScroll) {
339
- const bodyContainer = this.element.querySelector('div > div:nth-child(2)');
340
- if (!bodyContainer)
416
+ if (!this.scrollContent)
341
417
  return;
342
- const bodyTable = bodyContainer.querySelector('table');
343
- if (!bodyTable)
344
- return;
345
- tbody = bodyTable;
346
- }
347
- else {
348
- const table = this.element.querySelector('table');
349
- if (!table)
350
- return;
351
- tbody = table;
418
+ this.scrollWindowStart = Math.min(this.scrollWindowStart, Math.max(0, this.pageSize - this.maxVisibleRows));
419
+ this.renderScrollWindow(this.scrollWindowStart);
420
+ return;
352
421
  }
422
+ const table = this.element.querySelector('table');
423
+ if (!table)
424
+ return;
353
425
  // 清除现有数据行(保留表头)
354
- const rows = Array.from(tbody.querySelectorAll('tr'));
426
+ const rows = Array.from(table.querySelectorAll('tr'));
355
427
  rows.forEach((row, index) => {
356
- if (index > 0 || useScroll) { // 对于 scrollable 模式,表头在另一个 table,所以这里全部清除
428
+ if (index > 0) {
357
429
  row.remove();
358
430
  }
359
431
  });
360
432
  // 重新生成数据行
361
433
  for (let row = 0; row < this.pageSize; row++) {
362
- const rowHeight = useScroll ? dataRowHeight : this.model.heights[row + 1];
363
- tbody.appendChild(this.buildDataRow(row, rowHeight));
434
+ table.appendChild(this.buildDataRow(row, this.model.heights[row + 1]));
435
+ }
436
+ }
437
+ renderScrollWindow(startRow) {
438
+ const table = this.scrollContent;
439
+ if (!table)
440
+ return;
441
+ // 清除现有数据行(保留表头,即第一个 <tr>)
442
+ const rows = Array.from(table.querySelectorAll('tr'));
443
+ rows.forEach((row, index) => {
444
+ if (index > 0) {
445
+ row.remove();
446
+ }
447
+ });
448
+ for (let i = 0; i < this.maxVisibleRows; i++) {
449
+ table.appendChild(this.buildDataRow(startRow + i, this.rowHeight));
364
450
  }
451
+ this.updateScrollThumb();
452
+ }
453
+ // 滑块高度按"可见行数/总行数"的比例算,位置按当前窗口起始行占可滚动范围的比例算,
454
+ // 只用 top/height 两个数值属性更新,不涉及 transform,不会触发合成层
455
+ updateScrollThumb() {
456
+ if (!this.scrollTrack || !this.scrollThumb)
457
+ return;
458
+ const maxWindowStart = Math.max(0, this.pageSize - this.maxVisibleRows);
459
+ if (maxWindowStart <= 0) {
460
+ this.scrollThumb.style.display = 'none';
461
+ return;
462
+ }
463
+ this.scrollThumb.style.display = 'block';
464
+ const trackHeight = this.scrollTrack.clientHeight;
465
+ const thumbHeightRatio = Math.min(1, this.maxVisibleRows / this.pageSize);
466
+ const thumbHeight = Math.max(20, trackHeight * thumbHeightRatio);
467
+ const maxThumbTop = trackHeight - thumbHeight;
468
+ const thumbTop = maxThumbTop * (this.scrollWindowStart / maxWindowStart);
469
+ this.scrollThumb.style.height = `${thumbHeight}px`;
470
+ this.scrollThumb.style.top = `${thumbTop}px`;
365
471
  }
366
472
  getIconScale() {
367
473
  const initSize = this.model.initSize;
@@ -485,7 +591,8 @@ export class AlarmElement extends ConditionalDisplayElement {
485
591
  return tr;
486
592
  }
487
593
  renderPlainTable(elementHeight, operationAreaReservedHeight) {
488
- this.scrollContainer = null;
594
+ this.scrollContent = null;
595
+ this.scrollWindowStart = 0;
489
596
  const table = document.createElement('table');
490
597
  table.style.cssText = `border: 2px solid ${this.model.generalSetting.stroke};
491
598
  height: ${elementHeight - operationAreaReservedHeight}px;`;
@@ -501,42 +608,41 @@ export class AlarmElement extends ConditionalDisplayElement {
501
608
  renderScrollableTable(elementHeight, operationAreaReservedHeight) {
502
609
  const dataRowHeight = this.model.heights[1] || this.model.heights[0];
503
610
  this.rowHeight = dataRowHeight;
611
+ this.scrollWindowStart = 0;
612
+ // 之前用"表头/表体分两个 table + flex 包裹容器 + overflow/transform 滚动"的结构,
613
+ // 在 iOS WKWebView 上表体会明显放大错位,换了两种滚动实现方式(原生 overflow:auto、
614
+ // JS transform 平移)都复现同样的问题,怀疑是这套多层 div + 双 table 结构本身的问题。
615
+ // 这里改成和 renderPlainTable() 完全同构的单 table 结构(已验证在所有平台上都正常),
616
+ // DOM 里始终只保留 maxVisibleRows 行数据,滚动时只增删 <tr> 内容,不做任何位移/滚动。
617
+ // 自定义滚动条(轨道+滑块)只用 position + top/height 定位,不用 overflow/transform/
618
+ // will-change,这些属性都不会触发 WebKit 合成层提升,不会重新引入 iOS 缩放错位问题。
619
+ const scrollbarWidth = 6;
504
620
  const wrapper = document.createElement('div');
505
- wrapper.style.cssText = `display: flex;
506
- flex-direction: column;
507
- box-sizing: border-box;
508
- border: 2px solid ${this.model.generalSetting.stroke};
621
+ wrapper.style.cssText = `position: relative; width: ${this.model.size.width}px;
622
+ height: ${elementHeight - operationAreaReservedHeight}px;`;
623
+ const table = document.createElement('table');
624
+ table.style.cssText = `border: 2px solid ${this.model.generalSetting.stroke};
509
625
  height: ${elementHeight - operationAreaReservedHeight}px;
510
- overflow: hidden;`;
511
- const headerWrapper = document.createElement('div');
512
- headerWrapper.style.cssText = 'flex: none; box-sizing: border-box; overflow: hidden;';
513
- const headerTable = document.createElement('table');
514
- headerTable.style.cssText = 'width: 100%; table-layout: fixed;';
515
- headerTable.appendChild(this.buildHeaderRow());
516
- headerWrapper.appendChild(headerTable);
517
- const bodyContainer = document.createElement('div');
518
- bodyContainer.style.cssText = `flex: none;
519
- overflow-y: auto;
520
- overflow-x: hidden;
521
- height: ${dataRowHeight * this.maxVisibleRows}px;`;
522
- const bodyTable = document.createElement('table');
523
- bodyTable.style.cssText = 'width: 100%; table-layout: fixed;';
524
- for (let row = 0; row < this.pageSize; row++) {
525
- bodyTable.appendChild(this.buildDataRow(row, dataRowHeight));
526
- }
527
- bodyContainer.appendChild(bodyTable);
528
- wrapper.appendChild(headerWrapper);
529
- wrapper.appendChild(bodyContainer);
626
+ width: calc(100% - ${scrollbarWidth}px);`;
627
+ table.appendChild(this.buildHeaderRow());
628
+ wrapper.appendChild(table);
629
+ const track = document.createElement('div');
630
+ track.style.cssText = `position: absolute; top: 0; right: 0; width: ${scrollbarWidth}px;
631
+ height: 100%; background: rgba(0,0,0,0.06); border-radius: ${scrollbarWidth / 2}px;`;
632
+ const thumb = document.createElement('div');
633
+ thumb.style.cssText = `position: absolute; left: 0; width: 100%;
634
+ background: rgba(0,0,0,0.35); border-radius: ${scrollbarWidth / 2}px; cursor: pointer;`;
635
+ track.appendChild(thumb);
636
+ wrapper.appendChild(track);
530
637
  this.element.appendChild(wrapper);
531
- this.scrollContainer = bodyContainer;
532
- requestAnimationFrame(() => {
533
- const scrollbarWidth = bodyContainer.offsetWidth - bodyContainer.clientWidth;
534
- if (scrollbarWidth > 0) {
535
- headerWrapper.style.paddingRight = scrollbarWidth + 'px';
536
- }
537
- });
538
- this.hoverTarget = bodyContainer;
638
+ this.scrollContent = table;
639
+ this.scrollTrack = track;
640
+ this.scrollThumb = thumb;
641
+ this.renderScrollWindow(0);
642
+ this.updateScrollThumb();
643
+ this.hoverTarget = table;
539
644
  this.bindScrollHoverEvents();
645
+ this.bindScrollbarEvents();
540
646
  this.startAutoScroll();
541
647
  }
542
648
  bindScrollHoverEvents() {
@@ -544,41 +650,93 @@ export class AlarmElement extends ConditionalDisplayElement {
544
650
  return;
545
651
  this.hoverTarget.addEventListener('mouseenter', this.handleScrollMouseEnter);
546
652
  this.hoverTarget.addEventListener('mouseleave', this.handleScrollMouseLeave);
653
+ if (this.scrollContent) {
654
+ this.hoverTarget.addEventListener('wheel', this.handleScrollWheel, { passive: false });
655
+ this.hoverTarget.addEventListener('touchstart', this.handleScrollTouchStart, { passive: true });
656
+ this.hoverTarget.addEventListener('touchmove', this.handleScrollTouchMove, { passive: false });
657
+ }
547
658
  }
548
659
  unbindScrollHoverEvents() {
660
+ this.unbindScrollbarEvents();
549
661
  if (!this.hoverTarget)
550
662
  return;
551
663
  this.hoverTarget.removeEventListener('mouseenter', this.handleScrollMouseEnter);
552
664
  this.hoverTarget.removeEventListener('mouseleave', this.handleScrollMouseLeave);
665
+ this.hoverTarget.removeEventListener('wheel', this.handleScrollWheel);
666
+ this.hoverTarget.removeEventListener('touchstart', this.handleScrollTouchStart);
667
+ this.hoverTarget.removeEventListener('touchmove', this.handleScrollTouchMove);
553
668
  this.hoverTarget = null;
554
669
  }
670
+ // 手动滚动只在当前可见窗口范围内移动(不触发翻页),到顶/到底停住,
671
+ // 和自动滚动定时器(会在到底后自动翻页)职责区分开
672
+ moveScrollWindowBy(rowDelta) {
673
+ if (!this.scrollContent)
674
+ return;
675
+ const maxWindowStart = Math.max(0, this.pageSize - this.maxVisibleRows);
676
+ const nextStart = Math.min(maxWindowStart, Math.max(0, this.scrollWindowStart + rowDelta));
677
+ if (nextStart === this.scrollWindowStart)
678
+ return;
679
+ this.scrollWindowStart = nextStart;
680
+ this.renderScrollWindow(this.scrollWindowStart);
681
+ }
682
+ bindScrollbarEvents() {
683
+ if (!this.scrollTrack || !this.scrollThumb)
684
+ return;
685
+ this.scrollThumb.addEventListener('mousedown', this.handleThumbDragStart);
686
+ this.scrollThumb.addEventListener('touchstart', this.handleThumbDragStart, { passive: true });
687
+ this.scrollTrack.addEventListener('mousedown', this.handleTrackClick);
688
+ }
689
+ unbindScrollbarEvents() {
690
+ if (this.scrollThumb) {
691
+ this.scrollThumb.removeEventListener('mousedown', this.handleThumbDragStart);
692
+ this.scrollThumb.removeEventListener('touchstart', this.handleThumbDragStart);
693
+ }
694
+ if (this.scrollTrack) {
695
+ this.scrollTrack.removeEventListener('mousedown', this.handleTrackClick);
696
+ }
697
+ document.removeEventListener('mousemove', this.handleThumbDragMove);
698
+ document.removeEventListener('mouseup', this.handleThumbDragEnd);
699
+ document.removeEventListener('touchmove', this.handleThumbDragMove);
700
+ document.removeEventListener('touchend', this.handleThumbDragEnd);
701
+ this.scrollTrack = null;
702
+ this.scrollThumb = null;
703
+ }
704
+ getClientY(event) {
705
+ return 'touches' in event ? event.touches[0].clientY : event.clientY;
706
+ }
555
707
  startAutoScroll() {
556
708
  clearInterval(this.scrollIntervalId);
557
709
  if (!this.model.generalSetting.autoScroll)
558
710
  return;
559
711
  const totalPages = Math.max(1, Math.ceil(this.totalCount / this.pageSize));
560
- if (totalPages <= 1 && !this.scrollContainer)
712
+ if (totalPages <= 1 && !this.scrollContent)
561
713
  return;
562
714
  const duration = (this.model.generalSetting.scrollDuration || 10) * 1000;
563
715
  this.scrollIntervalId = setInterval(() => this.scrollOneRow(), duration);
564
716
  }
565
717
  scrollOneRow() {
566
- const el = this.scrollContainer;
567
- if (!el) {
718
+ if (!this.scrollContent) {
568
719
  this.autoNextPage();
569
720
  return;
570
721
  }
571
- const maxScrollTop = el.scrollHeight - el.clientHeight;
572
- if (maxScrollTop <= 1 || el.scrollTop >= maxScrollTop - 1) {
722
+ const maxWindowStart = this.pageSize - this.maxVisibleRows;
723
+ if (maxWindowStart <= 0 || this.scrollWindowStart >= maxWindowStart) {
573
724
  this.autoNextPage();
574
725
  return;
575
726
  }
576
- el.scrollTop = Math.min(el.scrollTop + this.rowHeight, maxScrollTop);
727
+ this.scrollWindowStart += 1;
728
+ this.renderScrollWindow(this.scrollWindowStart);
577
729
  }
578
730
  autoNextPage() {
579
731
  const totalPages = Math.max(1, Math.ceil(this.totalCount / this.pageSize));
580
- if (totalPages <= 1)
732
+ if (totalPages <= 1) {
733
+ // 只有一页数据:没有下一页可翻,循环回本页顶部继续滚动
734
+ if (this.scrollContent) {
735
+ this.scrollWindowStart = 0;
736
+ this.renderScrollWindow(0);
737
+ }
581
738
  return;
739
+ }
582
740
  const lastPage = totalPages - 1;
583
741
  this.page = this.page < lastPage ? this.page + 1 : 0;
584
742
  this.getAlarmData();
@@ -1 +1 @@
1
- [{"__symbolic":"module","version":4,"metadata":{"AlarmElement":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"../base/conditional-display-element","name":"ConditionalDisplayElement","line":21,"character":34},"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"error","message":"Could not resolve type","line":61,"character":25,"context":{"typeName":"HTMLElement"}},{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":62,"character":18},{"__symbolic":"reference","module":"../../service","name":"PermissionChecker","line":63,"character":27},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":64,"character":30},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":65,"character":23},{"__symbolic":"reference","module":"../../config","name":"AlarmsStore","line":66,"character":38},{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","module":"../../service","name":"SystemTextLibraryService","line":68,"character":52},{"__symbolic":"reference","module":"../../service","name":"LanguageService","line":69,"character":43},{"__symbolic":"reference","module":"../../gui/gui-context","name":"GuiContext","line":70,"character":38}]}],"dispose":[{"__symbolic":"method"}],"subscribeLanguageChange":[{"__symbolic":"method"}],"updateLanguageTexts":[{"__symbolic":"method"}],"getCurrentCulture":[{"__symbolic":"method"}],"getHeaderTextByColumn":[{"__symbolic":"method"}],"getValidTimePeriods":[{"__symbolic":"method"}],"getTimePeriodText":[{"__symbolic":"method"}],"getAlarmData":[{"__symbolic":"method"}],"refreshCurrentPageData":[{"__symbolic":"method"}],"updateTableContent":[{"__symbolic":"method"}],"getIconScale":[{"__symbolic":"method"}],"renderElement":[{"__symbolic":"method"}],"buildHeaderRow":[{"__symbolic":"method"}],"buildDataRow":[{"__symbolic":"method"}],"renderPlainTable":[{"__symbolic":"method"}],"renderScrollableTable":[{"__symbolic":"method"}],"bindScrollHoverEvents":[{"__symbolic":"method"}],"unbindScrollHoverEvents":[{"__symbolic":"method"}],"startAutoScroll":[{"__symbolic":"method"}],"scrollOneRow":[{"__symbolic":"method"}],"autoNextPage":[{"__symbolic":"method"}],"renderOperationArea":[{"__symbolic":"method"}],"updateTimeRange":[{"__symbolic":"method"}],"updateQueryTimeRange":[{"__symbolic":"method"}],"loadFirstPage":[{"__symbolic":"method"}],"loadNextPage":[{"__symbolic":"method"}],"loadPreviousPage":[{"__symbolic":"method"}],"loadLastPage":[{"__symbolic":"method"}],"setStatusAsNormal":[{"__symbolic":"method"}],"setStatusAsLoading":[{"__symbolic":"method"}],"renderStatus":[{"__symbolic":"method"}],"clearStatus":[{"__symbolic":"method"}]}}}}]
1
+ [{"__symbolic":"module","version":4,"metadata":{"AlarmElement":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"../base/conditional-display-element","name":"ConditionalDisplayElement","line":21,"character":34},"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"error","message":"Could not resolve type","line":69,"character":25,"context":{"typeName":"HTMLElement"}},{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":70,"character":18},{"__symbolic":"reference","module":"../../service","name":"PermissionChecker","line":71,"character":27},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":72,"character":30},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":73,"character":23},{"__symbolic":"reference","module":"../../config","name":"AlarmsStore","line":74,"character":38},{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","module":"../../service","name":"SystemTextLibraryService","line":76,"character":52},{"__symbolic":"reference","module":"../../service","name":"LanguageService","line":77,"character":43},{"__symbolic":"reference","module":"../../gui/gui-context","name":"GuiContext","line":78,"character":38}]}],"dispose":[{"__symbolic":"method"}],"subscribeLanguageChange":[{"__symbolic":"method"}],"updateLanguageTexts":[{"__symbolic":"method"}],"getCurrentCulture":[{"__symbolic":"method"}],"getHeaderTextByColumn":[{"__symbolic":"method"}],"getValidTimePeriods":[{"__symbolic":"method"}],"getTimePeriodText":[{"__symbolic":"method"}],"getAlarmData":[{"__symbolic":"method"}],"refreshCurrentPageData":[{"__symbolic":"method"}],"updateTableContent":[{"__symbolic":"method"}],"renderScrollWindow":[{"__symbolic":"method"}],"updateScrollThumb":[{"__symbolic":"method"}],"getIconScale":[{"__symbolic":"method"}],"renderElement":[{"__symbolic":"method"}],"buildHeaderRow":[{"__symbolic":"method"}],"buildDataRow":[{"__symbolic":"method"}],"renderPlainTable":[{"__symbolic":"method"}],"renderScrollableTable":[{"__symbolic":"method"}],"bindScrollHoverEvents":[{"__symbolic":"method"}],"unbindScrollHoverEvents":[{"__symbolic":"method"}],"moveScrollWindowBy":[{"__symbolic":"method"}],"bindScrollbarEvents":[{"__symbolic":"method"}],"unbindScrollbarEvents":[{"__symbolic":"method"}],"getClientY":[{"__symbolic":"method"}],"startAutoScroll":[{"__symbolic":"method"}],"scrollOneRow":[{"__symbolic":"method"}],"autoNextPage":[{"__symbolic":"method"}],"renderOperationArea":[{"__symbolic":"method"}],"updateTimeRange":[{"__symbolic":"method"}],"updateQueryTimeRange":[{"__symbolic":"method"}],"loadFirstPage":[{"__symbolic":"method"}],"loadNextPage":[{"__symbolic":"method"}],"loadPreviousPage":[{"__symbolic":"method"}],"loadLastPage":[{"__symbolic":"method"}],"setStatusAsNormal":[{"__symbolic":"method"}],"setStatusAsLoading":[{"__symbolic":"method"}],"renderStatus":[{"__symbolic":"method"}],"clearStatus":[{"__symbolic":"method"}]}}}}]
@@ -6,9 +6,6 @@ export class TextElementModal {
6
6
  this.width = width;
7
7
  this.height = height;
8
8
  this.isVariableText = isVariableText;
9
- if (/iPhone|iPod/i.test(navigator.userAgent)) {
10
- width += 10;
11
- }
12
9
  this._element = this.getforeignObjectElement(width, height);
13
10
  this._element.innerHTML = '';
14
11
  const text = this.createNewForeignObjectText(content, font, width, height, isVariableText);
@@ -32,10 +29,7 @@ export class TextElementModal {
32
29
  // 清空现有内容
33
30
  this._element.innerHTML = '';
34
31
  // 创建新的文本元素
35
- let width = this.width;
36
- if (/iPhone|iPod/i.test(navigator.userAgent)) {
37
- width += 10;
38
- }
32
+ const width = this.width;
39
33
  const text = this.createNewForeignObjectText(content, this.font, width, this.height, this.isVariableText);
40
34
  this._element.appendChild(text);
41
35
  }
@@ -64,7 +64,7 @@ VerifyPasswordModalComponent = __decorate([
64
64
  Component({
65
65
  selector: 'verify-password',
66
66
  template: "<form #verifyPasswordForm=\"ngForm\" novalidate (ngSubmit)=\"checkSecurity()\" bs-modal-drag> <div class=\"modal-header\"> <h4 class=\"modal-title\"> <span>{{localization.passwordVerify}}</span> </h4> <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"close()\"> <span aria-hidden=\"true\">&times;</span> </button> </div> <div class=\"modal-body\"> <span class=\"password-span\">{{localization.password}}: </span> <input type=\"password\" name=\"password\" autoFocus [class.verify-password-input]=\"!isMobileMode\" class=\"form-control element-password\" [(ngModel)]=\"password\" (keyup)=\"validate()\" autocomplete=\"off\"> <span class=\"help-block text-danger\" [hidden]=\"!passwordError\">{{validationErrorText}}</span> </div> <div class=\"modal-footer\" [class.verify-password-footer]=\"!isMobileMode\"> <button type=\"button\" class=\"btn md-skip btn-cancel\" (click)=\"close()\">{{localization.cancel}} </button> <button type=\"submit\" class=\"btn md-skip btn-primary\" [disabled]=\"passwordError\">{{localization.submit}}</button> </div> </form> ",
67
- styles: [".modal-header { padding: 10px; border-color: transparent; } .modal-body { position: relative; padding: 0px 5px !important; padding-top: 10px !important; } .modal-title { display: unset; margin-left: -6px; font-size: 16px !important; } .form-control { margin: 0 5%; float: none; width: 90%; } .modal-footer { padding: 10px 4px 20px 5px !important; text-align: right; border-color: transparent; color: #fff; } .text-danger { display: block; color: #ed6b75; font-size: 14px; margin: 5px 0px 0px 15px; } .btn-primary { color: #fff; height: 32px; min-width: 71px; margin-right: 10px; line-height: 0px } .password-span { color: #7f939e; font-size: 14px; margin-left: 15px; } .btn-cancel { color: #fff; height: 32px; min-width: 71px; margin-right: 6px; background-color: #dddddd; line-height: 0px } .element-password { padding-left: 8px; height: 32px; min-width: 71px; margin-left: 16px; } .verify-password-input { width: 600px; } .verify-password-footer { padding-right: 18px !important; }"]
67
+ styles: [".modal-header { padding: 10px; border-color: transparent; } .modal-body { position: relative; padding: 0px 5px !important; padding-top: 10px !important; } .modal-title { display: unset; margin-left: -6px; font-size: 16px !important; } .form-control { margin: 0 5%; float: none; width: 90%; } .modal-footer { padding: 10px 4px 20px 5px !important; text-align: right; border-color: transparent; color: #fff; } .text-danger { display: block; color: #ed6b75; font-size: 14px; margin: 5px 0px 0px 15px; } .btn-primary { color: #fff; height: 32px; min-width: 71px; margin-right: 10px; line-height: 0px } .password-span { color: #7f939e; font-size: 14px; margin-left: 15px; } .btn-cancel { color: #fff; height: 32px; min-width: 71px; margin-right: 6px; background-color: #dddddd; line-height: 0px } .element-password { padding-left: 8px; height: 32px; min-width: 71px; margin-left: 16px; } .verify-password-input { width: 600px; } .verify-password-footer { padding-right: 18px !important; } "]
68
68
  }),
69
69
  __param(0, Inject(LOCALIZATION)),
70
70
  __metadata("design:paramtypes", [Object, Injector])
@@ -71,4 +71,4 @@
71
71
 
72
72
  .verify-password-footer {
73
73
  padding-right: 18px !important;
74
- }
74
+ }
@@ -1 +1 @@
1
- [{"__symbolic":"module","version":4,"metadata":{"VerifyPasswordModalComponent":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Component","line":9,"character":1},"arguments":[{"selector":"verify-password","template":"<form #verifyPasswordForm=\"ngForm\" novalidate (ngSubmit)=\"checkSecurity()\" bs-modal-drag> <div class=\"modal-header\"> <h4 class=\"modal-title\"> <span>{{localization.passwordVerify}}</span> </h4> <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"close()\"> <span aria-hidden=\"true\">&times;</span> </button> </div> <div class=\"modal-body\"> <span class=\"password-span\">{{localization.password}}: </span> <input type=\"password\" name=\"password\" autoFocus [class.verify-password-input]=\"!isMobileMode\" class=\"form-control element-password\" [(ngModel)]=\"password\" (keyup)=\"validate()\" autocomplete=\"off\"> <span class=\"help-block text-danger\" [hidden]=\"!passwordError\">{{validationErrorText}}</span> </div> <div class=\"modal-footer\" [class.verify-password-footer]=\"!isMobileMode\"> <button type=\"button\" class=\"btn md-skip btn-cancel\" (click)=\"close()\">{{localization.cancel}} </button> <button type=\"submit\" class=\"btn md-skip btn-primary\" [disabled]=\"passwordError\">{{localization.submit}}</button> </div> </form> ","styles":[".modal-header { padding: 10px; border-color: transparent; } .modal-body { position: relative; padding: 0px 5px !important; padding-top: 10px !important; } .modal-title { display: unset; margin-left: -6px; font-size: 16px !important; } .form-control { margin: 0 5%; float: none; width: 90%; } .modal-footer { padding: 10px 4px 20px 5px !important; text-align: right; border-color: transparent; color: #fff; } .text-danger { display: block; color: #ed6b75; font-size: 14px; margin: 5px 0px 0px 15px; } .btn-primary { color: #fff; height: 32px; min-width: 71px; margin-right: 10px; line-height: 0px } .password-span { color: #7f939e; font-size: 14px; margin-left: 15px; } .btn-cancel { color: #fff; height: 32px; min-width: 71px; margin-right: 6px; background-color: #dddddd; line-height: 0px } .element-password { padding-left: 8px; height: 32px; min-width: 71px; margin-left: 16px; } .verify-password-input { width: 600px; } .verify-password-footer { padding-right: 18px !important; }"]}]}],"members":{"__ctor__":[{"__symbolic":"constructor","parameterDecorators":[[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Inject","line":29,"character":17},"arguments":[{"__symbolic":"reference","module":"../../localization","name":"LOCALIZATION","line":29,"character":24}]}],null],"parameters":[{"__symbolic":"reference","module":"../../localization","name":"Localization","line":29,"character":59},{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":29,"character":83}]}],"ngOnInit":[{"__symbolic":"method"}],"validate":[{"__symbolic":"method"}],"checkSecurity":[{"__symbolic":"method"}],"close":[{"__symbolic":"method"}]}}}}]
1
+ [{"__symbolic":"module","version":4,"metadata":{"VerifyPasswordModalComponent":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Component","line":9,"character":1},"arguments":[{"selector":"verify-password","template":"<form #verifyPasswordForm=\"ngForm\" novalidate (ngSubmit)=\"checkSecurity()\" bs-modal-drag> <div class=\"modal-header\"> <h4 class=\"modal-title\"> <span>{{localization.passwordVerify}}</span> </h4> <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"close()\"> <span aria-hidden=\"true\">&times;</span> </button> </div> <div class=\"modal-body\"> <span class=\"password-span\">{{localization.password}}: </span> <input type=\"password\" name=\"password\" autoFocus [class.verify-password-input]=\"!isMobileMode\" class=\"form-control element-password\" [(ngModel)]=\"password\" (keyup)=\"validate()\" autocomplete=\"off\"> <span class=\"help-block text-danger\" [hidden]=\"!passwordError\">{{validationErrorText}}</span> </div> <div class=\"modal-footer\" [class.verify-password-footer]=\"!isMobileMode\"> <button type=\"button\" class=\"btn md-skip btn-cancel\" (click)=\"close()\">{{localization.cancel}} </button> <button type=\"submit\" class=\"btn md-skip btn-primary\" [disabled]=\"passwordError\">{{localization.submit}}</button> </div> </form> ","styles":[".modal-header { padding: 10px; border-color: transparent; } .modal-body { position: relative; padding: 0px 5px !important; padding-top: 10px !important; } .modal-title { display: unset; margin-left: -6px; font-size: 16px !important; } .form-control { margin: 0 5%; float: none; width: 90%; } .modal-footer { padding: 10px 4px 20px 5px !important; text-align: right; border-color: transparent; color: #fff; } .text-danger { display: block; color: #ed6b75; font-size: 14px; margin: 5px 0px 0px 15px; } .btn-primary { color: #fff; height: 32px; min-width: 71px; margin-right: 10px; line-height: 0px } .password-span { color: #7f939e; font-size: 14px; margin-left: 15px; } .btn-cancel { color: #fff; height: 32px; min-width: 71px; margin-right: 6px; background-color: #dddddd; line-height: 0px } .element-password { padding-left: 8px; height: 32px; min-width: 71px; margin-left: 16px; } .verify-password-input { width: 600px; } .verify-password-footer { padding-right: 18px !important; } "]}]}],"members":{"__ctor__":[{"__symbolic":"constructor","parameterDecorators":[[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Inject","line":29,"character":17},"arguments":[{"__symbolic":"reference","module":"../../localization","name":"LOCALIZATION","line":29,"character":24}]}],null],"parameters":[{"__symbolic":"reference","module":"../../localization","name":"Localization","line":29,"character":59},{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":29,"character":83}]}],"ngOnInit":[{"__symbolic":"method"}],"validate":[{"__symbolic":"method"}],"checkSecurity":[{"__symbolic":"method"}],"close":[{"__symbolic":"method"}]}}}}]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "main": "bundles/fc-gui.umd.js",
3
- "version": "3.0.0-alpha.182",
3
+ "version": "3.0.0-alpha.183",
4
4
  "module": "public_api.js",
5
5
  "typings": "public_api.d.ts",
6
6
  "license": "UNLICENSED",