@flexem/fc-gui 3.0.0-alpha.147 → 3.0.0-alpha.149

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.
@@ -42,6 +42,8 @@ export declare class ScrollAlarmElement extends ConditionalDynamicDisplayElement
42
42
  private initDisplayContainer;
43
43
  private _buildFontAttrs;
44
44
  private _createSvgTextNode;
45
+ private _getSvgTextWidth;
46
+ private _updateUnderlineWidth;
45
47
  private renderNewPage;
46
48
  private _rebaseTextNodes;
47
49
  private removeOldestPage;
@@ -256,9 +256,9 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
256
256
  clipPath.setAttribute('id', clipId);
257
257
  const clipRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
258
258
  clipRect.setAttribute('x', '2');
259
- clipRect.setAttribute('y', '0');
259
+ clipRect.setAttribute('y', '1');
260
260
  clipRect.setAttribute('width', (elementWidth - 4).toString());
261
- clipRect.setAttribute('height', elementHeight.toString());
261
+ clipRect.setAttribute('height', (elementHeight - 2).toString());
262
262
  clipPath.appendChild(clipRect);
263
263
  defs.appendChild(clipPath);
264
264
  this.$element[0].appendChild(defs);
@@ -288,8 +288,10 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
288
288
  _createSvgTextNode(textContent) {
289
289
  const elementHeight = this.model.size.height;
290
290
  const fa = this._buildFontAttrs();
291
+ const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
291
292
  const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
292
- text.setAttribute('y', (elementHeight / 2).toString());
293
+ const textY = elementHeight / 2;
294
+ text.setAttribute('y', textY.toString());
293
295
  text.setAttribute('dominant-baseline', 'central');
294
296
  text.setAttribute('fill', fa.color);
295
297
  text.setAttribute('font-size', fa.fontSize.toString());
@@ -300,11 +302,41 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
300
302
  if (fa.isItalic) {
301
303
  text.setAttribute('font-style', 'italic');
302
304
  }
305
+ // 不使用 SVG text-decoration,避免跨平台下划线位置不一致(Chrome/Android 与 iOS Safari 渲染差异)
306
+ text.textContent = textContent;
307
+ g.appendChild(text);
303
308
  if (fa.isUnderline) {
304
- text.setAttribute('text-decoration', 'underline');
309
+ // dominant-baseline: central 下,基线约在 textY + fontSize*0.35
310
+ // 下划线紧贴文字底部(基线下 fontSize*0.1),再加 2px 间距避免与字形粘连
311
+ // stroke-width 随字号缩放,参照浏览器标准约 fontSize/14,最小 1px
312
+ const lineY = textY + Math.round(fa.fontSize * 0.35) + Math.round(fa.fontSize * 0.1) + 2;
313
+ const strokeWidth = Math.max(1, Math.round(fa.fontSize / 14));
314
+ const underline = document.createElementNS('http://www.w3.org/2000/svg', 'line');
315
+ underline.setAttribute('y1', lineY.toString());
316
+ underline.setAttribute('y2', lineY.toString());
317
+ underline.setAttribute('x1', '0');
318
+ underline.setAttribute('x2', '0'); // 宽度在 append 后由 _updateUnderlineWidth 设置
319
+ underline.setAttribute('stroke', fa.color);
320
+ underline.setAttribute('stroke-width', strokeWidth.toString());
321
+ underline.setAttribute('class', 'text-underline');
322
+ g.appendChild(underline);
323
+ }
324
+ return g;
325
+ }
326
+ _getSvgTextWidth(g) {
327
+ const text = g.querySelector('text');
328
+ if (!text) {
329
+ return 100;
330
+ }
331
+ return text.getComputedTextLength
332
+ ? text.getComputedTextLength()
333
+ : (text.getBBox ? text.getBBox().width : 100);
334
+ }
335
+ _updateUnderlineWidth(g, width) {
336
+ const underline = g.querySelector('line.text-underline');
337
+ if (underline) {
338
+ underline.setAttribute('x2', width.toString());
305
339
  }
306
- text.textContent = textContent;
307
- return text;
308
340
  }
309
341
  renderNewPage(pageData) {
310
342
  const GAP = 80;
@@ -336,11 +368,10 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
336
368
  contentParts.push(stateMap[alarm.state] || (isChinese ? '触发/未确认' : 'Triggered/Unconfirmed'));
337
369
  }
338
370
  const textNode = this._createSvgTextNode(contentParts.join(' '));
339
- textNode.setAttribute('x', xOffset.toString());
371
+ textNode.setAttribute('transform', `translate(${xOffset}, 0)`);
340
372
  this.allAlarmsContainer.appendChild(textNode);
341
- const textWidth = textNode.getComputedTextLength
342
- ? textNode.getComputedTextLength()
343
- : (textNode.getBBox ? textNode.getBBox().width : 100);
373
+ const textWidth = this._getSvgTextWidth(textNode);
374
+ this._updateUnderlineWidth(textNode, textWidth);
344
375
  xOffset += textWidth + GAP;
345
376
  pageWidth += (pageWidth > 0 ? GAP : 0) + textWidth;
346
377
  });
@@ -351,10 +382,9 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
351
382
  const GAP = 80;
352
383
  let x = 0;
353
384
  Array.from(this.allAlarmsContainer.children).forEach(node => {
354
- node.setAttribute('x', x.toString());
355
- const w = node.getComputedTextLength
356
- ? node.getComputedTextLength()
357
- : (node.getBBox ? node.getBBox().width : 100);
385
+ node.setAttribute('transform', `translate(${x}, 0)`);
386
+ const w = this._getSvgTextWidth(node);
387
+ this._updateUnderlineWidth(node, w);
358
388
  x += w + GAP;
359
389
  });
360
390
  const newTotal = x > 0 ? x - GAP : 0;
@@ -371,14 +401,13 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
371
401
  elementsToRemove.forEach(el => {
372
402
  this.allAlarmsContainer.removeChild(el);
373
403
  });
374
- // SVG text x 坐标从 0 重排(DOM删除后剩余节点要重新编排 x)
404
+ // g 元素的 transform 0 重排(DOM删除后剩余节点要重新编排位置)
375
405
  const GAP = 80;
376
406
  let x = 0;
377
407
  Array.from(this.allAlarmsContainer.children).forEach(node => {
378
- node.setAttribute('x', x.toString());
379
- const w = node.getComputedTextLength
380
- ? node.getComputedTextLength()
381
- : (node.getBBox ? node.getBBox().width : 100);
408
+ node.setAttribute('transform', `translate(${x}, 0)`);
409
+ const w = this._getSvgTextWidth(node);
410
+ this._updateUnderlineWidth(node, w);
382
411
  x += w + GAP;
383
412
  });
384
413
  // currentLeft 补偿被移除页的宽度(含 gap),保持视觉位置不变
@@ -588,14 +617,13 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
588
617
  }
589
618
  // 创建 SVG text 节点(与真实运行模式一致,不依赖 foreignObject)
590
619
  const textNode = this._createSvgTextNode(textParts.join(' '));
591
- textNode.setAttribute('x', '0');
620
+ textNode.setAttribute('transform', 'translate(0, 0)');
592
621
  this.currentLeft = this.model.size.width;
593
622
  this.allAlarmsContainer.setAttribute('transform', `translate(${this.currentLeft}, 0)`);
594
623
  this.allAlarmsContainer.appendChild(textNode);
595
- // SVG text 宽度可直接通过 getComputedTextLength 同步获取,无需 setTimeout
596
- const textWidth = textNode.getComputedTextLength
597
- ? textNode.getComputedTextLength()
598
- : (textNode.getBBox ? textNode.getBBox().width : 200);
624
+ // SVG text 宽度通过内部 text 元素的 getComputedTextLength 获取
625
+ const textWidth = this._getSvgTextWidth(textNode);
626
+ this._updateUnderlineWidth(textNode, textWidth);
599
627
  this.totalWidth = textWidth;
600
628
  this.pageWidths.push(textWidth);
601
629
  // 启动滚动(autoCycle 只控制是否循环,不控制是否滚动)
@@ -1 +1 @@
1
- [{"__symbolic":"module","version":4,"metadata":{"ScrollAlarmElement":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"../base/conditional-dynamic-display-element","name":"ConditionalDynamicDisplayElement","line":17,"character":40},"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"error","message":"Could not resolve type","line":52,"character":25,"context":{"typeName":"HTMLElement"}},{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":53,"character":18},{"__symbolic":"reference","module":"../../service","name":"PermissionChecker","line":54,"character":27},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":55,"character":30},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":56,"character":23},{"__symbolic":"reference","module":"../../config","name":"AlarmsStore","line":57,"character":38},{"__symbolic":"reference","name":"string"}]}],"dispose":[{"__symbolic":"method"}],"getAlarmData":[{"__symbolic":"method"}],"initDisplayContainer":[{"__symbolic":"method"}],"_buildFontAttrs":[{"__symbolic":"method"}],"_createSvgTextNode":[{"__symbolic":"method"}],"renderNewPage":[{"__symbolic":"method"}],"_rebaseTextNodes":[{"__symbolic":"method"}],"removeOldestPage":[{"__symbolic":"method"}],"scrollContent":[{"__symbolic":"method"}],"initScrolling":[{"__symbolic":"method"}],"resetToFirstPage":[{"__symbolic":"method"}],"updateQueryTimeRange":[{"__symbolic":"method"}],"setStatusAsNormal":[{"__symbolic":"method"}],"setStatusAsLoading":[{"__symbolic":"method"}],"renderStatus":[{"__symbolic":"method"}],"clearStatus":[{"__symbolic":"method"}],"renderStaticDisplay":[{"__symbolic":"method"}],"initStaticScrolling":[{"__symbolic":"method"}],"scrollStaticContent":[{"__symbolic":"method"}],"replaceCurrentScrollingContent":[{"__symbolic":"method"}]}}}}]
1
+ [{"__symbolic":"module","version":4,"metadata":{"ScrollAlarmElement":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"../base/conditional-dynamic-display-element","name":"ConditionalDynamicDisplayElement","line":17,"character":40},"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"error","message":"Could not resolve type","line":52,"character":25,"context":{"typeName":"HTMLElement"}},{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":53,"character":18},{"__symbolic":"reference","module":"../../service","name":"PermissionChecker","line":54,"character":27},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":55,"character":30},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":56,"character":23},{"__symbolic":"reference","module":"../../config","name":"AlarmsStore","line":57,"character":38},{"__symbolic":"reference","name":"string"}]}],"dispose":[{"__symbolic":"method"}],"getAlarmData":[{"__symbolic":"method"}],"initDisplayContainer":[{"__symbolic":"method"}],"_buildFontAttrs":[{"__symbolic":"method"}],"_createSvgTextNode":[{"__symbolic":"method"}],"_getSvgTextWidth":[{"__symbolic":"method"}],"_updateUnderlineWidth":[{"__symbolic":"method"}],"renderNewPage":[{"__symbolic":"method"}],"_rebaseTextNodes":[{"__symbolic":"method"}],"removeOldestPage":[{"__symbolic":"method"}],"scrollContent":[{"__symbolic":"method"}],"initScrolling":[{"__symbolic":"method"}],"resetToFirstPage":[{"__symbolic":"method"}],"updateQueryTimeRange":[{"__symbolic":"method"}],"setStatusAsNormal":[{"__symbolic":"method"}],"setStatusAsLoading":[{"__symbolic":"method"}],"renderStatus":[{"__symbolic":"method"}],"clearStatus":[{"__symbolic":"method"}],"renderStaticDisplay":[{"__symbolic":"method"}],"initStaticScrolling":[{"__symbolic":"method"}],"scrollStaticContent":[{"__symbolic":"method"}],"replaceCurrentScrollingContent":[{"__symbolic":"method"}]}}}}]
@@ -35,7 +35,19 @@ let WriteValueModalComponent = class WriteValueModalComponent {
35
35
  this.validate();
36
36
  }
37
37
  initData(option) {
38
+ var _a, _b, _c;
38
39
  this.variableName = option.variableName;
40
+ if (this.variableName === '当前语种ID') {
41
+ const language = (_c = (_b = (_a = window.abp) === null || _a === void 0 ? void 0 : _a.localization) === null || _b === void 0 ? void 0 : _b.currentLanguage) === null || _c === void 0 ? void 0 : _c.name;
42
+ const isChinese = language === 'zh-Hans' || language === 'zh';
43
+ const isTraditionalChinese = language === 'zh-Hant' || language === 'zh-TW' || language === 'zh-tw';
44
+ if (isTraditionalChinese) {
45
+ this.variableName = '當前語種ID';
46
+ }
47
+ else if (!isChinese) {
48
+ this.variableName = ' Current Language ID';
49
+ }
50
+ }
39
51
  this.dataType = option.dataType;
40
52
  this.fBoxDataType = option.fBoxDataType;
41
53
  this.integerDigits = option.integerDigits ? option.integerDigits : 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "main": "bundles/fc-gui.umd.js",
3
- "version": "3.0.0-alpha.147",
3
+ "version": "3.0.0-alpha.149",
4
4
  "module": "public_api.js",
5
5
  "typings": "public_api.d.ts",
6
6
  "license": "UNLICENSED",