cloud-web-corejs 1.1.0-dev.6 → 1.1.0-dev.8

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 (45) hide show
  1. package/package.json +1 -1
  2. package/src/components/VabUpload/view.vue +27 -26
  3. package/src/components/excelImport/index.vue +156 -156
  4. package/src/components/mobile/wf/addTaskUserdialog.vue +23 -3
  5. package/src/components/mobile/wf/content.vue +110 -67
  6. package/src/components/mobile/wf/deleteTaskUserDialog.vue +22 -3
  7. package/src/components/mobile/wf/selectUserDialog.vue +122 -0
  8. package/src/components/mobile/wf/setCandidateDialog.vue +25 -4
  9. package/src/components/mobile/wf/urgingDialog.vue +26 -3
  10. package/src/components/mobile/wf/wfModifyDialog.vue +4 -0
  11. package/src/components/xform/form-designer/designer.js +36 -52
  12. package/src/components/xform/form-designer/form-widget/dialog/importDialog.vue +185 -185
  13. package/src/components/xform/form-designer/form-widget/field-widget/singleUpload-widget.vue +1 -1
  14. package/src/components/xform/form-designer/form-widget/field-widget/vabUpload-widget.vue +2 -2
  15. package/src/components/xform/form-designer/indexMixin.js +25 -0
  16. package/src/components/xform/form-designer/setting-panel/property-editor/container-list-h5/list-h5-editor.vue +833 -860
  17. package/src/components/xform/form-designer/toolbar-panel/index.vue +874 -874
  18. package/src/components/xform/form-designer/widget-panel/index.vue +11 -7
  19. package/src/components/xform/form-designer/widget-panel/indexMixin.js +15 -2
  20. package/src/components/xform/form-designer/widget-panel/widgetsConfig.js +53 -1
  21. package/src/components/xform/form-render/container-item/list-h5-item.vue +154 -27
  22. package/src/components/xform/form-render/indexMixin.js +23 -3
  23. package/src/components/xform/styles/h5.scss +775 -588
  24. package/src/directive/append-to-body/index.js +48 -0
  25. package/src/index.js +4 -0
  26. package/src/layout/components/Sidebar/default.vue +1655 -1655
  27. package/src/router/index.js +48 -48
  28. package/src/utils/vab.js +1283 -1283
  29. package/src/views/bd/setting/form_template/edit.vue +378 -356
  30. package/src/views/bd/setting/form_template/formDesignerDialog.vue +6 -0
  31. package/src/views/bd/setting/form_template/formTemplateType.js +43 -0
  32. package/src/views/bd/setting/form_template/list.vue +304 -303
  33. package/src/views/bd/setting/form_template/mixins/edit.js +344 -280
  34. package/src/views/bd/setting/form_template/mixins/list.js +748 -721
  35. package/src/views/user/file_view_ins/list.vue +970 -970
  36. package/src/views/user/form/vform/designer.vue +823 -821
  37. package/src/views/user/home/default.vue +1117 -1117
  38. package/src/views/user/home/index.vue +103 -103
  39. package/src/views/user/notify_message/dialog.vue +139 -139
  40. package/src/views/user/outLink/form_view.vue +202 -202
  41. package/src/views/user/outLink/index.vue +110 -110
  42. package/src/views/user/wf/iframe/index.vue +51 -51
  43. package/src/views/user/wf/iframe/index2.vue +64 -64
  44. package/src/views/user/wf/wf_manage/list2.vue +871 -871
  45. package/src/views/user/wf/wf_manage/wfContentDialog.vue +134 -134
package/src/utils/vab.js CHANGED
@@ -1,1283 +1,1283 @@
1
- /**version-1.0*/
2
- let install = {};
3
-
4
- import request from "./request";
5
- import * as lodash from "lodash";
6
- import { Loading, Message, MessageBox, Notification, Form } from "element-ui";
7
- import store from "../store";
8
- import ElImageViewer from "../components/VabUpload/image-viewer";
9
-
10
- import { getToken } from "./auth";
11
- import XEUtils from "xe-utils";
12
-
13
- import prefixConfig from "@/prefixConfig.js";
14
- import moment from "moment";
15
- import { openView } from "./repeatOpen";
16
- import { assetUrl } from "./assetUrl";
17
-
18
- let imFun = {
19
- request,
20
- lodash,
21
- Loading,
22
- Message,
23
- MessageBox,
24
- Notification,
25
- Form,
26
- store,
27
- getToken,
28
- prefixConfig,
29
- };
30
-
31
- function reqImg(a) {
32
- /* webpack5 下 require 返回的是无原型的 Module 对象,直接当 src 用会崩,统一取真实 URL */
33
- return assetUrl(require("@/resources/images/" + a));
34
- }
35
-
36
- const FILE_ICON_NAME_MAP = {
37
- word: "ico-wrod.svg",
38
- excel: "ico-excel.svg",
39
- ppt: "ico-ppt.svg",
40
- pdf: "ico-pdf.svg",
41
- picture: "ico-photo.svg",
42
- video: "ico-video.svg",
43
- audio: "ico-music.svg",
44
- html: "ico-html.svg",
45
- txt: "ico-txt.svg",
46
- java: "ico-java.svg",
47
- vue: "ico-vue.svg",
48
- ftl: "ico-ftl.svg",
49
- xml: "ico-xml.svg",
50
- flash: "ico-flash.svg",
51
- zip: "ico-yasuobao.svg",
52
- exe: "ico-ext.svg",
53
- psd: "ico-psd.svg",
54
- folder: "ico-wenjianjia.svg",
55
- other: "ico-default_wenjian.svg",
56
- };
57
-
58
- const FILE_ICON_TYPE_MAP = {
59
- doc: "word",
60
- docx: "word",
61
- xls: "excel",
62
- xlsx: "excel",
63
- ppt: "ppt",
64
- pptx: "ppt",
65
- pdf: "pdf",
66
- jpg: "picture",
67
- jpeg: "picture",
68
- png: "picture",
69
- gif: "picture",
70
- mp3: "video",
71
- mp4: "video",
72
- mpg: "video",
73
- mkv: "video",
74
- rmvb: "video",
75
- avi: "video",
76
- mov: "video",
77
- wav: "audio",
78
- html: "html",
79
- htm: "html",
80
- txt: "txt",
81
- java: "java",
82
- vue: "vue",
83
- ftl: "ftl",
84
- xml: "xml",
85
- swf: "flash",
86
- zip: "zip",
87
- rar: "zip",
88
- "7z": "zip",
89
- // exe: 'exe',
90
- psd: "psd",
91
- };
92
-
93
- let typeList = [
94
- "doc",
95
- "docx",
96
- "xls",
97
- "xlsx",
98
- "ppt",
99
- "pptx",
100
- "csv",
101
- "wps",
102
- "dps",
103
- "et",
104
- "ett",
105
- "wpt",
106
- "vsd",
107
- "vsdx",
108
- "wmf",
109
- "emf",
110
- "psd",
111
- "eps",
112
- "pdf",
113
- "xmind",
114
- "obj",
115
- "3ds",
116
- "stl",
117
- "ply",
118
- "gltf",
119
- "glb",
120
- "off",
121
- "3dm",
122
- "fbx",
123
- "dae",
124
- "wrl",
125
- "3mf",
126
- "ifc",
127
- "brep",
128
- "step",
129
- "iges",
130
- "fcstd",
131
- "bim",
132
- "dwg",
133
- "dxf",
134
- "dwf",
135
- "iges",
136
- "igs",
137
- "dwt",
138
- "dng",
139
- "ifc",
140
- "dwfx",
141
- "stl",
142
- "cf2",
143
- "plt",
144
- "txt",
145
- "xml",
146
- "md",
147
- "java",
148
- "php",
149
- "py",
150
- "js",
151
- "css",
152
- "zip",
153
- "rar",
154
- "jar",
155
- "tar",
156
- "gzip",
157
- "7z",
158
- "mp3",
159
- "wav",
160
- "mp4",
161
- "flv",
162
- "avi",
163
- "mov",
164
- "rm",
165
- "mkv",
166
- "mpeg",
167
- "mpg",
168
- "rmvb",
169
- "wmv",
170
- "3gp",
171
- "swf",
172
- "drawio",
173
- "tif",
174
- "tiff",
175
- "jfif",
176
- "webp",
177
- "tga",
178
- "svg",
179
- "vue",
180
- "ftl",
181
- ];
182
-
183
- const accessToken = imFun.store.getters["user/token"];
184
-
185
- const loadingText = "";
186
- const messageDuration = 3000;
187
-
188
- install = (Vue, opts = {}) => {
189
- /**http请求*/
190
- let $http = async function (option) {
191
- option = option || {};
192
- if (!option.loadingTarget && this.$el) {
193
- option.loadingTarget = this.$el;
194
- }
195
- if (!option.vueTarget) {
196
- option.vueTarget = this;
197
- }
198
- if (option.sync === false) {
199
- return await imFun.request(option);
200
- } else {
201
- return imFun.request(option);
202
- }
203
- };
204
-
205
- Vue.prototype.$commonHttp = function (opts) {
206
- let defaultOption = {
207
- addCreateInfo: true,
208
- queryCreateInfo: window.$vueRoot.$store.getters.queryCreateInfo || "0",
209
- };
210
- let option = Object.assign({}, defaultOption, opts);
211
- if (opts.addCreateInfo === null || opts.addCreateInfo === undefined) {
212
- option.addCreateInfo = defaultOption.addCreateInfo;
213
- }
214
- if (
215
- opts.queryCreateInfo === null ||
216
- opts.queryCreateInfo === undefined ||
217
- opts.queryCreateInfo === true
218
- ) {
219
- option.queryCreateInfo = defaultOption.queryCreateInfo;
220
- }
221
- if (opts.queryCreateInfo === false) {
222
- option.queryCreateInfo = "0";
223
- }
224
- return this.$http(option);
225
- };
226
-
227
- Object.assign($http, imFun.request);
228
- $http.prototype = imFun.request.prototype;
229
- Vue.prototype.$http = $http;
230
-
231
- /* 通用打开菜单/路由:开关开启时以独立标签重复打开,否则按原逻辑跳转
232
- * 用法:this.$openView('/path') 或 this.$openView({ path, query }[, route]) */
233
- Vue.prototype.$openView = function (location, route) {
234
- return openView(this.$router, location, route);
235
- };
236
-
237
- /* 全局accessToken */
238
- Vue.prototype.$baseAccessToken = () => {
239
- return accessToken || imFun.getToken();
240
- };
241
-
242
- /* 全局加载层 */
243
- Vue.prototype.$baseLoading = function (option) {
244
- let d = this.$el;
245
- let loading;
246
- option = option || {};
247
- if (!option.index) {
248
- let opts = {
249
- lock: true,
250
- background: "hsla(0,0%,100%,.8)",
251
- target: d,
252
- };
253
- Object.assign(opts, option);
254
- loading = imFun.Loading.service(opts);
255
- } else {
256
- let opts = {
257
- lock: true,
258
- spinner: "vab-loading-type" + option.index,
259
- background: "hsla(0,0%,100%,.8)",
260
- target: d,
261
- };
262
- Object.assign(opts, option);
263
- loading = imFun.Loading.service(opts);
264
- }
265
- return loading;
266
- };
267
- /* 全局多彩加载层 */
268
- Vue.prototype.$baseColorfullLoading = function (index, text) {
269
- let loading;
270
- if (!index) {
271
- loading = imFun.Loading.service({
272
- lock: true,
273
- text: text || loadingText,
274
- spinner: "dots-loader",
275
- background: "hsla(0,0%,100%,.8)",
276
- target: this.target,
277
- fullscreen: true,
278
- });
279
- } else {
280
- switch (index) {
281
- case 1:
282
- index = "dots";
283
- break;
284
- case 2:
285
- index = "gauge";
286
- break;
287
- case 3:
288
- index = "inner-circles";
289
- break;
290
- case 4:
291
- index = "plus";
292
- break;
293
- }
294
- loading = imFun.Loading.service({
295
- lock: true,
296
- text: text || loadingText,
297
- spinner: index + "-loader",
298
- background: "hsla(0,0%,100%,.8)",
299
- target: this.target,
300
- });
301
- }
302
- return loading;
303
- };
304
- /* 全局Message */
305
- Vue.prototype.$baseMessage = ({ message, type, onClose }) => {
306
- imFun.Message({
307
- offset: 60,
308
- showClose: true,
309
- message: message,
310
- type: type,
311
- dangerouslyUseHTMLString: true,
312
- duration: messageDuration,
313
- onClose: onClose,
314
- });
315
- };
316
-
317
- /* 全局Alert */
318
- Vue.prototype.$baseAlert = function (content, title, callback) {
319
- imFun.MessageBox.alert(content, title || "提示", {
320
- confirmButtonText: "确定",
321
- dangerouslyUseHTMLString: true,
322
- target: this.$el,
323
- confirmButtonClass: "icondui",
324
- customClass: "dialog-style",
325
- callback: (action) => {
326
- if (callback) {
327
- callback();
328
- }
329
- },
330
- });
331
- };
332
-
333
- /* 全局Confirm */
334
- Vue.prototype.$baseConfirm = function (content, title) {
335
- return imFun.MessageBox.confirm(content, title || "提示", {
336
- confirmButtonText: "确定",
337
- cancelButtonText: "取消",
338
- closeOnClickModal: false,
339
- type: "warning",
340
- customClass: "dialog-style",
341
- cancelButtonClass: "iconguanbi",
342
- confirmButtonClass: "icondui",
343
- });
344
- };
345
-
346
- /* 全局Notification */
347
- Vue.prototype.$baseNotify = (message, title, type, position) => {
348
- imFun.Notification({
349
- title: title,
350
- message: message,
351
- position: position || "top-right",
352
- type: type || "success",
353
- duration: messageDuration,
354
- });
355
- };
356
-
357
- /* 全局TableHeight */
358
- Vue.prototype.$baseTableHeight = (formType) => {
359
- let height = window.innerHeight;
360
- let paddingHeight = 400;
361
- const formHeight = 50;
362
-
363
- if (true) {
364
- paddingHeight = 365;
365
- }
366
-
367
- if ("number" === typeof formType) {
368
- height = height - paddingHeight - formHeight * formType;
369
- } else {
370
- height = height - paddingHeight;
371
- }
372
- return height;
373
- };
374
-
375
- /* 全局map图层 */
376
- Vue.prototype.$baseMap = () => {
377
- return new maptalks.Map("map", {
378
- center: [116.41348403785, 39.910843952376],
379
- zoom: 12,
380
- minZoom: 1,
381
- maxZoom: 19,
382
- spatialReference: {
383
- projection: "baidu",
384
- },
385
- attribution: {
386
- content: "© vue-admin-beautiful",
387
- },
388
- baseLayer: new maptalks.TileLayer("base", {
389
- cssFilter: "sepia(100%) invert(90%)",
390
- urlTemplate:
391
- "http://online{s}.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl&scaler=1&p=1",
392
- subdomains: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
393
- attribution:
394
- '&copy; <a target="_blank" href="http://map.baidu.com">Baidu</a>',
395
- }),
396
- });
397
- };
398
-
399
- /* 全局lodash */
400
- Vue.prototype.$baseLodash = imFun.lodash;
401
- /* 全局事件总线 */
402
- Vue.prototype.$baseEventBus = new Vue();
403
- /* 模板里 :src="$assetUrl(require(...))" 用,见 utils/assetUrl.js */
404
- Vue.prototype.$assetUrl = assetUrl;
405
-
406
- Vue.prototype.$commonFileUtil = {
407
- // 文件类型获取与判断接口
408
- getFileSuffix: function (name) {
409
- let i = name.lastIndexOf(".");
410
- if (i < 0) {
411
- // 默认是文本类型
412
- return "";
413
- }
414
- let suffix = name.substring(i + 1, name.length).toLowerCase();
415
- return suffix;
416
- },
417
- isBinary: function (suffix) {
418
- if (!suffix || suffix === "") {
419
- return false;
420
- }
421
- let fileTypeMap = {
422
- bin: true,
423
- exe: true,
424
- dll: true,
425
- so: true,
426
- lib: true,
427
- war: true,
428
- jar: true,
429
- };
430
- let type = fileTypeMap[suffix];
431
- if (undefined === type) {
432
- return false;
433
- }
434
- return true;
435
- },
436
- isPicture: function (suffix) {
437
- if (!suffix || suffix === "") {
438
- return false;
439
- }
440
-
441
- let fileTypeMap = {
442
- jpg: true,
443
- jpeg: true,
444
- png: true,
445
- gif: true,
446
- bmp: true,
447
- mpg: true,
448
- webp: true,
449
- };
450
-
451
- let type = fileTypeMap[suffix];
452
- if (undefined === type) {
453
- return false;
454
- }
455
-
456
- return true;
457
- },
458
- isVideo: function (suffix) {
459
- if (!suffix || suffix === "") {
460
- return false;
461
- }
462
- let fileTypeMap = {
463
- avi: true,
464
- mov: true,
465
- mpeg: true,
466
- mpg: true,
467
- mp4: true,
468
- rmvb: true,
469
- asf: true,
470
- flv: true,
471
- ogg: true,
472
- };
473
-
474
- let type = fileTypeMap[suffix];
475
- if (undefined === type) {
476
- return false;
477
- }
478
-
479
- return true;
480
- },
481
- isText: function (suffix) {
482
- if (!suffix || suffix === "") {
483
- return false;
484
- }
485
- let fileTypeMap = {
486
- txt: true,
487
- log: true,
488
- md: true,
489
- py: true,
490
- java: true,
491
- cpp: true,
492
- hpp: true,
493
- c: true,
494
- h: true,
495
- json: true,
496
- xml: true,
497
- html: true,
498
- sql: true,
499
- js: true,
500
- css: true,
501
- jsp: true,
502
- php: true,
503
- properties: true,
504
- conf: true,
505
- out: true,
506
- sh: true,
507
- bat: true,
508
- msg: true,
509
- cmake: true,
510
- yaml: true,
511
- yml: true,
512
- };
513
-
514
- let type = fileTypeMap[suffix];
515
- if (undefined === type) {
516
- return false;
517
- }
518
-
519
- return true;
520
- },
521
- isZip: function (suffix) {
522
- if (!suffix || suffix === "") {
523
- return false;
524
- }
525
- let fileTypeMap = {
526
- zip: true,
527
- war: true,
528
- rar: true,
529
- "7z": true,
530
- gz: true,
531
- tgz: true,
532
- xz: true,
533
- txz: true,
534
- bz2: true,
535
- tbz2: true,
536
- tar: true,
537
- };
538
-
539
- let type = fileTypeMap[suffix];
540
- if (undefined === type) {
541
- return false;
542
- }
543
-
544
- return true;
545
- },
546
- isOffice: function (suffix) {
547
- if (!suffix || suffix === "") {
548
- return false;
549
- }
550
- let fileTypeMap = {
551
- doc: true,
552
- docx: true,
553
- ppt: true,
554
- pptx: true,
555
- xls: true,
556
- xlsx: true,
557
- };
558
-
559
- let type = fileTypeMap[suffix];
560
- if (undefined === type) {
561
- return false;
562
- }
563
-
564
- return true;
565
- },
566
- isPdf: function (suffix) {
567
- if (!suffix || suffix === "") {
568
- return false;
569
- }
570
- let fileTypeMap = {
571
- pdf: true,
572
- };
573
-
574
- let type = fileTypeMap[suffix];
575
- if (undefined === type) {
576
- return false;
577
- }
578
-
579
- return true;
580
- },
581
- isPictureFile: function (fileName) {
582
- if (!fileName) return false;
583
- let typeStr = Object.prototype.toString.call(fileName);
584
- let suffix = null;
585
- if (typeStr === "[object Object]") {
586
- suffix = this.getFileSuffix(fileName.name);
587
- } else {
588
- suffix = this.getFileSuffix(fileName);
589
- }
590
- return this.isPicture(suffix);
591
- },
592
- isTextFile: function (fileName) {
593
- let suffix = this.getFileSuffix(fileName);
594
- return this.isText(suffix);
595
- },
596
- getShowUrl(url, showImagePreview) {
597
- let index = url.lastIndexOf("/");
598
- let filename;
599
- if (index >= 0) {
600
- filename = url.substring(url.lastIndexOf("/") + 1);
601
- } else {
602
- filename = url;
603
- }
604
-
605
- if (this.isPictureFile(filename) && showImagePreview !== false) {
606
- return url;
607
- } else {
608
- return this.getFileIconRequire(filename);
609
- }
610
- },
611
- resolveFileIconName: function (name, showType) {
612
- let iconType = this.getDiyFileIconType(name) || "other";
613
- if (showType) {
614
- iconType = showType;
615
- }
616
- return FILE_ICON_NAME_MAP[iconType];
617
- },
618
- getFileIconRequire: function (name, showType) {
619
- return reqImg(this.resolveFileIconName(name, showType));
620
- },
621
- getFileIconPath: function (name, showType) {
622
- return "/resources/images/" + this.resolveFileIconName(name, showType);
623
- },
624
- getDiyFileIconType: function (name) {
625
- let suffix = this.getFileSuffix(name);
626
- if (suffix === "") {
627
- // 默认是文本类型
628
- return "";
629
- }
630
-
631
- let iconType = FILE_ICON_TYPE_MAP[suffix];
632
- if (undefined === iconType) {
633
- return "";
634
- }
635
- return iconType;
636
- },
637
- getFileExtension(urlString) {
638
- if (!urlString) return null;
639
- const url = new URL(urlString);
640
- // 获取路径部分,例如 "/images/photo.jpg"
641
- const pathname = url.pathname;
642
-
643
- // 使用 lastIndexOf 找到最后一个点的位置
644
- const lastDotIndex = pathname.lastIndexOf(".");
645
-
646
- // 如果没有点,或者点在最后一位(即没有后缀),返回空字符串
647
- if (lastDotIndex === -1 || lastDotIndex === pathname.length - 1) {
648
- return "";
649
- }
650
-
651
- // 截取点之后的部分
652
- return pathname.slice(lastDotIndex + 1).toLowerCase();
653
- },
654
- downloadFile: function () {
655
- let filePath, name;
656
- let opts;
657
- if (typeof arguments[0] === "string") {
658
- filePath = arguments[0];
659
- name = arguments[1];
660
- } else {
661
- opts = arguments[0];
662
- filePath = opts.filePath;
663
- name = opts.name;
664
- }
665
- if (filePath) {
666
- let url = null;
667
- if (filePath.indexOf("?") >= 0) {
668
- url = filePath + "&_d=true";
669
- } else {
670
- url = filePath + "?_d=true";
671
- }
672
- if (name) {
673
- let fileSuffix = this.getFileExtension(filePath);
674
- if (fileSuffix && !name.endsWith("." + fileSuffix)) {
675
- name = name + "." + fileSuffix;
676
- }
677
-
678
- url += "&_n=" + encodeURIComponent(name);
679
- }
680
- // window.open(url);
681
- openInNewTab(url);
682
- }
683
- },
684
- isPreviewFile(fileName) {
685
- let fileSuffix = this.getFileSuffix(fileName);
686
- return typeList.includes(fileSuffix);
687
- },
688
- };
689
-
690
- Vue.prototype.$openFilePreview = function () {
691
- let filePath;
692
- let opts;
693
- if (typeof arguments[0] === "string") {
694
- filePath = arguments[0];
695
- } else {
696
- let attachment = arguments[0];
697
- filePath = attachment.domain + attachment.url;
698
- }
699
- let fileSuffix = this.$commonFileUtil.getFileSuffix(filePath);
700
- if (!typeList.includes(fileSuffix)) {
701
- return;
702
- }
703
-
704
- this.$http({
705
- url: USER_PREFIX + "/sf_common/getFilePreviewUrl",
706
- method: `post`,
707
- data: {
708
- url: filePath,
709
- },
710
- isLoading: true,
711
- success: (res) => {
712
- if (res.objx) {
713
- openInNewTab(res.objx);
714
- }
715
- },
716
- });
717
- };
718
-
719
- function openInNewTab(url) {
720
- if (!url) return;
721
- let a = document.createElement("a");
722
- a.href = url;
723
- a.target = "_blank";
724
- document.body.appendChild(a);
725
- a.click();
726
- document.body.removeChild(a);
727
- }
728
-
729
- Vue.prototype.$getFilePreviewUrl = async function (obj, callback) {
730
- let filePath;
731
- let opts;
732
- if (typeof obj === "string") {
733
- filePath = obj;
734
- } else {
735
- let attachment = obj;
736
- filePath = attachment.domain + attachment.url;
737
- }
738
- let fileSuffix = this.$commonFileUtil.getFileSuffix(filePath);
739
- /*if (!typeList.includes(fileSuffix)) {
740
- return;
741
- }*/
742
-
743
- return this.$http({
744
- url: USER_PREFIX + "/sf_common/getFilePreviewUrl",
745
- method: `post`,
746
- data: {
747
- url: filePath,
748
- },
749
- isLoading: true,
750
- success: (res) => {
751
- callback && callback(res.objx);
752
- },
753
- });
754
- };
755
-
756
- Vue.prototype.$baseFilePreview = function (attachment, index) {
757
- let that = this;
758
- let openImagePreView = function (attachments, index) {
759
- let pictureIndex = -1;
760
- let pictureDtoList = [];
761
- index = index || 0;
762
- attachments.forEach((item, i) => {
763
- let typeStr = Object.prototype.toString.call(item);
764
- if (typeStr === "[object Object]") {
765
- if (that.$commonFileUtil.isPictureFile(item.url)) {
766
- if (i <= index) {
767
- pictureIndex++;
768
- }
769
- pictureDtoList.push(item.domain + item.url);
770
- }
771
- } else {
772
- if (that.$commonFileUtil.isPictureFile(item)) {
773
- if (i <= index) {
774
- pictureIndex++;
775
- }
776
- pictureDtoList.push(item);
777
- }
778
- }
779
- });
780
-
781
- let a = Vue.extend(ElImageViewer);
782
- let instance = new a({
783
- propsData: {
784
- onClose: () => {
785
- dom.remove();
786
- },
787
- initialIndex: pictureIndex,
788
- urlList: pictureDtoList,
789
- },
790
- });
791
- let dom = instance.$mount().$el;
792
- document.body.append(dom);
793
- };
794
- let openPreview = function (attachment, index) {
795
- if (Array.isArray(attachment)) {
796
- let currentFile = attachment[index];
797
- let typeStr = Object.prototype.toString.call(currentFile);
798
- let url =
799
- typeStr === "[object Object]"
800
- ? currentFile.domain + currentFile.url
801
- : currentFile;
802
- if (that.$commonFileUtil.isPictureFile(url)) {
803
- openImagePreView(attachment, index);
804
- } else if (that.$commonFileUtil.isPreviewFile(url)) {
805
- that.$openFilePreview(url);
806
- }
807
- } else {
808
- let typeStr = Object.prototype.toString.call(attachment);
809
- let url =
810
- typeStr === "[object Object]"
811
- ? attachment.domain + attachment.url
812
- : attachment;
813
- if (that.$commonFileUtil.isPictureFile(url)) {
814
- openImagePreView([url], 0);
815
- } else if (that.$commonFileUtil.isPreviewFile(url)) {
816
- that.$openFilePreview(url);
817
- }
818
- }
819
- };
820
- openPreview(attachment, index);
821
- };
822
-
823
- Vue.prototype.$openEditView = function (key) {
824
- this[key] = false;
825
- setTimeout(() => {
826
- this[key] = true;
827
- }, 200);
828
- };
829
-
830
- Vue.prototype.$baseReload = function (param) {
831
- this.$emit("reload", this, param);
832
- };
833
-
834
- Vue.prototype.$reloadHandle = function (target, param) {
835
- let visibleKey = target.$attrs["visible-key"] || "showEdit";
836
- let parentTarget = target.$attrs["parent-target"] || target.$parent;
837
- let originTarget = parentTarget.$refs._viewDialog ? parentTarget : target;
838
- let updateParam =
839
- param !== null &&
840
- param !== undefined &&
841
- param.updateParam !== null &&
842
- param.updateParam !== undefined
843
- ? param.updateParam
844
- : {};
845
- for (let key in updateParam) {
846
- originTarget.$emit("update:" + key, updateParam[key]);
847
- }
848
- parentTarget[visibleKey] = false;
849
- return new Promise((resolve) => {
850
- setTimeout(() => {
851
- parentTarget[visibleKey] = true;
852
- parentTarget.$nextTick(resolve);
853
- }, 200);
854
- });
855
- };
856
-
857
- Vue.prototype.$baseStartPickerOptions = function (value, type) {
858
- return {
859
- disabledDate: (time) => {
860
- if (value !== null && value !== undefined && value !== "") {
861
- let date = new Date(value.replace(/-/g, "/"));
862
- if (!type || type === "date") {
863
- date.setDate(date.getDate() + 1);
864
- return time.getTime() >= date.getTime();
865
- } else if (type === "year") {
866
- return time.getYear() > date.getYear();
867
- } else if (type === "month") {
868
- date.setMonth(date.getMonth() + 1);
869
- return time.getTime() >= date.getTime();
870
- }
871
- } else {
872
- return false;
873
- }
874
- },
875
- };
876
- };
877
-
878
- Vue.prototype.$baseEndPickerOptions = function (value, format) {
879
- return {
880
- disabledDate: (time) => {
881
- if (value !== null && value !== undefined && value !== "") {
882
- let date = new Date(value.replace(/-/g, "/"));
883
- return time.getTime() < date.getTime();
884
- } else {
885
- return false;
886
- }
887
- },
888
- };
889
- };
890
-
891
- //除法
892
- function baseDiv() {
893
- let value = 0;
894
- if (arguments.length) {
895
- value = arguments[0];
896
- for (let i = 1; i < arguments.length; i++) {
897
- value = XEUtils.divide(value, arguments[i]);
898
- }
899
- }
900
- return value;
901
- }
902
-
903
- //乘法
904
- function baseMul() {
905
- let value = 0;
906
- if (arguments.length) {
907
- value = arguments[0];
908
- for (let i = 1; i < arguments.length; i++) {
909
- value = XEUtils.multiply(value, arguments[i]);
910
- }
911
- }
912
- return value;
913
- }
914
-
915
- //加法
916
- function baseAdd() {
917
- let value = 0;
918
- if (arguments.length) {
919
- value = arguments[0];
920
- for (let i = 1; i < arguments.length; i++) {
921
- value = XEUtils.add(value, arguments[i]);
922
- }
923
- }
924
- return value;
925
- }
926
-
927
- //减法
928
- function baseSub() {
929
- let value = 0;
930
- if (arguments.length) {
931
- value = arguments[0];
932
- for (let i = 1; i < arguments.length; i++) {
933
- value = XEUtils.subtract(value, arguments[i]);
934
- }
935
- }
936
- return value;
937
- }
938
-
939
- Vue.prototype.$baseAdd = baseAdd;
940
- Vue.prototype.$baseSub = baseSub;
941
- Vue.prototype.$baseMul = baseMul;
942
- Vue.prototype.$baseDiv = baseDiv;
943
-
944
- /**
945
- * 格式化数字为带千分位的字符串。
946
- *
947
- * @param {string | number} value - 输入值
948
- * @param {Object} [options={}] - 配置
949
- * @param {boolean} [options.fixed=false] -
950
- * - `true`: 启用定点精度处理 —— 使用 toFixed(digits) 四舍五入并补零到指定小数位。
951
- * - `false`(默认): 保留原始小数形式(不四舍五入、不补零、保留尾随零)。
952
- * @param {number} [options.digits=2] - 小数位数(仅在 fixed: true 时生效)
953
- * @param {string} [options.thousandsSeparator=','] - 千分位分隔符(始终生效)
954
- * @param {string} [options.decimalSeparator='.'] - 小数点符号
955
- * @returns {string}
956
- *
957
- * @example
958
- * // 默认:保留原始小数
959
- * formatNumber(0.2); // "0.2"
960
- * formatNumber("0.2000"); // "0.2000"
961
- *
962
- * // 启用定点精度处理
963
- * formatNumber(0.2, { fixed: true }); // "0.20"
964
- * formatNumber("123.456", { fixed: true, digits: 1 }); // "123.5"
965
- * formatNumber(1000, { fixed: true, digits: 0 }); // "1,000"
966
- */
967
- function formatNumber(value, options = {}) {
968
- if (value === null || value === undefined || value === "") {
969
- return "";
970
- }
971
-
972
- const {
973
- fixed = false,
974
- digits = 2,
975
- thousandsSeparator = ",",
976
- decimalSeparator = ".",
977
- } = options;
978
-
979
- const isNumber = typeof value === "number";
980
- let str = String(value).trim();
981
-
982
- // Normalize ".123" → "0.123"
983
- if (str.charCodeAt(0) === 46) {
984
- str = "0" + str;
985
- } else if (str.startsWith("-.")) {
986
- str = "-0." + str.slice(2);
987
- }
988
-
989
- let intPart, decPart, isNegative;
990
-
991
- if (fixed) {
992
- // ✅ 启用精度处理:toFixed + 补零
993
- const num = isNumber ? value : parseFloat(str);
994
- if (num !== num) return str;
995
-
996
- const fixedStr = num.toFixed(digits);
997
- const dotIndex = fixedStr.indexOf(".");
998
- intPart = dotIndex === -1 ? fixedStr : fixedStr.slice(0, dotIndex);
999
- decPart = dotIndex === -1 ? "" : fixedStr.slice(dotIndex + 1);
1000
- isNegative = intPart.charCodeAt(0) === 45;
1001
- if (isNegative) intPart = intPart.slice(1);
1002
- } else {
1003
- // 保留原始小数
1004
- let s = str;
1005
- isNegative = s.charCodeAt(0) === 45;
1006
- if (isNegative) s = s.slice(1);
1007
-
1008
- const dotIndex = s.indexOf(".");
1009
- intPart = dotIndex === -1 ? s : s.slice(0, dotIndex);
1010
- decPart = dotIndex === -1 ? "" : s.slice(dotIndex + 1);
1011
-
1012
- if (intPart === "") intPart = "0";
1013
- if (!/^\d+$/.test(intPart)) return str;
1014
- }
1015
-
1016
- // 千分位(始终应用)
1017
- let fmtInt = intPart;
1018
- if (intPart !== "0") {
1019
- let out = "";
1020
- for (let i = intPart.length - 1, c = 0; i >= 0; i--, c++) {
1021
- if (c > 0 && c % 3 === 0) out = thousandsSeparator + out;
1022
- out = intPart[i] + out;
1023
- }
1024
- fmtInt = out;
1025
- }
1026
-
1027
- // 拼接
1028
- let result = isNegative ? "-" + fmtInt : fmtInt;
1029
- if (decPart) {
1030
- result += decimalSeparator + decPart;
1031
- } else if (fixed && digits > 0) {
1032
- result += decimalSeparator + "0".repeat(digits);
1033
- }
1034
-
1035
- return result;
1036
- }
1037
- Vue.prototype.$formatNumber = formatNumber;
1038
-
1039
- /**
1040
- * 生成一个符合 RFC4122 标准的随机 UUID (v4)
1041
- * @returns {string} 格式为 "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx" 的 UUID 字符串
1042
- */
1043
- function generateUUID() {
1044
- const buf = new Uint8Array(16);
1045
- crypto.getRandomValues(buf);
1046
- buf[6] = (buf[6] & 0x0f) | 0x40; // version 4
1047
- buf[8] = (buf[8] & 0x3f) | 0x80; // variant RFC4122
1048
- const hex = Array.from(buf, (b) => b.toString(16).padStart(2, "0")).join(
1049
- ""
1050
- );
1051
- return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(
1052
- 12,
1053
- 16
1054
- )}-${hex.slice(16, 20)}-${hex.slice(20)}`;
1055
- }
1056
- Vue.prototype.$generateUUID = generateUUID;
1057
-
1058
- //数字精确位数
1059
- Vue.prototype.$currency = function (value, priceScale, priceRoundType) {
1060
- if (value !== null && value !== undefined) {
1061
- if (priceScale === null || priceScale === undefined) {
1062
- priceScale = 2;
1063
- }
1064
- if (priceRoundType === null || priceRoundType === undefined) {
1065
- priceRoundType = "roundHalfUp";
1066
- }
1067
- let price;
1068
- if (priceRoundType === "roundHalfUp") {
1069
- price = (
1070
- Math.round(value * Math.pow(10, priceScale)) /
1071
- Math.pow(10, priceScale)
1072
- ).toFixed(priceScale);
1073
- } else if (priceRoundType === "roundUp") {
1074
- price = (
1075
- Math.ceil(value * Math.pow(10, priceScale)) / Math.pow(10, priceScale)
1076
- ).toFixed(priceScale);
1077
- } else {
1078
- price = (
1079
- Math.floor(value * Math.pow(10, priceScale)) /
1080
- Math.pow(10, priceScale)
1081
- ).toFixed(priceScale);
1082
- }
1083
- return price;
1084
- }
1085
- };
1086
-
1087
- Vue.prototype.$getBaseDicts = async function (option) {
1088
- let isLoading = option.isLoading || false;
1089
- return this.$http({
1090
- url: USER_PREFIX + "/common_attribute/listItems",
1091
- method: `post`,
1092
- data: {
1093
- code: option.code,
1094
- enabled: true,
1095
- forCompany: true,
1096
- ...option.data,
1097
- },
1098
- isLoading: isLoading,
1099
- modalStrictly: true,
1100
- success: (res) => {
1101
- let dicts = res.objx || [];
1102
- let dictMap = {};
1103
- for (let item of dicts) {
1104
- dictMap[item.sn] = item.value;
1105
- }
1106
- /* dicts.forEach((item) => {
1107
- dictMap[item.sn] = item.value;
1108
- }); */
1109
- option.success &&
1110
- option.success({
1111
- dicts,
1112
- dictMap,
1113
- });
1114
- },
1115
- });
1116
- };
1117
-
1118
- imFun.Form.methods.$baseValidate = function (callback, opt) {
1119
- let that = this;
1120
- that.validate((valid, obj, c, d) => {
1121
- if (!valid && (!opt || opt.errorTip !== false)) {
1122
- this.$message({
1123
- message: this.$t2("必填项不能为空", "system.message.required"),
1124
- type: "error",
1125
- duration: 2000,
1126
- });
1127
- }
1128
- scrollToFirstError(that);
1129
- callback(valid, obj);
1130
- });
1131
- };
1132
-
1133
- function scrollToFirstError(formTarget) {
1134
- // 获取第一个验证失败的字段
1135
- // let formTarget = this.$refs['renderForm'];
1136
- const firstErrorField = Object.keys(formTarget.fields).find((key) => {
1137
- return formTarget.fields[key].validateState === "error";
1138
- });
1139
-
1140
- if (firstErrorField) {
1141
- const field = formTarget.fields[firstErrorField];
1142
-
1143
- let dom = field.$el;
1144
- if (dom) {
1145
- // 滚动到该字段位置
1146
- dom.scrollIntoView({
1147
- behavior: "smooth",
1148
- block: "center",
1149
- });
1150
-
1151
- // 添加高亮效果
1152
- dom.classList.add("highlight");
1153
-
1154
- // 3秒后移除高亮效果
1155
- setTimeout(() => {
1156
- dom.classList.remove("highlight");
1157
- }, 3000);
1158
- }
1159
- }
1160
- }
1161
-
1162
- Vue.prototype.$getBillInfo = async function (option) {
1163
- let defaultOption = {
1164
- url: null,
1165
- method: `post`,
1166
- data: {},
1167
- isLoading: true,
1168
- modalStrictly: true,
1169
- success: null,
1170
- };
1171
- let opt = Object.assign({}, defaultOption, option);
1172
- delete opt.wfConfig;
1173
- return this.$http({
1174
- ...opt,
1175
- success: (res, response) => {
1176
- option.success && option.success(res, response);
1177
- },
1178
- });
1179
- };
1180
-
1181
- Vue.prototype.$downloadByFileWhole = function (fileWhole, fileName) {
1182
- let that = this;
1183
- if (!fileWhole) {
1184
- this.$baseAlert("凭证信息不存在");
1185
- return;
1186
- }
1187
- let getDownloadDomian = function (callback) {
1188
- that.$http({
1189
- method: "post",
1190
- url: USER_PREFIX + "/common/fileDownloadUrl",
1191
- data: {},
1192
- isLoading: true,
1193
- success: (res) => {
1194
- callback(res.objx);
1195
- },
1196
- });
1197
- };
1198
- getDownloadDomian((domain) => {
1199
- if (fileName) {
1200
- fileWhole.fileName = fileName;
1201
- }
1202
- that.$http({
1203
- method: "post",
1204
- url: domain + "/docfile/download",
1205
- data: fileWhole,
1206
- isLoading: true,
1207
- success: (res) => {
1208
- // window.open(res.objx.url);
1209
- let url = res.objx.url;
1210
- openInNewTab(url);
1211
- },
1212
- });
1213
- });
1214
- };
1215
-
1216
- let isDef = function (value) {
1217
- return value !== undefined && value !== null;
1218
- };
1219
-
1220
- Vue.prototype.$t2 = function (defaultValue, path, values) {
1221
- let that = window.$vueRoot;
1222
- if (!that.hasOwnProperty("_i18n")) {
1223
- return defaultValue;
1224
- }
1225
- const i18n = that.$i18n;
1226
- path = path || defaultValue;
1227
- return i18n.te(path) ? i18n.t(path, values) : defaultValue;
1228
- };
1229
-
1230
- Vue.prototype.$t1 = function (path, values) {
1231
- let that = window.$vueRoot;
1232
- if (!that.hasOwnProperty("_i18n")) {
1233
- return path;
1234
- }
1235
- let lang = that.$i18n.locale;
1236
- const i18n = that.$i18n;
1237
- if (lang === "zh") {
1238
- let val = i18n._t(path, lang, { zh: { [path]: path } }, null, values);
1239
- return val;
1240
- } else {
1241
- if (!i18n.te(path)) {
1242
- return i18n._t(path, lang, { zh: { [path]: path } }, null, values);
1243
- } else {
1244
- return (
1245
- i18n.t(path, values) ||
1246
- i18n._t(path, lang, { zh: { [path]: path } }, null, values)
1247
- );
1248
- }
1249
- }
1250
- };
1251
-
1252
- Vue.prototype.$i18nVal = function (zhValue, enValue) {
1253
- let that = window.$vueRoot;
1254
- if (!that.hasOwnProperty("_i18n")) {
1255
- return zhValue;
1256
- }
1257
- let $i18n = that.$i18n;
1258
- let value = zhValue;
1259
- if ($i18n.locale === "zh") {
1260
- value = zhValue;
1261
- } else if ($i18n.locale === "en") {
1262
- value = enValue;
1263
- }
1264
- return value;
1265
- };
1266
-
1267
- Vue.prototype.$utcToLocal = function (utcTime) {
1268
- if (!utcTime) return utcTime;
1269
- let offsetHours = this.$store.getters.utcTransformOffset; // 时区偏移量,单位:小时
1270
- if (!offsetHours || offsetHours === 0) return utcTime;
1271
- let localTime = moment(utcTime).add(offsetHours, "hours");
1272
- return localTime.format("YYYY-MM-DD HH:mm:ss");
1273
- };
1274
-
1275
- Vue.prototype.$window = window;
1276
- };
1277
-
1278
- window && Object.assign(window, imFun.prefixConfig);
1279
- if (typeof window !== "undefined" && window.Vue) {
1280
- install(window.Vue);
1281
- }
1282
-
1283
- export default install;
1
+ /**version-1.0*/
2
+ let install = {};
3
+
4
+ import request from "./request";
5
+ import * as lodash from "lodash";
6
+ import { Loading, Message, MessageBox, Notification, Form } from "element-ui";
7
+ import store from "../store";
8
+ import ElImageViewer from "../components/VabUpload/image-viewer";
9
+
10
+ import { getToken } from "./auth";
11
+ import XEUtils from "xe-utils";
12
+
13
+ import prefixConfig from "@/prefixConfig.js";
14
+ import moment from "moment";
15
+ import { openView } from "./repeatOpen";
16
+ import { assetUrl } from "./assetUrl";
17
+
18
+ let imFun = {
19
+ request,
20
+ lodash,
21
+ Loading,
22
+ Message,
23
+ MessageBox,
24
+ Notification,
25
+ Form,
26
+ store,
27
+ getToken,
28
+ prefixConfig,
29
+ };
30
+
31
+ function reqImg(a) {
32
+ /* webpack5 下 require 返回的是无原型的 Module 对象,直接当 src 用会崩,统一取真实 URL */
33
+ return assetUrl(require("@/resources/images/" + a));
34
+ }
35
+
36
+ const FILE_ICON_NAME_MAP = {
37
+ word: "ico-wrod.svg",
38
+ excel: "ico-excel.svg",
39
+ ppt: "ico-ppt.svg",
40
+ pdf: "ico-pdf.svg",
41
+ picture: "ico-photo.svg",
42
+ video: "ico-video.svg",
43
+ audio: "ico-music.svg",
44
+ html: "ico-html.svg",
45
+ txt: "ico-txt.svg",
46
+ java: "ico-java.svg",
47
+ vue: "ico-vue.svg",
48
+ ftl: "ico-ftl.svg",
49
+ xml: "ico-xml.svg",
50
+ flash: "ico-flash.svg",
51
+ zip: "ico-yasuobao.svg",
52
+ exe: "ico-ext.svg",
53
+ psd: "ico-psd.svg",
54
+ folder: "ico-wenjianjia.svg",
55
+ other: "ico-default_wenjian.svg",
56
+ };
57
+
58
+ const FILE_ICON_TYPE_MAP = {
59
+ doc: "word",
60
+ docx: "word",
61
+ xls: "excel",
62
+ xlsx: "excel",
63
+ ppt: "ppt",
64
+ pptx: "ppt",
65
+ pdf: "pdf",
66
+ jpg: "picture",
67
+ jpeg: "picture",
68
+ png: "picture",
69
+ gif: "picture",
70
+ mp3: "video",
71
+ mp4: "video",
72
+ mpg: "video",
73
+ mkv: "video",
74
+ rmvb: "video",
75
+ avi: "video",
76
+ mov: "video",
77
+ wav: "audio",
78
+ html: "html",
79
+ htm: "html",
80
+ txt: "txt",
81
+ java: "java",
82
+ vue: "vue",
83
+ ftl: "ftl",
84
+ xml: "xml",
85
+ swf: "flash",
86
+ zip: "zip",
87
+ rar: "zip",
88
+ "7z": "zip",
89
+ // exe: 'exe',
90
+ psd: "psd",
91
+ };
92
+
93
+ let typeList = [
94
+ "doc",
95
+ "docx",
96
+ "xls",
97
+ "xlsx",
98
+ "ppt",
99
+ "pptx",
100
+ "csv",
101
+ "wps",
102
+ "dps",
103
+ "et",
104
+ "ett",
105
+ "wpt",
106
+ "vsd",
107
+ "vsdx",
108
+ "wmf",
109
+ "emf",
110
+ "psd",
111
+ "eps",
112
+ "pdf",
113
+ "xmind",
114
+ "obj",
115
+ "3ds",
116
+ "stl",
117
+ "ply",
118
+ "gltf",
119
+ "glb",
120
+ "off",
121
+ "3dm",
122
+ "fbx",
123
+ "dae",
124
+ "wrl",
125
+ "3mf",
126
+ "ifc",
127
+ "brep",
128
+ "step",
129
+ "iges",
130
+ "fcstd",
131
+ "bim",
132
+ "dwg",
133
+ "dxf",
134
+ "dwf",
135
+ "iges",
136
+ "igs",
137
+ "dwt",
138
+ "dng",
139
+ "ifc",
140
+ "dwfx",
141
+ "stl",
142
+ "cf2",
143
+ "plt",
144
+ "txt",
145
+ "xml",
146
+ "md",
147
+ "java",
148
+ "php",
149
+ "py",
150
+ "js",
151
+ "css",
152
+ "zip",
153
+ "rar",
154
+ "jar",
155
+ "tar",
156
+ "gzip",
157
+ "7z",
158
+ "mp3",
159
+ "wav",
160
+ "mp4",
161
+ "flv",
162
+ "avi",
163
+ "mov",
164
+ "rm",
165
+ "mkv",
166
+ "mpeg",
167
+ "mpg",
168
+ "rmvb",
169
+ "wmv",
170
+ "3gp",
171
+ "swf",
172
+ "drawio",
173
+ "tif",
174
+ "tiff",
175
+ "jfif",
176
+ "webp",
177
+ "tga",
178
+ "svg",
179
+ "vue",
180
+ "ftl",
181
+ ];
182
+
183
+ const accessToken = imFun.store.getters["user/token"];
184
+
185
+ const loadingText = "";
186
+ const messageDuration = 3000;
187
+
188
+ install = (Vue, opts = {}) => {
189
+ /**http请求*/
190
+ let $http = async function (option) {
191
+ option = option || {};
192
+ if (!option.loadingTarget && this.$el) {
193
+ option.loadingTarget = this.$el;
194
+ }
195
+ if (!option.vueTarget) {
196
+ option.vueTarget = this;
197
+ }
198
+ if (option.sync === false) {
199
+ return await imFun.request(option);
200
+ } else {
201
+ return imFun.request(option);
202
+ }
203
+ };
204
+
205
+ Vue.prototype.$commonHttp = function (opts) {
206
+ let defaultOption = {
207
+ addCreateInfo: true,
208
+ queryCreateInfo: window.$vueRoot.$store.getters.queryCreateInfo || "0",
209
+ };
210
+ let option = Object.assign({}, defaultOption, opts);
211
+ if (opts.addCreateInfo === null || opts.addCreateInfo === undefined) {
212
+ option.addCreateInfo = defaultOption.addCreateInfo;
213
+ }
214
+ if (
215
+ opts.queryCreateInfo === null ||
216
+ opts.queryCreateInfo === undefined ||
217
+ opts.queryCreateInfo === true
218
+ ) {
219
+ option.queryCreateInfo = defaultOption.queryCreateInfo;
220
+ }
221
+ if (opts.queryCreateInfo === false) {
222
+ option.queryCreateInfo = "0";
223
+ }
224
+ return this.$http(option);
225
+ };
226
+
227
+ Object.assign($http, imFun.request);
228
+ $http.prototype = imFun.request.prototype;
229
+ Vue.prototype.$http = $http;
230
+
231
+ /* 通用打开菜单/路由:开关开启时以独立标签重复打开,否则按原逻辑跳转
232
+ * 用法:this.$openView('/path') 或 this.$openView({ path, query }[, route]) */
233
+ Vue.prototype.$openView = function (location, route) {
234
+ return openView(this.$router, location, route);
235
+ };
236
+
237
+ /* 全局accessToken */
238
+ Vue.prototype.$baseAccessToken = () => {
239
+ return accessToken || imFun.getToken();
240
+ };
241
+
242
+ /* 全局加载层 */
243
+ Vue.prototype.$baseLoading = function (option) {
244
+ let d = this.$el;
245
+ let loading;
246
+ option = option || {};
247
+ if (!option.index) {
248
+ let opts = {
249
+ lock: true,
250
+ background: "hsla(0,0%,100%,.8)",
251
+ target: d,
252
+ };
253
+ Object.assign(opts, option);
254
+ loading = imFun.Loading.service(opts);
255
+ } else {
256
+ let opts = {
257
+ lock: true,
258
+ spinner: "vab-loading-type" + option.index,
259
+ background: "hsla(0,0%,100%,.8)",
260
+ target: d,
261
+ };
262
+ Object.assign(opts, option);
263
+ loading = imFun.Loading.service(opts);
264
+ }
265
+ return loading;
266
+ };
267
+ /* 全局多彩加载层 */
268
+ Vue.prototype.$baseColorfullLoading = function (index, text) {
269
+ let loading;
270
+ if (!index) {
271
+ loading = imFun.Loading.service({
272
+ lock: true,
273
+ text: text || loadingText,
274
+ spinner: "dots-loader",
275
+ background: "hsla(0,0%,100%,.8)",
276
+ target: this.target,
277
+ fullscreen: true,
278
+ });
279
+ } else {
280
+ switch (index) {
281
+ case 1:
282
+ index = "dots";
283
+ break;
284
+ case 2:
285
+ index = "gauge";
286
+ break;
287
+ case 3:
288
+ index = "inner-circles";
289
+ break;
290
+ case 4:
291
+ index = "plus";
292
+ break;
293
+ }
294
+ loading = imFun.Loading.service({
295
+ lock: true,
296
+ text: text || loadingText,
297
+ spinner: index + "-loader",
298
+ background: "hsla(0,0%,100%,.8)",
299
+ target: this.target,
300
+ });
301
+ }
302
+ return loading;
303
+ };
304
+ /* 全局Message */
305
+ Vue.prototype.$baseMessage = ({ message, type, onClose }) => {
306
+ imFun.Message({
307
+ offset: 60,
308
+ showClose: true,
309
+ message: message,
310
+ type: type,
311
+ dangerouslyUseHTMLString: true,
312
+ duration: messageDuration,
313
+ onClose: onClose,
314
+ });
315
+ };
316
+
317
+ /* 全局Alert */
318
+ Vue.prototype.$baseAlert = function (content, title, callback) {
319
+ imFun.MessageBox.alert(content, title || "提示", {
320
+ confirmButtonText: "确定",
321
+ dangerouslyUseHTMLString: true,
322
+ target: this.$el,
323
+ confirmButtonClass: "icondui",
324
+ customClass: "dialog-style",
325
+ callback: (action) => {
326
+ if (callback) {
327
+ callback();
328
+ }
329
+ },
330
+ });
331
+ };
332
+
333
+ /* 全局Confirm */
334
+ Vue.prototype.$baseConfirm = function (content, title) {
335
+ return imFun.MessageBox.confirm(content, title || "提示", {
336
+ confirmButtonText: "确定",
337
+ cancelButtonText: "取消",
338
+ closeOnClickModal: false,
339
+ type: "warning",
340
+ customClass: "dialog-style",
341
+ cancelButtonClass: "iconguanbi",
342
+ confirmButtonClass: "icondui",
343
+ });
344
+ };
345
+
346
+ /* 全局Notification */
347
+ Vue.prototype.$baseNotify = (message, title, type, position) => {
348
+ imFun.Notification({
349
+ title: title,
350
+ message: message,
351
+ position: position || "top-right",
352
+ type: type || "success",
353
+ duration: messageDuration,
354
+ });
355
+ };
356
+
357
+ /* 全局TableHeight */
358
+ Vue.prototype.$baseTableHeight = (formType) => {
359
+ let height = window.innerHeight;
360
+ let paddingHeight = 400;
361
+ const formHeight = 50;
362
+
363
+ if (true) {
364
+ paddingHeight = 365;
365
+ }
366
+
367
+ if ("number" === typeof formType) {
368
+ height = height - paddingHeight - formHeight * formType;
369
+ } else {
370
+ height = height - paddingHeight;
371
+ }
372
+ return height;
373
+ };
374
+
375
+ /* 全局map图层 */
376
+ Vue.prototype.$baseMap = () => {
377
+ return new maptalks.Map("map", {
378
+ center: [116.41348403785, 39.910843952376],
379
+ zoom: 12,
380
+ minZoom: 1,
381
+ maxZoom: 19,
382
+ spatialReference: {
383
+ projection: "baidu",
384
+ },
385
+ attribution: {
386
+ content: "&copy; vue-admin-beautiful",
387
+ },
388
+ baseLayer: new maptalks.TileLayer("base", {
389
+ cssFilter: "sepia(100%) invert(90%)",
390
+ urlTemplate:
391
+ "http://online{s}.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl&scaler=1&p=1",
392
+ subdomains: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
393
+ attribution:
394
+ '&copy; <a target="_blank" href="http://map.baidu.com">Baidu</a>',
395
+ }),
396
+ });
397
+ };
398
+
399
+ /* 全局lodash */
400
+ Vue.prototype.$baseLodash = imFun.lodash;
401
+ /* 全局事件总线 */
402
+ Vue.prototype.$baseEventBus = new Vue();
403
+ /* 模板里 :src="$assetUrl(require(...))" 用,见 utils/assetUrl.js */
404
+ Vue.prototype.$assetUrl = assetUrl;
405
+
406
+ Vue.prototype.$commonFileUtil = {
407
+ // 文件类型获取与判断接口
408
+ getFileSuffix: function (name) {
409
+ let i = name.lastIndexOf(".");
410
+ if (i < 0) {
411
+ // 默认是文本类型
412
+ return "";
413
+ }
414
+ let suffix = name.substring(i + 1, name.length).toLowerCase();
415
+ return suffix;
416
+ },
417
+ isBinary: function (suffix) {
418
+ if (!suffix || suffix === "") {
419
+ return false;
420
+ }
421
+ let fileTypeMap = {
422
+ bin: true,
423
+ exe: true,
424
+ dll: true,
425
+ so: true,
426
+ lib: true,
427
+ war: true,
428
+ jar: true,
429
+ };
430
+ let type = fileTypeMap[suffix];
431
+ if (undefined === type) {
432
+ return false;
433
+ }
434
+ return true;
435
+ },
436
+ isPicture: function (suffix) {
437
+ if (!suffix || suffix === "") {
438
+ return false;
439
+ }
440
+
441
+ let fileTypeMap = {
442
+ jpg: true,
443
+ jpeg: true,
444
+ png: true,
445
+ gif: true,
446
+ bmp: true,
447
+ mpg: true,
448
+ webp: true,
449
+ };
450
+
451
+ let type = fileTypeMap[suffix];
452
+ if (undefined === type) {
453
+ return false;
454
+ }
455
+
456
+ return true;
457
+ },
458
+ isVideo: function (suffix) {
459
+ if (!suffix || suffix === "") {
460
+ return false;
461
+ }
462
+ let fileTypeMap = {
463
+ avi: true,
464
+ mov: true,
465
+ mpeg: true,
466
+ mpg: true,
467
+ mp4: true,
468
+ rmvb: true,
469
+ asf: true,
470
+ flv: true,
471
+ ogg: true,
472
+ };
473
+
474
+ let type = fileTypeMap[suffix];
475
+ if (undefined === type) {
476
+ return false;
477
+ }
478
+
479
+ return true;
480
+ },
481
+ isText: function (suffix) {
482
+ if (!suffix || suffix === "") {
483
+ return false;
484
+ }
485
+ let fileTypeMap = {
486
+ txt: true,
487
+ log: true,
488
+ md: true,
489
+ py: true,
490
+ java: true,
491
+ cpp: true,
492
+ hpp: true,
493
+ c: true,
494
+ h: true,
495
+ json: true,
496
+ xml: true,
497
+ html: true,
498
+ sql: true,
499
+ js: true,
500
+ css: true,
501
+ jsp: true,
502
+ php: true,
503
+ properties: true,
504
+ conf: true,
505
+ out: true,
506
+ sh: true,
507
+ bat: true,
508
+ msg: true,
509
+ cmake: true,
510
+ yaml: true,
511
+ yml: true,
512
+ };
513
+
514
+ let type = fileTypeMap[suffix];
515
+ if (undefined === type) {
516
+ return false;
517
+ }
518
+
519
+ return true;
520
+ },
521
+ isZip: function (suffix) {
522
+ if (!suffix || suffix === "") {
523
+ return false;
524
+ }
525
+ let fileTypeMap = {
526
+ zip: true,
527
+ war: true,
528
+ rar: true,
529
+ "7z": true,
530
+ gz: true,
531
+ tgz: true,
532
+ xz: true,
533
+ txz: true,
534
+ bz2: true,
535
+ tbz2: true,
536
+ tar: true,
537
+ };
538
+
539
+ let type = fileTypeMap[suffix];
540
+ if (undefined === type) {
541
+ return false;
542
+ }
543
+
544
+ return true;
545
+ },
546
+ isOffice: function (suffix) {
547
+ if (!suffix || suffix === "") {
548
+ return false;
549
+ }
550
+ let fileTypeMap = {
551
+ doc: true,
552
+ docx: true,
553
+ ppt: true,
554
+ pptx: true,
555
+ xls: true,
556
+ xlsx: true,
557
+ };
558
+
559
+ let type = fileTypeMap[suffix];
560
+ if (undefined === type) {
561
+ return false;
562
+ }
563
+
564
+ return true;
565
+ },
566
+ isPdf: function (suffix) {
567
+ if (!suffix || suffix === "") {
568
+ return false;
569
+ }
570
+ let fileTypeMap = {
571
+ pdf: true,
572
+ };
573
+
574
+ let type = fileTypeMap[suffix];
575
+ if (undefined === type) {
576
+ return false;
577
+ }
578
+
579
+ return true;
580
+ },
581
+ isPictureFile: function (fileName) {
582
+ if (!fileName) return false;
583
+ let typeStr = Object.prototype.toString.call(fileName);
584
+ let suffix = null;
585
+ if (typeStr === "[object Object]") {
586
+ suffix = this.getFileSuffix(fileName.name);
587
+ } else {
588
+ suffix = this.getFileSuffix(fileName);
589
+ }
590
+ return this.isPicture(suffix);
591
+ },
592
+ isTextFile: function (fileName) {
593
+ let suffix = this.getFileSuffix(fileName);
594
+ return this.isText(suffix);
595
+ },
596
+ getShowUrl(url, showImagePreview) {
597
+ let index = url.lastIndexOf("/");
598
+ let filename;
599
+ if (index >= 0) {
600
+ filename = url.substring(url.lastIndexOf("/") + 1);
601
+ } else {
602
+ filename = url;
603
+ }
604
+
605
+ if (this.isPictureFile(filename) && showImagePreview !== false) {
606
+ return url;
607
+ } else {
608
+ return this.getFileIconRequire(filename);
609
+ }
610
+ },
611
+ resolveFileIconName: function (name, showType) {
612
+ let iconType = this.getDiyFileIconType(name) || "other";
613
+ if (showType) {
614
+ iconType = showType;
615
+ }
616
+ return FILE_ICON_NAME_MAP[iconType];
617
+ },
618
+ getFileIconRequire: function (name, showType) {
619
+ return reqImg(this.resolveFileIconName(name, showType));
620
+ },
621
+ getFileIconPath: function (name, showType) {
622
+ return "/resources/images/" + this.resolveFileIconName(name, showType);
623
+ },
624
+ getDiyFileIconType: function (name) {
625
+ let suffix = this.getFileSuffix(name);
626
+ if (suffix === "") {
627
+ // 默认是文本类型
628
+ return "";
629
+ }
630
+
631
+ let iconType = FILE_ICON_TYPE_MAP[suffix];
632
+ if (undefined === iconType) {
633
+ return "";
634
+ }
635
+ return iconType;
636
+ },
637
+ getFileExtension(urlString) {
638
+ if (!urlString) return null;
639
+ const url = new URL(urlString);
640
+ // 获取路径部分,例如 "/images/photo.jpg"
641
+ const pathname = url.pathname;
642
+
643
+ // 使用 lastIndexOf 找到最后一个点的位置
644
+ const lastDotIndex = pathname.lastIndexOf(".");
645
+
646
+ // 如果没有点,或者点在最后一位(即没有后缀),返回空字符串
647
+ if (lastDotIndex === -1 || lastDotIndex === pathname.length - 1) {
648
+ return "";
649
+ }
650
+
651
+ // 截取点之后的部分
652
+ return pathname.slice(lastDotIndex + 1).toLowerCase();
653
+ },
654
+ downloadFile: function () {
655
+ let filePath, name;
656
+ let opts;
657
+ if (typeof arguments[0] === "string") {
658
+ filePath = arguments[0];
659
+ name = arguments[1];
660
+ } else {
661
+ opts = arguments[0];
662
+ filePath = opts.filePath;
663
+ name = opts.name;
664
+ }
665
+ if (filePath) {
666
+ let url = null;
667
+ if (filePath.indexOf("?") >= 0) {
668
+ url = filePath + "&_d=true";
669
+ } else {
670
+ url = filePath + "?_d=true";
671
+ }
672
+ if (name) {
673
+ let fileSuffix = this.getFileExtension(filePath);
674
+ if (fileSuffix && !name.endsWith("." + fileSuffix)) {
675
+ name = name + "." + fileSuffix;
676
+ }
677
+
678
+ url += "&_n=" + encodeURIComponent(name);
679
+ }
680
+ // window.open(url);
681
+ openInNewTab(url);
682
+ }
683
+ },
684
+ isPreviewFile(fileName) {
685
+ let fileSuffix = this.getFileSuffix(fileName);
686
+ return typeList.includes(fileSuffix);
687
+ },
688
+ };
689
+
690
+ Vue.prototype.$openFilePreview = function () {
691
+ let filePath;
692
+ let opts;
693
+ if (typeof arguments[0] === "string") {
694
+ filePath = arguments[0];
695
+ } else {
696
+ let attachment = arguments[0];
697
+ filePath = attachment.domain + attachment.url;
698
+ }
699
+ let fileSuffix = this.$commonFileUtil.getFileSuffix(filePath);
700
+ if (!typeList.includes(fileSuffix)) {
701
+ return;
702
+ }
703
+
704
+ this.$http({
705
+ url: USER_PREFIX + "/sf_common/getFilePreviewUrl",
706
+ method: `post`,
707
+ data: {
708
+ url: filePath,
709
+ },
710
+ isLoading: true,
711
+ success: (res) => {
712
+ if (res.objx) {
713
+ openInNewTab(res.objx);
714
+ }
715
+ },
716
+ });
717
+ };
718
+
719
+ function openInNewTab(url) {
720
+ if (!url) return;
721
+ let a = document.createElement("a");
722
+ a.href = url;
723
+ a.target = "_blank";
724
+ document.body.appendChild(a);
725
+ a.click();
726
+ document.body.removeChild(a);
727
+ }
728
+
729
+ Vue.prototype.$getFilePreviewUrl = async function (obj, callback) {
730
+ let filePath;
731
+ let opts;
732
+ if (typeof obj === "string") {
733
+ filePath = obj;
734
+ } else {
735
+ let attachment = obj;
736
+ filePath = attachment.domain + attachment.url;
737
+ }
738
+ let fileSuffix = this.$commonFileUtil.getFileSuffix(filePath);
739
+ /*if (!typeList.includes(fileSuffix)) {
740
+ return;
741
+ }*/
742
+
743
+ return this.$http({
744
+ url: USER_PREFIX + "/sf_common/getFilePreviewUrl",
745
+ method: `post`,
746
+ data: {
747
+ url: filePath,
748
+ },
749
+ isLoading: true,
750
+ success: (res) => {
751
+ callback && callback(res.objx);
752
+ },
753
+ });
754
+ };
755
+
756
+ Vue.prototype.$baseFilePreview = function (attachment, index) {
757
+ let that = this;
758
+ let openImagePreView = function (attachments, index) {
759
+ let pictureIndex = -1;
760
+ let pictureDtoList = [];
761
+ index = index || 0;
762
+ attachments.forEach((item, i) => {
763
+ let typeStr = Object.prototype.toString.call(item);
764
+ if (typeStr === "[object Object]") {
765
+ if (that.$commonFileUtil.isPictureFile(item.url)) {
766
+ if (i <= index) {
767
+ pictureIndex++;
768
+ }
769
+ pictureDtoList.push(item.domain + item.url);
770
+ }
771
+ } else {
772
+ if (that.$commonFileUtil.isPictureFile(item)) {
773
+ if (i <= index) {
774
+ pictureIndex++;
775
+ }
776
+ pictureDtoList.push(item);
777
+ }
778
+ }
779
+ });
780
+
781
+ let a = Vue.extend(ElImageViewer);
782
+ let instance = new a({
783
+ propsData: {
784
+ onClose: () => {
785
+ dom.remove();
786
+ },
787
+ initialIndex: pictureIndex,
788
+ urlList: pictureDtoList,
789
+ },
790
+ });
791
+ let dom = instance.$mount().$el;
792
+ document.body.append(dom);
793
+ };
794
+ let openPreview = function (attachment, index) {
795
+ if (Array.isArray(attachment)) {
796
+ let currentFile = attachment[index];
797
+ let typeStr = Object.prototype.toString.call(currentFile);
798
+ let url =
799
+ typeStr === "[object Object]"
800
+ ? currentFile.domain + currentFile.url
801
+ : currentFile;
802
+ if (that.$commonFileUtil.isPictureFile(url)) {
803
+ openImagePreView(attachment, index);
804
+ } else if (that.$commonFileUtil.isPreviewFile(url)) {
805
+ that.$openFilePreview(url);
806
+ }
807
+ } else {
808
+ let typeStr = Object.prototype.toString.call(attachment);
809
+ let url =
810
+ typeStr === "[object Object]"
811
+ ? attachment.domain + attachment.url
812
+ : attachment;
813
+ if (that.$commonFileUtil.isPictureFile(url)) {
814
+ openImagePreView([url], 0);
815
+ } else if (that.$commonFileUtil.isPreviewFile(url)) {
816
+ that.$openFilePreview(url);
817
+ }
818
+ }
819
+ };
820
+ openPreview(attachment, index);
821
+ };
822
+
823
+ Vue.prototype.$openEditView = function (key) {
824
+ this[key] = false;
825
+ setTimeout(() => {
826
+ this[key] = true;
827
+ }, 200);
828
+ };
829
+
830
+ Vue.prototype.$baseReload = function (param) {
831
+ this.$emit("reload", this, param);
832
+ };
833
+
834
+ Vue.prototype.$reloadHandle = function (target, param) {
835
+ let visibleKey = target.$attrs["visible-key"] || "showEdit";
836
+ let parentTarget = target.$attrs["parent-target"] || target.$parent;
837
+ let originTarget = parentTarget.$refs._viewDialog ? parentTarget : target;
838
+ let updateParam =
839
+ param !== null &&
840
+ param !== undefined &&
841
+ param.updateParam !== null &&
842
+ param.updateParam !== undefined
843
+ ? param.updateParam
844
+ : {};
845
+ for (let key in updateParam) {
846
+ originTarget.$emit("update:" + key, updateParam[key]);
847
+ }
848
+ parentTarget[visibleKey] = false;
849
+ return new Promise((resolve) => {
850
+ setTimeout(() => {
851
+ parentTarget[visibleKey] = true;
852
+ parentTarget.$nextTick(resolve);
853
+ }, 200);
854
+ });
855
+ };
856
+
857
+ Vue.prototype.$baseStartPickerOptions = function (value, type) {
858
+ return {
859
+ disabledDate: (time) => {
860
+ if (value !== null && value !== undefined && value !== "") {
861
+ let date = new Date(value.replace(/-/g, "/"));
862
+ if (!type || type === "date") {
863
+ date.setDate(date.getDate() + 1);
864
+ return time.getTime() >= date.getTime();
865
+ } else if (type === "year") {
866
+ return time.getYear() > date.getYear();
867
+ } else if (type === "month") {
868
+ date.setMonth(date.getMonth() + 1);
869
+ return time.getTime() >= date.getTime();
870
+ }
871
+ } else {
872
+ return false;
873
+ }
874
+ },
875
+ };
876
+ };
877
+
878
+ Vue.prototype.$baseEndPickerOptions = function (value, format) {
879
+ return {
880
+ disabledDate: (time) => {
881
+ if (value !== null && value !== undefined && value !== "") {
882
+ let date = new Date(value.replace(/-/g, "/"));
883
+ return time.getTime() < date.getTime();
884
+ } else {
885
+ return false;
886
+ }
887
+ },
888
+ };
889
+ };
890
+
891
+ //除法
892
+ function baseDiv() {
893
+ let value = 0;
894
+ if (arguments.length) {
895
+ value = arguments[0];
896
+ for (let i = 1; i < arguments.length; i++) {
897
+ value = XEUtils.divide(value, arguments[i]);
898
+ }
899
+ }
900
+ return value;
901
+ }
902
+
903
+ //乘法
904
+ function baseMul() {
905
+ let value = 0;
906
+ if (arguments.length) {
907
+ value = arguments[0];
908
+ for (let i = 1; i < arguments.length; i++) {
909
+ value = XEUtils.multiply(value, arguments[i]);
910
+ }
911
+ }
912
+ return value;
913
+ }
914
+
915
+ //加法
916
+ function baseAdd() {
917
+ let value = 0;
918
+ if (arguments.length) {
919
+ value = arguments[0];
920
+ for (let i = 1; i < arguments.length; i++) {
921
+ value = XEUtils.add(value, arguments[i]);
922
+ }
923
+ }
924
+ return value;
925
+ }
926
+
927
+ //减法
928
+ function baseSub() {
929
+ let value = 0;
930
+ if (arguments.length) {
931
+ value = arguments[0];
932
+ for (let i = 1; i < arguments.length; i++) {
933
+ value = XEUtils.subtract(value, arguments[i]);
934
+ }
935
+ }
936
+ return value;
937
+ }
938
+
939
+ Vue.prototype.$baseAdd = baseAdd;
940
+ Vue.prototype.$baseSub = baseSub;
941
+ Vue.prototype.$baseMul = baseMul;
942
+ Vue.prototype.$baseDiv = baseDiv;
943
+
944
+ /**
945
+ * 格式化数字为带千分位的字符串。
946
+ *
947
+ * @param {string | number} value - 输入值
948
+ * @param {Object} [options={}] - 配置
949
+ * @param {boolean} [options.fixed=false] -
950
+ * - `true`: 启用定点精度处理 —— 使用 toFixed(digits) 四舍五入并补零到指定小数位。
951
+ * - `false`(默认): 保留原始小数形式(不四舍五入、不补零、保留尾随零)。
952
+ * @param {number} [options.digits=2] - 小数位数(仅在 fixed: true 时生效)
953
+ * @param {string} [options.thousandsSeparator=','] - 千分位分隔符(始终生效)
954
+ * @param {string} [options.decimalSeparator='.'] - 小数点符号
955
+ * @returns {string}
956
+ *
957
+ * @example
958
+ * // 默认:保留原始小数
959
+ * formatNumber(0.2); // "0.2"
960
+ * formatNumber("0.2000"); // "0.2000"
961
+ *
962
+ * // 启用定点精度处理
963
+ * formatNumber(0.2, { fixed: true }); // "0.20"
964
+ * formatNumber("123.456", { fixed: true, digits: 1 }); // "123.5"
965
+ * formatNumber(1000, { fixed: true, digits: 0 }); // "1,000"
966
+ */
967
+ function formatNumber(value, options = {}) {
968
+ if (value === null || value === undefined || value === "") {
969
+ return "";
970
+ }
971
+
972
+ const {
973
+ fixed = false,
974
+ digits = 2,
975
+ thousandsSeparator = ",",
976
+ decimalSeparator = ".",
977
+ } = options;
978
+
979
+ const isNumber = typeof value === "number";
980
+ let str = String(value).trim();
981
+
982
+ // Normalize ".123" → "0.123"
983
+ if (str.charCodeAt(0) === 46) {
984
+ str = "0" + str;
985
+ } else if (str.startsWith("-.")) {
986
+ str = "-0." + str.slice(2);
987
+ }
988
+
989
+ let intPart, decPart, isNegative;
990
+
991
+ if (fixed) {
992
+ // ✅ 启用精度处理:toFixed + 补零
993
+ const num = isNumber ? value : parseFloat(str);
994
+ if (num !== num) return str;
995
+
996
+ const fixedStr = num.toFixed(digits);
997
+ const dotIndex = fixedStr.indexOf(".");
998
+ intPart = dotIndex === -1 ? fixedStr : fixedStr.slice(0, dotIndex);
999
+ decPart = dotIndex === -1 ? "" : fixedStr.slice(dotIndex + 1);
1000
+ isNegative = intPart.charCodeAt(0) === 45;
1001
+ if (isNegative) intPart = intPart.slice(1);
1002
+ } else {
1003
+ // 保留原始小数
1004
+ let s = str;
1005
+ isNegative = s.charCodeAt(0) === 45;
1006
+ if (isNegative) s = s.slice(1);
1007
+
1008
+ const dotIndex = s.indexOf(".");
1009
+ intPart = dotIndex === -1 ? s : s.slice(0, dotIndex);
1010
+ decPart = dotIndex === -1 ? "" : s.slice(dotIndex + 1);
1011
+
1012
+ if (intPart === "") intPart = "0";
1013
+ if (!/^\d+$/.test(intPart)) return str;
1014
+ }
1015
+
1016
+ // 千分位(始终应用)
1017
+ let fmtInt = intPart;
1018
+ if (intPart !== "0") {
1019
+ let out = "";
1020
+ for (let i = intPart.length - 1, c = 0; i >= 0; i--, c++) {
1021
+ if (c > 0 && c % 3 === 0) out = thousandsSeparator + out;
1022
+ out = intPart[i] + out;
1023
+ }
1024
+ fmtInt = out;
1025
+ }
1026
+
1027
+ // 拼接
1028
+ let result = isNegative ? "-" + fmtInt : fmtInt;
1029
+ if (decPart) {
1030
+ result += decimalSeparator + decPart;
1031
+ } else if (fixed && digits > 0) {
1032
+ result += decimalSeparator + "0".repeat(digits);
1033
+ }
1034
+
1035
+ return result;
1036
+ }
1037
+ Vue.prototype.$formatNumber = formatNumber;
1038
+
1039
+ /**
1040
+ * 生成一个符合 RFC4122 标准的随机 UUID (v4)
1041
+ * @returns {string} 格式为 "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx" 的 UUID 字符串
1042
+ */
1043
+ function generateUUID() {
1044
+ const buf = new Uint8Array(16);
1045
+ crypto.getRandomValues(buf);
1046
+ buf[6] = (buf[6] & 0x0f) | 0x40; // version 4
1047
+ buf[8] = (buf[8] & 0x3f) | 0x80; // variant RFC4122
1048
+ const hex = Array.from(buf, (b) => b.toString(16).padStart(2, "0")).join(
1049
+ ""
1050
+ );
1051
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(
1052
+ 12,
1053
+ 16
1054
+ )}-${hex.slice(16, 20)}-${hex.slice(20)}`;
1055
+ }
1056
+ Vue.prototype.$generateUUID = generateUUID;
1057
+
1058
+ //数字精确位数
1059
+ Vue.prototype.$currency = function (value, priceScale, priceRoundType) {
1060
+ if (value !== null && value !== undefined) {
1061
+ if (priceScale === null || priceScale === undefined) {
1062
+ priceScale = 2;
1063
+ }
1064
+ if (priceRoundType === null || priceRoundType === undefined) {
1065
+ priceRoundType = "roundHalfUp";
1066
+ }
1067
+ let price;
1068
+ if (priceRoundType === "roundHalfUp") {
1069
+ price = (
1070
+ Math.round(value * Math.pow(10, priceScale)) /
1071
+ Math.pow(10, priceScale)
1072
+ ).toFixed(priceScale);
1073
+ } else if (priceRoundType === "roundUp") {
1074
+ price = (
1075
+ Math.ceil(value * Math.pow(10, priceScale)) / Math.pow(10, priceScale)
1076
+ ).toFixed(priceScale);
1077
+ } else {
1078
+ price = (
1079
+ Math.floor(value * Math.pow(10, priceScale)) /
1080
+ Math.pow(10, priceScale)
1081
+ ).toFixed(priceScale);
1082
+ }
1083
+ return price;
1084
+ }
1085
+ };
1086
+
1087
+ Vue.prototype.$getBaseDicts = async function (option) {
1088
+ let isLoading = option.isLoading || false;
1089
+ return this.$http({
1090
+ url: USER_PREFIX + "/common_attribute/listItems",
1091
+ method: `post`,
1092
+ data: {
1093
+ code: option.code,
1094
+ enabled: true,
1095
+ forCompany: true,
1096
+ ...option.data,
1097
+ },
1098
+ isLoading: isLoading,
1099
+ modalStrictly: true,
1100
+ success: (res) => {
1101
+ let dicts = res.objx || [];
1102
+ let dictMap = {};
1103
+ for (let item of dicts) {
1104
+ dictMap[item.sn] = item.value;
1105
+ }
1106
+ /* dicts.forEach((item) => {
1107
+ dictMap[item.sn] = item.value;
1108
+ }); */
1109
+ option.success &&
1110
+ option.success({
1111
+ dicts,
1112
+ dictMap,
1113
+ });
1114
+ },
1115
+ });
1116
+ };
1117
+
1118
+ imFun.Form.methods.$baseValidate = function (callback, opt) {
1119
+ let that = this;
1120
+ that.validate((valid, obj, c, d) => {
1121
+ if (!valid && (!opt || opt.errorTip !== false)) {
1122
+ this.$message({
1123
+ message: this.$t2("必填项不能为空", "system.message.required"),
1124
+ type: "error",
1125
+ duration: 2000,
1126
+ });
1127
+ }
1128
+ scrollToFirstError(that);
1129
+ callback(valid, obj);
1130
+ });
1131
+ };
1132
+
1133
+ function scrollToFirstError(formTarget) {
1134
+ // 获取第一个验证失败的字段
1135
+ // let formTarget = this.$refs['renderForm'];
1136
+ const firstErrorField = Object.keys(formTarget.fields).find((key) => {
1137
+ return formTarget.fields[key].validateState === "error";
1138
+ });
1139
+
1140
+ if (firstErrorField) {
1141
+ const field = formTarget.fields[firstErrorField];
1142
+
1143
+ let dom = field.$el;
1144
+ if (dom) {
1145
+ // 滚动到该字段位置
1146
+ dom.scrollIntoView({
1147
+ behavior: "smooth",
1148
+ block: "center",
1149
+ });
1150
+
1151
+ // 添加高亮效果
1152
+ dom.classList.add("highlight");
1153
+
1154
+ // 3秒后移除高亮效果
1155
+ setTimeout(() => {
1156
+ dom.classList.remove("highlight");
1157
+ }, 3000);
1158
+ }
1159
+ }
1160
+ }
1161
+
1162
+ Vue.prototype.$getBillInfo = async function (option) {
1163
+ let defaultOption = {
1164
+ url: null,
1165
+ method: `post`,
1166
+ data: {},
1167
+ isLoading: true,
1168
+ modalStrictly: true,
1169
+ success: null,
1170
+ };
1171
+ let opt = Object.assign({}, defaultOption, option);
1172
+ delete opt.wfConfig;
1173
+ return this.$http({
1174
+ ...opt,
1175
+ success: (res, response) => {
1176
+ option.success && option.success(res, response);
1177
+ },
1178
+ });
1179
+ };
1180
+
1181
+ Vue.prototype.$downloadByFileWhole = function (fileWhole, fileName) {
1182
+ let that = this;
1183
+ if (!fileWhole) {
1184
+ this.$baseAlert("凭证信息不存在");
1185
+ return;
1186
+ }
1187
+ let getDownloadDomian = function (callback) {
1188
+ that.$http({
1189
+ method: "post",
1190
+ url: USER_PREFIX + "/common/fileDownloadUrl",
1191
+ data: {},
1192
+ isLoading: true,
1193
+ success: (res) => {
1194
+ callback(res.objx);
1195
+ },
1196
+ });
1197
+ };
1198
+ getDownloadDomian((domain) => {
1199
+ if (fileName) {
1200
+ fileWhole.fileName = fileName;
1201
+ }
1202
+ that.$http({
1203
+ method: "post",
1204
+ url: domain + "/docfile/download",
1205
+ data: fileWhole,
1206
+ isLoading: true,
1207
+ success: (res) => {
1208
+ // window.open(res.objx.url);
1209
+ let url = res.objx.url;
1210
+ openInNewTab(url);
1211
+ },
1212
+ });
1213
+ });
1214
+ };
1215
+
1216
+ let isDef = function (value) {
1217
+ return value !== undefined && value !== null;
1218
+ };
1219
+
1220
+ Vue.prototype.$t2 = function (defaultValue, path, values) {
1221
+ let that = window.$vueRoot;
1222
+ if (!that.hasOwnProperty("_i18n")) {
1223
+ return defaultValue;
1224
+ }
1225
+ const i18n = that.$i18n;
1226
+ path = path || defaultValue;
1227
+ return i18n.te(path) ? i18n.t(path, values) : defaultValue;
1228
+ };
1229
+
1230
+ Vue.prototype.$t1 = function (path, values) {
1231
+ let that = window.$vueRoot;
1232
+ if (!that.hasOwnProperty("_i18n")) {
1233
+ return path;
1234
+ }
1235
+ let lang = that.$i18n.locale;
1236
+ const i18n = that.$i18n;
1237
+ if (lang === "zh") {
1238
+ let val = i18n._t(path, lang, { zh: { [path]: path } }, null, values);
1239
+ return val;
1240
+ } else {
1241
+ if (!i18n.te(path)) {
1242
+ return i18n._t(path, lang, { zh: { [path]: path } }, null, values);
1243
+ } else {
1244
+ return (
1245
+ i18n.t(path, values) ||
1246
+ i18n._t(path, lang, { zh: { [path]: path } }, null, values)
1247
+ );
1248
+ }
1249
+ }
1250
+ };
1251
+
1252
+ Vue.prototype.$i18nVal = function (zhValue, enValue) {
1253
+ let that = window.$vueRoot;
1254
+ if (!that.hasOwnProperty("_i18n")) {
1255
+ return zhValue;
1256
+ }
1257
+ let $i18n = that.$i18n;
1258
+ let value = zhValue;
1259
+ if ($i18n.locale === "zh") {
1260
+ value = zhValue;
1261
+ } else if ($i18n.locale === "en") {
1262
+ value = enValue;
1263
+ }
1264
+ return value;
1265
+ };
1266
+
1267
+ Vue.prototype.$utcToLocal = function (utcTime) {
1268
+ if (!utcTime) return utcTime;
1269
+ let offsetHours = this.$store.getters.utcTransformOffset; // 时区偏移量,单位:小时
1270
+ if (!offsetHours || offsetHours === 0) return utcTime;
1271
+ let localTime = moment(utcTime).add(offsetHours, "hours");
1272
+ return localTime.format("YYYY-MM-DD HH:mm:ss");
1273
+ };
1274
+
1275
+ Vue.prototype.$window = window;
1276
+ };
1277
+
1278
+ window && Object.assign(window, imFun.prefixConfig);
1279
+ if (typeof window !== "undefined" && window.Vue) {
1280
+ install(window.Vue);
1281
+ }
1282
+
1283
+ export default install;