eoss-ui 0.8.23 → 0.8.25

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 (299) hide show
  1. package/lib/button-group.js +228 -231
  2. package/lib/button.js +166 -153
  3. package/lib/calendar.js +2 -2
  4. package/lib/calogin.js +393 -379
  5. package/lib/card.js +2 -2
  6. package/lib/cascader.js +2 -2
  7. package/lib/checkbox-group.js +162 -148
  8. package/lib/clients.js +2 -2
  9. package/lib/config/api.js +5 -0
  10. package/lib/data-table-form.js +162 -148
  11. package/lib/data-table.js +165 -151
  12. package/lib/date-picker.js +159 -146
  13. package/lib/dialog.js +166 -153
  14. package/lib/enable-drag.js +2 -2
  15. package/lib/enterprise.js +2 -2
  16. package/lib/eoss-ui.common.js +1362 -891
  17. package/lib/error-page.js +2 -2
  18. package/lib/flow-group.js +159 -146
  19. package/lib/flow-list.js +174 -161
  20. package/lib/flow.js +501 -487
  21. package/lib/form.js +161 -148
  22. package/lib/handle-user.js +160 -147
  23. package/lib/handler.js +160 -147
  24. package/lib/icon.js +160 -147
  25. package/lib/icons.js +2 -2
  26. package/lib/index.js +1 -1
  27. package/lib/input-number.js +159 -146
  28. package/lib/input.js +159 -146
  29. package/lib/label.js +2 -2
  30. package/lib/layout.js +2 -2
  31. package/lib/login.js +174 -160
  32. package/lib/main.js +523 -509
  33. package/lib/menu.js +2 -2
  34. package/lib/nav.js +159 -146
  35. package/lib/notify.js +157 -148
  36. package/lib/page.js +159 -146
  37. package/lib/pagination.js +159 -146
  38. package/lib/player.js +164 -151
  39. package/lib/qr-code.js +174 -161
  40. package/lib/radio-group.js +161 -148
  41. package/lib/retrial-auth.js +163 -150
  42. package/lib/select-ganged.js +161 -148
  43. package/lib/select.js +161 -148
  44. package/lib/selector-panel.js +178 -164
  45. package/lib/selector.js +161 -148
  46. package/lib/sizer.js +168 -155
  47. package/lib/steps.js +159 -146
  48. package/lib/switch.js +159 -146
  49. package/lib/table-form.js +159 -146
  50. package/lib/tabs-panel.js +2 -2
  51. package/lib/tabs.js +159 -146
  52. package/lib/theme-chalk/index.css +1 -1
  53. package/lib/theme-chalk/login.css +1 -1
  54. package/lib/theme-chalk/tree.css +1 -1
  55. package/lib/tips.js +160 -147
  56. package/lib/toolbar.js +2 -2
  57. package/lib/tree-group.js +159 -146
  58. package/lib/tree.js +160 -147
  59. package/lib/upload.js +698 -223
  60. package/lib/utils/util.js +5 -1
  61. package/lib/wujie.js +159 -146
  62. package/lib/wxlogin.js +159 -146
  63. package/package.json +2 -1
  64. package/packages/button/index.js +5 -5
  65. package/packages/button/src/main.vue +418 -418
  66. package/packages/button-group/index.js +5 -5
  67. package/packages/calendar/index.js +5 -5
  68. package/packages/calogin/index.js +5 -5
  69. package/packages/calogin/src/plugin.js +915 -915
  70. package/packages/card/index.js +5 -5
  71. package/packages/card/src/main.vue +156 -156
  72. package/packages/cascader/index.js +5 -5
  73. package/packages/cascader/src/main.vue +168 -168
  74. package/packages/checkbox-group/index.js +5 -5
  75. package/packages/checkbox-group/src/main.vue +333 -333
  76. package/packages/clients/index.js +5 -5
  77. package/packages/data-table/index.js +5 -5
  78. package/packages/data-table/src/children.vue +46 -46
  79. package/packages/data-table/src/main.vue +1876 -1876
  80. package/packages/data-table/src/sizer.vue +195 -195
  81. package/packages/data-table-form/index.js +5 -5
  82. package/packages/data-table-form/src/checkbox.vue +101 -101
  83. package/packages/data-table-form/src/colgroup.vue +17 -17
  84. package/packages/data-table-form/src/main.vue +181 -181
  85. package/packages/data-table-form/src/radio.vue +65 -65
  86. package/packages/data-table-form/src/table.vue +233 -233
  87. package/packages/data-table-form/src/tbody.vue +336 -336
  88. package/packages/data-table-form/src/thead.vue +68 -68
  89. package/packages/date-picker/index.js +5 -5
  90. package/packages/date-picker/src/main.vue +236 -236
  91. package/packages/dialog/index.js +5 -5
  92. package/packages/enable-drag/index.js +5 -5
  93. package/packages/enterprise/index.js +5 -5
  94. package/packages/enterprise/src/main.vue +66 -66
  95. package/packages/error-page/index.js +5 -5
  96. package/packages/error-page/src/main.vue +44 -44
  97. package/packages/flow/index.js +5 -5
  98. package/packages/flow/src/component/Circulate.vue +420 -420
  99. package/packages/flow/src/component/CustomPreset.vue +324 -324
  100. package/packages/flow/src/component/FreeCirculation.vue +245 -245
  101. package/packages/flow/src/component/Preset.vue +257 -257
  102. package/packages/flow/src/component/TimeLimit.vue +190 -190
  103. package/packages/flow/src/component/taskUnionExamine.vue +763 -763
  104. package/packages/flow/src/freeStartFlow.vue +2898 -2898
  105. package/packages/flow/src/main.vue +4248 -4248
  106. package/packages/flow/src/processForm.vue +1806 -1806
  107. package/packages/flow/src/processReject.vue +311 -311
  108. package/packages/flow/src/reset.vue +952 -952
  109. package/packages/flow/src/startTaskRead.vue +698 -698
  110. package/packages/flow/src/supervise.vue +162 -162
  111. package/packages/flow-group/index.js +5 -5
  112. package/packages/flow-group/src/main.vue +750 -750
  113. package/packages/flow-list/index.js +5 -5
  114. package/packages/form/index.js +5 -5
  115. package/packages/handle-user/index.js +5 -5
  116. package/packages/handle-user/src/main.vue +137 -137
  117. package/packages/handler/index.js +5 -5
  118. package/packages/handler/src/main.vue +499 -499
  119. package/packages/icon/index.js +5 -5
  120. package/packages/icons/index.js +5 -5
  121. package/packages/icons/src/main.vue +81 -81
  122. package/packages/input/index.js +5 -5
  123. package/packages/input/src/main.vue +356 -356
  124. package/packages/input-number/index.js +5 -5
  125. package/packages/input-number/src/main.vue +106 -106
  126. package/packages/label/index.js +5 -5
  127. package/packages/label/src/main.vue +457 -457
  128. package/packages/layout/index.js +5 -5
  129. package/packages/layout/src/item.vue +152 -152
  130. package/packages/layout/src/main.vue +31 -31
  131. package/packages/login/index.js +5 -5
  132. package/packages/login/src/main.vue +2088 -2088
  133. package/packages/main/index.js +5 -5
  134. package/packages/main/src/default/message.vue +249 -249
  135. package/packages/main/src/default/notice.vue +157 -157
  136. package/packages/main/src/default/userinfo.vue +513 -513
  137. package/packages/main/src/simplicity/index.vue +2403 -2403
  138. package/packages/main/src/simplicity/lists.vue +84 -84
  139. package/packages/main/src/simplicity/router-page.vue +45 -45
  140. package/packages/main/src/simplicity/userinfo.vue +408 -408
  141. package/packages/main/src/simplicityTop/index.vue +2688 -2688
  142. package/packages/main/src/simplicityTop/userinfo.vue +408 -408
  143. package/packages/menu/index.js +5 -5
  144. package/packages/menu/src/main.vue +597 -597
  145. package/packages/nav/index.js +5 -5
  146. package/packages/notify/index.js +5 -5
  147. package/packages/notify/src/main.vue +538 -538
  148. package/packages/page/index.js +5 -5
  149. package/packages/page/src/main.vue +167 -167
  150. package/packages/pagination/index.js +5 -5
  151. package/packages/pagination/src/main.vue +96 -96
  152. package/packages/player/index.js +5 -5
  153. package/packages/player/src/main.vue +194 -194
  154. package/packages/qr-code/index.js +5 -5
  155. package/packages/qr-code/src/main.vue +170 -170
  156. package/packages/radio-group/index.js +6 -6
  157. package/packages/radio-group/src/main.vue +319 -319
  158. package/packages/retrial-auth/index.js +5 -5
  159. package/packages/retrial-auth/src/main.vue +299 -299
  160. package/packages/select/index.js +5 -5
  161. package/packages/select-ganged/index.js +5 -5
  162. package/packages/select-ganged/src/main.vue +724 -724
  163. package/packages/selector/index.js +5 -5
  164. package/packages/selector-panel/index.js +5 -5
  165. package/packages/selector-panel/src/tree.vue +129 -129
  166. package/packages/sizer/index.js +5 -5
  167. package/packages/sizer/src/main.vue +257 -257
  168. package/packages/steps/index.js +5 -5
  169. package/packages/steps/src/main.vue +181 -181
  170. package/packages/switch/index.js +5 -5
  171. package/packages/table-form/index.js +5 -5
  172. package/packages/tabs/index.js +5 -5
  173. package/packages/tabs/src/main.vue +788 -788
  174. package/packages/tabs-panel/index.js +5 -5
  175. package/packages/tabs-panel/src/main.vue +29 -29
  176. package/packages/theme-chalk/gulpfile.js +25 -0
  177. package/packages/theme-chalk/src/base.scss +261 -261
  178. package/packages/theme-chalk/src/button-group.scss +176 -176
  179. package/packages/theme-chalk/src/button.scss +24 -24
  180. package/packages/theme-chalk/src/calendar.scss +113 -113
  181. package/packages/theme-chalk/src/card.scss +99 -99
  182. package/packages/theme-chalk/src/checkbox-group.scss +8 -8
  183. package/packages/theme-chalk/src/clients.scss +87 -87
  184. package/packages/theme-chalk/src/data-table-form.scss +67 -67
  185. package/packages/theme-chalk/src/date-picker.scss +7 -7
  186. package/packages/theme-chalk/src/dialog.scss +77 -77
  187. package/packages/theme-chalk/src/enable-drag.scss +181 -181
  188. package/packages/theme-chalk/src/enterprise.scss +5 -5
  189. package/packages/theme-chalk/src/error-page.scss +18 -18
  190. package/packages/theme-chalk/src/flow-group.scss +110 -110
  191. package/packages/theme-chalk/src/flow.scss +376 -376
  192. package/packages/theme-chalk/src/handle-user.scss +40 -40
  193. package/packages/theme-chalk/src/icons.scss +99 -99
  194. package/packages/theme-chalk/src/input.scss +9 -9
  195. package/packages/theme-chalk/src/label.scss +24 -24
  196. package/packages/theme-chalk/src/layout.scss +46 -46
  197. package/packages/theme-chalk/src/mixins/color.scss +117 -117
  198. package/packages/theme-chalk/src/nav.scss +111 -111
  199. package/packages/theme-chalk/src/page.scss +3 -3
  200. package/packages/theme-chalk/src/pagination.scss +29 -29
  201. package/packages/theme-chalk/src/player.scss +9 -9
  202. package/packages/theme-chalk/src/qr-code.scss +17 -17
  203. package/packages/theme-chalk/src/radio-group.scss +9 -9
  204. package/packages/theme-chalk/src/retrial-auth.scss +38 -38
  205. package/packages/theme-chalk/src/select-ganged.scss +8 -8
  206. package/packages/theme-chalk/src/select.scss +8 -8
  207. package/packages/theme-chalk/src/selector-panel.scss +204 -204
  208. package/packages/theme-chalk/src/sizer.scss +36 -36
  209. package/packages/theme-chalk/src/steps.scss +88 -88
  210. package/packages/theme-chalk/src/switch.scss +3 -3
  211. package/packages/theme-chalk/src/table-form.scss +1 -1
  212. package/packages/theme-chalk/src/tabs.scss +87 -87
  213. package/packages/theme-chalk/src/tips.scss +7 -7
  214. package/packages/theme-chalk/src/toolbar.scss +179 -179
  215. package/packages/theme-chalk/src/tree-group.scss +72 -72
  216. package/packages/theme-chalk/src/tree.scss +7 -5
  217. package/packages/theme-chalk/src/wxlogin.scss +3 -3
  218. package/packages/tips/index.js +5 -5
  219. package/packages/toolbar/index.js +5 -5
  220. package/packages/toolbar/src/main.vue +430 -430
  221. package/packages/tree/index.js +5 -5
  222. package/packages/tree-group/index.js +5 -5
  223. package/packages/upload/index.js +5 -5
  224. package/packages/upload/src/main.vue +1813 -1345
  225. package/packages/upload/src/picture.js +15 -15
  226. package/packages/wujie/index.js +5 -5
  227. package/packages/wxlogin/index.js +5 -5
  228. package/packages/wxlogin/src/main.vue +128 -128
  229. package/src/config/api.js +356 -351
  230. package/src/config/image.js +2 -2
  231. package/src/index.js +1 -1
  232. package/src/utils/bus.js +3 -3
  233. package/src/utils/date-util.js +312 -312
  234. package/src/utils/http.js +50 -50
  235. package/src/utils/store.js +21 -21
  236. package/src/utils/util.js +6 -1
  237. package/src/utils/webSocket.js +107 -107
  238. package/packages/theme-chalk/lib/base.css +0 -1
  239. package/packages/theme-chalk/lib/button-group.css +0 -1
  240. package/packages/theme-chalk/lib/button.css +0 -1
  241. package/packages/theme-chalk/lib/calendar.css +0 -1
  242. package/packages/theme-chalk/lib/calogin.css +0 -0
  243. package/packages/theme-chalk/lib/card.css +0 -1
  244. package/packages/theme-chalk/lib/cascader.css +0 -0
  245. package/packages/theme-chalk/lib/checkbox-group.css +0 -1
  246. package/packages/theme-chalk/lib/clients.css +0 -1
  247. package/packages/theme-chalk/lib/data-table-form.css +0 -1
  248. package/packages/theme-chalk/lib/data-table.css +0 -1
  249. package/packages/theme-chalk/lib/date-picker.css +0 -1
  250. package/packages/theme-chalk/lib/dialog.css +0 -1
  251. package/packages/theme-chalk/lib/enable-drag.css +0 -1
  252. package/packages/theme-chalk/lib/enterprise.css +0 -1
  253. package/packages/theme-chalk/lib/error-page.css +0 -1
  254. package/packages/theme-chalk/lib/flow-chart.css +0 -0
  255. package/packages/theme-chalk/lib/flow-group.css +0 -1
  256. package/packages/theme-chalk/lib/flow-list.css +0 -1
  257. package/packages/theme-chalk/lib/flow.css +0 -1
  258. package/packages/theme-chalk/lib/fonts/iconfont.ttf +0 -0
  259. package/packages/theme-chalk/lib/fonts/iconfont.woff +0 -0
  260. package/packages/theme-chalk/lib/form.css +0 -1
  261. package/packages/theme-chalk/lib/handle-user.css +0 -1
  262. package/packages/theme-chalk/lib/handler.css +0 -1
  263. package/packages/theme-chalk/lib/icon.css +0 -1
  264. package/packages/theme-chalk/lib/icons.css +0 -1
  265. package/packages/theme-chalk/lib/index.css +0 -1
  266. package/packages/theme-chalk/lib/input-number.css +0 -0
  267. package/packages/theme-chalk/lib/input.css +0 -1
  268. package/packages/theme-chalk/lib/label.css +0 -1
  269. package/packages/theme-chalk/lib/layout.css +0 -1
  270. package/packages/theme-chalk/lib/login.css +0 -1
  271. package/packages/theme-chalk/lib/main.css +0 -1
  272. package/packages/theme-chalk/lib/menu.css +0 -1
  273. package/packages/theme-chalk/lib/nav.css +0 -1
  274. package/packages/theme-chalk/lib/notify.css +0 -0
  275. package/packages/theme-chalk/lib/page.css +0 -1
  276. package/packages/theme-chalk/lib/pagination.css +0 -1
  277. package/packages/theme-chalk/lib/player.css +0 -1
  278. package/packages/theme-chalk/lib/qr-code.css +0 -1
  279. package/packages/theme-chalk/lib/radio-group.css +0 -1
  280. package/packages/theme-chalk/lib/retrial-auth.css +0 -1
  281. package/packages/theme-chalk/lib/select-ganged.css +0 -1
  282. package/packages/theme-chalk/lib/select.css +0 -1
  283. package/packages/theme-chalk/lib/selector-panel.css +0 -1
  284. package/packages/theme-chalk/lib/selector.css +0 -1
  285. package/packages/theme-chalk/lib/simplicity-top.css +0 -1
  286. package/packages/theme-chalk/lib/simplicity.css +0 -1
  287. package/packages/theme-chalk/lib/sizer.css +0 -1
  288. package/packages/theme-chalk/lib/steps.css +0 -1
  289. package/packages/theme-chalk/lib/switch.css +0 -1
  290. package/packages/theme-chalk/lib/table-form.css +0 -0
  291. package/packages/theme-chalk/lib/tabs-panel.css +0 -0
  292. package/packages/theme-chalk/lib/tabs.css +0 -1
  293. package/packages/theme-chalk/lib/tips.css +0 -1
  294. package/packages/theme-chalk/lib/toolbar.css +0 -1
  295. package/packages/theme-chalk/lib/tree-group.css +0 -1
  296. package/packages/theme-chalk/lib/tree.css +0 -1
  297. package/packages/theme-chalk/lib/upload.css +0 -1
  298. package/packages/theme-chalk/lib/wujie.css +0 -0
  299. package/packages/theme-chalk/lib/wxlogin.css +0 -1
@@ -1,1345 +1,1813 @@
1
- <template>
2
- <el-upload
3
- v-if="isRender && uploadUrl"
4
- ref="upload"
5
- v-bind="$attrs"
6
- class="es-upload"
7
- :portrait="portrait"
8
- :list-type="listType"
9
- :wait="1000"
10
- :height="boxHeight"
11
- :multiple="portrait ? false : multiple"
12
- :action="uploadUrl"
13
- :show-file-list="showList"
14
- :file-list="lists"
15
- :result-file="resultFile"
16
- :disabled="isDisabled || isReadonly"
17
- :readonly="isReadonly"
18
- :class="[
19
- {
20
- 'es-avatar-uploader': portrait && !$slots.default,
21
- 'es-upload-readonly': isReadonly && !downloads
22
- },
23
- 'es-upload-' + listType
24
- ]"
25
- :previewAdjunct="host + previewAdjunct"
26
- :headers="headers"
27
- :data="datas"
28
- :show-info="showList ? showInfo : undefined"
29
- :auto-upload="autoUpload"
30
- :response="true"
31
- :operate="operate"
32
- :accept="accepts"
33
- :drag-sort="isSort"
34
- :preview="preview"
35
- :exclude="excludes"
36
- :download="isDownload"
37
- :deleted="isRemove"
38
- :fileIcons="_icons"
39
- :picture="_picture"
40
- :before-upload="handleBeforeUpload"
41
- :before-remove="handleBeforeRemove"
42
- :on-preview="handlePreview"
43
- :on-downloads="handleDownloads"
44
- :on-download="handleDownload"
45
- :on-sort="handleSort"
46
- :on-success="handleSuccess"
47
- :on-change="handleChange"
48
- :on-remove="handleRemove"
49
- :on-error="handleError"
50
- >
51
- <template v-if="prepend">
52
- <template v-if="Array.isArray(prepend)">
53
- <el-button
54
- v-for="(item, index) in prepend"
55
- v-bind="{ ...item, size: btnSize }"
56
- :key="index"
57
- @click.stop="handleClick(item)"
58
- >
59
- {{ item.label || item.text }}
60
- </el-button>
61
- </template>
62
- <el-button
63
- v-else
64
- v-bind="{ ...prepend, size: btnSize }"
65
- @click.stop="handleClick(prepend)"
66
- >
67
- {{ prepend.label || prepend.text }}
68
- </el-button>
69
- </template>
70
- <slot>
71
- <expand-dom v-if="render" :render="render"></expand-dom>
72
- <template v-else>
73
- <template v-if="portrait">
74
- <img
75
- v-if="profile"
76
- :src="profile"
77
- class="avatar"
78
- :style="{ width: width, height: height }"
79
- />
80
- <i
81
- v-else
82
- class="avatar-uploader-icon"
83
- :class="{ 'el-icon-plus': !isReadonly, 'is-disabled': isDisabled }"
84
- :style="{ width: width, height: height, lineHeight: height }"
85
- ></i>
86
- </template>
87
- <template v-else>
88
- <template v-if="!isReadonly">
89
- <i
90
- class="el-icon-plus es-uploader-icon"
91
- :class="{ 'is-disabled': isDisabled }"
92
- v-if="selectType === 'icon-plus'"
93
- ></i>
94
- <el-button
95
- v-else
96
- class="es-upload-button"
97
- :class="icon"
98
- :type="selectType"
99
- :size="btnSize"
100
- :disabled="isDisabled"
101
- >{{
102
- text ? text : autoUpload ? '点击上传' : '选择文件'
103
- }}</el-button
104
- >
105
- <el-button
106
- class="es-upload-button"
107
- v-if="!autoUpload"
108
- :type="uploadType"
109
- :size="btnSize"
110
- :disabled="isDisabled"
111
- @click.stop="handleUpload"
112
- >
113
- 上传文件
114
- </el-button>
115
- </template>
116
- <el-button
117
- v-if="showFileList && isDownloads"
118
- slot="handle"
119
- class="es-upload-button es-upload-downloads"
120
- :size="btnSize"
121
- @click.stop="handleDownloads"
122
- >
123
- 批量下载
124
- </el-button>
125
- </template>
126
- </template>
127
- </slot>
128
- <template v-if="append">
129
- <template v-if="Array.isArray(append)">
130
- <el-button
131
- v-for="(item, index) in append"
132
- v-bind="{ ...item, size: btnSize }"
133
- :key="index"
134
- @click.stop="handleClick(item)"
135
- >
136
- {{ item.label || item.text }}
137
- </el-button>
138
- </template>
139
- <el-button
140
- v-else
141
- v-bind="{ ...append, size: btnSize }"
142
- @click.stop="handleClick(append)"
143
- >
144
- {{ append.label || append.text }}
145
- </el-button>
146
- </template>
147
- <template slot="tip">
148
- <slot name="tip">
149
- <div v-if="tips" class="el-upload__tip">{{ tips }}</div>
150
- </slot>
151
- </template>
152
- <el-image-viewer
153
- slot="dialog"
154
- v-if="previewScale && showImg"
155
- :z-index="9999"
156
- :initial-index="0"
157
- :url-list="[imgUrl]"
158
- :on-close="closeViewer"
159
- ></el-image-viewer>
160
- <es-dialog v-else :title="title" :visible.sync="showImg" slot="dialog">
161
- <div
162
- v-loading="imgChange"
163
- element-loading-background="rgba(0, 0, 0, 0.8)"
164
- class="es-upload-dialog"
165
- >
166
- <img v-show="!imgChange" ref="showImg" :src="imgUrl" :style="styles" />
167
- </div>
168
- </es-dialog>
169
- <es-dialog :title="title" :visible.sync="showVideo" slot="dialog">
170
- <es-player
171
- autoplay
172
- type="video/mp4"
173
- :is-pause="!showVideo"
174
- :source="source"
175
- ></es-player>
176
- </es-dialog>
177
- </el-upload>
178
- </template>
179
- <script>
180
- import {
181
- getAdjunctProperties,
182
- uploads,
183
- uploadOnlyOne,
184
- getAdjunctFileInfos,
185
- uploadDownloads,
186
- previewAdjunctOffice,
187
- previewAdjunct,
188
- previewAdjunct2,
189
- uploadSort,
190
- delAdjunct,
191
- downloadByAdjunctId
192
- } from 'eoss-ui/src/config/api.js';
193
- import { debounce } from 'throttle-debounce';
194
- import util from 'eoss-ui/src/utils/util.js';
195
- import picture from './picture.js';
196
- import store from 'eoss-ui/src/utils/store';
197
- import { Base64 } from 'js-base64';
198
- export default {
199
- name: 'EsUpload',
200
- components: {
201
- expandDom: {
202
- functional: true,
203
- props: {
204
- render: [Function, String]
205
- },
206
- render: (h, ctx) => {
207
- if (typeof ctx.props.render == 'string') {
208
- try {
209
- return util.toFunction(ctx.props.render)(h, params);
210
- } catch (error) {
211
- throw error;
212
- }
213
- }
214
- return ctx.props.render(h);
215
- }
216
- }
217
- },
218
- inheritAttrs: false,
219
- inject: {
220
- elForm: {
221
- default: ''
222
- },
223
- elFormItem: {
224
- default: ''
225
- }
226
- },
227
- props: {
228
- prepend: [Array, Object],
229
- append: [Array, Object],
230
- render: Function,
231
- template: String,
232
- value: [String, Array, Object],
233
- name: String,
234
- method: {
235
- type: String,
236
- default: 'get'
237
- },
238
- text: String,
239
- icon: {
240
- type: Boolean,
241
- default: true
242
- },
243
- headers: Object,
244
- listType: {
245
- type: String,
246
- default: 'table' // text,table,picture,picture-card
247
- },
248
- operate: {
249
- type: Boolean,
250
- default: true
251
- },
252
- accept: String,
253
- // 附件code
254
- code: String,
255
- // 业务id
256
- ownId: String,
257
- //附件文档id
258
- documentId: String,
259
- requiredOwnId: {
260
- type: Boolean,
261
- default: true
262
- },
263
- //
264
- downloads: {
265
- type: Boolean,
266
- default: false
267
- },
268
- // 附件扩展编码
269
- extendCode: String,
270
- // 是否添加文件md5值
271
- fileMd5: {
272
- type: Boolean,
273
- default: false
274
- },
275
- // 额外的参数
276
- data: {
277
- type: Object,
278
- default() {
279
- return {};
280
- }
281
- },
282
- param: {
283
- type: Object,
284
- default() {
285
- return {};
286
- }
287
- },
288
- // 单文件大小
289
- size: Number,
290
- totalSize: Number,
291
- // 是否头像模式上传
292
- portrait: {
293
- type: Boolean,
294
- default: false
295
- },
296
- photo: [String, Boolean],
297
- //头像按钮框宽度
298
- width: String,
299
- //头像按钮框高度度
300
- height: String,
301
- // 自定义的文字提示
302
- tips: {
303
- type: String,
304
- default: ''
305
- },
306
- dragSort: {
307
- type: Boolean,
308
- default: false
309
- },
310
- // 上传成功后绑定到file的内容
311
- showInfo: {
312
- type: Array,
313
- default() {
314
- return [
315
- { label: '上传时间', field: 'uploadTime', width: 170 },
316
- { label: '大小', field: 'fileSize', width: 100 },
317
- { label: '上传人', field: 'userName', width: 100 }
318
- ];
319
- }
320
- },
321
- // 上传地址
322
- action: String,
323
- // 自动上传
324
- autoUpload: {
325
- type: Boolean,
326
- default: true
327
- },
328
- // 是否支持多选文件
329
- multiple: {
330
- type: Boolean,
331
- default: true
332
- },
333
- // 显示文件列表
334
- showFileList: {
335
- type: Boolean,
336
- default: true
337
- },
338
- // 上传的文件列表
339
- fileList: [Array, String],
340
- requestFiles: {
341
- type: Boolean,
342
- default: true
343
- },
344
- filesParam: {
345
- type: Object,
346
- default() {
347
- return {};
348
- }
349
- },
350
- state: {
351
- type: Number,
352
- default: 1
353
- },
354
- selectType: {
355
- type: String,
356
- default: 'primary'
357
- },
358
- uploadType: {
359
- type: String,
360
- default: 'success'
361
- },
362
- host: {
363
- type: String,
364
- default() {
365
- return util.getStorage('host') ? util.getStorage('host') : '';
366
- }
367
- },
368
- message: Object,
369
- btnSize: {
370
- type: String,
371
- default: 'medium'
372
- },
373
- // 只读
374
- readonly: {
375
- type: Boolean,
376
- default: false
377
- },
378
- disabled: Boolean,
379
- preview: { type: [Boolean, String], default: true },
380
- exclude: String,
381
- download: { type: [Boolean, String], default: true },
382
- deleted: { type: [Boolean, String], default: true },
383
- remove: { type: [Boolean, String], default: true },
384
- beforeUpload: Function,
385
- onPreview: Function,
386
- // 文件列表排序
387
- onSort: Function,
388
- beforeRemove: Function,
389
- onDownloads: Function,
390
- onDownload: Function,
391
- onSort: Function,
392
- onSuccess: Function,
393
- onChange: Function,
394
- onRemove: Function,
395
- onError: Function,
396
- dangerouslyUseHTMLString: Boolean,
397
- fileCount: Number,
398
- listHeight: String,
399
- display: Boolean,
400
- resultFile: {
401
- type: Boolean,
402
- default: true
403
- },
404
- properties: {
405
- type: String,
406
- default() {
407
- return getAdjunctProperties;
408
- }
409
- },
410
- fileIcons: {
411
- type: Object,
412
- default() {
413
- return {};
414
- }
415
- },
416
- picture: {
417
- type: Object,
418
- default() {
419
- return {};
420
- }
421
- },
422
- previewScale: {
423
- type: Boolean,
424
- default: true
425
- },
426
- useCaseCode: String
427
- },
428
- data() {
429
- return {
430
- uploadUrl: this.action,
431
- lists: [],
432
- image: '',
433
- fileAccept: '',
434
- fileSize: 0,
435
- fileTotalSize: 0,
436
- filesTotalSize: 0,
437
- showImg: false,
438
- imgChange: false,
439
- title: '',
440
- imgUrl: '',
441
- styles: {},
442
- showVideo: false,
443
- videoChange: false,
444
- source: '',
445
- excludeNames: undefined,
446
- boxHeight: this.listHeight,
447
- previewAdjunct: previewAdjunct,
448
- kkfileview: null,
449
- dochubConfig: {}
450
- };
451
- },
452
- computed: {
453
- isRender() {
454
- let useCaseCodes = util.getStorage('useCaseCodes');
455
- if (useCaseCodes && this.useCaseCode) {
456
- return useCaseCodes.indexOf(this.useCaseCode) > -1;
457
- }
458
- return true;
459
- },
460
- _icons() {
461
- return {
462
- ppt: 'es-icon-ppt',
463
- png: 'es-icon-tupian',
464
- gif: 'es-icon-tupian',
465
- jpg: 'es-icon-tupian',
466
- jpeg: 'es-icon-tupian',
467
- xls: 'es-icon-Excel',
468
- xlsx: 'es-icon-Excel',
469
- docx: 'es-icon-word',
470
- doc: 'es-icon-word',
471
- rar: 'es-icon-yasuobao',
472
- zip: 'es-icon-yasuobao',
473
- txt: 'es-icon-txt',
474
- ipa: 'es-icon-ios',
475
- apk: 'es-icon-android',
476
- mp4: 'es-icon-kebofangwenjian',
477
- avi: 'es-icon-kebofangwenjian',
478
- mp3: 'es-icon-shengyinwenjian',
479
- wma: 'es-icon-shengyinwenjian',
480
- pdf: 'es-icon-pdf',
481
- ...this.fileIcons
482
- };
483
- },
484
- _picture() {
485
- return {
486
- ...picture,
487
- ...this.picture
488
- };
489
- },
490
- show() {
491
- if ((this.photo && typeof this.photo === 'string') || this.value) {
492
- return false;
493
- }
494
- return this.showFileList;
495
- },
496
- excludes() {
497
- return this.exclude ? this.exclude : this.excludeNames;
498
- },
499
- accepts() {
500
- return this.accept
501
- ? this.accept
502
- : this.fileAccept
503
- ? this.fileAccept
504
- : this.portrait
505
- ? 'image/*'
506
- : undefined;
507
- },
508
- _size() {
509
- return this.size ? this.size : this.fileSize ? this.fileSize : 0;
510
- },
511
- _totalSize() {
512
- return this.totalSize
513
- ? this.totalSize
514
- : this.fileTotalSize
515
- ? this.fileTotalSize
516
- : 0;
517
- },
518
- getAdjunctFileInfos() {
519
- return typeof this.fileList === 'string'
520
- ? this.fileList
521
- : getAdjunctFileInfos;
522
- },
523
- showList() {
524
- return this.portrait ? false : this.showFileList;
525
- },
526
- isDownloads() {
527
- return this.downloads;
528
- },
529
- isDownload() {
530
- if (this.download) {
531
- return true;
532
- }
533
- return false;
534
- },
535
- isDisabled() {
536
- return this.disabled || (this.elForm || {}).disabled;
537
- },
538
- isReadonly() {
539
- return this.readonly || (this.elForm || {}).readonly;
540
- },
541
- isRemove() {
542
- if (this.remove == false || this.deleted == false) {
543
- return false;
544
- }
545
- return true;
546
- },
547
- isSort() {
548
- // return this.dragSort && !this.isDisabled && this.isReadonly;
549
- return this.dragSort && !this.isDisabled;
550
- },
551
- datas() {
552
- if (this.data) {
553
- return util.extend({}, this.data, this.params);
554
- }
555
- return this.params;
556
- },
557
- params() {
558
- let params = { userId: util.getStorage('userId'), ...this.param };
559
- if (this.code !== undefined) {
560
- params.code = this.code;
561
- params.bucketCode = this.code;
562
- }
563
- if (this.ownId !== undefined) {
564
- params.ownId = this.ownId;
565
- params.businessId = this.ownId;
566
- }
567
- return params;
568
- },
569
- showMessage() {
570
- if (this.message !== undefined) {
571
- return util.extend({}, { success: true, error: true }, this.message);
572
- }
573
- return { success: true, error: true };
574
- },
575
- profile() {
576
- const previewAdjunct =
577
- this.dochubConfig.downloadDocumentUrl || this.previewAdjunct;
578
- if (this.image) {
579
- if (typeof this.image === 'string') {
580
- return this.image;
581
- }
582
- return `${this.host}${previewAdjunct}?documentId=${
583
- this.image.adjunctId
584
- }&adjunctId=${this.image.adjunctId}&_tt=${new Date().getTime()}`;
585
- }
586
- if (this.value) {
587
- if (typeof this.value === 'string') {
588
- if (this.value.indexOf('data:image/') === 0) {
589
- return this.value;
590
- } else if (this.value.indexOf(previewAdjunct) > -1) {
591
- let val =
592
- this.host +
593
- util.jointUrl({
594
- url: this.value,
595
- reg: '/main2'
596
- });
597
- return val;
598
- } else if (this.value.indexOf('/') === -1) {
599
- return `${this.host}${previewAdjunct}?documentId=${
600
- this.value
601
- }&adjunctId=${this.value}&_tt=${new Date().getTime()}`;
602
- }
603
- return this.value;
604
- } else if (Array.isArray(this.value)) {
605
- let adjunctId = this.value[0].response
606
- ? this.value[0].response.adjunctId
607
- : this.value[0].adjunctId;
608
- return `${
609
- this.host
610
- }${previewAdjunct}?documentId=${adjunctId}&adjunctId=${adjunctId}&_tt=${new Date().getTime()}`;
611
- } else {
612
- let adjunctId = this.value.response
613
- ? this.value.response.adjunctId
614
- : this.value.adjunctId;
615
- return `${
616
- this.host
617
- }${previewAdjunct}?documentId=${adjunctId}&adjunctId=${adjunctId}&_tt=${new Date().getTime()}`;
618
- }
619
- }
620
- if (this.photo && typeof this.photo === 'string') {
621
- if (this.photo.indexOf('data:image/') === 0) {
622
- return this.photo;
623
- } else if (this.photo.indexOf(previewAdjunct) > -1) {
624
- let val =
625
- this.host +
626
- util.jointUrl({
627
- url: this.value,
628
- reg: '/main2'
629
- });
630
- return val;
631
- } else if (this.photo.indexOf('/') === -1) {
632
- return `${this.host}${previewAdjunct}?documentId=${
633
- this.photo
634
- }&adjunctId=${this.photo}&_tt=${new Date().getTime()}`;
635
- }
636
- }
637
- return this.photo;
638
- }
639
- },
640
- watch: {
641
- fileList: {
642
- immediate: true,
643
- deep: true,
644
- handler(val) {
645
- if (Array.isArray(val) && val.length > 0) {
646
- this.lists = val;
647
- let filesTotalSize = 0;
648
- val.forEach((item) => {
649
- if (
650
- Object.prototype.hasOwnProperty.call(item, 'fileSize') &&
651
- item.fileSize
652
- ) {
653
- filesTotalSize += parseFloat(item.fileSize, 10);
654
- } else {
655
- filesTotalSize += item.size
656
- ? Math.round((item.size / 1024) * 10) / 10
657
- : 0;
658
- }
659
- });
660
- this.filesTotalSize = filesTotalSize;
661
- this.$emit('input', val);
662
- }
663
- }
664
- },
665
- value: {
666
- immediate: true,
667
- deep: true,
668
- handler(val) {
669
- if (val && typeof val === 'object' && this.showFileList) {
670
- if (Array.isArray(val)) {
671
- this.lists = val;
672
- } else {
673
- this.lists = [val];
674
- }
675
- }
676
- }
677
- },
678
- params: {
679
- deep: true,
680
- handler() {
681
- this.getFiles();
682
- }
683
- },
684
- lists: {
685
- deep: true,
686
- handler(val) {
687
- this.$emit('update:fileCount', val.length);
688
- this.$emit('getFilesAmount', val.length);
689
- }
690
- },
691
- display(val) {
692
- val && this.getHeight();
693
- }
694
- },
695
- beforeCreate() {
696
- this.getFiles = debounce(500, () => {
697
- this.getFileLists();
698
- });
699
- this.getAdjunctPropertie = debounce(500, () => {
700
- this.getAdjunctProperties();
701
- });
702
- },
703
- created() {
704
- const dochubConfig = sessionStorage.getItem('dochubConfig');
705
- if (dochubConfig) {
706
- this.dochubConfig = JSON.parse(dochubConfig);
707
- }
708
- this.getAdjunctPropertie();
709
- },
710
- mounted() {
711
- this.$nextTick(() => {
712
- this.getHeight();
713
- });
714
- },
715
- methods: {
716
- getHeight() {
717
- if (this.height === 'auto') {
718
- let pt =
719
- parseInt(util.getStyle(this.$el.parentNode, 'padding-top'), 10) || 0;
720
- let pb =
721
- parseInt(util.getStyle(this.$el.parentNode, 'padding-bottom'), 10) ||
722
- 0;
723
- let btn = this.$refs.upload
724
- ? this.$refs.upload.$children[0].$el.offsetHeight || 0
725
- : 0;
726
- this.boxHeight =
727
- this.$el.parentNode.offsetHeight - pt - pb - btn + 'px';
728
- }
729
- },
730
- //根据code获取附件参数配置
731
- getAdjunctProperties() {
732
- if (this.code !== undefined) {
733
- let config = store.get(this.code);
734
- if (config) {
735
- this.fileAccept = config.accept;
736
- this.fileSize = config.size;
737
- this.fileTotalSize = config.totalSize;
738
- if (config.dochubConfig) {
739
- this.dochubConfig = config.dochubConfig;
740
- }
741
-
742
- let url =
743
- this.portrait || this.documentId
744
- ? this.dochubConfig.reuploadDocumentUrl || uploadOnlyOne
745
- : this.dochubConfig.uploadDocumentUrl || uploads;
746
- this.uploadUrl = url.indexOf(this.host) > -1 ? url : this.host + url;
747
- this.requestFiles && this.getFiles();
748
- } else {
749
- util
750
- .ajax({
751
- method: this.method,
752
- url: this.properties,
753
- data: { code: this.code, ...this.param },
754
- params: { code: this.code, ...this.param }
755
- })
756
- .then((res) => {
757
- if (res.rCode === 0) {
758
- if (res.results) {
759
- this.excludeNames = res.results.excludeName;
760
- if (res.results.fileTypeExtName) {
761
- let fileTypeExtName =
762
- res.results.fileTypeExtName.split(';');
763
- this.fileAccept = fileTypeExtName
764
- .filter((item) => {
765
- return item;
766
- })
767
- .join(',');
768
- }
769
- if (res.results.dochubConfig) {
770
- this.dochubConfig = res.results.dochubConfig;
771
- sessionStorage.setItem(
772
- 'dochubConfig',
773
- JSON.stringify(res.results.dochubConfig)
774
- );
775
- }
776
- let url = this.portrait
777
- ? this.dochubConfig.reuploadDocumentUrl || uploadOnlyOne
778
- : this.dochubConfig.uploadDocumentUrl || uploads;
779
- this.uploadUrl =
780
- url.indexOf(this.host) > -1 ? url : this.host + url;
781
- if (res.results.kkViewRootPath) {
782
- this.kkfileview = res.results.kkViewRootPath;
783
- }
784
- this.fileSize = res.results.limitFileSize
785
- ? res.results.limitFileSize
786
- : 0;
787
- this.fileTotalSize = res.results.limitTotalSize;
788
- store.set(this.code, {
789
- accept: this.fileAccept,
790
- size: this.fileSize,
791
- totalSize: this.fileTotalSize,
792
- dochubConfig: this.dochubConfig
793
- });
794
- }
795
- this.requestFiles && this.getFiles();
796
- }
797
- })
798
- .catch((err) => {
799
- if (err.message && err.message !== 'canceled') {
800
- this.$message.error(err.message);
801
- }
802
- });
803
- }
804
- }
805
- },
806
- getFileLists() {
807
- if (
808
- !this.show ||
809
- (this.fileList &&
810
- Array.isArray(this.fileList) &&
811
- this.fileList.length) ||
812
- (this.requiredOwnId &&
813
- !Object.prototype.hasOwnProperty.call(this.params, 'ownId'))
814
- ) {
815
- return false;
816
- }
817
- let url =
818
- typeof this.fileList === 'string'
819
- ? this.fileList
820
- : this.dochubConfig.getDocumentList
821
- ? this.dochubConfig.getDocumentList
822
- : getAdjunctFileInfos;
823
- util
824
- .ajax({
825
- method: this.method,
826
- url: url,
827
- data: this.params,
828
- params: this.params,
829
- format: false
830
- })
831
- .then((res) => {
832
- if (res.rCode === 0) {
833
- if (this.portrait === true) {
834
- this.image = JSON.parse(JSON.stringify(res.results))[0];
835
- } else {
836
- this.lists = JSON.parse(JSON.stringify(res.results));
837
- let filesTotalSize = 0;
838
- this.lists.forEach((item) => {
839
- if (
840
- Object.prototype.hasOwnProperty.call(item, 'fileSize') &&
841
- item.fileSize
842
- ) {
843
- filesTotalSize += parseFloat(item.fileSize, 10);
844
- } else {
845
- filesTotalSize += item.size
846
- ? Math.round((item.size / 1024) * 10) / 10
847
- : 0;
848
- }
849
- });
850
- this.filesTotalSize = filesTotalSize;
851
- if (this.lists.length) {
852
- this.$emit('input', this.lists);
853
- }
854
- }
855
- } else {
856
- let msg = res.msg || '系统错误,请联系管理员!';
857
- this.$message.error(msg);
858
- }
859
- })
860
- .catch((err) => {
861
- if (err.message && err.message !== 'canceled') {
862
- this.$message.error(err.message);
863
- }
864
- });
865
- },
866
- handleUpload() {
867
- this.$refs.upload.submit();
868
- },
869
- openKkfileview(file) {
870
- let host = util.win.location.origin;
871
- if (this.host) {
872
- if (util.startWith(this.host, 'http')) {
873
- host = this.host;
874
- } else {
875
- host += this.host;
876
- }
877
- }
878
- let url = encodeURIComponent(
879
- Base64.encode(
880
- host +
881
- (typeof this.download === 'string'
882
- ? this.download
883
- : downloadByAdjunctId) +
884
- `?adjunctId=${
885
- file.adjunctId || file.response.adjunctId
886
- }&fullfilename=${file.originalName}`
887
- )
888
- );
889
- util.win.open(`${this.kkfileview}?url=${url}`);
890
- },
891
- handlePreview(res) {
892
- if (this.preview) {
893
- if (this.onPreview) {
894
- this.onPreview(res);
895
- } else {
896
- let file = res.response ? res.response : res;
897
- let url =
898
- typeof this.preview === 'string'
899
- ? this.preview
900
- : typeof this.preview === 'function'
901
- ? this.preview(file)
902
- : null;
903
- if (res.status === 'success' || res.status == 0) {
904
- let suffix = file.suffix;
905
- suffix = suffix.toLowerCase();
906
- if (this.dochubConfig.previewDocumentUrl) {
907
- if (
908
- suffix.includes('jpeg') ||
909
- suffix.includes('jpg') ||
910
- suffix.includes('gif') ||
911
- suffix.includes('png')
912
- ) {
913
- this.imgUrl =
914
- res.url && util.startWith(url, ['http', '/', true])
915
- ? res.url
916
- : this.host +
917
- (url
918
- ? url
919
- : `${this.dochubConfig.downloadDocumentUrl}?documentId=${file.adjunctId}`);
920
- this.title = file.originalName;
921
- this.showImg = true;
922
- this.$nextTick(() => {
923
- this.loadImage();
924
- });
925
- } else if (suffix.includes('mp4')) {
926
- this.source = {
927
- src:
928
- this.host +
929
- (url
930
- ? url
931
- : `${this.dochubConfig.downloadDocumentUrl}?documentId=${file.adjunctId}`)
932
- };
933
- this.title = file.originalName;
934
- this.showVideo = true;
935
- } else {
936
- util.win.open(
937
- this.host +
938
- (url
939
- ? url
940
- : `${this.dochubConfig.previewDocumentUrl}?documentId=${file.adjunctId}&action=附件预览`)
941
- );
942
- }
943
- } else {
944
- if (
945
- suffix.includes('doc') ||
946
- suffix.includes('docx') ||
947
- suffix.includes('xls') ||
948
- suffix.includes('xlsx') ||
949
- suffix.includes('ppt')
950
- ) {
951
- if (this.kkfileview) {
952
- this.openKkfileview(file);
953
- } else {
954
- util.win.open(
955
- this.host +
956
- (url ? url : previewAdjunctOffice) +
957
- '?cmd=view&bucketName=' +
958
- file.absolutePath +
959
- '&fileId=' +
960
- file.adjunctId +
961
- '&fileName=' +
962
- file.newName
963
- );
964
- }
965
- } else if (suffix.includes('pdf')) {
966
- if (this.kkfileview) {
967
- this.openKkfileview(file);
968
- } else {
969
- util.win.open(
970
- this.host +
971
- (url ? url : previewAdjunct2) +
972
- '/' +
973
- file.originalName +
974
- '?adjunctId=' +
975
- file.adjunctId
976
- );
977
- }
978
- } else if (
979
- suffix.includes('jpeg') ||
980
- suffix.includes('jpg') ||
981
- suffix.includes('gif') ||
982
- suffix.includes('png')
983
- ) {
984
- this.imgUrl =
985
- res.url && util.startWith(url, ['http', '/', true])
986
- ? res.url
987
- : this.host +
988
- (url ? url : this.previewAdjunct) +
989
- '?adjunctId=' +
990
- file.adjunctId;
991
- this.title = file.originalName;
992
- this.showImg = true;
993
- this.$nextTick(() => {
994
- this.loadImage();
995
- });
996
- } else if (suffix.includes('mp4')) {
997
- this.source = {
998
- src:
999
- this.host +
1000
- (url ? url : this.previewAdjunct) +
1001
- '?adjunctId=' +
1002
- file.adjunctId
1003
- };
1004
- this.title = file.originalName;
1005
- this.showVideo = true;
1006
- } else {
1007
- if (this.kkfileview) {
1008
- this.openKkfileview(file);
1009
- } else {
1010
- util.win.open(
1011
- this.host +
1012
- (url ? url : this.previewAdjunct) +
1013
- '?adjunctId=' +
1014
- file.adjunctId
1015
- );
1016
- }
1017
- }
1018
- }
1019
- } else {
1020
- util.win.open(URL.createObjectURL(file.raw));
1021
- }
1022
- }
1023
- }
1024
- },
1025
- closeViewer() {
1026
- this.showImg = false;
1027
- },
1028
- loadImage() {
1029
- this.$refs.showImg &&
1030
- (this.$refs.showImg.onload = () => {
1031
- this.imgChange = false;
1032
- let w = this.$refs.showImg.naturalWidth;
1033
- let h = this.$refs.showImg.naturalHeight;
1034
- let pw = this.$refs.showImg.parentNode.offsetWidth;
1035
- let ph = this.$refs.showImg.parentNode.offsetHeight;
1036
- if (w / h > pw / ph) {
1037
- this.styles = { 'max-width': '100%' };
1038
- } else {
1039
- this.styles = { 'max-height': '100%' };
1040
- }
1041
- if (w < pw) {
1042
- this.styles.width = w + 'px';
1043
- }
1044
- if (h < ph) {
1045
- this.styles.height = h + 'px';
1046
- }
1047
- });
1048
- },
1049
- isLt(file) {
1050
- let flag = false;
1051
- let flieArr = file.name.split('.');
1052
- let suffix = '.' + flieArr[flieArr.length - 1].toLowerCase();
1053
- if (this.accepts) {
1054
- let accepts = this.accepts.toLowerCase().split(',');
1055
- flag = accepts.includes(suffix);
1056
- if (!flag) {
1057
- this.$message.error(`文件类型错误,请上传${this.accepts}类型文件!`);
1058
- return flag;
1059
- }
1060
- }
1061
- let size = this._size;
1062
- let text = '单个附件';
1063
- let se = Math.round((file.size / 1024) * 10) / 10;
1064
- if (this._size === 0 && this._totalSize === 0) {
1065
- flag = true;
1066
- } else if (this._size > 0 && this._totalSize === 0) {
1067
- flag = se < this._size;
1068
- size = this._size;
1069
- text = '单个附件';
1070
- } else if (this._size === 0 && this._totalSize > 0) {
1071
- flag = this.filesTotalSize + se < this._totalSize;
1072
- size = this._totalSize;
1073
- text = '附件总';
1074
- } else {
1075
- flag = se < this._size && this.filesTotalSize + se < this._totalSize;
1076
- if (se < this._size) {
1077
- size = this._size;
1078
- text = '单个附件';
1079
- } else {
1080
- size = this._totalSize;
1081
- text = '附件总';
1082
- }
1083
- }
1084
- if (!flag) {
1085
- this.$message.error(`上传${text}大小不能超过${size}KB!`);
1086
- return flag;
1087
- }
1088
- return flag;
1089
- },
1090
- handleBeforeUpload(file) {
1091
- const flag = this.isLt(file);
1092
- if (this.portrait) {
1093
- if (flag && this.beforeUpload) {
1094
- return this.beforeUpload(file);
1095
- }
1096
- return flag;
1097
- }
1098
- if (this.beforeUpload) {
1099
- if (flag) {
1100
- return this.beforeUpload(file);
1101
- }
1102
- return flag;
1103
- }
1104
- return flag;
1105
- },
1106
- handleBeforeRemove(file, fileList) {
1107
- if (file && (file.status === 'success' || file.status == 0)) {
1108
- return this.$confirm('确定删除文件吗?', '提示', {
1109
- confirmButtonText: '确定',
1110
- cancelButtonText: '取消',
1111
- type: 'warning'
1112
- })
1113
- .then(() => {
1114
- if (this.beforeRemove) {
1115
- return this.beforeRemove(file, fileList);
1116
- } else if (file.status === 'success' || file.status == 0) {
1117
- let userName =
1118
- file.userName ||
1119
- (file.response && file.response.userName) ||
1120
- util.getStorage('userName');
1121
- // eslint-disable-next-line no-undef
1122
- return new Promise((resolve, reject) => {
1123
- let url =
1124
- typeof this.deleted === 'string'
1125
- ? this.deleted
1126
- : this.remove === 'string'
1127
- ? this.remove
1128
- : this.dochubConfig.deleteDocumentUrl || delAdjunct;
1129
- util
1130
- .ajax({
1131
- method: this.method,
1132
- url: url,
1133
- data: {
1134
- userName: userName,
1135
- documentId: file.adjunctId || file.response.adjunctId,
1136
- id: file.adjunctId || file.response.adjunctId
1137
- },
1138
- params: {
1139
- userName: userName,
1140
- documentId: file.adjunctId || file.response.adjunctId,
1141
- id: file.adjunctId || file.response.adjunctId
1142
- }
1143
- })
1144
- .then((res) => {
1145
- if (res.rCode === 0) {
1146
- let se =
1147
- this.filesTotalSize -
1148
- Math.round((file.size / 1024) * 10) / 10;
1149
- this.filesTotalSize = se;
1150
- this.$message.success(res.msg);
1151
- resolve();
1152
- } else {
1153
- let msg = res.msg || '系统错误,请联系管理员!';
1154
- this.$message.error(msg);
1155
- reject();
1156
- }
1157
- })
1158
- .catch((err) => {
1159
- if (err.message && err.message !== 'canceled') {
1160
- this.$message.error(err.message);
1161
- }
1162
- });
1163
- });
1164
- }
1165
- return true;
1166
- })
1167
- .catch(() => {
1168
- return flag;
1169
- });
1170
- }
1171
- },
1172
- handleDownloads() {
1173
- let url =
1174
- typeof this.downloads === 'string'
1175
- ? this.downloads
1176
- : this.dochubConfig.compressDownloadDocumentUrl || uploadDownloads;
1177
- util.win.open(
1178
- this.host +
1179
- url +
1180
- '?ownId=' +
1181
- this.ownId +
1182
- '&code=' +
1183
- this.code +
1184
- (this.extendCode ? '&extendCode=' + this.extendCode : '') +
1185
- '&businessId=' +
1186
- this.ownId +
1187
- '&fileName=文档.zip' +
1188
- '&bucketCode=' +
1189
- this.code
1190
- );
1191
- },
1192
- handleDownload(file) {
1193
- if (file.status === 'success' || file.status == 0) {
1194
- let url =
1195
- typeof this.download === 'string'
1196
- ? this.download
1197
- : this.dochubConfig.downloadDocumentUrl || downloadByAdjunctId;
1198
- util.win.open(
1199
- this.host +
1200
- url +
1201
- '?adjunctId=' +
1202
- (file.adjunctId || file.response.adjunctId) +
1203
- '&documentId=' +
1204
- (file.adjunctId || file.response.adjunctId)
1205
- );
1206
- } else {
1207
- this.aLinkDownload(file);
1208
- }
1209
- },
1210
- handleClick(res) {
1211
- if (res.event && typeof res.event === 'function') {
1212
- res.event(res);
1213
- } else {
1214
- this.$emit('click', res);
1215
- }
1216
- },
1217
- aLinkDownload(file) {
1218
- var a = document.createElement('a');
1219
- let event = new MouseEvent('click');
1220
- a.href = URL.createObjectURL(file.raw);
1221
- a.download = file.name;
1222
- a.dispatchEvent(event);
1223
- },
1224
- handleSort(files) {
1225
- if (this.isSort) {
1226
- if (this.onSort) {
1227
- this.onSort(files);
1228
- } else {
1229
- if (!this.ownId || !this.code || (this.fileList && this.fileList.length > 0)) return;
1230
- let ids = files.map((item) => {
1231
- if (item.status === 'success' || item.status == 0) {
1232
- return item.adjunctId || item.response.adjunctId;
1233
- }
1234
- });
1235
- ids = ids.join(',');
1236
- util
1237
- .ajax({
1238
- method: this.method,
1239
- url: this.dochubConfig.sortDocumentsUrl || uploadSort,
1240
- data: {
1241
- ids: ids,
1242
- documentIds: ids,
1243
- ownId: this.ownId,
1244
- code: this.code,
1245
- bucketCode: this.code,
1246
- businessId: this.ownId
1247
- },
1248
- params: {
1249
- ids: ids,
1250
- documentIds: ids,
1251
- ownId: this.ownId,
1252
- code: this.code,
1253
- bucketCode: this.code,
1254
- businessId: this.ownId
1255
- }
1256
- })
1257
- .then((res) => {
1258
- if (res.rCode === 0) {
1259
- this.$message.success(res.msg);
1260
- } else {
1261
- let msg = res.msg || '系统错误,请联系管理员!';
1262
- this.$message.error(msg);
1263
- }
1264
- })
1265
- .catch((err) => {
1266
- if (err.message && err.message !== 'canceled') {
1267
- this.$message.error(err.message);
1268
- }
1269
- });
1270
- }
1271
- }
1272
- },
1273
- handleSuccess(response, file, fileList) {
1274
- if (this.portrait) {
1275
- this.image = URL.createObjectURL(file.raw);
1276
- }
1277
- if (this.showMessage.success) {
1278
- if (response.rCode) {
1279
- if (this.dangerouslyUseHTMLString) {
1280
- this.$alert(
1281
- response.msg ? response.msg : '上传失败:请联系管理员',
1282
- '提示',
1283
- {
1284
- dangerouslyUseHTMLString: true,
1285
- setHeight: response.msg
1286
- }
1287
- ).catch();
1288
- } else {
1289
- this.$message({
1290
- type: 'error',
1291
- message: response.msg || '成功!'
1292
- });
1293
- }
1294
- } else {
1295
- this.$message.success(response.msg);
1296
- }
1297
- }
1298
- let se =
1299
- this.filesTotalSize +
1300
- (this.resultFile ? Math.round((file.size / 1024) * 10) / 10 : 0);
1301
- this.filesTotalSize = se;
1302
- this.onSuccess &&
1303
- this.onSuccess(response, file, fileList, this.dochubConfig);
1304
- this.$emit('success', response, file, fileList, this.dochubConfig);
1305
- if (this.resultFile) {
1306
- if (this.portrait) {
1307
- this.$emit('input', file);
1308
- } else {
1309
- this.$emit('input', fileList);
1310
- }
1311
- if (this.elForm) {
1312
- this.elForm.clearValidate(this.name);
1313
- }
1314
- }
1315
- },
1316
- handleChange(file, fileList) {
1317
- this.$emit('change', fileList);
1318
- this.onChange && this.onChange(file, fileList);
1319
- },
1320
- handleRemove(file, fileList) {
1321
- this.$emit('input', fileList.length ? fileList : '');
1322
- this.$emit('remove', file, fileList);
1323
- this.$emit('change', fileList);
1324
- this.onRemove && this.onRemove(file, fileList);
1325
- },
1326
- handleError(err, file, fileList) {
1327
- if (this.showMessage.error) {
1328
- if (this.dangerouslyUseHTMLString) {
1329
- this.$alert(err.msg ? err.msg : '上传失败:请联系管理员', '提示', {
1330
- dangerouslyUseHTMLString: true,
1331
- setHeight: err.msg
1332
- }).catch();
1333
- } else {
1334
- this.$message({
1335
- type: 'error',
1336
- message: '上传失败:' + (err.msg ? err.msg : '请联系管理员')
1337
- });
1338
- }
1339
- }
1340
- this.$emit('error', err, file, fileList);
1341
- this.onError && this.onError(err, file, fileList);
1342
- }
1343
- }
1344
- };
1345
- </script>
1
+ <template>
2
+ <el-upload
3
+ v-if="isRender && uploadUrl"
4
+ ref="upload"
5
+ v-bind="$attrs"
6
+ class="es-upload"
7
+ :portrait="portrait"
8
+ :list-type="listType"
9
+ :wait="1000"
10
+ :height="boxHeight"
11
+ :multiple="portrait ? false : multiple"
12
+ :action="uploadUrl"
13
+ :http-request="chunkHttpRequest"
14
+ :handles="chunkHandles"
15
+ :show-file-list="showList"
16
+ :file-list="lists"
17
+ :result-file="resultFile"
18
+ :disabled="isDisabled || isReadonly"
19
+ :readonly="isReadonly"
20
+ :class="[
21
+ {
22
+ 'es-avatar-uploader': portrait && !$slots.default,
23
+ 'es-upload-readonly': isReadonly && !downloads
24
+ },
25
+ 'es-upload-' + listType
26
+ ]"
27
+ :previewAdjunct="host + previewAdjunct"
28
+ :headers="headers"
29
+ :data="datas"
30
+ :show-info="showList ? showInfo : undefined"
31
+ :auto-upload="autoUpload"
32
+ :response="true"
33
+ :operate="operate"
34
+ :accept="accepts"
35
+ :drag-sort="isSort"
36
+ :preview="preview"
37
+ :exclude="excludes"
38
+ :download="isDownload"
39
+ :deleted="isRemove"
40
+ :fileIcons="_icons"
41
+ :picture="_picture"
42
+ :before-upload="handleBeforeUpload"
43
+ :before-remove="handleBeforeRemove"
44
+ :on-preview="handlePreview"
45
+ :on-downloads="handleDownloads"
46
+ :on-download="handleDownload"
47
+ :on-sort="handleSort"
48
+ :on-success="handleSuccess"
49
+ :on-change="handleChange"
50
+ :on-remove="handleRemove"
51
+ :on-error="handleError"
52
+ >
53
+ <template v-if="prepend">
54
+ <template v-if="Array.isArray(prepend)">
55
+ <el-button
56
+ v-for="(item, index) in prepend"
57
+ v-bind="{ ...item, size: btnSize }"
58
+ :key="index"
59
+ @click.stop="handleClick(item)"
60
+ >
61
+ {{ item.label || item.text }}
62
+ </el-button>
63
+ </template>
64
+ <el-button
65
+ v-else
66
+ v-bind="{ ...prepend, size: btnSize }"
67
+ @click.stop="handleClick(prepend)"
68
+ >
69
+ {{ prepend.label || prepend.text }}
70
+ </el-button>
71
+ </template>
72
+ <slot>
73
+ <expand-dom v-if="render" :render="render"></expand-dom>
74
+ <template v-else>
75
+ <template v-if="portrait">
76
+ <img
77
+ v-if="profile"
78
+ :src="profile"
79
+ class="avatar"
80
+ :style="{ width: width, height: height }"
81
+ />
82
+ <i
83
+ v-else
84
+ class="avatar-uploader-icon"
85
+ :class="{ 'el-icon-plus': !isReadonly, 'is-disabled': isDisabled }"
86
+ :style="{ width: width, height: height, lineHeight: height }"
87
+ ></i>
88
+ </template>
89
+ <template v-else>
90
+ <template v-if="!isReadonly">
91
+ <i
92
+ class="el-icon-plus es-uploader-icon"
93
+ :class="{ 'is-disabled': isDisabled }"
94
+ v-if="selectType === 'icon-plus'"
95
+ ></i>
96
+ <el-button
97
+ v-else
98
+ class="es-upload-button"
99
+ :class="icon"
100
+ :type="selectType"
101
+ :size="btnSize"
102
+ :disabled="isDisabled"
103
+ >{{ text ? text : autoUpload ? '点击上传' : '选择文件' }}
104
+ </el-button>
105
+ <el-button
106
+ class="es-upload-button"
107
+ v-if="!autoUpload"
108
+ :type="uploadType"
109
+ :size="btnSize"
110
+ :disabled="isDisabled"
111
+ @click.stop="handleUpload"
112
+ >
113
+ 上传文件
114
+ </el-button>
115
+ </template>
116
+ <el-button
117
+ v-if="showFileList && isDownloads"
118
+ slot="handle"
119
+ class="es-upload-button es-upload-downloads"
120
+ :size="btnSize"
121
+ @click.stop="handleDownloads"
122
+ >
123
+ 批量下载
124
+ </el-button>
125
+ </template>
126
+ </template>
127
+ </slot>
128
+ <template v-if="append">
129
+ <template v-if="Array.isArray(append)">
130
+ <el-button
131
+ v-for="(item, index) in append"
132
+ v-bind="{ ...item, size: btnSize }"
133
+ :key="index"
134
+ @click.stop="handleClick(item)"
135
+ >
136
+ {{ item.label || item.text }}
137
+ </el-button>
138
+ </template>
139
+ <el-button
140
+ v-else
141
+ v-bind="{ ...append, size: btnSize }"
142
+ @click.stop="handleClick(append)"
143
+ >
144
+ {{ append.label || append.text }}
145
+ </el-button>
146
+ </template>
147
+ <template slot="tip">
148
+ <slot name="tip">
149
+ <div v-if="tips" class="el-upload__tip">{{ tips }}</div>
150
+ </slot>
151
+ </template>
152
+ <el-image-viewer
153
+ slot="dialog"
154
+ v-if="previewScale && showImg"
155
+ :z-index="9999"
156
+ :initial-index="0"
157
+ :url-list="[imgUrl]"
158
+ :on-close="closeViewer"
159
+ ></el-image-viewer>
160
+ <es-dialog v-else :title="title" :visible.sync="showImg" slot="dialog">
161
+ <div
162
+ v-loading="imgChange"
163
+ element-loading-background="rgba(0, 0, 0, 0.8)"
164
+ class="es-upload-dialog"
165
+ >
166
+ <img v-show="!imgChange" ref="showImg" :src="imgUrl" :style="styles" />
167
+ </div>
168
+ </es-dialog>
169
+ <es-dialog :title="title" :visible.sync="showVideo" slot="dialog">
170
+ <es-player
171
+ autoplay
172
+ type="video/mp4"
173
+ :is-pause="!showVideo"
174
+ :source="source"
175
+ ></es-player>
176
+ </es-dialog>
177
+ </el-upload>
178
+ </template>
179
+ <script>
180
+ import {
181
+ chunkCheckFile,
182
+ chunkMergeChunk,
183
+ chunkUploadChunk,
184
+ delAdjunct,
185
+ downloadByAdjunctId,
186
+ getAdjunctFileInfos,
187
+ getAdjunctProperties,
188
+ getDochubBucket,
189
+ previewAdjunct,
190
+ previewAdjunct2,
191
+ previewAdjunctOffice,
192
+ uploadDownloads,
193
+ uploadOnlyOne,
194
+ uploads,
195
+ uploadSort
196
+ } from 'eoss-ui/src/config/api.js';
197
+ import { debounce } from 'throttle-debounce';
198
+ import util from 'eoss-ui/src/utils/util.js';
199
+ import picture from './picture.js';
200
+ import store from 'eoss-ui/src/utils/store';
201
+ import { Base64 } from 'js-base64';
202
+ import SparkMD5 from 'spark-md5';
203
+
204
+ export default {
205
+ name: 'EsUpload',
206
+ components: {
207
+ expandDom: {
208
+ functional: true,
209
+ props: {
210
+ render: [Function, String]
211
+ },
212
+ render: (h, ctx) => {
213
+ if (typeof ctx.props.render == 'string') {
214
+ try {
215
+ return util.toFunction(ctx.props.render)(h, params);
216
+ } catch (error) {
217
+ throw error;
218
+ }
219
+ }
220
+ return ctx.props.render(h);
221
+ }
222
+ }
223
+ },
224
+ inheritAttrs: false,
225
+ inject: {
226
+ elForm: {
227
+ default: ''
228
+ },
229
+ elFormItem: {
230
+ default: ''
231
+ }
232
+ },
233
+ props: {
234
+ prepend: [Array, Object],
235
+ append: [Array, Object],
236
+ render: Function,
237
+ template: String,
238
+ value: [String, Array, Object],
239
+ name: String,
240
+ method: {
241
+ type: String,
242
+ default: 'get'
243
+ },
244
+ text: String,
245
+ icon: {
246
+ type: Boolean,
247
+ default: true
248
+ },
249
+ headers: Object,
250
+ listType: {
251
+ type: String,
252
+ default: 'table' // text,table,picture,picture-card
253
+ },
254
+ operate: {
255
+ type: Boolean,
256
+ default: true
257
+ },
258
+ accept: String,
259
+ // 附件code
260
+ code: String,
261
+ // 业务id
262
+ ownId: String,
263
+ //附件文档id
264
+ documentId: String,
265
+ requiredOwnId: {
266
+ type: Boolean,
267
+ default: true
268
+ },
269
+ //
270
+ downloads: {
271
+ type: Boolean,
272
+ default: false
273
+ },
274
+ // 附件扩展编码
275
+ extendCode: String,
276
+ // 是否添加文件md5值
277
+ fileMd5: {
278
+ type: Boolean,
279
+ default: false
280
+ },
281
+ // 额外的参数
282
+ data: {
283
+ type: Object,
284
+ default() {
285
+ return {};
286
+ }
287
+ },
288
+ param: {
289
+ type: Object,
290
+ default() {
291
+ return {};
292
+ }
293
+ },
294
+ // 单文件大小
295
+ size: Number,
296
+ totalSize: Number,
297
+ // 是否头像模式上传
298
+ portrait: {
299
+ type: Boolean,
300
+ default: false
301
+ },
302
+ photo: [String, Boolean],
303
+ //头像按钮框宽度
304
+ width: String,
305
+ //头像按钮框高度度
306
+ height: String,
307
+ // 自定义的文字提示
308
+ tips: {
309
+ type: String,
310
+ default: ''
311
+ },
312
+ dragSort: {
313
+ type: Boolean,
314
+ default: false
315
+ },
316
+ // 上传成功后绑定到file的内容
317
+ showInfo: {
318
+ type: Array,
319
+ default() {
320
+ return [
321
+ { label: '上传时间', field: 'uploadTime', width: 170 },
322
+ { label: '大小', field: 'fileSize', width: 100 },
323
+ { label: '上传人', field: 'userName', width: 100 }
324
+ ];
325
+ }
326
+ },
327
+ // 上传地址
328
+ action: String,
329
+ // 自动上传
330
+ autoUpload: {
331
+ type: Boolean,
332
+ default: true
333
+ },
334
+ // 是否支持多选文件
335
+ multiple: {
336
+ type: Boolean,
337
+ default: true
338
+ },
339
+ // 显示文件列表
340
+ showFileList: {
341
+ type: Boolean,
342
+ default: true
343
+ },
344
+ // 上传的文件列表
345
+ fileList: [Array, String],
346
+ requestFiles: {
347
+ type: Boolean,
348
+ default: true
349
+ },
350
+ filesParam: {
351
+ type: Object,
352
+ default() {
353
+ return {};
354
+ }
355
+ },
356
+ state: {
357
+ type: Number,
358
+ default: 1
359
+ },
360
+ selectType: {
361
+ type: String,
362
+ default: 'primary'
363
+ },
364
+ uploadType: {
365
+ type: String,
366
+ default: 'success'
367
+ },
368
+ host: {
369
+ type: String,
370
+ default() {
371
+ return util.getStorage('host') ? util.getStorage('host') : '';
372
+ }
373
+ },
374
+ message: Object,
375
+ btnSize: {
376
+ type: String,
377
+ default: 'medium'
378
+ },
379
+ // 只读
380
+ readonly: {
381
+ type: Boolean,
382
+ default: false
383
+ },
384
+ disabled: Boolean,
385
+ preview: { type: [Boolean, String], default: true },
386
+ exclude: String,
387
+ download: { type: [Boolean, String], default: true },
388
+ deleted: { type: [Boolean, String], default: true },
389
+ remove: { type: [Boolean, String], default: true },
390
+ beforeUpload: Function,
391
+ onPreview: Function,
392
+ // 文件列表排序
393
+ onSort: Function,
394
+ beforeRemove: Function,
395
+ onDownloads: Function,
396
+ onDownload: Function,
397
+ onSort: Function,
398
+ onSuccess: Function,
399
+ onChange: Function,
400
+ onRemove: Function,
401
+ onError: Function,
402
+ dangerouslyUseHTMLString: Boolean,
403
+ fileCount: Number,
404
+ listHeight: String,
405
+ display: Boolean,
406
+ resultFile: {
407
+ type: Boolean,
408
+ default: true
409
+ },
410
+ properties: {
411
+ type: String,
412
+ default() {
413
+ return getAdjunctProperties;
414
+ }
415
+ },
416
+ fileIcons: {
417
+ type: Object,
418
+ default() {
419
+ return {};
420
+ }
421
+ },
422
+ picture: {
423
+ type: Object,
424
+ default() {
425
+ return {};
426
+ }
427
+ },
428
+ previewScale: {
429
+ type: Boolean,
430
+ default: true
431
+ },
432
+ useCaseCode: String
433
+ },
434
+ data() {
435
+ return {
436
+ uploadUrl: this.action,
437
+ lists: [],
438
+ image: '',
439
+ fileAccept: '',
440
+ fileSize: 0,
441
+ fileTotalSize: 0,
442
+ filesTotalSize: 0,
443
+ showImg: false,
444
+ imgChange: false,
445
+ title: '',
446
+ imgUrl: '',
447
+ styles: {},
448
+ showVideo: false,
449
+ videoChange: false,
450
+ source: '',
451
+ excludeNames: undefined,
452
+ boxHeight: this.listHeight,
453
+ previewAdjunct: previewAdjunct,
454
+ kkfileview: null,
455
+ dochubConfig: {},
456
+ // 文档中台桶配置下发的分片上传配置(baseBucketConfig),null 表示未下发 → 回退组件 props
457
+ bucketChunkConfig: null
458
+ };
459
+ },
460
+ computed: {
461
+ isRender() {
462
+ let useCaseCodes = util.getStorage('useCaseCodes');
463
+ if (useCaseCodes && this.useCaseCode) {
464
+ return useCaseCodes.indexOf(this.useCaseCode) > -1;
465
+ }
466
+ return true;
467
+ },
468
+ _icons() {
469
+ return {
470
+ ppt: 'es-icon-ppt',
471
+ png: 'es-icon-tupian',
472
+ gif: 'es-icon-tupian',
473
+ jpg: 'es-icon-tupian',
474
+ jpeg: 'es-icon-tupian',
475
+ xls: 'es-icon-Excel',
476
+ xlsx: 'es-icon-Excel',
477
+ docx: 'es-icon-word',
478
+ doc: 'es-icon-word',
479
+ rar: 'es-icon-yasuobao',
480
+ zip: 'es-icon-yasuobao',
481
+ txt: 'es-icon-txt',
482
+ ipa: 'es-icon-ios',
483
+ apk: 'es-icon-android',
484
+ mp4: 'es-icon-kebofangwenjian',
485
+ avi: 'es-icon-kebofangwenjian',
486
+ mp3: 'es-icon-shengyinwenjian',
487
+ wma: 'es-icon-shengyinwenjian',
488
+ pdf: 'es-icon-pdf',
489
+ ...this.fileIcons
490
+ };
491
+ },
492
+ _picture() {
493
+ return {
494
+ ...picture,
495
+ ...this.picture
496
+ };
497
+ },
498
+ show() {
499
+ if ((this.photo && typeof this.photo === 'string') || this.value) {
500
+ return false;
501
+ }
502
+ return this.showFileList;
503
+ },
504
+ excludes() {
505
+ return this.exclude ? this.exclude : this.excludeNames;
506
+ },
507
+ accepts() {
508
+ return this.accept
509
+ ? this.accept
510
+ : this.fileAccept
511
+ ? this.fileAccept
512
+ : this.portrait
513
+ ? 'image/*'
514
+ : undefined;
515
+ },
516
+ _size() {
517
+ return this.size ? this.size : this.fileSize ? this.fileSize : 0;
518
+ },
519
+ _totalSize() {
520
+ return this.totalSize
521
+ ? this.totalSize
522
+ : this.fileTotalSize
523
+ ? this.fileTotalSize
524
+ : 0;
525
+ },
526
+ getAdjunctFileInfos() {
527
+ return typeof this.fileList === 'string'
528
+ ? this.fileList
529
+ : getAdjunctFileInfos;
530
+ },
531
+ showList() {
532
+ return this.portrait ? false : this.showFileList;
533
+ },
534
+ isDownloads() {
535
+ return this.downloads;
536
+ },
537
+ isDownload() {
538
+ if (this.download) {
539
+ return true;
540
+ }
541
+ return false;
542
+ },
543
+ isDisabled() {
544
+ return this.disabled || (this.elForm || {}).disabled;
545
+ },
546
+ isReadonly() {
547
+ return this.readonly || (this.elForm || {}).readonly;
548
+ },
549
+ isRemove() {
550
+ if (this.remove == false || this.deleted == false) {
551
+ return false;
552
+ }
553
+ return true;
554
+ },
555
+ isSort() {
556
+ // return this.dragSort && !this.isDisabled && this.isReadonly;
557
+ return this.dragSort && !this.isDisabled;
558
+ },
559
+ datas() {
560
+ if (this.data) {
561
+ return util.extend({}, this.data, this.params);
562
+ }
563
+ return this.params;
564
+ },
565
+ params() {
566
+ let params = { userId: util.getStorage('userId'), ...this.param };
567
+ if (this.code !== undefined) {
568
+ params.code = this.code;
569
+ params.bucketCode = this.code;
570
+ }
571
+ if (this.ownId !== undefined) {
572
+ params.ownId = this.ownId;
573
+ params.businessId = this.ownId;
574
+ }
575
+ return params;
576
+ },
577
+ showMessage() {
578
+ if (this.message !== undefined) {
579
+ return util.extend({}, { success: true, error: true }, this.message);
580
+ }
581
+ return { success: true, error: true };
582
+ },
583
+ profile() {
584
+ const previewAdjunct =
585
+ this.dochubConfig.downloadDocumentUrl || this.previewAdjunct;
586
+ if (this.image) {
587
+ if (typeof this.image === 'string') {
588
+ return this.image;
589
+ }
590
+ return `${this.host}${previewAdjunct}?documentId=${
591
+ this.image.adjunctId
592
+ }&adjunctId=${this.image.adjunctId}&_tt=${new Date().getTime()}`;
593
+ }
594
+ if (this.value) {
595
+ if (typeof this.value === 'string') {
596
+ if (this.value.indexOf('data:image/') === 0) {
597
+ return this.value;
598
+ } else if (this.value.indexOf(previewAdjunct) > -1) {
599
+ let val =
600
+ this.host +
601
+ util.jointUrl({
602
+ url: this.value,
603
+ reg: '/main2'
604
+ });
605
+ return val;
606
+ } else if (this.value.indexOf('/') === -1) {
607
+ return `${this.host}${previewAdjunct}?documentId=${
608
+ this.value
609
+ }&adjunctId=${this.value}&_tt=${new Date().getTime()}`;
610
+ }
611
+ return this.value;
612
+ } else if (Array.isArray(this.value)) {
613
+ let adjunctId = this.value[0].response
614
+ ? this.value[0].response.adjunctId
615
+ : this.value[0].adjunctId;
616
+ return `${
617
+ this.host
618
+ }${previewAdjunct}?documentId=${adjunctId}&adjunctId=${adjunctId}&_tt=${new Date().getTime()}`;
619
+ } else {
620
+ let adjunctId = this.value.response
621
+ ? this.value.response.adjunctId
622
+ : this.value.adjunctId;
623
+ return `${
624
+ this.host
625
+ }${previewAdjunct}?documentId=${adjunctId}&adjunctId=${adjunctId}&_tt=${new Date().getTime()}`;
626
+ }
627
+ }
628
+ if (this.photo && typeof this.photo === 'string') {
629
+ if (this.photo.indexOf('data:image/') === 0) {
630
+ return this.photo;
631
+ } else if (this.photo.indexOf(previewAdjunct) > -1) {
632
+ let val =
633
+ this.host +
634
+ util.jointUrl({
635
+ url: this.value,
636
+ reg: '/main2'
637
+ });
638
+ return val;
639
+ } else if (this.photo.indexOf('/') === -1) {
640
+ return `${this.host}${previewAdjunct}?documentId=${
641
+ this.photo
642
+ }&adjunctId=${this.photo}&_tt=${new Date().getTime()}`;
643
+ }
644
+ }
645
+ return this.photo;
646
+ },
647
+ // 是否走分片上传:完全由后台桶配置(/v2/chunk/config)的开关决定,且具备桶编码(code)与业务id(ownId)
648
+ isChunk() {
649
+ const cfg = this.bucketChunkConfig;
650
+ return !!(cfg && cfg.enableChunkUpload) && !!this.code && !!this.ownId;
651
+ },
652
+ // 生效的分片大小(字节):桶配置 > 默认 5MB
653
+ _chunkSize() {
654
+ const cfg = this.bucketChunkConfig;
655
+ return (
656
+ (cfg && Number(cfg.chunkSize) > 0 && Number(cfg.chunkSize)) ||
657
+ 5 * 1024 * 1024
658
+ );
659
+ },
660
+ // 生效的分片并发数:桶配置 > 默认 3
661
+ _chunkConcurrent() {
662
+ const cfg = this.bucketChunkConfig;
663
+ return (
664
+ (cfg &&
665
+ Number(cfg.chunkConcurrent) > 0 &&
666
+ Number(cfg.chunkConcurrent)) ||
667
+ 3
668
+ );
669
+ },
670
+ // 分片三接口地址:优先 dochubConfig 下发,否则回退 api.js 常量(与本组件 dochubConfig.x || 常量 的写法一致)
671
+ chunkUrls() {
672
+ const cfg = this.dochubConfig || {};
673
+ return {
674
+ check: cfg.chunkCheckUrl || chunkCheckFile,
675
+ upload: cfg.chunkUploadUrl || chunkUploadChunk,
676
+ merge: cfg.chunkMergeUrl || chunkMergeChunk
677
+ };
678
+ },
679
+ // 传给 el-upload 的自定义上传实现;非分片模式返回 undefined 以走默认上传
680
+ chunkHttpRequest() {
681
+ return this.isChunk ? this.chunkUpload : undefined;
682
+ },
683
+ // 操作列按钮:非分片模式回退用户经 $attrs 传入的 handles(或 undefined → el-upload 默认),
684
+ // 分片模式注入"暂停/继续"并保留预览/下载/删除(emit 复用既有事件链)。仅分片模式改变渲染,不影响存量业务。
685
+ chunkHandles() {
686
+ if (!this.isChunk) return this.$attrs.handles;
687
+ const done = (f) => f.status === 'success' || f.status == 0;
688
+ return [
689
+ {
690
+ icon: 'el-icon-video-pause',
691
+ title: '暂停',
692
+ rules: (f) => this.isChunkUploading(f) && !f.chunkPaused,
693
+ event: (f) => this.pauseUpload(f)
694
+ },
695
+ {
696
+ icon: 'el-icon-video-play',
697
+ title: '继续',
698
+ rules: (f) => this.isChunkUploading(f) && !!f.chunkPaused,
699
+ event: (f) => this.resumeUpload(f)
700
+ },
701
+ {
702
+ icon: 'el-icon-document-copy',
703
+ title: '预览',
704
+ rules: (f) => !!this.preview && done(f),
705
+ emit: 'preview'
706
+ },
707
+ {
708
+ icon: 'el-icon-download',
709
+ title: '下载',
710
+ rules: (f) => this.isDownload && done(f),
711
+ emit: 'download'
712
+ },
713
+ {
714
+ icon: 'el-icon-delete',
715
+ title: '删除',
716
+ rules: (f) => this.isRemove,
717
+ emit: 'remove'
718
+ }
719
+ ];
720
+ }
721
+ },
722
+ watch: {
723
+ fileList: {
724
+ immediate: true,
725
+ deep: true,
726
+ handler(val) {
727
+ if (Array.isArray(val) && val.length > 0) {
728
+ this.lists = val;
729
+ let filesTotalSize = 0;
730
+ val.forEach((item) => {
731
+ if (
732
+ Object.prototype.hasOwnProperty.call(item, 'fileSize') &&
733
+ item.fileSize
734
+ ) {
735
+ filesTotalSize += parseFloat(item.fileSize, 10);
736
+ } else {
737
+ filesTotalSize += item.size
738
+ ? Math.round((item.size / 1024) * 10) / 10
739
+ : 0;
740
+ }
741
+ });
742
+ this.filesTotalSize = filesTotalSize;
743
+ this.$emit('input', val);
744
+ }
745
+ }
746
+ },
747
+ value: {
748
+ immediate: true,
749
+ deep: true,
750
+ handler(val) {
751
+ if (val && typeof val === 'object' && this.showFileList) {
752
+ if (Array.isArray(val)) {
753
+ this.lists = val;
754
+ } else {
755
+ this.lists = [val];
756
+ }
757
+ }
758
+ }
759
+ },
760
+ params: {
761
+ deep: true,
762
+ handler() {
763
+ this.getFiles();
764
+ }
765
+ },
766
+ lists: {
767
+ deep: true,
768
+ handler(val) {
769
+ this.$emit('update:fileCount', val.length);
770
+ this.$emit('getFilesAmount', val.length);
771
+ }
772
+ },
773
+ display(val) {
774
+ val && this.getHeight();
775
+ }
776
+ },
777
+ beforeCreate() {
778
+ this.getFiles = debounce(500, () => {
779
+ this.getFileLists();
780
+ });
781
+ this.getAdjunctPropertie = debounce(500, () => {
782
+ this.getAdjunctProperties();
783
+ });
784
+ },
785
+ created() {
786
+ // 分片上传的运行态(按 file.uid 索引,非响应式,仅用于流程控制)
787
+ this._chunkState = {};
788
+ const dochubConfig = sessionStorage.getItem('dochubConfig');
789
+ if (dochubConfig) {
790
+ this.dochubConfig = JSON.parse(dochubConfig);
791
+ }
792
+ this.getAdjunctPropertie();
793
+ },
794
+ mounted() {
795
+ this.$nextTick(() => {
796
+ this.getHeight();
797
+ });
798
+ },
799
+ methods: {
800
+ getHeight() {
801
+ if (this.height === 'auto') {
802
+ let pt =
803
+ parseInt(util.getStyle(this.$el.parentNode, 'padding-top'), 10) || 0;
804
+ let pb =
805
+ parseInt(util.getStyle(this.$el.parentNode, 'padding-bottom'), 10) ||
806
+ 0;
807
+ let btn = this.$refs.upload
808
+ ? this.$refs.upload.$children[0].$el.offsetHeight || 0
809
+ : 0;
810
+ this.boxHeight =
811
+ this.$el.parentNode.offsetHeight - pt - pb - btn + 'px';
812
+ }
813
+ },
814
+ //根据code获取附件参数配置
815
+ getAdjunctProperties() {
816
+ if (this.code !== undefined) {
817
+ let config = store.get(this.code);
818
+ if (config) {
819
+ this.fileAccept = config.accept;
820
+ this.fileSize = config.size;
821
+ this.fileTotalSize = config.totalSize;
822
+ if (config.dochubConfig) {
823
+ this.dochubConfig = config.dochubConfig;
824
+ if (config.bucketChunkConfig !== undefined) {
825
+ this.bucketChunkConfig = config.bucketChunkConfig;
826
+ } else {
827
+ this.getBucketChunkConfig();
828
+ }
829
+ }
830
+
831
+ let url =
832
+ this.portrait || this.documentId
833
+ ? this.dochubConfig.reuploadDocumentUrl || uploadOnlyOne
834
+ : this.dochubConfig.uploadDocumentUrl || uploads;
835
+ this.uploadUrl = url.indexOf(this.host) > -1 ? url : this.host + url;
836
+ this.requestFiles && this.getFiles();
837
+ } else {
838
+ util
839
+ .ajax({
840
+ method: this.method,
841
+ url: this.properties,
842
+ data: { code: this.code, ...this.param },
843
+ params: { code: this.code, ...this.param }
844
+ })
845
+ .then((res) => {
846
+ if (res.rCode === 0) {
847
+ if (res.results) {
848
+ this.excludeNames = res.results.excludeName;
849
+ if (res.results.fileTypeExtName) {
850
+ let fileTypeExtName =
851
+ res.results.fileTypeExtName.split(';');
852
+ this.fileAccept = fileTypeExtName
853
+ .filter((item) => {
854
+ return item;
855
+ })
856
+ .join(',');
857
+ }
858
+ if (res.results.dochubConfig) {
859
+ this.dochubConfig = res.results.dochubConfig;
860
+ sessionStorage.setItem(
861
+ 'dochubConfig',
862
+ JSON.stringify(res.results.dochubConfig)
863
+ );
864
+ // dochubConfig 有数据 → 走文档中台,再拉取该桶的桶配置(分片上传开关/参数)
865
+ this.getBucketChunkConfig();
866
+ }
867
+ let url = this.portrait
868
+ ? this.dochubConfig.reuploadDocumentUrl || uploadOnlyOne
869
+ : this.dochubConfig.uploadDocumentUrl || uploads;
870
+ this.uploadUrl =
871
+ url.indexOf(this.host) > -1 ? url : this.host + url;
872
+ if (res.results.kkViewRootPath) {
873
+ this.kkfileview = res.results.kkViewRootPath;
874
+ }
875
+ this.fileSize = res.results.limitFileSize
876
+ ? res.results.limitFileSize
877
+ : 0;
878
+ this.fileTotalSize = res.results.limitTotalSize;
879
+ store.set(this.code, {
880
+ accept: this.fileAccept,
881
+ size: this.fileSize,
882
+ totalSize: this.fileTotalSize,
883
+ dochubConfig: this.dochubConfig
884
+ });
885
+ }
886
+ this.requestFiles && this.getFiles();
887
+ }
888
+ })
889
+ .catch((err) => {
890
+ if (err.message && err.message !== 'canceled') {
891
+ this.$message.error(err.message);
892
+ }
893
+ });
894
+ }
895
+ }
896
+ },
897
+ // 根据桶编码调中台获取桶配置接口(/v2/getBucket),取 baseBucketConfig 中的分片上传开关与参数。
898
+ getBucketChunkConfig() {
899
+ if (!this.code) return;
900
+ let url = getDochubBucket;
901
+ util
902
+ .ajax({
903
+ method: this.method,
904
+ url: url,
905
+ data: { bucketCode: this.code },
906
+ params: { bucketCode: this.code }
907
+ })
908
+ .then((res) => {
909
+ if (res.rCode === 0 && res.results && res.results.baseBucketConfig) {
910
+ const cfg = res.results.baseBucketConfig;
911
+ this.bucketChunkConfig = {
912
+ enableChunkUpload: cfg.enableChunkUpload,
913
+ chunkSize: cfg.chunkSize,
914
+ chunkConcurrent: cfg.chunkConcurrent
915
+ };
916
+ } else {
917
+ this.bucketChunkConfig = null;
918
+ }
919
+ // 回写本地缓存,避免同 code 的其他实例重复请求
920
+ let cached = store.get(this.code);
921
+ if (cached) {
922
+ store.set(this.code, {
923
+ ...cached,
924
+ bucketChunkConfig: this.bucketChunkConfig
925
+ });
926
+ }
927
+ })
928
+ .catch(() => {
929
+ // 桶配置获取失败不阻断上传,维持 props 行为
930
+ this.bucketChunkConfig = null;
931
+ });
932
+ },
933
+ getFileLists() {
934
+ if (
935
+ !this.show ||
936
+ (this.fileList &&
937
+ Array.isArray(this.fileList) &&
938
+ this.fileList.length) ||
939
+ (this.requiredOwnId &&
940
+ !Object.prototype.hasOwnProperty.call(this.params, 'ownId'))
941
+ ) {
942
+ return false;
943
+ }
944
+ let url =
945
+ typeof this.fileList === 'string'
946
+ ? this.fileList
947
+ : this.dochubConfig.getDocumentList
948
+ ? this.dochubConfig.getDocumentList
949
+ : getAdjunctFileInfos;
950
+ util
951
+ .ajax({
952
+ method: this.method,
953
+ url: url,
954
+ data: this.params,
955
+ params: this.params,
956
+ format: false
957
+ })
958
+ .then((res) => {
959
+ if (res.rCode === 0) {
960
+ if (this.portrait === true) {
961
+ this.image = JSON.parse(JSON.stringify(res.results))[0];
962
+ } else {
963
+ this.lists = JSON.parse(JSON.stringify(res.results));
964
+ let filesTotalSize = 0;
965
+ this.lists.forEach((item) => {
966
+ if (
967
+ Object.prototype.hasOwnProperty.call(item, 'fileSize') &&
968
+ item.fileSize
969
+ ) {
970
+ filesTotalSize += parseFloat(item.fileSize, 10);
971
+ } else {
972
+ filesTotalSize += item.size
973
+ ? Math.round((item.size / 1024) * 10) / 10
974
+ : 0;
975
+ }
976
+ });
977
+ this.filesTotalSize = filesTotalSize;
978
+ if (this.lists.length) {
979
+ this.$emit('input', this.lists);
980
+ }
981
+ }
982
+ } else {
983
+ let msg = res.msg || '系统错误,请联系管理员!';
984
+ this.$message.error(msg);
985
+ }
986
+ })
987
+ .catch((err) => {
988
+ if (err.message && err.message !== 'canceled') {
989
+ this.$message.error(err.message);
990
+ }
991
+ });
992
+ },
993
+ handleUpload() {
994
+ this.$refs.upload.submit();
995
+ },
996
+ openKkfileview(file) {
997
+ let host = util.win.location.origin;
998
+ if (this.host) {
999
+ if (util.startWith(this.host, 'http')) {
1000
+ host = this.host;
1001
+ } else {
1002
+ host += this.host;
1003
+ }
1004
+ }
1005
+ let url = encodeURIComponent(
1006
+ Base64.encode(
1007
+ host +
1008
+ (typeof this.download === 'string'
1009
+ ? this.download
1010
+ : downloadByAdjunctId) +
1011
+ `?adjunctId=${
1012
+ file.adjunctId || file.response.adjunctId
1013
+ }&fullfilename=${file.originalName}`
1014
+ )
1015
+ );
1016
+ util.win.open(`${this.kkfileview}?url=${url}`);
1017
+ },
1018
+ handlePreview(res) {
1019
+ if (this.preview) {
1020
+ if (this.onPreview) {
1021
+ this.onPreview(res);
1022
+ } else {
1023
+ let file = res.response ? res.response : res;
1024
+ let url =
1025
+ typeof this.preview === 'string'
1026
+ ? this.preview
1027
+ : typeof this.preview === 'function'
1028
+ ? this.preview(file)
1029
+ : null;
1030
+ if (res.status === 'success' || res.status == 0) {
1031
+ let suffix = file.suffix;
1032
+ suffix = suffix.toLowerCase();
1033
+ if (this.dochubConfig.previewDocumentUrl) {
1034
+ if (
1035
+ suffix.includes('jpeg') ||
1036
+ suffix.includes('jpg') ||
1037
+ suffix.includes('gif') ||
1038
+ suffix.includes('png')
1039
+ ) {
1040
+ this.imgUrl =
1041
+ res.url && util.startWith(url, ['http', '/', true])
1042
+ ? res.url
1043
+ : this.host +
1044
+ (url
1045
+ ? url
1046
+ : `${this.dochubConfig.downloadDocumentUrl}?documentId=${file.adjunctId}`);
1047
+ this.title = file.originalName;
1048
+ this.showImg = true;
1049
+ this.$nextTick(() => {
1050
+ this.loadImage();
1051
+ });
1052
+ } else if (suffix.includes('mp4')) {
1053
+ this.source = {
1054
+ src:
1055
+ this.host +
1056
+ (url
1057
+ ? url
1058
+ : `${this.dochubConfig.downloadDocumentUrl}?documentId=${file.adjunctId}`)
1059
+ };
1060
+ this.title = file.originalName;
1061
+ this.showVideo = true;
1062
+ } else {
1063
+ util.win.open(
1064
+ this.host +
1065
+ (url
1066
+ ? url
1067
+ : `${this.dochubConfig.previewDocumentUrl}?documentId=${file.adjunctId}&action=附件预览`)
1068
+ );
1069
+ }
1070
+ } else {
1071
+ if (
1072
+ suffix.includes('doc') ||
1073
+ suffix.includes('docx') ||
1074
+ suffix.includes('xls') ||
1075
+ suffix.includes('xlsx') ||
1076
+ suffix.includes('ppt')
1077
+ ) {
1078
+ if (this.kkfileview) {
1079
+ this.openKkfileview(file);
1080
+ } else {
1081
+ util.win.open(
1082
+ this.host +
1083
+ (url ? url : previewAdjunctOffice) +
1084
+ '?cmd=view&bucketName=' +
1085
+ file.absolutePath +
1086
+ '&fileId=' +
1087
+ file.adjunctId +
1088
+ '&fileName=' +
1089
+ file.newName
1090
+ );
1091
+ }
1092
+ } else if (suffix.includes('pdf')) {
1093
+ if (this.kkfileview) {
1094
+ this.openKkfileview(file);
1095
+ } else {
1096
+ util.win.open(
1097
+ this.host +
1098
+ (url ? url : previewAdjunct2) +
1099
+ '/' +
1100
+ file.originalName +
1101
+ '?adjunctId=' +
1102
+ file.adjunctId
1103
+ );
1104
+ }
1105
+ } else if (
1106
+ suffix.includes('jpeg') ||
1107
+ suffix.includes('jpg') ||
1108
+ suffix.includes('gif') ||
1109
+ suffix.includes('png')
1110
+ ) {
1111
+ this.imgUrl =
1112
+ res.url && util.startWith(url, ['http', '/', true])
1113
+ ? res.url
1114
+ : this.host +
1115
+ (url ? url : this.previewAdjunct) +
1116
+ '?adjunctId=' +
1117
+ file.adjunctId;
1118
+ this.title = file.originalName;
1119
+ this.showImg = true;
1120
+ this.$nextTick(() => {
1121
+ this.loadImage();
1122
+ });
1123
+ } else if (suffix.includes('mp4')) {
1124
+ this.source = {
1125
+ src:
1126
+ this.host +
1127
+ (url ? url : this.previewAdjunct) +
1128
+ '?adjunctId=' +
1129
+ file.adjunctId
1130
+ };
1131
+ this.title = file.originalName;
1132
+ this.showVideo = true;
1133
+ } else {
1134
+ if (this.kkfileview) {
1135
+ this.openKkfileview(file);
1136
+ } else {
1137
+ util.win.open(
1138
+ this.host +
1139
+ (url ? url : this.previewAdjunct) +
1140
+ '?adjunctId=' +
1141
+ file.adjunctId
1142
+ );
1143
+ }
1144
+ }
1145
+ }
1146
+ } else {
1147
+ util.win.open(URL.createObjectURL(file.raw));
1148
+ }
1149
+ }
1150
+ }
1151
+ },
1152
+ closeViewer() {
1153
+ this.showImg = false;
1154
+ },
1155
+ loadImage() {
1156
+ this.$refs.showImg &&
1157
+ (this.$refs.showImg.onload = () => {
1158
+ this.imgChange = false;
1159
+ let w = this.$refs.showImg.naturalWidth;
1160
+ let h = this.$refs.showImg.naturalHeight;
1161
+ let pw = this.$refs.showImg.parentNode.offsetWidth;
1162
+ let ph = this.$refs.showImg.parentNode.offsetHeight;
1163
+ if (w / h > pw / ph) {
1164
+ this.styles = { 'max-width': '100%' };
1165
+ } else {
1166
+ this.styles = { 'max-height': '100%' };
1167
+ }
1168
+ if (w < pw) {
1169
+ this.styles.width = w + 'px';
1170
+ }
1171
+ if (h < ph) {
1172
+ this.styles.height = h + 'px';
1173
+ }
1174
+ });
1175
+ },
1176
+ isLt(file) {
1177
+ let flag = false;
1178
+ let flieArr = file.name.split('.');
1179
+ let suffix = '.' + flieArr[flieArr.length - 1].toLowerCase();
1180
+ if (this.accepts) {
1181
+ let accepts = this.accepts.toLowerCase().split(',');
1182
+ flag = accepts.includes(suffix);
1183
+ if (!flag) {
1184
+ this.$message.error(`文件类型错误,请上传${this.accepts}类型文件!`);
1185
+ return flag;
1186
+ }
1187
+ }
1188
+ let size = this._size;
1189
+ let text = '单个附件';
1190
+ let se = Math.round((file.size / 1024) * 10) / 10;
1191
+ if (this._size === 0 && this._totalSize === 0) {
1192
+ flag = true;
1193
+ } else if (this._size > 0 && this._totalSize === 0) {
1194
+ flag = se < this._size;
1195
+ size = this._size;
1196
+ text = '单个附件';
1197
+ } else if (this._size === 0 && this._totalSize > 0) {
1198
+ flag = this.filesTotalSize + se < this._totalSize;
1199
+ size = this._totalSize;
1200
+ text = '附件总';
1201
+ } else {
1202
+ flag = se < this._size && this.filesTotalSize + se < this._totalSize;
1203
+ if (se < this._size) {
1204
+ size = this._size;
1205
+ text = '单个附件';
1206
+ } else {
1207
+ size = this._totalSize;
1208
+ text = '附件总';
1209
+ }
1210
+ }
1211
+ if (!flag) {
1212
+ this.$message.error(`上传${text}大小不能超过${size}KB!`);
1213
+ return flag;
1214
+ }
1215
+ return flag;
1216
+ },
1217
+ handleBeforeUpload(file) {
1218
+ const flag = this.isLt(file);
1219
+ if (this.portrait) {
1220
+ if (flag && this.beforeUpload) {
1221
+ return this.beforeUpload(file);
1222
+ }
1223
+ return flag;
1224
+ }
1225
+ if (this.beforeUpload) {
1226
+ if (flag) {
1227
+ return this.beforeUpload(file);
1228
+ }
1229
+ return flag;
1230
+ }
1231
+ return flag;
1232
+ },
1233
+ handleBeforeRemove(file, fileList) {
1234
+ if (file && (file.status === 'success' || file.status == 0)) {
1235
+ return this.$confirm('确定删除文件吗?', '提示', {
1236
+ confirmButtonText: '确定',
1237
+ cancelButtonText: '取消',
1238
+ type: 'warning'
1239
+ })
1240
+ .then(() => {
1241
+ if (this.beforeRemove) {
1242
+ return this.beforeRemove(file, fileList);
1243
+ } else if (file.status === 'success' || file.status == 0) {
1244
+ let userName =
1245
+ file.userName ||
1246
+ (file.response && file.response.userName) ||
1247
+ util.getStorage('userName');
1248
+ // eslint-disable-next-line no-undef
1249
+ return new Promise((resolve, reject) => {
1250
+ let url =
1251
+ typeof this.deleted === 'string'
1252
+ ? this.deleted
1253
+ : this.remove === 'string'
1254
+ ? this.remove
1255
+ : this.dochubConfig.deleteDocumentUrl || delAdjunct;
1256
+ util
1257
+ .ajax({
1258
+ method: this.method,
1259
+ url: url,
1260
+ data: {
1261
+ userName: userName,
1262
+ documentId: file.adjunctId || file.response.adjunctId,
1263
+ id: file.adjunctId || file.response.adjunctId
1264
+ },
1265
+ params: {
1266
+ userName: userName,
1267
+ documentId: file.adjunctId || file.response.adjunctId,
1268
+ id: file.adjunctId || file.response.adjunctId
1269
+ }
1270
+ })
1271
+ .then((res) => {
1272
+ if (res.rCode === 0) {
1273
+ let se =
1274
+ this.filesTotalSize -
1275
+ Math.round((file.size / 1024) * 10) / 10;
1276
+ this.filesTotalSize = se;
1277
+ this.$message.success(res.msg);
1278
+ resolve();
1279
+ } else {
1280
+ let msg = res.msg || '系统错误,请联系管理员!';
1281
+ this.$message.error(msg);
1282
+ reject();
1283
+ }
1284
+ })
1285
+ .catch((err) => {
1286
+ if (err.message && err.message !== 'canceled') {
1287
+ this.$message.error(err.message);
1288
+ }
1289
+ });
1290
+ });
1291
+ }
1292
+ return true;
1293
+ })
1294
+ .catch(() => {
1295
+ return flag;
1296
+ });
1297
+ }
1298
+ },
1299
+ handleDownloads() {
1300
+ let url =
1301
+ typeof this.downloads === 'string'
1302
+ ? this.downloads
1303
+ : this.dochubConfig.compressDownloadDocumentUrl || uploadDownloads;
1304
+ util.win.open(
1305
+ this.host +
1306
+ url +
1307
+ '?ownId=' +
1308
+ this.ownId +
1309
+ '&code=' +
1310
+ this.code +
1311
+ (this.extendCode ? '&extendCode=' + this.extendCode : '') +
1312
+ '&businessId=' +
1313
+ this.ownId +
1314
+ '&fileName=文档.zip' +
1315
+ '&bucketCode=' +
1316
+ this.code
1317
+ );
1318
+ },
1319
+ handleDownload(file) {
1320
+ if (file.status === 'success' || file.status == 0) {
1321
+ let url =
1322
+ typeof this.download === 'string'
1323
+ ? this.download
1324
+ : this.dochubConfig.downloadDocumentUrl || downloadByAdjunctId;
1325
+ util.win.open(
1326
+ this.host +
1327
+ url +
1328
+ '?adjunctId=' +
1329
+ (file.adjunctId || file.response.adjunctId) +
1330
+ '&documentId=' +
1331
+ (file.adjunctId || file.response.adjunctId)
1332
+ );
1333
+ } else {
1334
+ this.aLinkDownload(file);
1335
+ }
1336
+ },
1337
+ handleClick(res) {
1338
+ if (res.event && typeof res.event === 'function') {
1339
+ res.event(res);
1340
+ } else {
1341
+ this.$emit('click', res);
1342
+ }
1343
+ },
1344
+ aLinkDownload(file) {
1345
+ var a = document.createElement('a');
1346
+ let event = new MouseEvent('click');
1347
+ a.href = URL.createObjectURL(file.raw);
1348
+ a.download = file.name;
1349
+ a.dispatchEvent(event);
1350
+ },
1351
+ handleSort(files) {
1352
+ if (this.isSort) {
1353
+ if (this.onSort) {
1354
+ this.onSort(files);
1355
+ } else {
1356
+ if (
1357
+ !this.ownId ||
1358
+ !this.code ||
1359
+ (this.fileList && this.fileList.length > 0)
1360
+ )
1361
+ return;
1362
+ let ids = files.map((item) => {
1363
+ if (item.status === 'success' || item.status == 0) {
1364
+ return item.adjunctId || item.response.adjunctId;
1365
+ }
1366
+ });
1367
+ ids = ids.join(',');
1368
+ util
1369
+ .ajax({
1370
+ method: this.method,
1371
+ url: this.dochubConfig.sortDocumentsUrl || uploadSort,
1372
+ data: {
1373
+ ids: ids,
1374
+ documentIds: ids,
1375
+ ownId: this.ownId,
1376
+ code: this.code,
1377
+ bucketCode: this.code,
1378
+ businessId: this.ownId
1379
+ },
1380
+ params: {
1381
+ ids: ids,
1382
+ documentIds: ids,
1383
+ ownId: this.ownId,
1384
+ code: this.code,
1385
+ bucketCode: this.code,
1386
+ businessId: this.ownId
1387
+ }
1388
+ })
1389
+ .then((res) => {
1390
+ if (res.rCode === 0) {
1391
+ this.$message.success(res.msg);
1392
+ } else {
1393
+ let msg = res.msg || '系统错误,请联系管理员!';
1394
+ this.$message.error(msg);
1395
+ }
1396
+ })
1397
+ .catch((err) => {
1398
+ if (err.message && err.message !== 'canceled') {
1399
+ this.$message.error(err.message);
1400
+ }
1401
+ });
1402
+ }
1403
+ }
1404
+ },
1405
+ handleSuccess(response, file, fileList) {
1406
+ if (this.portrait) {
1407
+ this.image = URL.createObjectURL(file.raw);
1408
+ }
1409
+ if (this.showMessage.success) {
1410
+ if (response.rCode) {
1411
+ if (this.dangerouslyUseHTMLString) {
1412
+ this.$alert(
1413
+ response.msg ? response.msg : '上传失败:请联系管理员',
1414
+ '提示',
1415
+ {
1416
+ dangerouslyUseHTMLString: true,
1417
+ setHeight: response.msg
1418
+ }
1419
+ ).catch();
1420
+ } else {
1421
+ this.$message({
1422
+ type: 'error',
1423
+ message: response.msg || '成功!'
1424
+ });
1425
+ }
1426
+ } else {
1427
+ this.$message.success(response.msg);
1428
+ }
1429
+ }
1430
+ let se =
1431
+ this.filesTotalSize +
1432
+ (this.resultFile ? Math.round((file.size / 1024) * 10) / 10 : 0);
1433
+ this.filesTotalSize = se;
1434
+ this.onSuccess &&
1435
+ this.onSuccess(response, file, fileList, this.dochubConfig);
1436
+ this.$emit('success', response, file, fileList, this.dochubConfig);
1437
+ if (this.resultFile) {
1438
+ if (this.portrait) {
1439
+ this.$emit('input', file);
1440
+ } else {
1441
+ this.$emit('input', fileList);
1442
+ }
1443
+ if (this.elForm) {
1444
+ this.elForm.clearValidate(this.name);
1445
+ }
1446
+ }
1447
+ },
1448
+ handleChange(file, fileList) {
1449
+ this.$emit('change', fileList);
1450
+ this.onChange && this.onChange(file, fileList);
1451
+ },
1452
+ handleRemove(file, fileList) {
1453
+ this.cleanupChunk(file);
1454
+ this.$emit('input', fileList.length ? fileList : '');
1455
+ this.$emit('remove', file, fileList);
1456
+ this.$emit('change', fileList);
1457
+ this.onRemove && this.onRemove(file, fileList);
1458
+ },
1459
+ handleError(err, file, fileList) {
1460
+ if (this.showMessage.error) {
1461
+ if (this.dangerouslyUseHTMLString) {
1462
+ this.$alert(err.msg ? err.msg : '上传失败:请联系管理员', '提示', {
1463
+ dangerouslyUseHTMLString: true,
1464
+ setHeight: err.msg
1465
+ }).catch();
1466
+ } else {
1467
+ this.$message({
1468
+ type: 'error',
1469
+ message: '上传失败:' + (err.msg ? err.msg : '请联系管理员')
1470
+ });
1471
+ }
1472
+ }
1473
+ this.$emit('error', err, file, fileList);
1474
+ this.onError && this.onError(err, file, fileList);
1475
+ },
1476
+ // el-upload 的自定义上传实现:建立可暂停的运行态并返回受控 Promise。
1477
+ // 暂停时不 resolve/reject(promise 维持 pending,文件保持"上传中"而非失败),继续时再次进入流程。
1478
+ chunkUpload(options) {
1479
+ const file = options.file;
1480
+ const uid = file.uid;
1481
+ const state = {
1482
+ paused: false,
1483
+ controller: null,
1484
+ fileMd5: '',
1485
+ totalChunks: Math.max(1, Math.ceil(file.size / this._chunkSize)),
1486
+ options: options
1487
+ };
1488
+ this._chunkState[uid] = state;
1489
+ return new Promise((resolve, reject) => {
1490
+ state.resolve = resolve;
1491
+ state.reject = reject;
1492
+ this.runChunkFlow(uid);
1493
+ });
1494
+ },
1495
+ // 分片主流程(可被"继续"重新进入):MD5(缓存) → 秒传/断点续传检测 → 并发上传缺失分片 → 合并入库。
1496
+ runChunkFlow(uid) {
1497
+ const state = this._chunkState[uid];
1498
+ if (!state) return;
1499
+ const options = state.options;
1500
+ const file = options.file;
1501
+ const onProgress = options.onProgress || function () {};
1502
+ const baseParams = () => ({
1503
+ ...this.param,
1504
+ fileMd5: state.fileMd5,
1505
+ fileName: file.name,
1506
+ fileSize: file.size,
1507
+ totalChunks: state.totalChunks,
1508
+ bucketCode: this.code,
1509
+ businessId: this.ownId
1510
+ });
1511
+ const isAbort = (e) =>
1512
+ !!e &&
1513
+ (e.__aborted === true ||
1514
+ e.name === 'CanceledError' ||
1515
+ e.name === 'AbortError' ||
1516
+ (typeof e.message === 'string' && /cancel|abort/i.test(e.message)));
1517
+
1518
+ Promise.resolve()
1519
+ .then(() => state.fileMd5 || this.computeFileMd5(file, onProgress))
1520
+ .then((md5) => {
1521
+ state.fileMd5 = md5;
1522
+ if (state.paused) return null;
1523
+ return util.ajax({
1524
+ method: 'post',
1525
+ url: this.chunkUrls.check,
1526
+ data: baseParams(),
1527
+ params: baseParams(),
1528
+ headers: options.headers
1529
+ });
1530
+ })
1531
+ .then((checkRes) => {
1532
+ if (!checkRes) return; // 暂停于 MD5/检测阶段,维持 pending
1533
+ if (checkRes.rCode !== 0) return Promise.reject(checkRes);
1534
+ const info = checkRes.results || {};
1535
+ // 秒传命中:该业务桶下已存在同 MD5 文件,直接视为成功
1536
+ if (info.instant) {
1537
+ onProgress({ percent: 100 });
1538
+ this.normalizeChunkDoc(info, file.name);
1539
+ this.finishChunk(uid, {
1540
+ rCode: 0,
1541
+ msg: checkRes.msg || '秒传成功',
1542
+ results: info
1543
+ });
1544
+ // 秒传文件已存在于服务端,刷新列表以展示其完整信息(含可下载/预览的 id)
1545
+ this.requestFiles && this.getFiles();
1546
+ return;
1547
+ }
1548
+ // 断点续传:跳过服务端已存在的分片
1549
+ const uploaded = new Set(info.uploadedChunks || []);
1550
+ const pending = [];
1551
+ for (let i = 0; i < state.totalChunks; i++) {
1552
+ if (!uploaded.has(i)) pending.push(i);
1553
+ }
1554
+ let finished = state.totalChunks - pending.length;
1555
+ // 上传阶段占 5~95%(MD5 校验已占 0~5%),保证进度单调不回退
1556
+ onProgress({
1557
+ percent: Math.min(
1558
+ 95,
1559
+ 5 + Math.round((finished / state.totalChunks) * 90)
1560
+ )
1561
+ });
1562
+ state.controller =
1563
+ typeof AbortController !== 'undefined'
1564
+ ? new AbortController()
1565
+ : null;
1566
+ const signal = state.controller ? state.controller.signal : undefined;
1567
+ return this.runChunkQueue(pending, this._chunkConcurrent, (index) => {
1568
+ if (state.paused) return Promise.reject({ __aborted: true });
1569
+ return this.uploadOneChunk(
1570
+ file,
1571
+ index,
1572
+ state.totalChunks,
1573
+ state.fileMd5,
1574
+ options.headers,
1575
+ signal
1576
+ ).then(() => {
1577
+ finished++;
1578
+ onProgress({
1579
+ percent: Math.min(
1580
+ 95,
1581
+ 5 + Math.round((finished / state.totalChunks) * 90)
1582
+ )
1583
+ });
1584
+ });
1585
+ }).then(() => {
1586
+ if (state.paused) return; // 暂停于上传阶段,维持 pending
1587
+ return util
1588
+ .ajax({
1589
+ method: 'post',
1590
+ url: this.chunkUrls.merge,
1591
+ data: baseParams(),
1592
+ params: baseParams(),
1593
+ headers: options.headers
1594
+ })
1595
+ .then((mergeRes) => {
1596
+ if (mergeRes.rCode !== 0) return Promise.reject(mergeRes);
1597
+ onProgress({ percent: 100 });
1598
+ this.normalizeChunkDoc(mergeRes.results, file.name);
1599
+ this.finishChunk(uid, mergeRes);
1600
+ // 刷新列表:让刚入库的文件以与其他行一致的结构展示(时间/大小/上传人等)
1601
+ this.requestFiles && this.getFiles();
1602
+ });
1603
+ });
1604
+ })
1605
+ .catch((e) => {
1606
+ // 暂停导致的中止:保持 pending 等待"继续";其余才算失败
1607
+ if (state.paused || isAbort(e)) return;
1608
+ this.failChunk(uid, e);
1609
+ });
1610
+ },
1611
+ // 暂停:置暂停标记并中止在传分片;promise 维持 pending,文件保持"上传中"
1612
+ pauseUpload(file) {
1613
+ const state = file && this._chunkState[file.uid];
1614
+ if (!state) return;
1615
+ state.paused = true;
1616
+ if (state.controller) {
1617
+ try {
1618
+ state.controller.abort();
1619
+ } catch (e) {
1620
+ /* ignore */
1621
+ }
1622
+ }
1623
+ this.$set(file, 'chunkPaused', true);
1624
+ this.$emit('chunk-pause', file);
1625
+ },
1626
+ // 继续:清暂停标记,重新进入流程(checkFile 会返回已传分片,自动续传)
1627
+ resumeUpload(file) {
1628
+ const state = file && this._chunkState[file.uid];
1629
+ if (!state || !state.paused) return; // 仅暂停态可续传,防止重复触发并发流程
1630
+ state.paused = false;
1631
+ this.$set(file, 'chunkPaused', false);
1632
+ this.$emit('chunk-resume', file);
1633
+ this.runChunkFlow(file.uid);
1634
+ },
1635
+ // 该文件是否处于分片上传运行态(用于操作列按钮显隐)
1636
+ isChunkUploading(file) {
1637
+ return !!(file && this._chunkState && this._chunkState[file.uid]);
1638
+ },
1639
+ // 归一化合并响应:dochub Document 用 docTagId 标识、且无 suffix 字段,
1640
+ // 而组件下载读 adjunctId、预览读 suffix/originalName,这里统一映射补齐,避免预览取 suffix 报错。
1641
+ normalizeChunkDoc(results, fileName) {
1642
+ if (!results || typeof results !== 'object') return results;
1643
+ const id =
1644
+ results.adjunctId ||
1645
+ results.docTagId ||
1646
+ results.documentId ||
1647
+ results.id;
1648
+ if (id) {
1649
+ if (!results.adjunctId) results.adjunctId = id;
1650
+ if (!results.documentId) results.documentId = id;
1651
+ }
1652
+ // 文件名:优先用上传时的原始名,其次后端 documentFile.docName
1653
+ const name =
1654
+ fileName ||
1655
+ (results.documentFile && results.documentFile.docName) ||
1656
+ results.originalName ||
1657
+ results.name ||
1658
+ '';
1659
+ if (!results.originalName && name) results.originalName = name;
1660
+ // 后缀:预览按后缀判断类型,缺省从文件名推导;始终保证为字符串
1661
+ if (results.suffix === undefined || results.suffix === null) {
1662
+ results.suffix =
1663
+ name && name.lastIndexOf('.') > -1
1664
+ ? name.slice(name.lastIndexOf('.') + 1)
1665
+ : '';
1666
+ }
1667
+ // 展示字段:dochub 的元数据在 documentFile 下且字段名不同,映射成 showInfo 默认读取的扁平字段
1668
+ const df = results.documentFile;
1669
+ if (df && typeof df === 'object') {
1670
+ if (!results.uploadTime) {
1671
+ results.uploadTime = df.createTime || df.lastModifyTime || '';
1672
+ }
1673
+ if (!results.userName) {
1674
+ results.userName = df.createUserName || df.lastModifyUserName || '';
1675
+ }
1676
+ if (!results.fileSize && (df.docSize || df.docSize === 0)) {
1677
+ results.fileSize = this.formatFileSize(df.docSize);
1678
+ }
1679
+ }
1680
+ return results;
1681
+ },
1682
+ // 字节数格式化为可读大小(与列表展示风格一致:1 位小数、无空格)
1683
+ formatFileSize(bytes) {
1684
+ const n = Number(bytes);
1685
+ if (!n || n <= 0) return '0B';
1686
+ if (n >= 1073741824) return (n / 1073741824).toFixed(1) + 'GB';
1687
+ if (n >= 1048576) return (n / 1048576).toFixed(1) + 'MB';
1688
+ if (n >= 1024) return (n / 1024).toFixed(1) + 'KB';
1689
+ return n + 'B';
1690
+ },
1691
+ // 完成:兑现 promise 并清理运行态
1692
+ finishChunk(uid, response) {
1693
+ const state = this._chunkState[uid];
1694
+ if (!state) return;
1695
+ state.resolve && state.resolve(response);
1696
+ delete this._chunkState[uid];
1697
+ },
1698
+ // 失败:拒绝 promise 并清理运行态
1699
+ failChunk(uid, err) {
1700
+ const state = this._chunkState[uid];
1701
+ if (!state) return;
1702
+ state.reject && state.reject(err);
1703
+ delete this._chunkState[uid];
1704
+ },
1705
+ // 移除文件时清理分片运行态(中止在传分片,孤立 pending promise 不再触发回调)
1706
+ cleanupChunk(file) {
1707
+ const uid = file && file.uid;
1708
+ const state = uid && this._chunkState && this._chunkState[uid];
1709
+ if (!state) return;
1710
+ state.paused = true;
1711
+ state.resolve = null;
1712
+ state.reject = null;
1713
+ if (state.controller) {
1714
+ try {
1715
+ state.controller.abort();
1716
+ } catch (e) {
1717
+ /* ignore */
1718
+ }
1719
+ }
1720
+ delete this._chunkState[uid];
1721
+ },
1722
+ // 上传单个分片(multipart/form-data);signal 用于暂停时中止
1723
+ uploadOneChunk(file, index, totalChunks, fileMd5, headers, signal) {
1724
+ const start = index * this._chunkSize;
1725
+ const end = Math.min(start + this._chunkSize, file.size);
1726
+ const formData = new FormData();
1727
+ formData.append('file', file.slice(start, end), file.name);
1728
+ formData.append('fileMd5', fileMd5);
1729
+ formData.append('fileName', file.name);
1730
+ formData.append('fileSize', file.size);
1731
+ formData.append('chunkIndex', index);
1732
+ formData.append('totalChunks', totalChunks);
1733
+ formData.append('bucketCode', this.code);
1734
+ formData.append('businessId', this.ownId);
1735
+ Object.keys(this.param || {}).forEach((key) => {
1736
+ formData.append(key, this.param[key]);
1737
+ });
1738
+ return util
1739
+ .ajax({
1740
+ method: 'post',
1741
+ url: this.chunkUrls.upload,
1742
+ data: formData,
1743
+ format: false,
1744
+ headers: headers,
1745
+ signal: signal
1746
+ })
1747
+ .then((res) => {
1748
+ if (res.rCode !== 0) return Promise.reject(res);
1749
+ return res;
1750
+ });
1751
+ },
1752
+ // 分块读取文件并增量计算 MD5(避免大文件一次性读入内存)
1753
+ computeFileMd5(file, onProgress) {
1754
+ return new Promise((resolve, reject) => {
1755
+ const size = this._chunkSize;
1756
+ const chunks = Math.max(1, Math.ceil(file.size / size));
1757
+ const spark = new SparkMD5.ArrayBuffer();
1758
+ const reader = new FileReader();
1759
+ let current = 0;
1760
+ const loadNext = () => {
1761
+ const start = current * size;
1762
+ reader.readAsArrayBuffer(
1763
+ file.slice(start, Math.min(start + size, file.size))
1764
+ );
1765
+ };
1766
+ reader.onload = (e) => {
1767
+ spark.append(e.target.result);
1768
+ current++;
1769
+ // 校验阶段占进度 0~5%,剩余留给上传与合并
1770
+ onProgress &&
1771
+ onProgress({ percent: Math.round((current / chunks) * 5) });
1772
+ if (current < chunks) {
1773
+ loadNext();
1774
+ } else {
1775
+ // 取标准 32 位 MD5 的中间 16 位,与后端 hutool digestHex16(即 doc_md5)口径一致,
1776
+ // 否则秒传按 md5 比对永远不命中
1777
+ resolve(spark.end().substring(8, 24));
1778
+ }
1779
+ };
1780
+ reader.onerror = () => reject({ msg: '文件读取失败,无法计算MD5' });
1781
+ loadNext();
1782
+ });
1783
+ },
1784
+ // 限制并发的分片任务队列
1785
+ runChunkQueue(indexes, concurrency, worker) {
1786
+ return new Promise((resolve, reject) => {
1787
+ if (!indexes.length) return resolve();
1788
+ let cursor = 0;
1789
+ let active = 0;
1790
+ let failed = false;
1791
+ const schedule = () => {
1792
+ if (failed) return;
1793
+ if (cursor >= indexes.length && active === 0) return resolve();
1794
+ while (active < concurrency && cursor < indexes.length) {
1795
+ const index = indexes[cursor++];
1796
+ active++;
1797
+ worker(index)
1798
+ .then(() => {
1799
+ active--;
1800
+ schedule();
1801
+ })
1802
+ .catch((err) => {
1803
+ failed = true;
1804
+ reject(err);
1805
+ });
1806
+ }
1807
+ };
1808
+ schedule();
1809
+ });
1810
+ }
1811
+ }
1812
+ };
1813
+ </script>