@flexem/fc-gui 3.0.0-alpha.126 → 3.0.0-alpha.128

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.
@@ -3,5 +3,11 @@ export declare class HistoryDataModel {
3
3
  readonly error: string;
4
4
  readonly isUnbind: boolean;
5
5
  readonly values: Array<HistoryDataValue>;
6
- constructor(error: string, isUnbind: boolean, values: Array<HistoryDataValue>);
6
+ readonly historyDataItems?: Array<HistoryDataItemModel>;
7
+ constructor(error: string, isUnbind: boolean, values: Array<HistoryDataValue>, historyDataItems?: Array<HistoryDataItemModel>);
8
+ }
9
+ export declare class HistoryDataItemModel {
10
+ readonly itemName: string;
11
+ readonly rows: Array<HistoryDataValue>;
12
+ constructor(itemName: string, rows: Array<HistoryDataValue>);
7
13
  }
@@ -1,7 +1,15 @@
1
1
  export class HistoryDataModel {
2
- constructor(error, isUnbind, values) {
2
+ constructor(error, isUnbind, values, historyDataItems // 新增:多条目独立数据
3
+ ) {
3
4
  this.error = error;
4
5
  this.isUnbind = isUnbind;
5
6
  this.values = values;
7
+ this.historyDataItems = historyDataItems;
8
+ }
9
+ }
10
+ export class HistoryDataItemModel {
11
+ constructor(itemName, rows) {
12
+ this.itemName = itemName;
13
+ this.rows = rows;
6
14
  }
7
15
  }
@@ -1 +1 @@
1
- [{"__symbolic":"module","version":4,"metadata":{"HistoryDataModel":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","name":"boolean"},{"__symbolic":"reference","name":"Array","arguments":[{"__symbolic":"reference","module":"./history-data-value","name":"HistoryDataValue","line":3,"character":91}]}]}]}}}}]
1
+ [{"__symbolic":"module","version":4,"metadata":{"HistoryDataModel":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","name":"boolean"},{"__symbolic":"reference","name":"Array","arguments":[{"__symbolic":"reference","module":"./history-data-value","name":"HistoryDataValue","line":6,"character":31}]},{"__symbolic":"reference","name":"Array","arguments":[{"__symbolic":"reference","module":"./history-data-value","name":"HistoryDataValue","line":6,"character":31}]}]}]}},"HistoryDataItemModel":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","name":"Array","arguments":[{"__symbolic":"reference","module":"./history-data-value","name":"HistoryDataValue","line":6,"character":31}]}]}]}}}}]
@@ -1,4 +1,4 @@
1
1
  export { HistoryDataStore } from './history-data.store';
2
- export { HistoryDataModel } from './history-data.model';
2
+ export { HistoryDataModel, HistoryDataItemModel } from './history-data.model';
3
3
  export { HistoryDataValue } from './history-data-value';
4
4
  export { GetHistoryDataArgs } from './get-history-data-args';
@@ -1,3 +1,3 @@
1
- export { HistoryDataModel } from './history-data.model';
1
+ export { HistoryDataModel, HistoryDataItemModel } from './history-data.model';
2
2
  export { HistoryDataValue } from './history-data-value';
3
3
  export { GetHistoryDataArgs } from './get-history-data-args';
@@ -1 +1 @@
1
- [{"__symbolic":"module","version":4,"metadata":{},"exports":[{"from":"./history-data.store","export":["HistoryDataStore"]},{"from":"./history-data.model","export":["HistoryDataModel"]},{"from":"./history-data-value","export":["HistoryDataValue"]},{"from":"./get-history-data-args","export":["GetHistoryDataArgs"]}]}]
1
+ [{"__symbolic":"module","version":4,"metadata":{},"exports":[{"from":"./history-data.store","export":["HistoryDataStore"]},{"from":"./history-data.model","export":["HistoryDataModel","HistoryDataItemModel"]},{"from":"./history-data-value","export":["HistoryDataValue"]},{"from":"./get-history-data-args","export":["GetHistoryDataArgs"]}]}]
@@ -70,6 +70,11 @@ export declare class HistoricalCurveElement extends ConditionalDisplayElement {
70
70
  private handleQueryResult;
71
71
  setupTooltipAutoHide(chart: any): void;
72
72
  private renderChart;
73
+ /**
74
+ * 【新格式】多条目独立数据的曲线渲染
75
+ * 每个条目独立保持自己的时间戳,不会出现时间戳混乱的问题
76
+ */
77
+ private renderChartWithMultiItems;
73
78
  initPoint(): void;
74
79
  private getLineChart;
75
80
  private getMultiBarWithFocusChart;
@@ -232,7 +232,50 @@ export class HistoricalCurveElement extends ConditionalDisplayElement {
232
232
  }
233
233
  }
234
234
  handleQueryResult(result) {
235
- if (result.error) {
235
+ // 【新格式】多条目模式下的错误处理
236
+ if (result.historyDataItems && result.historyDataItems.length > 0) {
237
+ // 只要有条目正常返回(即使没有数据),就走正常逻辑
238
+ // 这样可以确保即使部分条目失败,只要有条目成功返回,就显示正常状态
239
+ this.clearStatus();
240
+ if (result.isUnbind) {
241
+ this.updateElementStatus(HistoricalCurveElementStatus.Unbound);
242
+ }
243
+ else {
244
+ this.updateElementStatus(HistoricalCurveElementStatus.Normal);
245
+ }
246
+ // 如果有错误信息,在控制台输出警告
247
+ if (result.error) {
248
+ this.logger.warn(`[历史曲线] 部分条目查询失败: ${result.error}`);
249
+ }
250
+ // 检查是否有任何条目有数据
251
+ const hasAnyData = result.historyDataItems.some(item => item.rows && item.rows.length > 0);
252
+ if (hasAnyData) {
253
+ // 有数据,计算所有条目的最小和最大时间,确保时间轴覆盖所有数据
254
+ let globalMinTime = null;
255
+ let globalMaxTime = null;
256
+ result.historyDataItems.forEach(item => {
257
+ if (item.rows && item.rows.length > 0) {
258
+ const itemMinTime = moment(first(item.rows).time);
259
+ const itemMaxTime = moment(last(item.rows).time);
260
+ if (!globalMinTime || itemMinTime.isBefore(globalMinTime)) {
261
+ globalMinTime = itemMinTime;
262
+ }
263
+ if (!globalMaxTime || itemMaxTime.isAfter(globalMaxTime)) {
264
+ globalMaxTime = itemMaxTime;
265
+ }
266
+ }
267
+ });
268
+ // 设置全局时间范围
269
+ if (globalMinTime && globalMaxTime) {
270
+ this.currentStartTime = globalMinTime;
271
+ this.currentEndTime = globalMaxTime;
272
+ }
273
+ }
274
+ // 无论是否有数据,都渲染曲线(没有数据会显示空曲线)
275
+ this.chartElement = this.renderChartWithMultiItems(result.historyDataItems);
276
+ }
277
+ // 【旧格式】单条目模式的错误处理
278
+ else if (result.error) {
236
279
  this.updateElementStatus(HistoricalCurveElementStatus.LoadFailed, result.error);
237
280
  }
238
281
  else {
@@ -243,6 +286,7 @@ export class HistoricalCurveElement extends ConditionalDisplayElement {
243
286
  else {
244
287
  this.updateElementStatus(HistoricalCurveElementStatus.Normal);
245
288
  }
289
+ // 【旧格式】单条目数据,使用原有渲染方式
246
290
  if (result.values.length) {
247
291
  this.currentStartTime = moment(first(result.values).time);
248
292
  this.currentEndTime = moment(last(result.values).time);
@@ -276,31 +320,61 @@ export class HistoricalCurveElement extends ConditionalDisplayElement {
276
320
  const chartWidth = this.model.displaySetting.size.width;
277
321
  const chartHeight = this.model.displaySetting.size.height - this.displayOption.operationAreaHeight - this.displayOption.operationAreaMarginTop;
278
322
  const data = new Array();
279
- // 【新格式】多条目模式:曲线名称使用"条目名-通道名"格式
280
- if (this.model.dataSetting.dataItems && this.model.dataSetting.dataItems.length > 0) {
281
- let channelIndex = 0;
282
- each(this.model.dataSetting.dataItems, dataItem => {
283
- each(dataItem.channels, channel => {
284
- const values = new Array();
285
- each(result, v => values.push({ x: moment(v.time).local().toDate().valueOf(), y: v.values[channelIndex] }));
286
- // 使用"条目名-通道名"格式
287
- const displayName = `${dataItem.dataName}-${channel.name}`;
288
- data.push({ key: displayName, area: channel.projectEnabled, values: values });
289
- channelIndex++;
290
- });
291
- });
292
- }
293
- // 【旧格式】单条目模式:同样使用"条目名-通道名"格式
294
- else {
295
- const dataItemName = this.model.dataSetting.dataName;
296
- each(this.model.dataSetting.channels, (channel, key) => {
323
+ // 【旧格式】单条目模式:只显示通道名
324
+ each(this.model.dataSetting.channels, (channel, key) => {
325
+ const values = new Array();
326
+ each(result, v => values.push({ x: moment(v.time).local().toDate().valueOf(), y: v.values[key] }));
327
+ const displayName = channel.name;
328
+ data.push({ key: displayName, area: channel.projectEnabled, values: values });
329
+ });
330
+ this.data = data;
331
+ nv.addGraph(() => {
332
+ let chart;
333
+ if (this.model.displaySetting.curveType === CurveType.BarGroup || this.model.displaySetting.curveType === CurveType.BarStack) {
334
+ chart = this.getMultiBarWithFocusChart(chartWidth, chartHeight, data);
335
+ }
336
+ else {
337
+ chart = this.getLineChart(chartWidth, chartHeight, data);
338
+ }
339
+ // 设置 tooltip 自动隐藏逻辑
340
+ this.setupTooltipAutoHide(chart);
341
+ return chart;
342
+ });
343
+ }
344
+ /**
345
+ * 【新格式】多条目独立数据的曲线渲染
346
+ * 每个条目独立保持自己的时间戳,不会出现时间戳混乱的问题
347
+ */
348
+ renderChartWithMultiItems(historyDataItems) {
349
+ const chartWidth = this.model.displaySetting.size.width;
350
+ const chartHeight = this.model.displaySetting.size.height - this.displayOption.operationAreaHeight - this.displayOption.operationAreaMarginTop;
351
+ const data = new Array();
352
+ // 创建一个 Map 用于快速查找条目数据
353
+ const itemDataMap = new Map();
354
+ each(historyDataItems, item => {
355
+ if (item && item.itemName) {
356
+ itemDataMap.set(item.itemName, item.rows || []);
357
+ }
358
+ });
359
+ // 判断是否只有一个条目
360
+ const isSingleItem = this.model.dataSetting.dataItems && this.model.dataSetting.dataItems.length === 1;
361
+ // 为每个条目的每个通道创建独立的曲线
362
+ each(this.model.dataSetting.dataItems, (dataItem) => {
363
+ const itemName = dataItem.dataName;
364
+ // 通过 itemName 匹配数据,而不是通过索引
365
+ const itemRows = itemDataMap.get(itemName) || [];
366
+ each(dataItem.channels, (channel, channelIdx) => {
297
367
  const values = new Array();
298
- each(result, v => values.push({ x: moment(v.time).local().toDate().valueOf(), y: v.values[key] }));
299
- // 使用"条目名-通道名"格式
300
- const displayName = `${dataItemName}-${channel.name}`;
368
+ // 每个条目使用自己的时间戳和数据
369
+ each(itemRows, row => {
370
+ const value = row.values && row.values[channelIdx] !== undefined ? row.values[channelIdx] : null;
371
+ values.push({ x: moment(row.time).local().toDate().valueOf(), y: value });
372
+ });
373
+ // 只有多个条目时才使用"条目名-通道名"格式,单条目时只显示通道名
374
+ const displayName = isSingleItem ? channel.name : `${itemName}-${channel.name}`;
301
375
  data.push({ key: displayName, area: channel.projectEnabled, values: values });
302
376
  });
303
- }
377
+ });
304
378
  this.data = data;
305
379
  nv.addGraph(() => {
306
380
  let chart;
@@ -1 +1 @@
1
- [{"__symbolic":"module","version":4,"metadata":{"HistoricalCurveElement":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"../base/conditional-display-element","name":"ConditionalDisplayElement","line":23,"character":44},"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"error","message":"Could not resolve type","line":71,"character":25,"context":{"typeName":"HTMLElement"}},{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":72,"character":18},{"__symbolic":"reference","module":"../../service","name":"PermissionChecker","line":73,"character":27},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":74,"character":30},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":75,"character":23},{"__symbolic":"reference","module":"../../config","name":"HistoryDataStore","line":76,"character":43},{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","module":"../../service","name":"SystemTextLibraryService","line":78,"character":52},{"__symbolic":"reference","module":"../../service","name":"LanguageService","line":79,"character":43},{"__symbolic":"reference","module":"../../gui/gui-context","name":"GuiContext","line":80,"character":38}]}],"dispose":[{"__symbolic":"method"}],"initKeyboardListener":[{"__symbolic":"method"}],"subscribeLanguageChange":[{"__symbolic":"method"}],"updateLanguageTexts":[{"__symbolic":"method"}],"getCurrentCulture":[{"__symbolic":"method"}],"getValidTimePeriods":[{"__symbolic":"method"}],"getTimePeriodText":[{"__symbolic":"method"}],"updateTimeRange":[{"__symbolic":"method"}],"updateQueryTimeRange":[{"__symbolic":"method"}],"reRenderElement":[{"__symbolic":"method"}],"renderElement":[{"__symbolic":"method"}],"handleQueryResult":[{"__symbolic":"method"}],"setupTooltipAutoHide":[{"__symbolic":"method"}],"renderChart":[{"__symbolic":"method"}],"initPoint":[{"__symbolic":"method"}],"getLineChart":[{"__symbolic":"method"}],"getMultiBarWithFocusChart":[{"__symbolic":"method"}],"renderCommonProperty":[{"__symbolic":"method"}],"renderOperationArea":[{"__symbolic":"method"}],"timeFormat":[{"__symbolic":"method"}],"loadFirstPage":[{"__symbolic":"method"}],"loadNextPage":[{"__symbolic":"method"}],"loadPreviousPage":[{"__symbolic":"method"}],"loadLastPage":[{"__symbolic":"method"}],"initElementStatus":[{"__symbolic":"method"}],"updateElementStatus":[{"__symbolic":"method"}],"setStatusAsUnbound":[{"__symbolic":"method"}],"setStatusAsLoading":[{"__symbolic":"method"}],"setStatusAsLoadFailed":[{"__symbolic":"method"}],"renderStatus":[{"__symbolic":"method"}],"clearStatus":[{"__symbolic":"method"}]}}}}]
1
+ [{"__symbolic":"module","version":4,"metadata":{"HistoricalCurveElement":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"../base/conditional-display-element","name":"ConditionalDisplayElement","line":23,"character":44},"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"error","message":"Could not resolve type","line":71,"character":25,"context":{"typeName":"HTMLElement"}},{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":72,"character":18},{"__symbolic":"reference","module":"../../service","name":"PermissionChecker","line":73,"character":27},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":74,"character":30},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":75,"character":23},{"__symbolic":"reference","module":"../../config","name":"HistoryDataStore","line":76,"character":43},{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","module":"../../service","name":"SystemTextLibraryService","line":78,"character":52},{"__symbolic":"reference","module":"../../service","name":"LanguageService","line":79,"character":43},{"__symbolic":"reference","module":"../../gui/gui-context","name":"GuiContext","line":80,"character":38}]}],"dispose":[{"__symbolic":"method"}],"initKeyboardListener":[{"__symbolic":"method"}],"subscribeLanguageChange":[{"__symbolic":"method"}],"updateLanguageTexts":[{"__symbolic":"method"}],"getCurrentCulture":[{"__symbolic":"method"}],"getValidTimePeriods":[{"__symbolic":"method"}],"getTimePeriodText":[{"__symbolic":"method"}],"updateTimeRange":[{"__symbolic":"method"}],"updateQueryTimeRange":[{"__symbolic":"method"}],"reRenderElement":[{"__symbolic":"method"}],"renderElement":[{"__symbolic":"method"}],"handleQueryResult":[{"__symbolic":"method"}],"setupTooltipAutoHide":[{"__symbolic":"method"}],"renderChart":[{"__symbolic":"method"}],"renderChartWithMultiItems":[{"__symbolic":"method"}],"initPoint":[{"__symbolic":"method"}],"getLineChart":[{"__symbolic":"method"}],"getMultiBarWithFocusChart":[{"__symbolic":"method"}],"renderCommonProperty":[{"__symbolic":"method"}],"renderOperationArea":[{"__symbolic":"method"}],"timeFormat":[{"__symbolic":"method"}],"loadFirstPage":[{"__symbolic":"method"}],"loadNextPage":[{"__symbolic":"method"}],"loadPreviousPage":[{"__symbolic":"method"}],"loadLastPage":[{"__symbolic":"method"}],"initElementStatus":[{"__symbolic":"method"}],"updateElementStatus":[{"__symbolic":"method"}],"setStatusAsUnbound":[{"__symbolic":"method"}],"setStatusAsLoading":[{"__symbolic":"method"}],"setStatusAsLoadFailed":[{"__symbolic":"method"}],"renderStatus":[{"__symbolic":"method"}],"clearStatus":[{"__symbolic":"method"}]}}}}]
@@ -229,7 +229,10 @@ export class NumericalDisplayElement extends ReadableElement {
229
229
  }
230
230
  }, 30000);
231
231
  }
232
- this.variableCommunicator.write(this.writeVariableName, writeValue).subscribe();
232
+ // 如果是系统变量"当前语种ID",跳过写值操作(已在 handleCurrentLanguageIdSave 中处理)
233
+ if (this.writeVariableName !== '当前语种ID') {
234
+ this.variableCommunicator.write(this.writeVariableName, writeValue).subscribe();
235
+ }
233
236
  }
234
237
  else {
235
238
  this.writeValueMmodalRef.hide();
@@ -150,10 +150,16 @@ let WriteValueModalComponent = class WriteValueModalComponent {
150
150
  }
151
151
  // 转换为数字类型
152
152
  const languageId = value === '' || value == null ? null : Number(value);
153
- // 调用 GuiContext 的更新方法
153
+ // 调用 GuiContext 的语种切换方法
154
154
  this.args.guiContext.updateCurrentLanguageId(languageId).then(() => {
155
- // 更新成功,关闭弹窗
156
- this.bsModalRef.hide();
155
+ // 语种切换成功,调用 onClosed 回调,让数字显示元件也能更新
156
+ this.onClosed({
157
+ value: value,
158
+ showValue: value,
159
+ enableNumericalOperation: false,
160
+ isNumericalOperation: false,
161
+ variableRwType: 6
162
+ });
157
163
  }).catch(() => {
158
164
  this.showValidationErrorInfo(this.localization.loadFailed);
159
165
  this.isSubmitting = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "main": "bundles/fc-gui.umd.js",
3
- "version": "3.0.0-alpha.126",
3
+ "version": "3.0.0-alpha.128",
4
4
  "module": "public_api.js",
5
5
  "typings": "public_api.d.ts",
6
6
  "license": "UNLICENSED",