@flexem/fc-gui 3.0.0-alpha.12 → 3.0.0-alpha.120

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.
Files changed (142) hide show
  1. package/CHANGELOG.md +444 -1
  2. package/assets/img/black_first_page.png +0 -0
  3. package/assets/img/black_last_page.png +0 -0
  4. package/assets/img/black_next_page.png +0 -0
  5. package/assets/img/black_previous_page.png +0 -0
  6. package/bundles/@flexem/fc-gui.umd.js +19506 -17220
  7. package/bundles/@flexem/fc-gui.umd.js.map +1 -1
  8. package/bundles/@flexem/fc-gui.umd.min.js +5 -5
  9. package/bundles/@flexem/fc-gui.umd.min.js.map +1 -1
  10. package/communication/variable/variable-communicator.d.ts +2 -0
  11. package/communication/variable/variable-value.d.ts +4 -1
  12. package/communication/variable/variable-value.js +4 -1
  13. package/communication/variable/variable-value.metadata.json +1 -1
  14. package/config/alarm/alarm.store.d.ts +6 -0
  15. package/config/alarm/alarm.store.js +0 -0
  16. package/config/alarm/alarm.store.metadata.json +1 -0
  17. package/config/alarm/get-alarms-args.d.ts +9 -0
  18. package/config/alarm/get-alarms-args.js +9 -0
  19. package/config/alarm/get-alarms-args.metadata.json +1 -0
  20. package/config/alarm/index.d.ts +2 -0
  21. package/config/alarm/index.js +1 -0
  22. package/config/alarm/index.metadata.json +1 -0
  23. package/config/config-store.d.ts +2 -0
  24. package/config/index.d.ts +1 -0
  25. package/config/index.js +1 -0
  26. package/config/index.metadata.json +1 -1
  27. package/elements/air-quality/air-quality-element.d.ts +31 -0
  28. package/elements/air-quality/air-quality-element.js +194 -0
  29. package/elements/air-quality/air-quality-element.metadata.json +1 -0
  30. package/elements/alarm/alarm-element.d.ts +44 -0
  31. package/elements/alarm/alarm-element.js +386 -0
  32. package/elements/alarm/alarm-element.metadata.json +1 -0
  33. package/elements/bar-graph-element.d.ts +10 -2
  34. package/elements/bar-graph-element.js +135 -5
  35. package/elements/bar-graph-element.metadata.json +1 -1
  36. package/elements/base/readable-element.d.ts +6 -1
  37. package/elements/base/readable-element.js +55 -2
  38. package/elements/base/readable-element.metadata.json +1 -1
  39. package/elements/base/state-control-element.d.ts +3 -1
  40. package/elements/base/state-control-element.js +3 -0
  41. package/elements/datetime-display/datetime-display-element.d.ts +1 -0
  42. package/elements/datetime-display/datetime-display-element.js +10 -2
  43. package/elements/datetime-display/datetime-display-element.metadata.json +1 -1
  44. package/elements/datetime-display/time-zone-select-json.d.ts +8 -0
  45. package/elements/datetime-display/time-zone-select-json.js +558 -0
  46. package/elements/historical-curve/historical-curve.element.d.ts +9 -0
  47. package/elements/historical-curve/historical-curve.element.js +252 -13
  48. package/elements/historical-curve/historical-curve.element.metadata.json +1 -1
  49. package/elements/main-element.d.ts +1 -0
  50. package/elements/main-element.js +50 -4
  51. package/elements/main-element.metadata.json +1 -1
  52. package/elements/meter-element.d.ts +7 -1
  53. package/elements/meter-element.js +76 -7
  54. package/elements/meter-element.metadata.json +1 -1
  55. package/elements/numerical-display/numerical-display-element.d.ts +8 -2
  56. package/elements/numerical-display/numerical-display-element.js +55 -11
  57. package/elements/numerical-display/numerical-display-element.metadata.json +1 -1
  58. package/elements/per-view-variable-communicator.d.ts +3 -0
  59. package/elements/per-view-variable-communicator.js +11 -0
  60. package/elements/per-view-variable-communicator.metadata.json +1 -1
  61. package/elements/ring-graph/ring-graph-element.d.ts +13 -1
  62. package/elements/ring-graph/ring-graph-element.js +164 -3
  63. package/elements/ring-graph/ring-graph-element.metadata.json +1 -1
  64. package/elements/shared/graph/graph-state-element.js +0 -3
  65. package/elements/shared/text/text-element.js +13 -2
  66. package/elements/shared/text/text-state-element.d.ts +0 -1
  67. package/elements/shared/text/text-state-element.js +39 -61
  68. package/elements/shared/text/text-state-element.metadata.json +1 -1
  69. package/elements/switch-indicator-light/bit-switch-operator.d.ts +1 -0
  70. package/elements/switch-indicator-light/bit-switch-operator.js +19 -0
  71. package/elements/switch-indicator-light/bit-switch-operator.metadata.json +1 -1
  72. package/elements/switch-indicator-light/switch-indicator-light-element.d.ts +8 -0
  73. package/elements/switch-indicator-light/switch-indicator-light-element.js +93 -23
  74. package/elements/switch-indicator-light/switch-indicator-light-element.metadata.json +1 -1
  75. package/elements/switch-indicator-light/switch-operator.d.ts +1 -0
  76. package/elements/switch-indicator-light/word-switch-operator.d.ts +1 -0
  77. package/elements/switch-indicator-light/word-switch-operator.js +6 -0
  78. package/elements/switch-indicator-light/word-switch-operator.metadata.json +1 -1
  79. package/elements/video/video-element.d.ts +4 -0
  80. package/elements/video/video-element.js +81 -21
  81. package/elements/video/video-element.metadata.json +1 -1
  82. package/elements/view-operation/view-operation.element.js +8 -0
  83. package/elements/weather/weater-element.js +0 -1
  84. package/gui/gui-context.d.ts +2 -1
  85. package/gui/gui-host.d.ts +1 -1
  86. package/gui/gui-view.d.ts +2 -0
  87. package/gui/gui-view.js +20 -0
  88. package/gui/gui-view.metadata.json +1 -1
  89. package/gui/gui.component.d.ts +3 -0
  90. package/gui/gui.component.js +15 -2
  91. package/gui/gui.component.metadata.json +1 -1
  92. package/localization/localization.service.d.ts +7 -0
  93. package/localization/localization.service.js +10 -3
  94. package/localization/localization.service.metadata.json +1 -1
  95. package/localization/localization.service.zh_CN.js +8 -1
  96. package/localization/localization.service.zh_CN.metadata.json +1 -1
  97. package/modal/write-value/write-value-modal-args.d.ts +3 -1
  98. package/modal/write-value/write-value-modal-args.js +2 -1
  99. package/modal/write-value/write-value-modal-args.metadata.json +1 -1
  100. package/modal/write-value/write-value-modal.component.d.ts +8 -7
  101. package/modal/write-value/write-value-modal.component.html +9 -4
  102. package/modal/write-value/write-value-modal.component.js +42 -15
  103. package/modal/write-value/write-value-modal.component.metadata.json +1 -1
  104. package/model/air-quality/air-quality-info.d.ts +23 -0
  105. package/model/air-quality/air-quality-info.js +4 -0
  106. package/model/air-quality/air-quality-info.metadata.json +1 -0
  107. package/model/air-quality/air-quality.model.d.ts +7 -0
  108. package/model/air-quality/air-quality.model.js +0 -0
  109. package/model/air-quality/air-quality.model.metadata.json +1 -0
  110. package/model/alarm/alarm.model.d.ts +13 -0
  111. package/model/alarm/alarm.model.js +0 -0
  112. package/model/alarm/alarm.model.metadata.json +1 -0
  113. package/model/bar-graph/bar-graph.d.ts +4 -0
  114. package/model/base/readable-model.d.ts +4 -0
  115. package/model/datetime-display/datetime-display.d.ts +1 -0
  116. package/model/historical-curve/historical-curve-axis-settings.d.ts +11 -0
  117. package/model/historical-curve/historical-curve-axis-settings.js +5 -0
  118. package/model/historical-curve/historical-curve-axis-settings.metadata.json +1 -1
  119. package/model/historical-curve/historical-curve-chanel.model.d.ts +8 -0
  120. package/model/meter/meter.d.ts +4 -0
  121. package/model/ring-graph/ring-graph.model.d.ts +8 -0
  122. package/model/switch-indicator-light/bit-switch-operation.d.ts +2 -1
  123. package/model/switch-indicator-light/bit-switch-operation.js +1 -0
  124. package/model/switch-indicator-light/bit-switch-operation.metadata.json +1 -1
  125. package/package.json +1 -1
  126. package/remote/communication/variable/remote-variable-communicator.d.ts +7 -0
  127. package/remote/communication/variable/remote-variable-communicator.js +47 -1
  128. package/remote/communication/variable/remote-variable-communicator.metadata.json +1 -1
  129. package/remote/communication/variable/remote-variable-protocol.d.ts +5 -0
  130. package/service/index.d.ts +1 -0
  131. package/service/index.metadata.json +1 -1
  132. package/service/released-variable/index.d.ts +1 -0
  133. package/service/released-variable/index.js +0 -0
  134. package/service/released-variable/index.metadata.json +1 -0
  135. package/service/released-variable/released-variable.service.d.ts +4 -0
  136. package/service/released-variable/released-variable.service.js +0 -0
  137. package/service/released-variable/released-variable.service.metadata.json +1 -0
  138. package/service/weather.service.d.ts +1 -0
  139. package/shared/gui-consts.d.ts +2 -0
  140. package/shared/gui-consts.js +2 -0
  141. package/shared/gui-consts.metadata.json +1 -1
  142. package/utils/data-type/fbox-data-type.service.js +40 -0
@@ -1,5 +1,4 @@
1
1
  import { Flicker } from '../../../model';
2
- import { isNil } from 'lodash';
3
2
  export class TextStateElement {
4
3
  constructor(textStates, width, height, logger, version, faultFlickers) {
5
4
  this.textStates = textStates;
@@ -23,7 +22,7 @@ export class TextStateElement {
23
22
  return;
24
23
  }
25
24
  const content = textState.text.content;
26
- if (content === '') {
25
+ if (content === '' || content == null) {
27
26
  this.removeForeignObjectlement();
28
27
  return;
29
28
  }
@@ -33,72 +32,51 @@ export class TextStateElement {
33
32
  this.logger.debug('The font is undefined.');
34
33
  return;
35
34
  }
36
- const foreignObjectElement = this.getforeignObjectElement();
37
- foreignObjectElement.innerHTML = '';
38
- const text = this.createNewForeignObjectText(content, font);
39
- foreignObjectElement.appendChild(text);
40
- this.doFaultFlicker(foreignObjectElement, stateId);
35
+ const textElement = this.getforeignObjectElement();
36
+ // 清空旧内容
37
+ textElement.textContent = '';
38
+ // 设置 text-anchor 和 dominant-baseline
39
+ textElement.setAttribute('text-anchor', 'middle');
40
+ textElement.setAttribute('dominant-baseline', 'middle');
41
+ textElement.setAttribute('pointer-events', 'auto');
42
+ // 拆分换行
43
+ const lines = content.split('\n');
44
+ const fontSize = parseInt(font.fontSize, 10);
45
+ const lineHeight = fontSize + 4;
46
+ // 总高度 = 行数 * 行高
47
+ const totalHeight = lines.length * lineHeight;
48
+ // 调整文本整体垂直居中(通过 dy)
49
+ const startY = (this.height / 2) - (totalHeight / 2) + (lineHeight / 2);
50
+ // 添加每行文本
51
+ for (let i = 0; i < lines.length; i++) {
52
+ const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
53
+ tspan.setAttribute('x', (this.width / 2).toString());
54
+ tspan.setAttribute('y', startY + i * lineHeight + 'px');
55
+ tspan.textContent = lines[i].replace(/ /g, '\u00A0');
56
+ tspan.setAttribute('font-size', font.fontSize);
57
+ tspan.setAttribute('fill', font.color);
58
+ tspan.setAttribute('font-family', font.fontFamily);
59
+ tspan.setAttribute('font-weight', font.isBold ? 'bold' : 'normal');
60
+ tspan.setAttribute('font-style', font.isItalic ? 'italic' : 'normal');
61
+ tspan.setAttribute('text-decoration', font.isUnderline ? 'underline' : 'none');
62
+ tspan.setAttribute('text-anchor', 'middle');
63
+ tspan.setAttribute('dominant-baseline', 'middle');
64
+ textElement.appendChild(tspan);
65
+ }
66
+ this.doFaultFlicker(textElement, stateId);
41
67
  }
42
68
  getforeignObjectElement() {
43
69
  if (!this.textElement) {
44
- this.textElement = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
45
- this.textElement.setAttribute('width', this.width.toString());
46
- this.textElement.setAttribute('height', this.height.toString());
70
+ this.textElement = document.createElementNS('http://www.w3.org/2000/svg', 'text');
71
+ this.textElement.setAttribute('x', (this.width / 2).toString());
72
+ this.textElement.setAttribute('y', (this.height / 2).toString());
73
+ this.textElement.setAttribute('text-anchor', 'middle');
74
+ this.textElement.setAttribute('dominant-baseline', 'middle');
75
+ this.textElement.setAttribute('pointer-events', 'auto'); // 确保能接收事件
47
76
  this._element.appendChild(this.textElement);
48
77
  }
49
78
  return this.textElement;
50
79
  }
51
- createNewForeignObjectText(content, font) {
52
- if (font) {
53
- font.fontFamily += ',msyh';
54
- }
55
- const bodyDiv = document.createElement('div');
56
- bodyDiv.style.textAlign = font.textAlign ? font.textAlign : 'center';
57
- bodyDiv.style.userSelect = 'none';
58
- bodyDiv.style.display = 'table-cell';
59
- bodyDiv.style.verticalAlign = 'middle';
60
- if (isNil(content)) {
61
- content = '';
62
- }
63
- let textArray = content.toString().split('\n');
64
- textArray = textArray.map(item => {
65
- return item.toString().replace(/\s/g, '&nbsp;');
66
- });
67
- const fragment = document.createDocumentFragment();
68
- for (let index = 0; index < textArray.length; index++) {
69
- const textDiv = document.createElement('div');
70
- textDiv.innerHTML = textArray[index] ? textArray[index] : '&nbsp;';
71
- let fontString = '';
72
- if (font.isItalic) {
73
- fontString += 'italic ';
74
- }
75
- if (font.isBold) {
76
- fontString += 'bold ';
77
- }
78
- textDiv.style.wordBreak = 'break-word';
79
- textDiv.style.color = font.color;
80
- let lineHeight = 0;
81
- lineHeight = parseInt(font.fontSize, 10) + 5;
82
- fontString += font.fontSize + 'px/' + lineHeight + 'px ' + font.fontFamily;
83
- textDiv.style.font = fontString;
84
- if (font.isUnderline) {
85
- textDiv.style.textDecoration = 'underline';
86
- }
87
- fragment.appendChild(textDiv);
88
- }
89
- bodyDiv.appendChild(fragment);
90
- const contentDiv = document.createElement('div');
91
- contentDiv.style.display = 'table';
92
- contentDiv.style.width = '100%';
93
- contentDiv.style.height = '100%';
94
- contentDiv.appendChild(bodyDiv);
95
- const containerDiv = document.createElement('div');
96
- containerDiv.style.overflow = 'hidden';
97
- containerDiv.style.width = this.width.toString() + 'px';
98
- containerDiv.style.height = this.height.toString() + 'px';
99
- containerDiv.appendChild(contentDiv);
100
- return containerDiv;
101
- }
102
80
  removeForeignObjectlement() {
103
81
  if (this.textElement) {
104
82
  this._element.removeChild(this.textElement);
@@ -1 +1 @@
1
- [{"__symbolic":"module","version":4,"metadata":{"TextStateElement":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","name":"Array","arguments":[{"__symbolic":"reference","module":"./text-state.model","name":"TextState","line":18,"character":45}]},{"__symbolic":"reference","name":"number"},{"__symbolic":"reference","name":"number"},{"__symbolic":"reference","module":"../../../logger","name":"LoggerService","line":21,"character":33},{"__symbolic":"reference","name":"number"},{"__symbolic":"reference","name":"Array","arguments":[{"__symbolic":"reference","module":"../../../model/switch-indicator-light/indicator-light-fault-flicker","name":"IndicatorLightFaultFlicker","line":23,"character":41}]}]}],"switchToState":[{"__symbolic":"method"}],"getforeignObjectElement":[{"__symbolic":"method"}],"createNewForeignObjectText":[{"__symbolic":"method"}],"removeForeignObjectlement":[{"__symbolic":"method"}],"doFaultFlicker":[{"__symbolic":"method"}],"clearFlickerInterval":[{"__symbolic":"method"}]}}}}]
1
+ [{"__symbolic":"module","version":4,"metadata":{"TextStateElement":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","name":"Array","arguments":[{"__symbolic":"reference","module":"./text-state.model","name":"TextState","line":17,"character":45}]},{"__symbolic":"reference","name":"number"},{"__symbolic":"reference","name":"number"},{"__symbolic":"reference","module":"../../../logger","name":"LoggerService","line":20,"character":33},{"__symbolic":"reference","name":"number"},{"__symbolic":"reference","name":"Array","arguments":[{"__symbolic":"reference","module":"../../../model/switch-indicator-light/indicator-light-fault-flicker","name":"IndicatorLightFaultFlicker","line":22,"character":41}]}]}],"switchToState":[{"__symbolic":"method"}],"getforeignObjectElement":[{"__symbolic":"method"}],"removeForeignObjectlement":[{"__symbolic":"method"}],"doFaultFlicker":[{"__symbolic":"method"}],"clearFlickerInterval":[{"__symbolic":"method"}]}}}}]
@@ -15,4 +15,5 @@ export declare class BitSwitchOperator implements SwitchOperator {
15
15
  constructor(settings: BitSwitchSettings, variableCommunicator: VariableCommunicator, variableStore: VariableStore, signalRAppId: string);
16
16
  canExecute(): boolean;
17
17
  execute(): Promise<VariableOptionModel>;
18
+ writeValue(value: any): Promise<VariableOptionModel>;
18
19
  }
@@ -72,6 +72,8 @@ export class BitSwitchOperator {
72
72
  }
73
73
  }
74
74
  break;
75
+ case BitSwitchOperation.Restoration:
76
+ break;
75
77
  default:
76
78
  throw new Error(`Unknown BitSwitchOperation:${settings.operation}`);
77
79
  }
@@ -85,4 +87,21 @@ export class BitSwitchOperator {
85
87
  newValue: newValue
86
88
  });
87
89
  }
90
+ writeValue(value) {
91
+ if (this.settings.isBitwiseIndex) {
92
+ this.variableCommunicator.writeWordByBit(this.variableName, this.settings.bitIndex, value).subscribe();
93
+ }
94
+ else {
95
+ this.variableCommunicator.write(this.variableName, value).subscribe();
96
+ }
97
+ let originValue;
98
+ if (this.currentValue && this.currentValue.value !== undefined) {
99
+ originValue = this.currentValue.value;
100
+ }
101
+ return Promise.resolve({
102
+ variableName: this.variableName,
103
+ originValue: originValue,
104
+ newValue: value
105
+ });
106
+ }
88
107
  }
@@ -1 +1 @@
1
- [{"__symbolic":"module","version":4,"metadata":{"BitSwitchOperator":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../../model","name":"BitSwitchSettings","line":21,"character":43},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":21,"character":101},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":22,"character":40},{"__symbolic":"reference","name":"string"}]}],"canExecute":[{"__symbolic":"method"}],"execute":[{"__symbolic":"method"}]}}}}]
1
+ [{"__symbolic":"module","version":4,"metadata":{"BitSwitchOperator":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../../model","name":"BitSwitchSettings","line":21,"character":43},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":21,"character":101},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":22,"character":40},{"__symbolic":"reference","name":"string"}]}],"canExecute":[{"__symbolic":"method"}],"execute":[{"__symbolic":"method"}],"writeValue":[{"__symbolic":"method"}]}}}}]
@@ -19,9 +19,17 @@ export declare class SwitchIndicatorLightElement extends ConditionalEnableElemen
19
19
  private graphStateElement?;
20
20
  private textStateElement;
21
21
  private isMobileMode;
22
+ private isBitRestoration;
23
+ private isVerifiedForRestoration;
24
+ private restorationTimer;
25
+ private isWriteRestorationDownValue;
26
+ private onDocMouseUp;
22
27
  constructor(element: HTMLElement, injector: Injector, modalService: BsModalService, variableCommunicator: VariableCommunicator, graphStore: GraphStore, permissionChecker: PermissionChecker, operationRecordService: OperationRecordService, securityChecker: SecurityChecker, variableStore: VariableStore, localization: Localization, signalRAppId: string);
28
+ handleMouseUp(): void;
29
+ private initOnDocMouseUpEvent;
23
30
  private checkElementPassword;
24
31
  private doSwitchOperator;
32
+ private writeValue;
25
33
  private initSwitchOperator;
26
34
  private initIndictorLightOperator;
27
35
  private currentStateIdChange;
@@ -1,7 +1,7 @@
1
1
  import { LOGGER_SERVICE_TOKEN } from '../../logger';
2
2
  import * as d3 from 'd3-selection';
3
3
  import { isUndefined } from 'lodash';
4
- import { IndicatorLightType, SwitchType, State } from '../../model';
4
+ import { IndicatorLightType, SwitchType, State, BitSwitchOperation } from '../../model';
5
5
  import { VariableState } from '../../communication';
6
6
  import { ConditionalEnableElement } from '../base/conditional-enable-element';
7
7
  import { GraphStateElement } from '../shared/graph/graph-state-element';
@@ -23,13 +23,17 @@ export class SwitchIndicatorLightElement extends ConditionalEnableElement {
23
23
  this.graphStore = graphStore;
24
24
  this.operationRecordService = operationRecordService;
25
25
  this.securityChecker = securityChecker;
26
+ this.isBitRestoration = false; // 是否是 位设定且执行设置是复位
27
+ this.isVerifiedForRestoration = false; // 位设定且执行设置是复位情况下,是否已经完成了验证
28
+ this.isWriteRestorationDownValue = false;
26
29
  this.logger = injector.get(LOGGER_SERVICE_TOKEN);
27
30
  this.isMobileMode = DisplayMode.Mobile === injector.get(GlobalSettings).displayMode;
28
31
  this.checkState();
29
32
  if (this.model.useSwitch) {
30
33
  this.initSwitchOperator();
31
34
  this.rootElement.style('cursor', 'hand');
32
- this.rootElement.on('mousedown', () => {
35
+ const isMobile = navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i);
36
+ this.rootElement.on(this.isMobileMode && isMobile ? 'touchstart' : 'mousedown', () => {
33
37
  if (!this.isInitialized) {
34
38
  return;
35
39
  }
@@ -43,31 +47,39 @@ export class SwitchIndicatorLightElement extends ConditionalEnableElement {
43
47
  return;
44
48
  }
45
49
  if (this.switchOperator.canExecute()) {
46
- if (this.model.useSecurity) {
47
- const modalRef = this.modalService.show(ConfirmOperationModalComponent, { backdrop: 'static', class: 'gui-modal-dialog-position', animated: false });
48
- const onClosedSub = modalRef.content.onClosed.subscribe(result => {
49
- modalRef.hide();
50
- onClosedSub.unsubscribe();
51
- if (result) {
52
- this.checkElementPassword();
50
+ if (!this.isBitRestoration || !this.isVerifiedForRestoration) {
51
+ if (this.model.useSecurity) {
52
+ const modalRef = this.modalService.show(ConfirmOperationModalComponent, { backdrop: 'static', class: 'gui-modal-dialog-position', animated: false });
53
+ const onClosedSub = modalRef.content.onClosed.subscribe(result => {
54
+ modalRef.hide();
55
+ onClosedSub.unsubscribe();
56
+ if (result) {
57
+ this.checkElementPassword(true);
58
+ }
59
+ });
60
+ }
61
+ else {
62
+ this.checkElementPassword(false);
63
+ if (!this.model.useIndicatorLight) {
64
+ this.switchToState(1);
53
65
  }
54
- });
66
+ }
55
67
  }
56
68
  else {
57
- this.checkElementPassword();
58
- if (!this.model.useIndicatorLight && !this.isMobileMode) {
59
- this.switchToState(1);
60
- }
69
+ document.addEventListener(this.isMobileMode ? 'touchend' : 'mouseup', this.onDocMouseUp);
70
+ this.restorationTimer = setTimeout(() => {
71
+ this.writeValue(1);
72
+ this.isWriteRestorationDownValue = true;
73
+ }, 1000);
61
74
  }
62
75
  d3.event.preventDefault();
63
76
  }
64
77
  });
65
- if (!this.model.useIndicatorLight && !this.isMobileMode) {
66
- this.rootElement.on('mouseup', () => {
67
- this.switchToState(0);
68
- d3.event.preventDefault();
69
- });
70
- }
78
+ this.rootElement.on(this.isMobileMode && isMobile ? 'touchend' : 'mouseup', () => {
79
+ this.handleMouseUp();
80
+ d3.event.stopPropagation();
81
+ });
82
+ this.initOnDocMouseUpEvent();
71
83
  }
72
84
  this.initGraphAndText();
73
85
  if (this.model.useIndicatorLight) {
@@ -77,19 +89,62 @@ export class SwitchIndicatorLightElement extends ConditionalEnableElement {
77
89
  this.switchToState(0);
78
90
  }
79
91
  }
80
- checkElementPassword() {
92
+ handleMouseUp() {
93
+ if (this.restorationTimer) {
94
+ clearTimeout(this.restorationTimer);
95
+ this.restorationTimer = undefined;
96
+ }
97
+ if (this.isBitRestoration && this.isWriteRestorationDownValue) {
98
+ this.writeValue(0);
99
+ }
100
+ document.removeEventListener(this.isMobileMode ? 'touchend' : 'mouseup', this.onDocMouseUp);
101
+ this.isVerifiedForRestoration = false;
102
+ this.isWriteRestorationDownValue = false;
103
+ if (!this.model.useIndicatorLight) {
104
+ this.switchToState(0);
105
+ if (d3.event) {
106
+ d3.event.preventDefault();
107
+ }
108
+ }
109
+ }
110
+ initOnDocMouseUpEvent() {
111
+ this.onDocMouseUp = () => {
112
+ this.handleMouseUp();
113
+ };
114
+ }
115
+ checkElementPassword(afterConfirm) {
81
116
  if (this.model.enablePassword) {
82
117
  const modalRef = this.modalService.show(VerifyPasswordModalComponent, { initialState: { securityChecker: this.securityChecker }, backdrop: 'static', class: 'gui-modal-dialog-position', animated: false });
83
118
  const onClosedSub = modalRef.content.onClosed.subscribe(result => {
84
119
  modalRef.hide();
85
120
  onClosedSub.unsubscribe();
86
121
  if (result) {
87
- this.doSwitchOperator();
122
+ if (!this.isBitRestoration) {
123
+ this.doSwitchOperator();
124
+ }
125
+ else {
126
+ this.isVerifiedForRestoration = true;
127
+ }
88
128
  }
89
129
  });
90
130
  }
91
131
  else {
92
- this.doSwitchOperator();
132
+ if (!this.isBitRestoration) {
133
+ this.doSwitchOperator();
134
+ }
135
+ else {
136
+ if (afterConfirm) {
137
+ this.isVerifiedForRestoration = true;
138
+ }
139
+ else {
140
+ this.isVerifiedForRestoration = true;
141
+ document.addEventListener(this.isMobileMode ? 'touchend' : 'mouseup', this.onDocMouseUp);
142
+ this.restorationTimer = setTimeout(() => {
143
+ this.writeValue(1);
144
+ this.isWriteRestorationDownValue = true;
145
+ }, 1000);
146
+ }
147
+ }
93
148
  }
94
149
  }
95
150
  doSwitchOperator() {
@@ -106,12 +161,27 @@ export class SwitchIndicatorLightElement extends ConditionalEnableElement {
106
161
  throw new Error('Failure of the operation record:switchOperator');
107
162
  });
108
163
  }
164
+ writeValue(value) {
165
+ this.switchOperator.writeValue(value).then(args => {
166
+ if (this.model.isRecordOperation || this.model.isRecordOperation === undefined) {
167
+ if (args.newValue !== undefined || args.originValue !== undefined) {
168
+ this.operationRecordService.record({
169
+ variableOptionModel: args,
170
+ operationDescription: this.model.operationDescription
171
+ });
172
+ }
173
+ }
174
+ }).catch(() => {
175
+ throw new Error('Failure of the operation record:switchOperator');
176
+ });
177
+ }
109
178
  initSwitchOperator() {
110
179
  const settings = this.model.switchSettings;
111
180
  switch (settings.type) {
112
181
  case SwitchType.Bit:
113
182
  this.switchOperator =
114
183
  new BitSwitchOperator(settings.settings, this.variableCommunicator, this.variableStore, this.signalRAppId);
184
+ this.isBitRestoration = settings.settings.operation === BitSwitchOperation.Restoration;
115
185
  break;
116
186
  case SwitchType.Word:
117
187
  this.switchOperator =
@@ -1 +1 @@
1
- [{"__symbolic":"module","version":4,"metadata":{"SwitchIndicatorLightElement":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"../base/conditional-enable-element","name":"ConditionalEnableElement","line":32,"character":49},"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"error","message":"Could not resolve type","line":44,"character":25,"context":{"typeName":"HTMLElement"}},{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":45,"character":18},{"__symbolic":"reference","module":"ngx-bootstrap/modal","name":"BsModalService","line":46,"character":39},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":47,"character":30},{"__symbolic":"reference","module":"../../config","name":"GraphStore","line":48,"character":37},{"__symbolic":"reference","module":"../../service","name":"PermissionChecker","line":49,"character":27},{"__symbolic":"reference","module":"../../service","name":"OperationRecordService","line":50,"character":49},{"__symbolic":"reference","module":"../../security","name":"SecurityChecker","line":51,"character":42},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":52,"character":23},{"__symbolic":"reference","module":"../../localization","name":"Localization","line":53,"character":22},{"__symbolic":"reference","name":"string"}]}],"checkElementPassword":[{"__symbolic":"method"}],"doSwitchOperator":[{"__symbolic":"method"}],"initSwitchOperator":[{"__symbolic":"method"}],"initIndictorLightOperator":[{"__symbolic":"method"}],"currentStateIdChange":[{"__symbolic":"method"}],"switchToState":[{"__symbolic":"method"}],"initGraphAndText":[{"__symbolic":"method"}],"checkState":[{"__symbolic":"method"}]}}}}]
1
+ [{"__symbolic":"module","version":4,"metadata":{"SwitchIndicatorLightElement":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"../base/conditional-enable-element","name":"ConditionalEnableElement","line":32,"character":49},"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"error","message":"Could not resolve type","line":50,"character":25,"context":{"typeName":"HTMLElement"}},{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":51,"character":18},{"__symbolic":"reference","module":"ngx-bootstrap/modal","name":"BsModalService","line":52,"character":39},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":53,"character":30},{"__symbolic":"reference","module":"../../config","name":"GraphStore","line":54,"character":37},{"__symbolic":"reference","module":"../../service","name":"PermissionChecker","line":55,"character":27},{"__symbolic":"reference","module":"../../service","name":"OperationRecordService","line":56,"character":49},{"__symbolic":"reference","module":"../../security","name":"SecurityChecker","line":57,"character":42},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":58,"character":23},{"__symbolic":"reference","module":"../../localization","name":"Localization","line":59,"character":22},{"__symbolic":"reference","name":"string"}]}],"handleMouseUp":[{"__symbolic":"method"}],"initOnDocMouseUpEvent":[{"__symbolic":"method"}],"checkElementPassword":[{"__symbolic":"method"}],"doSwitchOperator":[{"__symbolic":"method"}],"writeValue":[{"__symbolic":"method"}],"initSwitchOperator":[{"__symbolic":"method"}],"initIndictorLightOperator":[{"__symbolic":"method"}],"currentStateIdChange":[{"__symbolic":"method"}],"switchToState":[{"__symbolic":"method"}],"initGraphAndText":[{"__symbolic":"method"}],"checkState":[{"__symbolic":"method"}]}}}}]
@@ -2,4 +2,5 @@ import { VariableOptionModel } from '../../service';
2
2
  export interface SwitchOperator {
3
3
  canExecute(): boolean;
4
4
  execute(): Promise<VariableOptionModel>;
5
+ writeValue(value: number): Promise<VariableOptionModel>;
5
6
  }
@@ -14,4 +14,5 @@ export declare class WordSwitchOperator implements SwitchOperator {
14
14
  constructor(settings: WordSwitchSettings, variableCommunicator: VariableCommunicator, variableStore: VariableStore, signalRAppId: string);
15
15
  canExecute(): boolean;
16
16
  execute(): Promise<VariableOptionModel>;
17
+ writeValue(value: any): Promise<VariableOptionModel>;
17
18
  }
@@ -66,4 +66,10 @@ export class WordSwitchOperator {
66
66
  newValue: newValue
67
67
  });
68
68
  }
69
+ // 此方法为 位设定添加的,字设定目前不会用到,为了解决接口error,添加一个空实现
70
+ writeValue(value) {
71
+ return Promise.resolve({
72
+ newValue: value
73
+ });
74
+ }
69
75
  }
@@ -1 +1 @@
1
- [{"__symbolic":"module","version":4,"metadata":{"WordSwitchOperator":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../../model","name":"WordSwitchSettings","line":20,"character":43},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":20,"character":102},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":21,"character":40},{"__symbolic":"reference","name":"string"}]}],"canExecute":[{"__symbolic":"method"}],"execute":[{"__symbolic":"method"}]}}}}]
1
+ [{"__symbolic":"module","version":4,"metadata":{"WordSwitchOperator":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../../model","name":"WordSwitchSettings","line":20,"character":43},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":20,"character":102},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":21,"character":40},{"__symbolic":"reference","name":"string"}]}],"canExecute":[{"__symbolic":"method"}],"execute":[{"__symbolic":"method"}],"writeValue":[{"__symbolic":"method"}]}}}}]
@@ -16,6 +16,9 @@ export declare class VideoElement extends ConditionalDisplayElement {
16
16
  private videoId;
17
17
  private isShow;
18
18
  private videoPlayer;
19
+ private refreshTimer;
20
+ private isFullscreen;
21
+ private videoUrl;
19
22
  constructor(element: HTMLElement, injector: Injector, permissionChecker: PermissionChecker, variableCommunicator: VariableCommunicator, variableStore: VariableStore, videoService: VideoService, guiSize: Size, svgRootClass: string, signalRAppId: string);
20
23
  dispose(): void;
21
24
  hide(): void;
@@ -24,4 +27,5 @@ export declare class VideoElement extends ConditionalDisplayElement {
24
27
  private initVideo;
25
28
  private addVideoAddressToolTip;
26
29
  private setAndroidVideo;
30
+ private setIosVideo;
27
31
  }
@@ -11,6 +11,7 @@ export class VideoElement extends ConditionalDisplayElement {
11
11
  this.guiSize = guiSize;
12
12
  this.svgRootClass = svgRootClass;
13
13
  this.videoId = '';
14
+ this.isFullscreen = false;
14
15
  this.isMobileMode = DisplayMode.Mobile === injector.get(GlobalSettings).displayMode;
15
16
  this.localization = injector.get(LOCALIZATION);
16
17
  this.init();
@@ -50,12 +51,13 @@ export class VideoElement extends ConditionalDisplayElement {
50
51
  .attr('width', this.model.size.width)
51
52
  .attr('height', this.model.size.height);
52
53
  this.videoService.getVideoUrl(this.model.videoTag).then(result => {
53
- this.initVideo(result.url, result.isMobileType, this.videoId);
54
+ this.videoUrl = result.url;
55
+ this.initVideo(result.url, this.videoId);
54
56
  }).catch(() => {
55
57
  throw new Error('Failure of the videoService');
56
58
  });
57
59
  }
58
- initVideo(videoUrl, isMobileType, videoId) {
60
+ initVideo(videoUrl, videoId) {
59
61
  const patt = /https:.+.m3u8/;
60
62
  if (videoUrl.indexOf('http:') !== -1) {
61
63
  videoUrl = videoUrl.replace('http:', 'https:');
@@ -68,6 +70,8 @@ export class VideoElement extends ConditionalDisplayElement {
68
70
  this.addVideoAddressToolTip(videoToolTip);
69
71
  return;
70
72
  }
73
+ const isAndroid = !!navigator.userAgent.match(/(Android)/i);
74
+ const isIos = !!navigator.userAgent.match(/(Mac)/i);
71
75
  const currentRect = this.$element.find('rect#rect' + videoId).first();
72
76
  if (!currentRect.length) {
73
77
  return;
@@ -77,17 +81,19 @@ export class VideoElement extends ConditionalDisplayElement {
77
81
  const chartHeight = clientRect.height;
78
82
  const left = this.model.location.x / this.guiSize.width * $('.' + this.svgRootClass).find('.svg-content').width();
79
83
  const top = this.model.location.y / this.guiSize.height * $('.' + this.svgRootClass).find('.svg-content').height();
80
- let videoHtml = `<video scareX="${this.model.location.x / this.guiSize.width}"
81
- scareY="${this.model.location.y / this.guiSize.height}" id="${videoId}" src="${videoUrl}" style="
82
- position: absolute;top:${top}px;left:${left}px;width:${chartWidth}px;height:${chartHeight}px;object-fit:fill;z-index:0"
83
- playsInline webkit-playsinline `;
84
- const isAndroid = !!navigator.userAgent.match(/(Android)/i);
84
+ const scareX = this.model.location.x / this.guiSize.width;
85
+ const scareY = this.model.location.y / this.guiSize.height;
86
+ if (isIos) {
87
+ videoUrl = videoUrl + '#t=1';
88
+ }
89
+ const preload = isIos ? ' preload=\'metadata\'' : '';
90
+ let videoHtml = `<video scareX="${scareX}"
91
+ scareY="${scareY}" id="${videoId}" ${preload} src="${videoUrl}" width="${chartWidth}" height="${chartHeight}"
92
+ style="position: absolute;top:${top}px;left:${left}px;object-fit:fill;z-index:0;"
93
+ playsInline webkit-playsinline `;
85
94
  if (this.isMobileMode) {
86
95
  if (isAndroid) {
87
- if (isMobileType) {
88
- videoHtml += ' controls ';
89
- }
90
- videoHtml += ' autoplay muted></video>';
96
+ videoHtml += ' muted></video>';
91
97
  }
92
98
  else {
93
99
  videoHtml += ' controls muted></video>';
@@ -100,10 +106,31 @@ export class VideoElement extends ConditionalDisplayElement {
100
106
  if (this.isShow === false) {
101
107
  $('#' + this.videoId).hide();
102
108
  }
103
- this.videoPlayer = new EZUIPlayer(videoId);
104
- if (isAndroid && !isMobileType) {
105
- this.setAndroidVideo(videoId);
106
- }
109
+ setTimeout(() => {
110
+ if (isAndroid) {
111
+ this.setAndroidVideo(videoId);
112
+ }
113
+ else if (isIos) {
114
+ this.setIosVideo(this.videoUrl, videoId);
115
+ }
116
+ try {
117
+ this.videoPlayer = new EZUIPlayer(videoId);
118
+ if (isAndroid) {
119
+ // 确保在 EZUIPlayer 初始化后才调用 play 方法
120
+ this.videoPlayer.on('canplay', () => {
121
+ this.videoPlayer.play();
122
+ });
123
+ }
124
+ }
125
+ catch (err) {
126
+ console.log(err);
127
+ }
128
+ }, 1000);
129
+ const style = document.createElement('style');
130
+ style.innerHTML = `#${videoId}::-webkit-media-controls-enclosure {
131
+ display: none;
132
+ }`;
133
+ document.head.append();
107
134
  }
108
135
  addVideoAddressToolTip(videoToolTip) {
109
136
  const size = this.model.size;
@@ -126,35 +153,68 @@ export class VideoElement extends ConditionalDisplayElement {
126
153
  this.$element.append(textElement.Element);
127
154
  }
128
155
  setAndroidVideo(videoId) {
129
- let isFullscreen = false;
130
156
  const videoElement = $('#' + videoId);
131
157
  let preHeight = videoElement.height();
132
158
  let preWidth = videoElement.width();
133
159
  let preTop = videoElement.css('top');
134
160
  let preLeft = videoElement.css('left');
161
+ const { StatusBar } = window;
135
162
  videoElement.on('click', () => {
136
- if (!isFullscreen) {
163
+ if (!this.isFullscreen) {
164
+ if (StatusBar) {
165
+ StatusBar.hide();
166
+ }
137
167
  preHeight = videoElement.height();
138
168
  preWidth = videoElement.width();
139
169
  preTop = videoElement.css('top');
140
170
  preLeft = videoElement.css('left');
141
- const width = document.body.clientWidth;
142
- const height = width * 9 / 16;
171
+ const width = document.documentElement.clientWidth;
172
+ const height = document.documentElement.clientHeight;
173
+ videoElement.css('object-fit', 'contain');
174
+ videoElement.css('background', '#000000');
143
175
  videoElement.css('width', width + 'px');
144
176
  videoElement.css('height', height + 'px');
145
177
  videoElement.css('left', '0px');
146
178
  videoElement.css('top', '0px');
147
179
  videoElement.css('z-index', '99');
148
- isFullscreen = true;
180
+ videoElement.css('position', 'fixed');
181
+ this.isFullscreen = true;
182
+ try {
183
+ screen.orientation.lock(screen.orientation.type);
184
+ }
185
+ catch (error) {
186
+ console.error(error);
187
+ }
149
188
  }
150
189
  else {
190
+ videoElement.css('object-fit', 'fill');
151
191
  videoElement.css('width', preWidth + 'px');
152
192
  videoElement.css('height', preHeight + 'px');
153
193
  videoElement.css('left', preLeft);
154
194
  videoElement.css('top', preTop);
155
195
  videoElement.css('z-index', '0');
156
- isFullscreen = false;
196
+ videoElement.css('position', 'absolute');
197
+ this.isFullscreen = false;
198
+ try {
199
+ if (screen.orientation.type.includes('portrait')) {
200
+ StatusBar.show();
201
+ }
202
+ }
203
+ catch (error) {
204
+ console.error(error);
205
+ }
157
206
  }
158
207
  });
159
208
  }
209
+ setIosVideo(videoUrl, videoId) {
210
+ const video = $('#' + this.videoId);
211
+ video.on('webkitendfullscreen', () => {
212
+ video.remove();
213
+ clearTimeout(this.refreshTimer);
214
+ this.refreshTimer = null;
215
+ this.refreshTimer = setTimeout(() => {
216
+ this.initVideo(videoUrl, videoId);
217
+ }, 500);
218
+ });
219
+ }
160
220
  }
@@ -1 +1 @@
1
- [{"__symbolic":"module","version":4,"metadata":{"VideoElement":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"../base/conditional-display-element","name":"ConditionalDisplayElement","line":15,"character":34},"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"error","message":"Could not resolve type","line":23,"character":25,"context":{"typeName":"HTMLElement"}},{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":24,"character":18},{"__symbolic":"reference","module":"../../service","name":"PermissionChecker","line":25,"character":27},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":26,"character":30},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":27,"character":23},{"__symbolic":"reference","module":"../../service","name":"VideoService","line":28,"character":39},{"__symbolic":"reference","module":"../../model","name":"Size","line":29,"character":34},{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","name":"string"}]}],"dispose":[{"__symbolic":"method"}],"hide":[{"__symbolic":"method"}],"show":[{"__symbolic":"method"}],"init":[{"__symbolic":"method"}],"initVideo":[{"__symbolic":"method"}],"addVideoAddressToolTip":[{"__symbolic":"method"}],"setAndroidVideo":[{"__symbolic":"method"}]}}}}]
1
+ [{"__symbolic":"module","version":4,"metadata":{"VideoElement":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"../base/conditional-display-element","name":"ConditionalDisplayElement","line":15,"character":34},"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"error","message":"Could not resolve type","line":27,"character":25,"context":{"typeName":"HTMLElement"}},{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":28,"character":18},{"__symbolic":"reference","module":"../../service","name":"PermissionChecker","line":29,"character":27},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":30,"character":30},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":31,"character":23},{"__symbolic":"reference","module":"../../service","name":"VideoService","line":32,"character":39},{"__symbolic":"reference","module":"../../model","name":"Size","line":33,"character":34},{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","name":"string"}]}],"dispose":[{"__symbolic":"method"}],"hide":[{"__symbolic":"method"}],"show":[{"__symbolic":"method"}],"init":[{"__symbolic":"method"}],"initVideo":[{"__symbolic":"method"}],"addVideoAddressToolTip":[{"__symbolic":"method"}],"setAndroidVideo":[{"__symbolic":"method"}],"setIosVideo":[{"__symbolic":"method"}]}}}}]