@hzab/utils 0.0.1

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.
@@ -0,0 +1,152 @@
1
+ export const TYPE_VIDEO = "video";
2
+ export const TYPE_IMG = "image";
3
+ export const TYPE_AUDIO = "audio";
4
+
5
+ /**
6
+ * 检查 url 是否带有指定后缀
7
+ * @param {string} url url 地址
8
+ * @param {Array} types 后缀数组
9
+ * @returns
10
+ */
11
+ export function checkUrlSuffix(url, types = [], caseSensitive = false) {
12
+ if (!url) {
13
+ return false;
14
+ }
15
+ let _url = url?.replace(/\?.+/, "");
16
+ const reg = new RegExp(`\.(${types.join("|")})$`, caseSensitive ? undefined : "i");
17
+ if (reg.test(_url)) {
18
+ return true;
19
+ }
20
+ }
21
+
22
+ /**
23
+ * 获取文件类型(文件自身类型,如:video/mp4、image/jpeg)
24
+ * @param file
25
+ * @returns
26
+ */
27
+ export function getFileType(file) {
28
+ if (typeof file === "object" && file?.type) {
29
+ return file?.type;
30
+ }
31
+ if (typeof file === "string") {
32
+ let type = null;
33
+ if (checkVideoUrl(file)) {
34
+ type = "video/mp4";
35
+ } else if (checkImageUrl(file)) {
36
+ type = "image/jpeg";
37
+ } else if (checkAudioUrl(file)) {
38
+ type = "audio/3gpp";
39
+ } else if (checkUrlSuffix(file, ["pdf"])) {
40
+ type = "application/pdf";
41
+ } else if (checkUrlSuffix(file, ["pdf"])) {
42
+ type = "application/pdf";
43
+ } else if (checkUrlSuffix(file, ["xlsx", "xls", "csv", "xlsm", "xlsb"])) {
44
+ type = "application/vnd.ms-excel";
45
+ } else if (checkUrlSuffix(file, ["doc", "docx"])) {
46
+ type = "application/msword";
47
+ } else if (checkUrlSuffix(file, ["ppt", "pptx"])) {
48
+ type = "application/vnd.ms-powerpoint";
49
+ }
50
+ return type;
51
+ }
52
+ }
53
+
54
+ /**
55
+ * 判断 url 是否带有指定图片后缀
56
+ * @param {string} url
57
+ * @returns
58
+ */
59
+ export function checkImageUrl(url) {
60
+ // base64
61
+ if (/^data:image\/\w+;base64/i.test(url)) {
62
+ return true;
63
+ }
64
+ const imgTypes = [
65
+ "apng",
66
+ "avif",
67
+ "bmp",
68
+ "gif",
69
+ "ico",
70
+ "cur",
71
+ "jpg",
72
+ "jpeg",
73
+ "jfif",
74
+ "pjpeg",
75
+ "pjp",
76
+ "png",
77
+ "svg",
78
+ "tif",
79
+ "tiff",
80
+ "webp",
81
+ ];
82
+ return checkUrlSuffix(url, imgTypes);
83
+ }
84
+
85
+ /**
86
+ * 判断是否是合法的媒体类型
87
+ * @param {String} input
88
+ * @returns
89
+ */
90
+ export function isValidMediaType(input) {
91
+ const validPrefixes = ["image/", "video/", "audio/"];
92
+ return validPrefixes.some((prefix) => input?.startsWith(prefix));
93
+ }
94
+
95
+ /**
96
+ * 判断 url 是否带有指定视频后缀
97
+ * @param {string} url
98
+ * @returns
99
+ */
100
+ export function checkVideoUrl(url) {
101
+ const imgTypes = ["3gp", "mpg", "mpeg", "mp4", "m4v", "m4p", "ogv", "ogg", "mov", "webm"];
102
+ return checkUrlSuffix(url, imgTypes);
103
+ }
104
+
105
+ /**
106
+ * 判断 url 是否带有指定音频后缀
107
+ * @param {string} url
108
+ * @returns
109
+ */
110
+ export function checkAudioUrl(url) {
111
+ const imgTypes = ["3gp", "adts", "mpeg", "mp3", "mp4", "ogg", "mov", "webm", "rtp", "amr", "wav"];
112
+ return checkUrlSuffix(url, imgTypes);
113
+ }
114
+
115
+ /**
116
+ * 获取文件类型(项目内部枚举,如:图片-image、视频-video)
117
+ * @param file
118
+ * @returns
119
+ */
120
+ export function getFileTypeStr(file) {
121
+ const { type, url = file?.ossUrl } = file || {};
122
+ let fileType = "";
123
+ // 判断文件类型,获取对应展示的数据
124
+ if (url) {
125
+ // 图片
126
+ if (url.startsWith("data:image/") || checkImageUrl(url)) {
127
+ fileType = TYPE_IMG;
128
+ } else if (checkVideoUrl(url)) {
129
+ // 视频
130
+ fileType = TYPE_VIDEO;
131
+ } else if (checkAudioUrl(url)) {
132
+ // 音频
133
+ fileType = TYPE_AUDIO;
134
+ }
135
+ } else if (type) {
136
+ // 图片
137
+ if (type?.startsWith("image/")) {
138
+ fileType = TYPE_IMG;
139
+ }
140
+
141
+ // 视频
142
+ if (type?.startsWith("video/")) {
143
+ fileType = TYPE_VIDEO;
144
+ }
145
+
146
+ // 音频
147
+ if (type?.startsWith("audio/")) {
148
+ fileType = TYPE_AUDIO;
149
+ }
150
+ }
151
+ return fileType || type;
152
+ }
@@ -0,0 +1,68 @@
1
+ import _ from "lodash";
2
+
3
+ export function mergeSchema(BaseSchema, InsideSchema, title = "") {
4
+ const _schema = {
5
+ form: BaseSchema.form,
6
+ schema: _.cloneDeep(BaseSchema.schema),
7
+ };
8
+ let idx = Object.keys(_schema.schema.properties).length;
9
+
10
+ if (title) {
11
+ _schema.schema.properties.insideTitle = {
12
+ type: "string",
13
+ "x-component": "Text",
14
+ "x-component-props": {
15
+ content: title || "内部情况",
16
+ },
17
+ "x-designable-id": "insideTitle" + idx,
18
+ "x-index": idx,
19
+ };
20
+ }
21
+
22
+ Object.keys(InsideSchema.schema.properties).forEach((key) => {
23
+ const obj = InsideSchema.schema.properties[key];
24
+ idx += 1;
25
+ obj["x-index"] = idx;
26
+ _schema.schema.properties[key] = obj;
27
+ });
28
+ return _schema;
29
+ }
30
+
31
+ export function mergeSchemas(schemas) {
32
+ if (!(Array.isArray(schemas) && schemas.length > 0)) {
33
+ console.error("请传入 schema");
34
+ return;
35
+ }
36
+ const _schemaList = _.cloneDeep(schemas);
37
+ const _schema = {
38
+ form: _schemaList[0].json.form,
39
+ schema: {
40
+ type: "object",
41
+ properties: {},
42
+ "x-designable-id": _.uniqueId("schema-merge-"),
43
+ },
44
+ };
45
+
46
+ let idx = 0;
47
+ _schemaList.forEach((schema, i) => {
48
+ const titleName = `insideTitle-${i}`;
49
+ _schema.schema.properties[titleName] = {
50
+ type: "string",
51
+ "x-component": "Text",
52
+ "x-component-props": {
53
+ content: schema.title,
54
+ },
55
+ "x-designable-id": titleName,
56
+ "x-index": idx,
57
+ };
58
+ idx += 1;
59
+ Object.keys(schema.json.schema.properties).forEach((key) => {
60
+ const obj = schema.json.schema.properties[key];
61
+ obj["x-index"] = idx;
62
+ _schema.schema.properties[key] = obj;
63
+ idx += 1;
64
+ });
65
+ });
66
+
67
+ return _schema;
68
+ }
@@ -0,0 +1,340 @@
1
+ export class IMAGE_TYPES {
2
+ static JPEG = "image/jpeg";
3
+ static PNG = "image/png";
4
+ }
5
+
6
+ /**
7
+ * 检测空图片
8
+ * @param img
9
+ * @returns
10
+ */
11
+ export function checkEmptyImg(img: HTMLImageElement) {
12
+ // 创建一个 Canvas 元素
13
+ const canvas = document.createElement("canvas");
14
+ const ctx = canvas.getContext("2d");
15
+ if (!ctx) {
16
+ return;
17
+ }
18
+
19
+ // 设置 Canvas 的宽度和高度与图片一致
20
+ canvas.width = img.width;
21
+ canvas.height = img.height;
22
+ // 将图片绘制到Canvas上
23
+ ctx.drawImage(img, 0, 0);
24
+ // 获取Canvas中的像素数据
25
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
26
+ const data = imageData.data;
27
+
28
+ // 判断从左上角到右下角的像素是否都是黑色
29
+ let topLeftToBottomRight = true;
30
+
31
+ const iUp = 0;
32
+ const redUp = data[iUp];
33
+ const greenUp = data[iUp + 1];
34
+ const blueUp = data[iUp + 2];
35
+ const alphaUp = data[iUp + 3];
36
+ for (let i = 0; i < data.length; i += 4) {
37
+ const red = data[i];
38
+ const green = data[i + 1];
39
+ const blue = data[i + 2];
40
+ const alpha = data[i + 3];
41
+
42
+ if (red !== redUp || green !== greenUp || blue !== blueUp || alpha !== alphaUp) {
43
+ topLeftToBottomRight = false;
44
+ break;
45
+ }
46
+ }
47
+
48
+ // 判断从右上角到左下角的像素是否都是黑色
49
+ let topRightToBottomLeft = true;
50
+ const jDown = data.length - 4;
51
+ const redDown = data[jDown];
52
+ const greenDown = data[jDown + 1];
53
+ const blueDown = data[jDown + 2];
54
+ const alphaDown = data[jDown + 3];
55
+
56
+ for (let j = jDown; j >= 0; j -= 4) {
57
+ const red = data[j];
58
+ const green = data[j + 1];
59
+ const blue = data[j + 2];
60
+ const alpha = data[j + 3];
61
+
62
+ if (red !== redDown || green !== greenDown || blue !== blueDown || alpha !== alphaDown) {
63
+ topRightToBottomLeft = false;
64
+ break;
65
+ }
66
+ }
67
+
68
+ // 打印结果
69
+ if (topLeftToBottomRight && topRightToBottomLeft) {
70
+ return false;
71
+ } else {
72
+ return true;
73
+ }
74
+ }
75
+
76
+ /**
77
+ * 获取dom元素宽高
78
+ * @param d dom元素
79
+ * @returns {{width: number, height: number}}
80
+ */
81
+ export function getDomWH(d: HTMLElement | HTMLImageElement | HTMLCanvasElement) {
82
+ if (d instanceof Image || d instanceof HTMLCanvasElement) {
83
+ return {
84
+ width: d.width || d.offsetWidth,
85
+ height: d.width || d.offsetHeight,
86
+ };
87
+ }
88
+ return {
89
+ width: d.offsetWidth,
90
+ height: d.offsetHeight,
91
+ };
92
+ }
93
+
94
+ /**
95
+ * 设置dom元素宽高
96
+ * @param d dom元素
97
+ * @param w 宽
98
+ * @param h 高
99
+ */
100
+ export function setDomWH(dom: HTMLElement, w: number, h: number) {
101
+ dom.setAttribute("width", `${w}`);
102
+ dom.setAttribute("height", `${h}`);
103
+ }
104
+
105
+ /**
106
+ * 获取当前 canvas 图片 Blob 对象
107
+ * @param canvas
108
+ * @returns {Promise<Blob>}
109
+ */
110
+ export function getCanvasPic(canvas: HTMLCanvasElement): Blob {
111
+ var gl = canvas.getContext("2d", { preserveDrawingBuffer: true });
112
+
113
+ return dataURItoBlob(canvas.toDataURL(IMAGE_TYPES.PNG, 1));
114
+ }
115
+
116
+ /**
117
+ * base64 字符串转 blob
118
+ * @param base64
119
+ * @returns
120
+ */
121
+ export function dataURItoBlob(base64: string): Blob {
122
+ let arr = base64.split(",");
123
+ let mime = arr[0]?.match(/:(.*?);/)?.[1];
124
+ let bstr = atob(arr[1]);
125
+ let n = bstr.length;
126
+ let u8arr = new Uint8Array(n);
127
+ while (n--) {
128
+ u8arr[n] = bstr.charCodeAt(n);
129
+ }
130
+ return new Blob([u8arr], { type: mime });
131
+ }
132
+
133
+ /**
134
+ * 获取图片元素
135
+ * @param imgSrc
136
+ * @returns
137
+ */
138
+ export function getImgEle(imgSrc: string): Promise<HTMLImageElement> {
139
+ return new Promise((resolve) => {
140
+ const img = new Image();
141
+ img.onload = function () {
142
+ resolve(img);
143
+ };
144
+ img.src = imgSrc;
145
+ });
146
+ }
147
+
148
+ /**
149
+ * 获取图片 Base64 字符串
150
+ * @param imgSrc
151
+ * @returns
152
+ */
153
+ export function getImgBase64(imgSrc: string): Promise<string> {
154
+ return getImgEle(imgSrc).then((img) => {
155
+ const canvas = document.createElement("canvas");
156
+ let { width, height } = getDomWH(img);
157
+ setDomWH(canvas, width, height);
158
+ const ctx = canvas.getContext("2d");
159
+ ctx && ctx.drawImage(img, 0, 0, width, height, 0, 0, width, height);
160
+ return canvas.toDataURL(IMAGE_TYPES.PNG, 1);
161
+ });
162
+ }
163
+
164
+ /**
165
+ * 通过图片地址获取对应 canvas
166
+ * @param imgSrc
167
+ * @returns
168
+ */
169
+ export function getCanvas(imgSrc: string): Promise<HTMLCanvasElement> {
170
+ return getImgEle(imgSrc).then((img) => {
171
+ const canvas = document.createElement("canvas");
172
+ let { width, height } = getDomWH(img);
173
+ setDomWH(canvas, width, height);
174
+ const ctx = canvas.getContext("2d");
175
+ ctx && ctx.drawImage(img, 0, 0, width, height, 0, 0, width, height);
176
+ return canvas;
177
+ });
178
+ }
179
+
180
+ /**
181
+ * 通过图片地址获取对应 canvas
182
+ * @param img
183
+ * @returns
184
+ */
185
+ export function getCanvasByImg(img: HTMLImageElement): HTMLCanvasElement {
186
+ const canvas = document.createElement("canvas");
187
+ let { width, height } = getDomWH(img);
188
+ setDomWH(canvas, width, height);
189
+ const ctx = canvas.getContext("2d");
190
+ ctx && ctx.drawImage(img, 0, 0, width, height, 0, 0, width, height);
191
+ return canvas;
192
+ }
193
+
194
+ /**
195
+ * 截取图片
196
+ * @param img
197
+ * @param opt
198
+ * @param opt.startX
199
+ * @param opt.startY
200
+ * @param opt.width
201
+ * @param opt.height
202
+ * @returns Promise<string>
203
+ */
204
+ export function cropImage(
205
+ img: HTMLImageElement | HTMLCanvasElement,
206
+ opt: { startX: number; startY: number; width: number; height: number },
207
+ ) {
208
+ return cropImageToCanvas(img, opt).toDataURL(IMAGE_TYPES.PNG, 1);
209
+ }
210
+
211
+ /**
212
+ * 截取图片
213
+ * @param img
214
+ * @param opt
215
+ * @param opt.startX
216
+ * @param opt.startY
217
+ * @param opt.width
218
+ * @param opt.height
219
+ * @returns Promise<HTMLCanvasElement>
220
+ */
221
+ export function cropImageToCanvas(
222
+ img: HTMLImageElement | HTMLCanvasElement,
223
+ opt: { startX: number; startY: number; width: number; height: number },
224
+ ) {
225
+ const { startX, startY, width, height } = opt;
226
+ const canvas = document.createElement("canvas");
227
+ const ctx = canvas.getContext("2d");
228
+ // 设置 canvas 的宽度和高度为裁剪后的尺寸
229
+ canvas.width = width; // 裁剪后的宽度
230
+ canvas.height = height; // 裁剪后的高度
231
+ // 在 canvas 上绘制裁剪后的图像
232
+ ctx?.drawImage(img, startX, startY, width, height, 0, 0, width, height);
233
+ // 可以将裁剪后的图像数据获取出来
234
+ return canvas;
235
+ }
236
+
237
+ /**
238
+ * 绘制图片
239
+ * @param img
240
+ * @param opt
241
+ * @param opt.startX
242
+ * @param opt.startY
243
+ * @param opt.width
244
+ * @param opt.height
245
+ * @returns Promise<string>
246
+ */
247
+ export function imgToCanvas(img: HTMLImageElement) {
248
+ const canvas = document.createElement("canvas");
249
+ const ctx = canvas.getContext("2d");
250
+ canvas.width = img.width;
251
+ canvas.height = img.height;
252
+ ctx?.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
253
+ return canvas;
254
+ }
255
+
256
+ /**
257
+ * 缩放图片
258
+ * @param img
259
+ * @param opt
260
+ * @returns base64
261
+ */
262
+ export function scaleImage(img: HTMLImageElement | HTMLCanvasElement, opt = { scaleFactor: 1 }) {
263
+ return scaleImageToCanvas(img, opt).toDataURL(IMAGE_TYPES.PNG, 1);
264
+ }
265
+
266
+ /**
267
+ * 缩放图片,返回 canvas
268
+ * @param img
269
+ * @param opt
270
+ * @returns canvas
271
+ */
272
+ export function scaleImageToCanvas(img: HTMLImageElement | HTMLCanvasElement, opt = { scaleFactor: 1 }) {
273
+ const { scaleFactor = 1 } = opt;
274
+ const canvas = document.createElement("canvas");
275
+ const ctx = canvas.getContext("2d");
276
+ canvas.width = img.width * scaleFactor;
277
+ canvas.height = img.height * scaleFactor;
278
+ ctx?.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
279
+ return canvas;
280
+ }
281
+
282
+ /**
283
+ * 图片转为 base64
284
+ * @param img
285
+ * @returns
286
+ */
287
+ export async function imgToBase64(img: string | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement) {
288
+ if (!img || img instanceof Blob) {
289
+ return img;
290
+ }
291
+ let _img = img;
292
+ if (img instanceof Image) {
293
+ _img = img.src;
294
+ } else if (img instanceof HTMLVideoElement) {
295
+ // 从视频中获取图片
296
+ const canvas = document.createElement("canvas");
297
+ let { width, height } = getDomWH(img);
298
+ setDomWH(canvas, width, height);
299
+ const ctx = canvas.getContext("2d");
300
+ ctx && ctx.drawImage(img, 0, 0, width, height, 0, 0, width, height);
301
+ _img = canvas.toDataURL(IMAGE_TYPES.PNG, 1);
302
+ } else if (img instanceof HTMLCanvasElement) {
303
+ _img = img.toDataURL(IMAGE_TYPES.PNG, 1);
304
+ } else if (typeof _img === "string" && !_img.startsWith("data:image/")) {
305
+ // 加载图片,并获取图片 base64
306
+ _img = await getImgBase64(_img);
307
+ }
308
+ return _img;
309
+ }
310
+
311
+ /**
312
+ * 图片转为 Blob
313
+ * @param img
314
+ * @returns
315
+ */
316
+ export async function imgToBlob(img: string | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement): Promise<Blob> {
317
+ if (!img) {
318
+ throw new Error("请传入图片数据");
319
+ }
320
+ if (img instanceof Blob) {
321
+ return Promise.resolve(img);
322
+ }
323
+ const _img = await imgToBase64(img);
324
+ if (typeof _img !== "string") {
325
+ throw new Error("传入的图片数据不正确");
326
+ }
327
+ return dataURItoBlob(_img);
328
+ }
329
+
330
+ /**
331
+ * 获取图片的 base64、blob 格式
332
+ * @param img
333
+ */
334
+ export async function getAllTypeImg(img: string | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement) {
335
+ const base64 = await imgToBase64(img);
336
+ return {
337
+ base64,
338
+ blob: typeof base64 === "string" && dataURItoBlob(base64),
339
+ };
340
+ }
@@ -0,0 +1,26 @@
1
+ export const DEFAULT_POSITION = {
2
+ lon: 120.168893,
3
+ lat: 30.225404,
4
+ addr: "浙江省杭州市上城区南星街道杭州西湖风景名胜区",
5
+ };
6
+
7
+ /**
8
+ * 获取当前定位
9
+ * @param config
10
+ * @returns
11
+ */
12
+ export function getCurrentPosition(config?: any): Promise<any> {
13
+ return new Promise((resolve, reject) => {
14
+ navigator?.geolocation?.getCurrentPosition(
15
+ (position) => {
16
+ resolve(position);
17
+ },
18
+ reject,
19
+ {
20
+ enableHighAccuracy: true,
21
+ timeout: 5000,
22
+ ...config,
23
+ },
24
+ );
25
+ });
26
+ }
package/src/nanoid.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { customAlphabet } from "nanoid";
2
+
3
+ /**
4
+ * 指定 nanoid 字符集合
5
+ * 数字和大小写字母
6
+ */
7
+ export const numALetters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
8
+
9
+ /** nanoid 数字和大小写字母 */
10
+ export const nanoidNumALetters = customAlphabet(numALetters, 8);