cloud-web-corejs 1.0.281 → 1.1.0-dev.11

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