@lingxiteam/ebe-utils 0.0.3 → 0.0.5

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.
package/es/index.d.ts CHANGED
@@ -24,6 +24,9 @@ interface CodeServices {
24
24
  findApplication: (params: {
25
25
  appId: string;
26
26
  }) => Promise<any>;
27
+ getWaterMarkByAppId: (params: {
28
+ appId: string;
29
+ }) => Promise<any>;
27
30
  }
28
31
  interface CodeOptions {
29
32
  appId: string;
@@ -49,9 +52,10 @@ export declare const fetchData: ({ appId, services, platform, baseUrl, onProgres
49
52
  frontendHookList: any;
50
53
  };
51
54
  attrSpecPage: any;
52
- themeCss: string;
55
+ themeCss: any;
53
56
  models: Record<string, any>;
54
57
  appInfo: Record<string, any>;
58
+ waterMark: any;
55
59
  };
56
60
  cleanedTree: any;
57
61
  }>;
package/es/index.js CHANGED
@@ -266,7 +266,7 @@ export var init = /*#__PURE__*/function () {
266
266
  }();
267
267
  export var fetchData = /*#__PURE__*/function () {
268
268
  var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(_ref4) {
269
- var appId, services, platform, baseUrl, onProgress, appInfo, attrSpecPage, resultObject, frontendHookList, themeCss, temCompAssetList, compAssetList, globalDataInfo, dataSourceList, globalDataMap, pageIdMapping, appPageList, lastPageId, data, pages, itemHash, itemLists, busiData, busiCompMapping, busiPages, pageDSLS, options, cleanedTree;
269
+ var appId, services, platform, baseUrl, onProgress, appInfo, attrSpecPage, resultObject, frontendHookList, themeCss, temCompAssetList, compAssetList, globalDataInfo, dataSourceList, globalDataMap, pageIdMapping, appPageList, lastPageId, data, pages, itemHash, itemLists, busiData, busiCompMapping, busiPages, pageDSLS, waterMark, options, cleanedTree;
270
270
  return _regeneratorRuntime().wrap(function _callee2$(_context2) {
271
271
  while (1) switch (_context2.prev = _context2.next) {
272
272
  case 0:
@@ -311,11 +311,17 @@ export var fetchData = /*#__PURE__*/function () {
311
311
  themeCss = '';
312
312
  _context2.prev = 16;
313
313
  _context2.next = 19;
314
- return Promise.race([services.getThemeCss({
315
- appId: appId,
316
- terminalType: platform
317
- }), new Promise(function (resolve) {
318
- return setTimeout(resolve, 3000);
314
+ return Promise.race([new Promise(function (resolve, reject) {
315
+ services.getThemeCss({
316
+ appId: appId,
317
+ terminalType: platform
318
+ }).then(function (res) {
319
+ resolve(res);
320
+ });
321
+ }), new Promise(function (resolve, reject) {
322
+ setTimeout(function () {
323
+ resolve('');
324
+ }, 3000);
319
325
  })]);
320
326
  case 19:
321
327
  themeCss = _context2.sent;
@@ -421,6 +427,17 @@ export var fetchData = /*#__PURE__*/function () {
421
427
  return busiData;
422
428
  }); // 合并页面,生成器那边支持页面类型和业务组件类型
423
429
  pageDSLS = [].concat(_toConsumableArray(pages), _toConsumableArray(busiPages));
430
+ onProgress({
431
+ log: '查询水印配置信息',
432
+ progress: 7
433
+ });
434
+ // 获取水印
435
+ _context2.next = 60;
436
+ return services.getWaterMarkByAppId({
437
+ appId: appId
438
+ });
439
+ case 60:
440
+ waterMark = _context2.sent;
424
441
  options = {
425
442
  platform: platform,
426
443
  appId: appId,
@@ -436,11 +453,12 @@ export var fetchData = /*#__PURE__*/function () {
436
453
  }),
437
454
  themeCss: themeCss,
438
455
  models: globalDataMap,
439
- appInfo: clearAppInfo(appInfo)
456
+ appInfo: clearAppInfo(appInfo),
457
+ waterMark: waterMark
440
458
  };
441
459
  onProgress({
442
460
  log: '清理无用数据',
443
- progress: 7
461
+ progress: 8
444
462
  });
445
463
  cleanedTree = cleanTree(pageDSLS, ['path']); // 清理字段'b'和字段'e'
446
464
  cleanedTree = clearLXPagesDSL(cleanedTree);
@@ -448,7 +466,7 @@ export var fetchData = /*#__PURE__*/function () {
448
466
  options: options,
449
467
  cleanedTree: cleanedTree
450
468
  });
451
- case 62:
469
+ case 66:
452
470
  case "end":
453
471
  return _context2.stop();
454
472
  }
@@ -0,0 +1,183 @@
1
+ /**
2
+ * 将角度转成弧度
3
+ * @param degrees 角度
4
+ * @returns 弧度
5
+ */
6
+ const degreesToRadians = (degrees: number) => {
7
+ return (degrees * Math.PI) / 180;
8
+ };
9
+
10
+ /**
11
+ * 计算原始矩形旋转后占用的面积
12
+ * @param sourceWidth 原始宽度
13
+ * @param sourceHeight 原始高度
14
+ * @param degrees 旋转角度逆时针 0 - 360°
15
+ */
16
+ const calculateRotateSize = (
17
+ _sourceWidth: number,
18
+ _sourceHeight: number,
19
+ _degrees: number,
20
+ ): {
21
+ width: number;
22
+ height: number;
23
+ } => {
24
+ switch (_degrees) {
25
+ case 0:
26
+ case 180:
27
+ case 360:
28
+ return { width: _sourceWidth, height: _sourceHeight };
29
+ case 90:
30
+ case 270:
31
+ return { width: _sourceHeight, height: _sourceWidth };
32
+ default:
33
+ break;
34
+ }
35
+
36
+ let sourceWidth = _sourceWidth;
37
+ let sourceHeight = _sourceHeight;
38
+ let degrees = _degrees;
39
+
40
+ if (degrees > 90 && degrees < 180) {
41
+ degrees = 180 - degrees;
42
+ sourceWidth = _sourceHeight;
43
+ sourceHeight = _sourceWidth;
44
+ } else if (degrees > 180 && degrees < 270) {
45
+ degrees = 270 - degrees;
46
+ // sourceWidth = _sourceHeight;
47
+ // sourceHeight = _sourceWidth;
48
+ } else if (degrees > 270 && degrees < 360) {
49
+ degrees = 360 - degrees;
50
+ sourceWidth = _sourceHeight;
51
+ sourceHeight = _sourceWidth;
52
+ }
53
+
54
+ // 旋转弧度
55
+ const radians = degreesToRadians(degrees);
56
+
57
+ const widthA = sourceWidth * Math.cos(radians);
58
+
59
+ const heightA = sourceWidth * Math.sin(radians);
60
+
61
+ const widthB = sourceHeight * Math.sin(radians);
62
+
63
+ const heightB = sourceHeight * Math.cos(radians);
64
+
65
+ const res = {
66
+ width: Math.ceil(widthA + widthB),
67
+ height: Math.ceil(heightA + heightB),
68
+ };
69
+
70
+ return res;
71
+ };
72
+
73
+ const laodImage = (baseData: string): Promise<HTMLImageElement> =>
74
+ new Promise((resolve) => {
75
+ const img = new Image();
76
+ img.src = baseData;
77
+ img.onload = () => {
78
+ resolve(img);
79
+ };
80
+ });
81
+
82
+ /**
83
+ * 生成水印图片
84
+ * @param content 水印内容
85
+ * @param width 宽度
86
+ * @param height 高度
87
+ * @param fontSize 字号大小
88
+ * @param fontColor 字体颜色
89
+ * @param alpha 透明度
90
+ * @param angle 旋转角度
91
+ */
92
+ const generatorImage = async (
93
+ content: string,
94
+ width: number,
95
+ height: number,
96
+ fontSize: number,
97
+ fontColor: string,
98
+ alpha: number,
99
+ angle: number,
100
+ ): Promise<string | null> => {
101
+ // 文字行高
102
+ const lineHeight = fontSize + 2;
103
+
104
+ const sourceCanvas = document.createElement('canvas');
105
+ const sourceCtx = sourceCanvas.getContext('2d') as CanvasRenderingContext2D;
106
+
107
+ sourceCanvas.width = width;
108
+ sourceCanvas.height = height;
109
+ sourceCtx.font = `300 ${fontSize}px Microsoft YaHei`;
110
+ sourceCtx.globalAlpha = alpha;
111
+ sourceCtx.fillStyle = fontColor;
112
+
113
+ const strList = [];
114
+
115
+ const measureTextWidth = (str: string) => {
116
+ return sourceCtx.measureText(str).width;
117
+ };
118
+
119
+ // 回车替换成空格 多个空格合并成一个
120
+ const nextStr = content.replace(/\n/g, ' ').replace(/\s{2,}/, ' ');
121
+ let length = 0;
122
+ let currentLine = '';
123
+ while (length < nextStr.length) {
124
+ const char = nextStr[length];
125
+ const newLine = currentLine + char;
126
+ if (measureTextWidth(newLine) < 300) {
127
+ currentLine = newLine;
128
+ } else {
129
+ currentLine = '';
130
+ strList.push({
131
+ x: 0,
132
+ content: newLine,
133
+ });
134
+ }
135
+ length += 1;
136
+ }
137
+
138
+ // 最后一行文字没有填充满 计算居中偏移量
139
+ if (currentLine) {
140
+ strList.push({
141
+ x: (width - measureTextWidth(currentLine)) / 2,
142
+ content: currentLine,
143
+ });
144
+ }
145
+
146
+ // 根据行数计算起始位置
147
+ const contentHeight = strList.length * 26;
148
+ let offsetY = (height - contentHeight) / 2;
149
+ offsetY = offsetY < 0 ? 0 : offsetY;
150
+
151
+ // 逐行添加文字
152
+ for (let i = 0; i < strList.length; i += 1) {
153
+ const { x, content } = strList[i];
154
+ const y = (i + 1) * lineHeight + offsetY;
155
+ sourceCtx.fillText(content, x, y);
156
+ }
157
+
158
+ // 图片base64
159
+ let imgBase64 = sourceCanvas.toDataURL('image/png');
160
+
161
+ // 存在角度旋转
162
+ if (angle > 0) {
163
+ const nextCanvas = document.createElement('canvas');
164
+ const nextCtx = nextCanvas.getContext('2d') as CanvasRenderingContext2D;
165
+ const { width: nextWidth, height: nextHeight } = calculateRotateSize(
166
+ width,
167
+ height,
168
+ angle,
169
+ );
170
+ nextCanvas.width = nextWidth;
171
+ nextCanvas.height = nextHeight;
172
+ const img = await laodImage(imgBase64);
173
+ const _offsetX = -img.width / 2;
174
+ const _offsetY = -img.height / 2;
175
+ nextCtx.translate(nextWidth / 2, nextHeight / 2);
176
+ nextCtx.rotate(-degreesToRadians(angle));
177
+ nextCtx.drawImage(img, _offsetX, _offsetY, img.width, img.height);
178
+ imgBase64 = nextCanvas.toDataURL('image/png');
179
+ }
180
+ return imgBase64;
181
+ };
182
+
183
+ export default generatorImage;
@@ -0,0 +1,10 @@
1
+ @prefix: engine;
2
+ .@{prefix}-watermark {
3
+ position: fixed;
4
+ height: 100%;
5
+ width: 100%;
6
+ z-index: 10000;
7
+ top: 0;
8
+ left:0;
9
+ pointer-events: none;
10
+ }
@@ -0,0 +1,58 @@
1
+ import { FC, useEffect, useRef, useState } from 'react';
2
+ import generatorImage from './generatorImage';
3
+ import './index.less';
4
+
5
+ /**
6
+ * 水印配置
7
+ */
8
+ interface AppWaterMarkCfgType {
9
+ fontColor: string;
10
+ fontSize: string;
11
+ tiltAngle?: string;
12
+ waterMarkInfoResultValue: string;
13
+ isEnable: string;
14
+ fontTransparency: number;
15
+ blockWidth?: number;
16
+ blockHeight?: number;
17
+ }
18
+
19
+ interface WatermarkProps {
20
+ config: AppWaterMarkCfgType;
21
+ }
22
+
23
+ const Watermark: FC<WatermarkProps> = (props) => {
24
+ const watermarkInfo = props.config || {};
25
+ const [previewURL, setPreviewURL] = useState<string>();
26
+ const watermarkRef = useRef<HTMLDivElement>(null);
27
+ const getWaterMark = () => {
28
+ // 如果存在水印就不需要展示,不然弹窗等会叠加水印
29
+ generatorImage(
30
+ watermarkInfo.waterMarkInfoResultValue,
31
+ watermarkInfo.blockWidth || 200,
32
+ watermarkInfo.blockHeight || 200,
33
+ Number(watermarkInfo.fontSize || 16),
34
+ watermarkInfo.fontColor || '#000',
35
+ (watermarkInfo.fontTransparency || 50) / 100,
36
+ Number(watermarkInfo.tiltAngle) || 0,
37
+ ).then((res) => {
38
+ if (res) {
39
+ setPreviewURL(res);
40
+ }
41
+ });
42
+ };
43
+ useEffect(() => {
44
+ getWaterMark();
45
+ }, [watermarkInfo]);
46
+
47
+ return previewURL ? (
48
+ <div
49
+ ref={watermarkRef}
50
+ className="engine-watermark"
51
+ style={{ background: previewURL ? `url(${previewURL})` : '#FFFFFF' }}
52
+ />
53
+ ) : (
54
+ <></>
55
+ );
56
+ };
57
+
58
+ export default Watermark;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lingxiteam/ebe-utils",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "author": "",
@@ -17,7 +17,7 @@
17
17
  "@babel/parser": "^7.12.12",
18
18
  "@babel/traverse": "^7.12.12",
19
19
  "@babel/types": "^7.12.12",
20
- "@lingxiteam/ebe": "0.0.3",
20
+ "@lingxiteam/ebe": "0.0.5",
21
21
  "cac": "^6.7.14",
22
22
  "fs-extra": "9.x"
23
23
  },