@flexem/fc-gui 3.0.0-alpha.124 → 3.0.0-alpha.125

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 (48) hide show
  1. package/bundles/@flexem/fc-gui.umd.js +899 -316
  2. package/bundles/@flexem/fc-gui.umd.js.map +1 -1
  3. package/bundles/@flexem/fc-gui.umd.min.js +4 -4
  4. package/bundles/@flexem/fc-gui.umd.min.js.map +1 -1
  5. package/communication/variable/variable-communicator.d.ts +2 -0
  6. package/elements/alarm/alarm-element.d.ts +17 -2
  7. package/elements/alarm/alarm-element.js +74 -6
  8. package/elements/alarm/alarm-element.metadata.json +1 -1
  9. package/elements/base/readable-element.js +14 -5
  10. package/elements/base/state-control-element.js +2 -2
  11. package/elements/historical-curve/historical-curve.element.d.ts +17 -2
  12. package/elements/historical-curve/historical-curve.element.js +64 -4
  13. package/elements/historical-curve/historical-curve.element.metadata.json +1 -1
  14. package/elements/main-element.js +7 -7
  15. package/elements/numerical-display/numerical-display-element.d.ts +9 -2
  16. package/elements/numerical-display/numerical-display-element.js +22 -2
  17. package/elements/numerical-display/numerical-display-element.metadata.json +1 -1
  18. package/elements/shared/text/text-element.d.ts +9 -0
  19. package/elements/shared/text/text-element.js +20 -0
  20. package/elements/shared/text/text-element.metadata.json +1 -1
  21. package/elements/shared/text/text-state-element.d.ts +15 -2
  22. package/elements/shared/text/text-state-element.js +70 -10
  23. package/elements/shared/text/text-state-element.metadata.json +1 -1
  24. package/elements/static-elements/hyperlink-element.d.ts +15 -1
  25. package/elements/static-elements/hyperlink-element.js +69 -10
  26. package/elements/static-elements/hyperlink-element.metadata.json +1 -1
  27. package/elements/static-elements/text-element.d.ts +14 -1
  28. package/elements/static-elements/text-element.js +64 -10
  29. package/elements/static-elements/text-element.metadata.json +1 -1
  30. package/elements/switch-indicator-light/switch-indicator-light-element.d.ts +7 -1
  31. package/elements/switch-indicator-light/switch-indicator-light-element.js +25 -2
  32. package/elements/switch-indicator-light/switch-indicator-light-element.metadata.json +1 -1
  33. package/elements/view-operation/view-operation.element.d.ts +23 -2
  34. package/elements/view-operation/view-operation.element.js +95 -1
  35. package/elements/view-operation/view-operation.element.metadata.json +1 -1
  36. package/gui/gui-context.d.ts +7 -1
  37. package/gui/gui-view.js +20 -4
  38. package/modal/write-value/write-value-modal-args.d.ts +3 -1
  39. package/modal/write-value/write-value-modal-args.js +2 -1
  40. package/modal/write-value/write-value-modal-args.metadata.json +1 -1
  41. package/modal/write-value/write-value-modal.component.d.ts +4 -0
  42. package/modal/write-value/write-value-modal.component.js +25 -0
  43. package/modal/write-value/write-value-modal.component.metadata.json +1 -1
  44. package/model/view-operation/view-operation-element.model.d.ts +7 -1
  45. package/package.json +1 -1
  46. package/remote/communication/variable/remote-variable-communicator.d.ts +15 -0
  47. package/remote/communication/variable/remote-variable-communicator.js +76 -2
  48. package/remote/communication/variable/remote-variable-communicator.metadata.json +1 -1
@@ -17,7 +17,7 @@ import { DisplayMode, GlobalSettings } from '../../settings';
17
17
  import { VariableUtil } from '../../utils/variable-util';
18
18
  import { VariableDefinition } from '../../communication/variable/variable-definition';
19
19
  export class SwitchIndicatorLightElement extends ConditionalEnableElement {
20
- constructor(element, injector, modalService, variableCommunicator, graphStore, permissionChecker, operationRecordService, securityChecker, variableStore, localization, signalRAppId, textLibraryService, languageService) {
20
+ constructor(element, injector, modalService, variableCommunicator, graphStore, permissionChecker, operationRecordService, securityChecker, variableStore, localization, signalRAppId, textLibraryService, languageService, guiContext) {
21
21
  super(element, permissionChecker, variableCommunicator, variableStore, localization, signalRAppId);
22
22
  this.modalService = modalService;
23
23
  this.graphStore = graphStore;
@@ -25,6 +25,7 @@ export class SwitchIndicatorLightElement extends ConditionalEnableElement {
25
25
  this.securityChecker = securityChecker;
26
26
  this.textLibraryService = textLibraryService;
27
27
  this.languageService = languageService;
28
+ this.guiContext = guiContext;
28
29
  this.isBitRestoration = false; // 是否是 位设定且执行设置是复位
29
30
  this.isVerifiedForRestoration = false; // 位设定且执行设置是复位情况下,是否已经完成了验证
30
31
  this.isWriteRestorationDownValue = false;
@@ -240,9 +241,31 @@ export class SwitchIndicatorLightElement extends ConditionalEnableElement {
240
241
  this.graphStateElement = new GraphStateElement(this.model.graphSetting, width, height, this.graphStore, this.logger, this.model.version, this.model.states);
241
242
  this.$element.append(this.graphStateElement.Element);
242
243
  }
243
- this.textStateElement = new TextStateElement(this.model.states, width, height, this.logger, this.model.version, this.model.states, this.model.textLibrary, this.textLibraryService, this.languageService);
244
+ this.textStateElement = new TextStateElement(this.model.states, width, height, this.logger, this.model.version, this.model.states, this.model.textLibrary, this.textLibraryService, this.languageService, this.guiContext);
244
245
  this.$element.append(this.textStateElement.Element);
245
246
  }
247
+ /**
248
+ * 释放资源
249
+ */
250
+ dispose() {
251
+ // 释放文本元素资源(取消语种变化订阅等)
252
+ if (this.textStateElement) {
253
+ this.textStateElement.dispose();
254
+ }
255
+ // 释放指示灯操作器资源
256
+ if (this.indicatorLightOperator) {
257
+ // indicatorLightOperator 可能有自己的dispose方法
258
+ }
259
+ // 清除定时器
260
+ if (this.restorationTimer) {
261
+ clearTimeout(this.restorationTimer);
262
+ this.restorationTimer = undefined;
263
+ }
264
+ // 移除事件监听
265
+ if (this.onDocMouseUp) {
266
+ document.removeEventListener(this.isMobileMode ? 'touchend' : 'mouseup', this.onDocMouseUp);
267
+ }
268
+ }
246
269
  checkState() {
247
270
  if (!this.model.states) {
248
271
  throw new Error('The switch indicator light\'s states is undefined.');
@@ -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":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"},{"__symbolic":"reference","module":"../../service","name":"TextLibraryService","line":61,"character":46},{"__symbolic":"reference","module":"../../service","name":"LanguageService","line":62,"character":43}]}],"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"}]}}}}]
1
+ [{"__symbolic":"module","version":4,"metadata":{"SwitchIndicatorLightElement":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"../base/conditional-enable-element","name":"ConditionalEnableElement","line":33,"character":49},"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"error","message":"Could not resolve type","line":51,"character":25,"context":{"typeName":"HTMLElement"}},{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":52,"character":18},{"__symbolic":"reference","module":"ngx-bootstrap/modal","name":"BsModalService","line":53,"character":39},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":54,"character":30},{"__symbolic":"reference","module":"../../config","name":"GraphStore","line":55,"character":37},{"__symbolic":"reference","module":"../../service","name":"PermissionChecker","line":56,"character":27},{"__symbolic":"reference","module":"../../service","name":"OperationRecordService","line":57,"character":49},{"__symbolic":"reference","module":"../../security","name":"SecurityChecker","line":58,"character":42},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":59,"character":23},{"__symbolic":"reference","module":"../../localization","name":"Localization","line":60,"character":22},{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","module":"../../service","name":"TextLibraryService","line":62,"character":46},{"__symbolic":"reference","module":"../../service","name":"LanguageService","line":63,"character":43},{"__symbolic":"reference","module":"../../gui/gui-context","name":"GuiContext","line":64,"character":38}]}],"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"}],"dispose":[{"__symbolic":"method"}],"checkState":[{"__symbolic":"method"}]}}}}]
@@ -3,11 +3,12 @@ import { BsModalService } from 'ngx-bootstrap/modal';
3
3
  import { Localization } from '../../localization';
4
4
  import { GraphStore, VariableStore } from '../../config';
5
5
  import { ViewOperationElementModel } from '../../model';
6
- import { PermissionChecker, OperationRecordService } from '../../service';
6
+ import { PermissionChecker, OperationRecordService, TextLibraryService, LanguageService } from '../../service';
7
7
  import { VariableCommunicator } from '../../communication';
8
8
  import { ConditionalEnableElement } from '../base/conditional-enable-element';
9
9
  import { PopupViewService } from '../../view/popup-view.service';
10
10
  import { SecurityChecker } from '../../security';
11
+ import { GuiContext } from '../../gui/gui-context';
11
12
  export declare class ViewOperationElement extends ConditionalEnableElement {
12
13
  private readonly modalService;
13
14
  private readonly graphStore;
@@ -16,13 +17,17 @@ export declare class ViewOperationElement extends ConditionalEnableElement {
16
17
  private readonly popupViewService;
17
18
  private readonly hostContainerId;
18
19
  private readonly el;
20
+ private readonly textLibraryService?;
21
+ private readonly languageService?;
22
+ private readonly guiContext?;
19
23
  protected model: ViewOperationElementModel;
20
24
  private readonly logger;
21
25
  private readonly viewService;
22
26
  private graphStateElement?;
27
+ private languageChangeSubscription?;
23
28
  private touchedScreenX;
24
29
  private touchedScreenY;
25
- constructor(element: HTMLElement, injector: Injector, modalService: BsModalService, variableCommunicator: VariableCommunicator, variableStore: VariableStore, graphStore: GraphStore, permissionChecker: PermissionChecker, operationRecordService: OperationRecordService, securityChecker: SecurityChecker, localization: Localization, popupViewService: PopupViewService, hostContainerId: string, el: ElementRef, signalRAppId: string);
30
+ constructor(element: HTMLElement, injector: Injector, modalService: BsModalService, variableCommunicator: VariableCommunicator, variableStore: VariableStore, graphStore: GraphStore, permissionChecker: PermissionChecker, operationRecordService: OperationRecordService, securityChecker: SecurityChecker, localization: Localization, popupViewService: PopupViewService, hostContainerId: string, el: ElementRef, signalRAppId: string, textLibraryService?: TextLibraryService, languageService?: LanguageService, guiContext?: GuiContext);
26
31
  private initElement;
27
32
  private switchToState;
28
33
  private initGraph;
@@ -33,4 +38,20 @@ export declare class ViewOperationElement extends ConditionalEnableElement {
33
38
  private closeView;
34
39
  private moveView;
35
40
  private recordViewOperation;
41
+ /**
42
+ * 订阅语种变化事件
43
+ */
44
+ private subscribeLanguageChange;
45
+ /**
46
+ * 更新文本内容(支持文本库和语种切换)
47
+ */
48
+ private updateTextContent;
49
+ /**
50
+ * 获取显示文本
51
+ */
52
+ private getDisplayText;
53
+ /**
54
+ * 释放资源
55
+ */
56
+ dispose(): void;
36
57
  }
@@ -9,7 +9,7 @@ import { ConfirmOperationModalComponent } from '../../modal/confirm-operation/co
9
9
  import { VerifyPasswordModalComponent } from '../../modal/verify-password/verify-password-modal.component';
10
10
  import { ViewService } from '../../view/view.service';
11
11
  export class ViewOperationElement extends ConditionalEnableElement {
12
- constructor(element, injector, modalService, variableCommunicator, variableStore, graphStore, permissionChecker, operationRecordService, securityChecker, localization, popupViewService, hostContainerId, el, signalRAppId) {
12
+ constructor(element, injector, modalService, variableCommunicator, variableStore, graphStore, permissionChecker, operationRecordService, securityChecker, localization, popupViewService, hostContainerId, el, signalRAppId, textLibraryService, languageService, guiContext) {
13
13
  super(element, permissionChecker, variableCommunicator, variableStore, localization, signalRAppId);
14
14
  this.modalService = modalService;
15
15
  this.graphStore = graphStore;
@@ -18,20 +18,27 @@ export class ViewOperationElement extends ConditionalEnableElement {
18
18
  this.popupViewService = popupViewService;
19
19
  this.hostContainerId = hostContainerId;
20
20
  this.el = el;
21
+ this.textLibraryService = textLibraryService;
22
+ this.languageService = languageService;
23
+ this.guiContext = guiContext;
21
24
  this.touchedScreenX = 0;
22
25
  this.touchedScreenY = 0;
23
26
  this.logger = injector.get(LOGGER_SERVICE_TOKEN);
24
27
  this.viewService = injector.get(ViewService);
25
28
  this.initElement();
29
+ this.subscribeLanguageChange();
26
30
  }
27
31
  initElement() {
28
32
  const width = this.model.size.width;
29
33
  const height = this.model.size.height;
30
34
  this.initGraph(width, height);
31
35
  this.rootElement.append('rect').attr('id', 'StateFrame').attr('width', width).attr('height', height).attr('fill', 'transparent');
36
+ // 初始化文本显示
32
37
  const $dateTimeText = this.$element.find('text').last();
33
38
  const fontStyle = this.model.label.font.fontStyle;
34
39
  $dateTimeText.css('font', fontStyle + ',msyh');
40
+ // 设置初始文本内容(支持文本库)
41
+ this.updateTextContent($dateTimeText);
35
42
  this.switchToState(0);
36
43
  this.rootElement.on('mousedown', () => {
37
44
  if (!this.isInitialized) {
@@ -199,4 +206,91 @@ export class ViewOperationElement extends ConditionalEnableElement {
199
206
  this.operationRecordService.record({ operationDescription: this.model.operationDescription });
200
207
  }
201
208
  }
209
+ /**
210
+ * 订阅语种变化事件
211
+ */
212
+ subscribeLanguageChange() {
213
+ // 只有使用文本库时才需要订阅语种变化
214
+ if (!this.model.textLibrary || this.model.textLibrary.labelType !== 'textLibrary') {
215
+ return;
216
+ }
217
+ if (this.guiContext && this.guiContext.languageChanged$) {
218
+ this.languageChangeSubscription = this.guiContext.languageChanged$.subscribe(() => {
219
+ // 更新文本内容
220
+ const $dateTimeText = this.$element.find('text').last();
221
+ this.updateTextContent($dateTimeText);
222
+ });
223
+ }
224
+ }
225
+ /**
226
+ * 更新文本内容(支持文本库和语种切换)
227
+ */
228
+ updateTextContent($textElement) {
229
+ const displayText = this.getDisplayText();
230
+ $textElement.text(displayText);
231
+ }
232
+ /**
233
+ * 获取显示文本
234
+ */
235
+ getDisplayText() {
236
+ var _a, _b, _c, _d, _e, _f;
237
+ // 检查是否使用文本库
238
+ if (this.model.textLibrary && this.model.textLibrary.labelType === 'textLibrary') {
239
+ const textLibraryId = this.model.textLibrary.selectedTextLibraryItem;
240
+ const textItem = this.model.textLibrary.selectedTextItem;
241
+ if (textLibraryId && textItem && this.textLibraryService) {
242
+ // 获取文本库数据
243
+ const textLibraryData = this.textLibraryService.getTextLibraryById(typeof textLibraryId === 'string' ? parseInt(textLibraryId, 10) : textLibraryId);
244
+ if (textLibraryData && textLibraryData.data) {
245
+ // 查找对应的文本条目
246
+ const textEntry = textLibraryData.data.find(entry => entry.key === textItem.toString());
247
+ if (textEntry) {
248
+ // 获取当前语种ID
249
+ const currentLanguageId = (_c = (_b = (_a = this.guiContext) === null || _a === void 0 ? void 0 : _a.getCurrentLanguageId) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : null;
250
+ // 确定要使用的语种代码(culture)
251
+ let targetLanguage;
252
+ const defaultLanguage = ((_d = this.languageService) === null || _d === void 0 ? void 0 : _d.getDefaultLanguage()) || 'zh-CN';
253
+ if (currentLanguageId === null || currentLanguageId === undefined) {
254
+ // 设备未设置当前语种,使用默认语种
255
+ targetLanguage = defaultLanguage;
256
+ }
257
+ else {
258
+ // 设备已设置当前语种,获取对应的语种代码
259
+ const currentLanguage = (_f = (_e = this.guiContext) === null || _e === void 0 ? void 0 : _e.getLanguageCultureById) === null || _f === void 0 ? void 0 : _f.call(_e, currentLanguageId);
260
+ if (currentLanguage) {
261
+ targetLanguage = currentLanguage;
262
+ }
263
+ else {
264
+ // 无法获取语种代码,使用默认语种
265
+ targetLanguage = defaultLanguage;
266
+ }
267
+ }
268
+ // 返回对应语种的文本
269
+ if (textEntry.cultures && textEntry.cultures[targetLanguage]) {
270
+ return textEntry.cultures[targetLanguage];
271
+ }
272
+ // 如果没有对应语种,返回空字符串
273
+ return '';
274
+ }
275
+ }
276
+ }
277
+ // 文本库配置但未找到数据,返回空字符串
278
+ return '';
279
+ }
280
+ // 默认返回文本内容
281
+ return this.model.label.content || '';
282
+ }
283
+ /**
284
+ * 释放资源
285
+ */
286
+ dispose() {
287
+ // 取消语种变化订阅
288
+ if (this.languageChangeSubscription) {
289
+ this.languageChangeSubscription.unsubscribe();
290
+ this.languageChangeSubscription = undefined;
291
+ }
292
+ if (this.$element) {
293
+ this.$element.remove();
294
+ }
295
+ }
202
296
  }
@@ -1 +1 @@
1
- [{"__symbolic":"module","version":4,"metadata":{"ViewOperationElement":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"../base/conditional-enable-element","name":"ConditionalEnableElement","line":20,"character":42},"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"error","message":"Could not resolve type","line":31,"character":25,"context":{"typeName":"HTMLElement"}},{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":31,"character":48},{"__symbolic":"reference","module":"ngx-bootstrap/modal","name":"BsModalService","line":32,"character":39},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":33,"character":30},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":34,"character":23},{"__symbolic":"reference","module":"../../config","name":"GraphStore","line":35,"character":37},{"__symbolic":"reference","module":"../../service","name":"PermissionChecker","line":36,"character":27},{"__symbolic":"reference","module":"../../service","name":"OperationRecordService","line":37,"character":49},{"__symbolic":"reference","module":"../../security","name":"SecurityChecker","line":38,"character":42},{"__symbolic":"reference","module":"../../localization","name":"Localization","line":39,"character":22},{"__symbolic":"reference","module":"../../view/popup-view.service","name":"PopupViewService","line":40,"character":43},{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","module":"@angular/core","name":"ElementRef","line":42,"character":29},{"__symbolic":"reference","name":"string"}]}],"initElement":[{"__symbolic":"method"}],"switchToState":[{"__symbolic":"method"}],"initGraph":[{"__symbolic":"method"}],"checkElementPassword":[{"__symbolic":"method"}],"executeViewOperation":[{"__symbolic":"method"}],"toggleView":[{"__symbolic":"method"}],"popView":[{"__symbolic":"method"}],"closeView":[{"__symbolic":"method"}],"moveView":[{"__symbolic":"method"}],"recordViewOperation":[{"__symbolic":"method"}]}}}}]
1
+ [{"__symbolic":"module","version":4,"metadata":{"ViewOperationElement":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"../base/conditional-enable-element","name":"ConditionalEnableElement","line":22,"character":42},"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"error","message":"Could not resolve type","line":34,"character":25,"context":{"typeName":"HTMLElement"}},{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":34,"character":48},{"__symbolic":"reference","module":"ngx-bootstrap/modal","name":"BsModalService","line":35,"character":39},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":36,"character":30},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":37,"character":23},{"__symbolic":"reference","module":"../../config","name":"GraphStore","line":38,"character":37},{"__symbolic":"reference","module":"../../service","name":"PermissionChecker","line":39,"character":27},{"__symbolic":"reference","module":"../../service","name":"OperationRecordService","line":40,"character":49},{"__symbolic":"reference","module":"../../security","name":"SecurityChecker","line":41,"character":42},{"__symbolic":"reference","module":"../../localization","name":"Localization","line":42,"character":22},{"__symbolic":"reference","module":"../../view/popup-view.service","name":"PopupViewService","line":43,"character":43},{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","module":"@angular/core","name":"ElementRef","line":45,"character":29},{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","module":"../../service","name":"TextLibraryService","line":47,"character":46},{"__symbolic":"reference","module":"../../service","name":"LanguageService","line":48,"character":43},{"__symbolic":"reference","module":"../../gui/gui-context","name":"GuiContext","line":49,"character":38}]}],"initElement":[{"__symbolic":"method"}],"switchToState":[{"__symbolic":"method"}],"initGraph":[{"__symbolic":"method"}],"checkElementPassword":[{"__symbolic":"method"}],"executeViewOperation":[{"__symbolic":"method"}],"toggleView":[{"__symbolic":"method"}],"popView":[{"__symbolic":"method"}],"closeView":[{"__symbolic":"method"}],"moveView":[{"__symbolic":"method"}],"recordViewOperation":[{"__symbolic":"method"}],"subscribeLanguageChange":[{"__symbolic":"method"}],"updateTextContent":[{"__symbolic":"method"}],"getDisplayText":[{"__symbolic":"method"}],"dispose":[{"__symbolic":"method"}]}}}}]
@@ -2,6 +2,7 @@ import { ConfigStore } from '../config';
2
2
  import { VariableCommunicator } from '../communication';
3
3
  import { SecurityChecker } from '../security';
4
4
  import { VideoService, WeatherService, PermissionChecker, OperationRecordService, ReleasedVariableService, TextLibraryService, LanguageService, SystemTextLibraryService } from '../service';
5
+ import { Subject } from 'rxjs';
5
6
  export interface GuiContext {
6
7
  readonly configStore: ConfigStore;
7
8
  readonly variableCommunicator: VariableCommunicator;
@@ -16,5 +17,10 @@ export interface GuiContext {
16
17
  readonly systemTextLibraryService?: SystemTextLibraryService;
17
18
  readonly configureViewId?: number;
18
19
  readonly configureViewCode?: string;
19
- dispose(): any;
20
+ readonly languageChanged$?: Subject<number | null>;
21
+ getCurrentLanguageId?(): number | null;
22
+ getDefaultLanguageId?(): number;
23
+ getLanguageCultureById?(languageId: number | null): string | null;
24
+ updateCurrentLanguageId?(languageId: number | null): Promise<void>;
25
+ dispose(): void;
20
26
  }
package/gui/gui-view.js CHANGED
@@ -72,7 +72,23 @@ export class GuiView {
72
72
  this.openVariableStatesSubscription.unsubscribe();
73
73
  }
74
74
  this.openedVariableNames = this.mainElement.getVariableNames();
75
- if (this.openedVariableNames.indexOf('设备状态') !== -1) {
75
+ // 分离系统变量和普通变量
76
+ const systemVariables = [];
77
+ const normalVariablesForState = [];
78
+ this.openedVariableNames.forEach(variableName => {
79
+ if (variableName === '当前语种ID') {
80
+ // 系统变量直接订阅,不需要等待状态
81
+ systemVariables.push(variableName);
82
+ }
83
+ else {
84
+ normalVariablesForState.push(variableName);
85
+ }
86
+ });
87
+ // 立即订阅系统变量
88
+ if (systemVariables.length > 0) {
89
+ this.normalOpenedVariableNames(systemVariables);
90
+ }
91
+ if (normalVariablesForState.indexOf('设备状态') !== -1) {
76
92
  if (this.requestVirtualDeviceState) {
77
93
  this.requestVirtualDeviceState.unsubscribe();
78
94
  }
@@ -84,13 +100,13 @@ export class GuiView {
84
100
  this.perViewVariableCommunicator.requestVirtualDeviceState().subscribe({
85
101
  complete: () => { }
86
102
  });
87
- this.openedVariableNames = this.openedVariableNames.filter(name => name !== '设备状态');
103
+ normalVariablesForState.splice(normalVariablesForState.indexOf('设备状态'), 1);
88
104
  }
89
- if (this.openedVariableNames.length === 0) {
105
+ if (normalVariablesForState.length === 0) {
90
106
  return;
91
107
  }
92
108
  this.openVariableStatesSubscription =
93
- this.perViewVariableCommunicator.subscribeVariableStates(this.openedVariableNames).subscribe((states) => {
109
+ this.perViewVariableCommunicator.subscribeVariableStates(normalVariablesForState).subscribe((states) => {
94
110
  this.mainElement.reportVariableStates(states);
95
111
  const normalVariableNames = [];
96
112
  each(states, v => {
@@ -1,5 +1,6 @@
1
1
  import { NumericalOperation } from '../../model';
2
2
  import { ReleasedVariableService } from '../../service';
3
+ import { GuiContext } from '../../gui/gui-context';
3
4
  export declare class WriteValueModalArgs {
4
5
  variableName: string;
5
6
  dataType: number;
@@ -10,5 +11,6 @@ export declare class WriteValueModalArgs {
10
11
  version: number;
11
12
  enableDataParsed: boolean;
12
13
  releasedVariableService: ReleasedVariableService;
13
- constructor(variableName: string, dataType: number, fBoxDataType: number, integerDigits: number, fractionDigits: number, numericalOperation: NumericalOperation, version: number, enableDataParsed: boolean, releasedVariableService: ReleasedVariableService);
14
+ guiContext?: GuiContext;
15
+ constructor(variableName: string, dataType: number, fBoxDataType: number, integerDigits: number, fractionDigits: number, numericalOperation: NumericalOperation, version: number, enableDataParsed: boolean, releasedVariableService: ReleasedVariableService, guiContext?: GuiContext);
14
16
  }
@@ -1,5 +1,5 @@
1
1
  export class WriteValueModalArgs {
2
- constructor(variableName, dataType, fBoxDataType, integerDigits, fractionDigits, numericalOperation, version, enableDataParsed, releasedVariableService) {
2
+ constructor(variableName, dataType, fBoxDataType, integerDigits, fractionDigits, numericalOperation, version, enableDataParsed, releasedVariableService, guiContext) {
3
3
  this.variableName = variableName;
4
4
  this.dataType = dataType;
5
5
  this.fBoxDataType = fBoxDataType;
@@ -9,5 +9,6 @@ export class WriteValueModalArgs {
9
9
  this.version = version;
10
10
  this.enableDataParsed = enableDataParsed;
11
11
  this.releasedVariableService = releasedVariableService;
12
+ this.guiContext = guiContext;
12
13
  }
13
14
  }
@@ -1 +1 @@
1
- [{"__symbolic":"module","version":4,"metadata":{"WriteValueModalArgs":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","name":"number"},{"__symbolic":"reference","name":"number"},{"__symbolic":"reference","name":"number"},{"__symbolic":"reference","name":"number"},{"__symbolic":"reference","module":"../../model","name":"NumericalOperation","line":10,"character":35},{"__symbolic":"reference","name":"number"},{"__symbolic":"reference","name":"boolean"},{"__symbolic":"reference","module":"../../service","name":"ReleasedVariableService","line":13,"character":40}]}]}}}}]
1
+ [{"__symbolic":"module","version":4,"metadata":{"WriteValueModalArgs":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","name":"number"},{"__symbolic":"reference","name":"number"},{"__symbolic":"reference","name":"number"},{"__symbolic":"reference","name":"number"},{"__symbolic":"reference","module":"../../model","name":"NumericalOperation","line":11,"character":35},{"__symbolic":"reference","name":"number"},{"__symbolic":"reference","name":"boolean"},{"__symbolic":"reference","module":"../../service","name":"ReleasedVariableService","line":14,"character":40},{"__symbolic":"reference","module":"../../gui/gui-context","name":"GuiContext","line":15,"character":28}]}]}}}}]
@@ -42,6 +42,10 @@ export declare class WriteValueModalComponent implements OnInit {
42
42
  private setValueRangeAccordToDataParsed;
43
43
  getWriteValueRangeText(): string;
44
44
  save(): void;
45
+ /**
46
+ * 处理"当前语种ID"系统变量的保存
47
+ */
48
+ private handleCurrentLanguageIdSave;
45
49
  close(): void;
46
50
  validate(event?: any): void;
47
51
  private showValidationErrorInfo;
@@ -110,6 +110,11 @@ let WriteValueModalComponent = class WriteValueModalComponent {
110
110
  value = this.formatWriteValue();
111
111
  }
112
112
  }
113
+ // 处理系统变量"当前语种ID"
114
+ if (this.variableName === '当前语种ID') {
115
+ this.handleCurrentLanguageIdSave(value);
116
+ return;
117
+ }
113
118
  if (!this.args.releasedVariableService) {
114
119
  this.onClosed({
115
120
  value: value,
@@ -134,6 +139,26 @@ let WriteValueModalComponent = class WriteValueModalComponent {
134
139
  });
135
140
  });
136
141
  }
142
+ /**
143
+ * 处理"当前语种ID"系统变量的保存
144
+ */
145
+ handleCurrentLanguageIdSave(value) {
146
+ if (!this.args.guiContext || !this.args.guiContext.updateCurrentLanguageId) {
147
+ this.showValidationErrorInfo(this.localization.loadFailed);
148
+ this.isSubmitting = false;
149
+ return;
150
+ }
151
+ // 转换为数字类型
152
+ const languageId = value === '' || value == null ? null : Number(value);
153
+ // 调用 GuiContext 的更新方法
154
+ this.args.guiContext.updateCurrentLanguageId(languageId).then(() => {
155
+ // 更新成功,关闭弹窗
156
+ this.bsModalRef.hide();
157
+ }).catch(() => {
158
+ this.showValidationErrorInfo(this.localization.loadFailed);
159
+ this.isSubmitting = false;
160
+ });
161
+ }
137
162
  close() {
138
163
  this.bsModalRef.hide();
139
164
  }
@@ -1 +1 @@
1
- [{"__symbolic":"module","version":4,"metadata":{"WriteValueModalComponent":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Component","line":10,"character":1},"arguments":[{"selector":"writeValueModal","template":"<form #writeValueForm=\"ngForm\" novalidate (ngSubmit)=\"save()\" bs-modal-drag> <div class=\"modal-header\"> <h4 class=\"modal-title\"> <span>{{localization.setting}}</span> <span>{{variableName}}</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=\"write-value-range\">{{localization.writeValueRange}}:</span> <div class=\"write-value-range\"> {{writeValueRangeText}} <span *ngIf=\"valueType\">({{valueType}})</span> </div> <input type=\"text\" name=\"valueInput\" autoFocus class=\"form-control write-value\" [(ngModel)]=\"value\" (keyup)=\"validate($event)\" autocomplete=\"off\"> <span class=\"help-block text-danger\" [hidden]=\"!validationError\">{{validationErrorText}}</span> </div> <div class=\"modal-footer\"> <button type=\"submit\" class=\"btn md-skip btn-primary btn-block\" [disabled]=\"validationError || isSubmitting\"> <ng-container *ngIf=\"!isSubmitting\">{{localization.submit}}</ng-container> <ng-container *ngIf=\"isSubmitting\">{{localization.submitting}}</ng-container> </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; } .text-danger { display: block; color: #ed6b75; font-size: 14px; margin: 5px 0px 0px 15px; } .btn-primary { background-color: #3B97FC; border-color: #3B97FC; padding: 5px 30px; width: 90%; margin: 0 5%; height: 32px; } .write-value-range { color: #7f939e; font-size: 14px; margin-left: 15px; } .write-value { padding-left: 8px; margin-left: 16px; height: 32px; } "]}]}],"members":{"invalidErrorText":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Output","line":44,"character":5}}]}],"__ctor__":[{"__symbolic":"constructor","parameterDecorators":[[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Inject","line":50,"character":9},"arguments":[{"__symbolic":"reference","module":"../../localization","name":"LOCALIZATION","line":50,"character":16}]}],null,null,null,null],"parameters":[{"__symbolic":"reference","module":"../../localization","name":"Localization","line":50,"character":51},{"__symbolic":"reference","module":"../../utils/data-type/data-type.service","name":"DataTypeService","line":51,"character":42},{"__symbolic":"reference","module":"../../utils/fraction-digit.service","name":"FractionDigitService","line":52,"character":47},{"__symbolic":"reference","module":"../../utils/numerical-operation.service","name":"NumericalOperationService","line":53,"character":52},{"__symbolic":"reference","module":"ngx-bootstrap/modal","name":"BsModalRef","line":54,"character":37}]}],"ngOnInit":[{"__symbolic":"method"}],"initData":[{"__symbolic":"method"}],"setValueRangeAccordToDataParsed":[{"__symbolic":"method"}],"getWriteValueRangeText":[{"__symbolic":"method"}],"save":[{"__symbolic":"method"}],"close":[{"__symbolic":"method"}],"validate":[{"__symbolic":"method"}],"showValidationErrorInfo":[{"__symbolic":"method"}],"hideValidationErrorInfo":[{"__symbolic":"method"}],"getFractionDigits":[{"__symbolic":"method"}],"formatWriteValue":[{"__symbolic":"method"}]}}}}]
1
+ [{"__symbolic":"module","version":4,"metadata":{"WriteValueModalComponent":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Component","line":10,"character":1},"arguments":[{"selector":"writeValueModal","template":"<form #writeValueForm=\"ngForm\" novalidate (ngSubmit)=\"save()\" bs-modal-drag> <div class=\"modal-header\"> <h4 class=\"modal-title\"> <span>{{localization.setting}}</span> <span>{{variableName}}</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=\"write-value-range\">{{localization.writeValueRange}}:</span> <div class=\"write-value-range\"> {{writeValueRangeText}} <span *ngIf=\"valueType\">({{valueType}})</span> </div> <input type=\"text\" name=\"valueInput\" autoFocus class=\"form-control write-value\" [(ngModel)]=\"value\" (keyup)=\"validate($event)\" autocomplete=\"off\"> <span class=\"help-block text-danger\" [hidden]=\"!validationError\">{{validationErrorText}}</span> </div> <div class=\"modal-footer\"> <button type=\"submit\" class=\"btn md-skip btn-primary btn-block\" [disabled]=\"validationError || isSubmitting\"> <ng-container *ngIf=\"!isSubmitting\">{{localization.submit}}</ng-container> <ng-container *ngIf=\"isSubmitting\">{{localization.submitting}}</ng-container> </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; } .text-danger { display: block; color: #ed6b75; font-size: 14px; margin: 5px 0px 0px 15px; } .btn-primary { background-color: #3B97FC; border-color: #3B97FC; padding: 5px 30px; width: 90%; margin: 0 5%; height: 32px; } .write-value-range { color: #7f939e; font-size: 14px; margin-left: 15px; } .write-value { padding-left: 8px; margin-left: 16px; height: 32px; } "]}]}],"members":{"invalidErrorText":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Output","line":44,"character":5}}]}],"__ctor__":[{"__symbolic":"constructor","parameterDecorators":[[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Inject","line":50,"character":9},"arguments":[{"__symbolic":"reference","module":"../../localization","name":"LOCALIZATION","line":50,"character":16}]}],null,null,null,null],"parameters":[{"__symbolic":"reference","module":"../../localization","name":"Localization","line":50,"character":51},{"__symbolic":"reference","module":"../../utils/data-type/data-type.service","name":"DataTypeService","line":51,"character":42},{"__symbolic":"reference","module":"../../utils/fraction-digit.service","name":"FractionDigitService","line":52,"character":47},{"__symbolic":"reference","module":"../../utils/numerical-operation.service","name":"NumericalOperationService","line":53,"character":52},{"__symbolic":"reference","module":"ngx-bootstrap/modal","name":"BsModalRef","line":54,"character":37}]}],"ngOnInit":[{"__symbolic":"method"}],"initData":[{"__symbolic":"method"}],"setValueRangeAccordToDataParsed":[{"__symbolic":"method"}],"getWriteValueRangeText":[{"__symbolic":"method"}],"save":[{"__symbolic":"method"}],"handleCurrentLanguageIdSave":[{"__symbolic":"method"}],"close":[{"__symbolic":"method"}],"validate":[{"__symbolic":"method"}],"showValidationErrorInfo":[{"__symbolic":"method"}],"hideValidationErrorInfo":[{"__symbolic":"method"}],"getFractionDigits":[{"__symbolic":"method"}],"formatWriteValue":[{"__symbolic":"method"}]}}}}]
@@ -2,12 +2,14 @@ import { Size, Text, GraphSetting } from '../shared';
2
2
  import { ConditionalEnableModel } from '../base/conditional-enable-model';
3
3
  import { SecurityModel } from '../base';
4
4
  import { ViewOperationType } from './view-operation-type';
5
+ import { TextLibrarySetting } from '../base/font-setting-model';
5
6
  export interface ViewOperationElementModel extends ConditionalEnableModel, SecurityModel {
6
7
  /**
7
8
  * 版本 2 : 动态行为调整
8
9
  * 版本 3 :使能控制调整
9
10
  * 版本 4 :新增操作记录
10
- * 版本 5 :新增页面操作类型,之前类型都为“切换页面”
11
+ * 版本 5 :新增页面操作类型,之前类型都为"切换页面"
12
+ * 版本 6 :新增文本库支持
11
13
  */
12
14
  readonly version?: number;
13
15
  readonly viewIndex?: number;
@@ -16,4 +18,8 @@ export interface ViewOperationElementModel extends ConditionalEnableModel, Secur
16
18
  readonly useGraph: boolean;
17
19
  readonly graphSetting: GraphSetting;
18
20
  readonly operationType: ViewOperationType;
21
+ /**
22
+ * 文本库配置(版本6新增)
23
+ */
24
+ readonly textLibrary?: TextLibrarySetting;
19
25
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "main": "bundles/fc-gui.umd.js",
3
- "version": "3.0.0-alpha.124",
3
+ "version": "3.0.0-alpha.125",
4
4
  "module": "public_api.js",
5
5
  "typings": "public_api.d.ts",
6
6
  "license": "UNLICENSED",
@@ -20,6 +20,7 @@ export declare class RemoteVariableCommunicator implements VariableCommunicator
20
20
  private variableStatesToBeClosed;
21
21
  private alarmObservers;
22
22
  private alarmChangedSubscription;
23
+ private systemVariableHandlers;
23
24
  constructor(remoteVariableProtocol: RemoteVariableProtocol, logger: LoggerService);
24
25
  private doAlarmChanged;
25
26
  private doVariableValuesChanged;
@@ -33,5 +34,19 @@ export declare class RemoteVariableCommunicator implements VariableCommunicator
33
34
  write(variableName: string, value: any): Observable<VariableValue>;
34
35
  writeWordByBit(variableName: string, index: number, value: number): Observable<VariableValue>;
35
36
  subscribeUserDeviceAlarms(appId?: string): Observable<any[]>;
37
+ /**
38
+ * 注册系统变量处理器
39
+ * @param variableName 变量名(如"当前语种ID")
40
+ * @param getValue 获取值的函数
41
+ * @param setValue 设置值的函数
42
+ */
43
+ registerSystemVariableHandler(variableName: string, getValue: () => Promise<any>, setValue: (value: any) => Promise<void>): void;
44
+ /**
45
+ * 通知系统变量值变化
46
+ * 用于在系统变量值改变时通知所有订阅者
47
+ * @param variableName 变量名
48
+ * @param value 新值
49
+ */
50
+ notifySystemVariableChange(variableName: string, value: any): void;
36
51
  dispose(): void;
37
52
  }
@@ -11,6 +11,8 @@ export class RemoteVariableCommunicator {
11
11
  this.variableStateObservers = new Map();
12
12
  this.variableStateCache = new Map();
13
13
  this.alarmObservers = [];
14
+ // 系统变量处理器
15
+ this.systemVariableHandlers = new Map();
14
16
  this.variableValueCache = new StringifyingMap(k => JSON.stringify(k));
15
17
  this.connectedSubscription = this.remoteVariableProtocol.connected.subscribe(() => {
16
18
  const variableNamesToStart = [];
@@ -175,7 +177,33 @@ export class RemoteVariableCommunicator {
175
177
  }
176
178
  }
177
179
  });
178
- variablesToStart = uniq(variablesToStart);
180
+ // 过滤掉系统变量,它们不需要通过SignalR订阅
181
+ const normalVariables = variablesToStart.filter(v => !this.systemVariableHandlers.has(v));
182
+ const systemVariables = variablesToStart.filter(v => this.systemVariableHandlers.has(v));
183
+ // 处理系统变量的初始值
184
+ systemVariables.forEach(variableName => {
185
+ const handler = this.systemVariableHandlers.get(variableName);
186
+ if (handler && handler.getValue) {
187
+ void handler.getValue().then(value => {
188
+ const variableValue = {
189
+ variableName: variableName,
190
+ value: value,
191
+ state: 1 // Normal state
192
+ };
193
+ this.variableValueCache.set(variableName, variableValue);
194
+ if (this.observers.has(variableName)) {
195
+ each(this.observers.get(variableName), ob => {
196
+ ob.next([variableValue]);
197
+ });
198
+ }
199
+ }).catch(error => {
200
+ if (this.logger) {
201
+ this.logger.error(`[RemoteVariableCommunicator] Failed to get system variable "${variableName}" value:`, error);
202
+ }
203
+ });
204
+ }
205
+ });
206
+ variablesToStart = uniq(normalVariables);
179
207
  if (variablesToStart && variablesToStart.length > 0) {
180
208
  if (!this.variablesToBeOpened) {
181
209
  this.variablesToBeOpened = [];
@@ -220,8 +248,24 @@ export class RemoteVariableCommunicator {
220
248
  }
221
249
  write(variableName, value) {
222
250
  if (!variableName) {
223
- return;
251
+ return new Observable(observer => {
252
+ observer.complete();
253
+ });
224
254
  }
255
+ // 检查是否为系统变量
256
+ if (this.systemVariableHandlers.has(variableName)) {
257
+ const handler = this.systemVariableHandlers.get(variableName);
258
+ // 调用系统变量的setValue处理器
259
+ void handler.setValue(value).catch(error => {
260
+ if (this.logger) {
261
+ this.logger.error('[RemoteVariableCommunicator] Failed to set system variable value:', error);
262
+ }
263
+ });
264
+ return new Observable(__ => {
265
+ /* 系统变量通过自己的机制通知变化 */
266
+ });
267
+ }
268
+ // 普通变量通过SignalR写入
225
269
  this.remoteVariableProtocol.writeVariable(variableName, value);
226
270
  return new Observable(__ => {
227
271
  /* do nothing right now, if want value change immediately, can use this code below:
@@ -247,6 +291,36 @@ export class RemoteVariableCommunicator {
247
291
  };
248
292
  });
249
293
  }
294
+ /**
295
+ * 注册系统变量处理器
296
+ * @param variableName 变量名(如"当前语种ID")
297
+ * @param getValue 获取值的函数
298
+ * @param setValue 设置值的函数
299
+ */
300
+ registerSystemVariableHandler(variableName, getValue, setValue) {
301
+ this.systemVariableHandlers.set(variableName, { getValue, setValue });
302
+ }
303
+ /**
304
+ * 通知系统变量值变化
305
+ * 用于在系统变量值改变时通知所有订阅者
306
+ * @param variableName 变量名
307
+ * @param value 新值
308
+ */
309
+ notifySystemVariableChange(variableName, value) {
310
+ const variableValue = {
311
+ variableName: variableName,
312
+ value: value,
313
+ state: 1 // Normal state
314
+ };
315
+ // 更新缓存
316
+ this.variableValueCache.set(variableName, variableValue);
317
+ // 通知所有订阅者
318
+ if (this.observers.has(variableName)) {
319
+ each(this.observers.get(variableName), ob => {
320
+ ob.next([variableValue]);
321
+ });
322
+ }
323
+ }
250
324
  dispose() {
251
325
  // TODO调用所有的ob.complete()。
252
326
  this.connectedSubscription.unsubscribe();
@@ -1 +1 @@
1
- [{"__symbolic":"module","version":4,"metadata":{"RemoteVariableCommunicator":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"./remote-variable-protocol","name":"RemoteVariableProtocol","line":28,"character":57},{"__symbolic":"reference","module":"../../../logger","name":"LoggerService","line":28,"character":106}]}],"doAlarmChanged":[{"__symbolic":"method"}],"doVariableValuesChanged":[{"__symbolic":"method"}],"doVirtualDeviceStatesChanged":[{"__symbolic":"method"}],"doVariableStatesChanged":[{"__symbolic":"method"}],"subscribeVariableStates":[{"__symbolic":"method"}],"subscribeVariableState":[{"__symbolic":"method"}],"requestVirtualDeviceState":[{"__symbolic":"method"}],"openVariables":[{"__symbolic":"method"}],"openVariable":[{"__symbolic":"method"}],"write":[{"__symbolic":"method"}],"writeWordByBit":[{"__symbolic":"method"}],"subscribeUserDeviceAlarms":[{"__symbolic":"method"}],"dispose":[{"__symbolic":"method"}]}}}}]
1
+ [{"__symbolic":"module","version":4,"metadata":{"RemoteVariableCommunicator":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"./remote-variable-protocol","name":"RemoteVariableProtocol","line":34,"character":57},{"__symbolic":"reference","module":"../../../logger","name":"LoggerService","line":34,"character":106}]}],"doAlarmChanged":[{"__symbolic":"method"}],"doVariableValuesChanged":[{"__symbolic":"method"}],"doVirtualDeviceStatesChanged":[{"__symbolic":"method"}],"doVariableStatesChanged":[{"__symbolic":"method"}],"subscribeVariableStates":[{"__symbolic":"method"}],"subscribeVariableState":[{"__symbolic":"method"}],"requestVirtualDeviceState":[{"__symbolic":"method"}],"openVariables":[{"__symbolic":"method"}],"openVariable":[{"__symbolic":"method"}],"write":[{"__symbolic":"method"}],"writeWordByBit":[{"__symbolic":"method"}],"subscribeUserDeviceAlarms":[{"__symbolic":"method"}],"registerSystemVariableHandler":[{"__symbolic":"method"}],"notifySystemVariableChange":[{"__symbolic":"method"}],"dispose":[{"__symbolic":"method"}]}}}}]