@jari-ace/element-plus-component 0.3.2 → 0.3.4

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 (159) hide show
  1. package/dist/components/autoComplete/JaAutoComplete.vue.d.ts +956 -1179
  2. package/dist/components/autoComplete/JaAutoComplete.vue.d.ts.map +1 -1
  3. package/dist/components/button/JaButton.vue.d.ts +114 -450
  4. package/dist/components/button/JaButton.vue.d.ts.map +1 -1
  5. package/dist/components/checkbox/JaCheckbox.vue.d.ts +228 -150
  6. package/dist/components/checkbox/JaCheckbox.vue.d.ts.map +1 -1
  7. package/dist/components/checkboxGroup/JaCheckboxGroup.vue.d.ts +215 -137
  8. package/dist/components/checkboxGroup/JaCheckboxGroup.vue.d.ts.map +1 -1
  9. package/dist/components/dropdownButton/JaDropdownButton.vue.d.ts +700 -1596
  10. package/dist/components/dropdownButton/JaDropdownButton.vue.d.ts.map +1 -1
  11. package/dist/components/form/JaForm.vue.d.ts +1 -1
  12. package/dist/components/formItem/JaFormItem.vue.d.ts +83 -293
  13. package/dist/components/formItem/JaFormItem.vue.d.ts.map +1 -1
  14. package/dist/components/input/JaInput.vue.d.ts +244 -609
  15. package/dist/components/input/JaInput.vue.d.ts.map +1 -1
  16. package/dist/components/inputI18n/I18nBundleEditor.vue.d.ts +1 -1
  17. package/dist/components/inputI18n/I18nBundleEditor.vue.d.ts.map +1 -1
  18. package/dist/components/inputI18n/I18nBundleEditor.vue.js +1 -1
  19. package/dist/components/inputI18n/I18nBundleEditor.vue.js.map +1 -1
  20. package/dist/components/inputI18n/InputI18n.vue.d.ts.map +1 -1
  21. package/dist/components/inputI18n/InputI18n.vue.js +14 -5
  22. package/dist/components/inputI18n/InputI18n.vue.js.map +1 -1
  23. package/dist/components/inputNumber/JaInputNumber.vue.d.ts +117 -471
  24. package/dist/components/inputNumber/JaInputNumber.vue.d.ts.map +1 -1
  25. package/dist/components/inputNumber/JaInputNumber.vue.js +4 -1
  26. package/dist/components/inputNumber/JaInputNumber.vue.js.map +1 -1
  27. package/dist/components/properyPicker/PropertyPicker.vue.d.ts.map +1 -1
  28. package/dist/components/properyPicker/PropertyPicker.vue.js +4 -8
  29. package/dist/components/properyPicker/PropertyPicker.vue.js.map +1 -1
  30. package/dist/components/radioGroup/JaRadioGroup.vue.d.ts +96 -287
  31. package/dist/components/radioGroup/JaRadioGroup.vue.d.ts.map +1 -1
  32. package/dist/components/rolePicker/RoleCategorySelector.vue.d.ts +14 -0
  33. package/dist/components/rolePicker/RoleCategorySelector.vue.d.ts.map +1 -0
  34. package/dist/components/rolePicker/RoleCategorySelector.vue.js +410 -0
  35. package/dist/components/rolePicker/RoleCategorySelector.vue.js.map +1 -0
  36. package/dist/components/rolePicker/RoleEditor.vue.d.ts +1 -0
  37. package/dist/components/rolePicker/RoleEditor.vue.d.ts.map +1 -1
  38. package/dist/components/rolePicker/RoleEditor.vue.js +64 -31
  39. package/dist/components/rolePicker/RoleEditor.vue.js.map +1 -1
  40. package/dist/components/rolePicker/baseRolePicker.vue.d.ts.map +1 -1
  41. package/dist/components/rolePicker/baseRolePicker.vue.js +7 -9
  42. package/dist/components/rolePicker/baseRolePicker.vue.js.map +1 -1
  43. package/dist/components/rolePicker/index.d.ts +2 -0
  44. package/dist/components/rolePicker/index.d.ts.map +1 -1
  45. package/dist/components/rolePicker/index.js +2 -0
  46. package/dist/components/rolePicker/index.js.map +1 -1
  47. package/dist/components/scrollbar/Scrollbar.vue.d.ts +110 -378
  48. package/dist/components/scrollbar/Scrollbar.vue.d.ts.map +1 -1
  49. package/dist/components/switch/JaSwitch.vue.d.ts +96 -431
  50. package/dist/components/switch/JaSwitch.vue.d.ts.map +1 -1
  51. package/dist/components/upload/JaUploader.vue.d.ts +58 -6
  52. package/dist/components/upload/JaUploader.vue.d.ts.map +1 -1
  53. package/dist/components/upload/index.d.ts +88 -9
  54. package/dist/components/upload/index.d.ts.map +1 -1
  55. package/dist/components/upload/index.js +1 -0
  56. package/dist/components/upload/index.js.map +1 -1
  57. package/dist/components/upload/types.d.ts +3 -0
  58. package/dist/components/upload/types.d.ts.map +1 -0
  59. package/dist/components/upload/types.js +2 -0
  60. package/dist/components/upload/types.js.map +1 -0
  61. package/dist/components/upload/uploader.vue.d.ts +31 -3
  62. package/dist/components/upload/uploader.vue.d.ts.map +1 -1
  63. package/dist/components/upload/uploader.vue.js +42 -15
  64. package/dist/components/upload/uploader.vue.js.map +1 -1
  65. package/dist/components/userGroupTree/src/userGroupTree.vue.d.ts +1808 -0
  66. package/dist/components/userGroupTree/src/userGroupTree.vue.d.ts.map +1 -0
  67. package/dist/components/userGroupTree/src/userGroupTree.vue.js +23 -14
  68. package/dist/components/userGroupTree/src/userGroupTree.vue.js.map +1 -1
  69. package/dist/components/userPicker/src/JaUserList.vue.d.ts +4 -0
  70. package/dist/components/userPicker/src/JaUserList.vue.d.ts.map +1 -1
  71. package/dist/components/userPicker/src/JaUserList.vue.js +9 -1
  72. package/dist/components/userPicker/src/JaUserList.vue.js.map +1 -1
  73. package/dist/components/userPicker/src/UserPicker.vue.d.ts +10 -0
  74. package/dist/components/userPicker/src/UserPicker.vue.d.ts.map +1 -1
  75. package/dist/components/userPicker/src/UserPicker.vue.js +46 -5
  76. package/dist/components/userPicker/src/UserPicker.vue.js.map +1 -1
  77. package/dist/components/userSelectDialog/src/userSelectDialog.vue.d.ts +19 -2
  78. package/dist/components/userSelectDialog/src/userSelectDialog.vue.d.ts.map +1 -1
  79. package/dist/components/userSelectDialog/src/userSelectDialog.vue.js +60 -12
  80. package/dist/components/userSelectDialog/src/userSelectDialog.vue.js.map +1 -1
  81. package/dist/hooks/useAppInstances.d.ts +17 -4
  82. package/dist/hooks/useAppInstances.d.ts.map +1 -1
  83. package/dist/hooks/useAppInstances.js +109 -24
  84. package/dist/hooks/useAppInstances.js.map +1 -1
  85. package/dist/hooks/useClassificationLevels.d.ts.map +1 -1
  86. package/dist/hooks/useClassificationLevels.js +30 -7
  87. package/dist/hooks/useClassificationLevels.js.map +1 -1
  88. package/dist/hooks/useConstraintProviders.d.ts +5 -0
  89. package/dist/hooks/useConstraintProviders.d.ts.map +1 -0
  90. package/dist/hooks/useConstraintProviders.js +31 -0
  91. package/dist/hooks/useConstraintProviders.js.map +1 -0
  92. package/dist/hooks/useEntities.d.ts +9 -0
  93. package/dist/hooks/useEntities.d.ts.map +1 -0
  94. package/dist/hooks/useEntities.js +40 -0
  95. package/dist/hooks/useEntities.js.map +1 -0
  96. package/dist/hooks/useEntityPropDataTypes.d.ts +5 -0
  97. package/dist/hooks/useEntityPropDataTypes.d.ts.map +1 -0
  98. package/dist/hooks/useEntityPropDataTypes.js +31 -0
  99. package/dist/hooks/useEntityPropDataTypes.js.map +1 -0
  100. package/dist/hooks/useFileConfigurations.d.ts +6 -0
  101. package/dist/hooks/useFileConfigurations.d.ts.map +1 -0
  102. package/dist/hooks/useFileConfigurations.js +37 -0
  103. package/dist/hooks/useFileConfigurations.js.map +1 -0
  104. package/dist/hooks/useGroups.d.ts +7 -0
  105. package/dist/hooks/useGroups.d.ts.map +1 -0
  106. package/dist/hooks/useGroups.js +75 -0
  107. package/dist/hooks/useGroups.js.map +1 -0
  108. package/dist/hooks/useNumberTemplates.d.ts +6 -0
  109. package/dist/hooks/useNumberTemplates.d.ts.map +1 -0
  110. package/dist/hooks/useNumberTemplates.js +37 -0
  111. package/dist/hooks/useNumberTemplates.js.map +1 -0
  112. package/dist/hooks/useProperties.d.ts +9 -0
  113. package/dist/hooks/useProperties.d.ts.map +1 -0
  114. package/dist/hooks/useProperties.js +40 -0
  115. package/dist/hooks/useProperties.js.map +1 -0
  116. package/dist/hooks/useRoleCategories.d.ts +6 -0
  117. package/dist/hooks/useRoleCategories.d.ts.map +1 -0
  118. package/dist/hooks/useRoleCategories.js +37 -0
  119. package/dist/hooks/useRoleCategories.js.map +1 -0
  120. package/dist/hooks/useRoles.d.ts +6 -0
  121. package/dist/hooks/useRoles.d.ts.map +1 -0
  122. package/dist/hooks/useRoles.js +38 -0
  123. package/dist/hooks/useRoles.js.map +1 -0
  124. package/dist/index.d.ts +9 -0
  125. package/dist/index.d.ts.map +1 -1
  126. package/dist/index.js +9 -0
  127. package/dist/index.js.map +1 -1
  128. package/lib/index.css +1 -1
  129. package/lib/index.js +9019 -8458
  130. package/lib/index.umd.cjs +39 -34
  131. package/package.json +7 -7
  132. package/packages/components/input/JaInput.vue +1 -1
  133. package/packages/components/inputI18n/I18nBundleEditor.vue +2 -2
  134. package/packages/components/inputI18n/InputI18n.vue +33 -25
  135. package/packages/components/inputNumber/JaInputNumber.vue +6 -5
  136. package/packages/components/properyPicker/PropertyPicker.vue +4 -8
  137. package/packages/components/rolePicker/RoleCategorySelector.vue +154 -0
  138. package/packages/components/rolePicker/RoleEditor.vue +16 -7
  139. package/packages/components/rolePicker/baseRolePicker.vue +6 -13
  140. package/packages/components/rolePicker/index.ts +3 -0
  141. package/packages/components/upload/index.ts +1 -0
  142. package/packages/components/upload/types.ts +4 -0
  143. package/packages/components/upload/uploader.vue +469 -381
  144. package/packages/components/userGroupTree/src/userGroupTree.vue +54 -17
  145. package/packages/components/userPicker/src/JaUserList.vue +14 -2
  146. package/packages/components/userPicker/src/UserPicker.vue +47 -4
  147. package/packages/components/userSelectDialog/src/userSelectDialog.vue +45 -8
  148. package/packages/hooks/useAppInstances.ts +121 -25
  149. package/packages/hooks/useClassificationLevels.ts +31 -7
  150. package/packages/hooks/useConstraintProviders.ts +36 -0
  151. package/packages/hooks/useEntities.ts +44 -0
  152. package/packages/hooks/useEntityPropDataTypes.ts +37 -0
  153. package/packages/hooks/useFileConfigurations.ts +41 -0
  154. package/packages/hooks/useGroups.ts +81 -0
  155. package/packages/hooks/useNumberTemplates.ts +43 -0
  156. package/packages/hooks/useProperties.ts +44 -0
  157. package/packages/hooks/useRoleCategories.ts +42 -0
  158. package/packages/hooks/useRoles.ts +44 -0
  159. package/packages/index.ts +9 -0
@@ -1,16 +1,16 @@
1
1
  <script setup lang="ts">
2
2
  import {
3
- createAxiosWithoutCache,
4
- type FileInfo, Jari,
5
- useFilesApi,
6
- useLoginUser,
7
- type ClassificationLevel, type UploadInitParams, useLoading
3
+ createAxiosWithoutCache,
4
+ type FileInfo, Jari,
5
+ useFilesApi,
6
+ useLoginUser,
7
+ type ClassificationLevel, type UploadInitParams, useLoading
8
8
  } from "@jari-ace/app-bolts";
9
9
  import { nextTick, onMounted, onUnmounted, ref, watch } from "vue";
10
10
  import { ArrowDown, Download, Upload } from "@element-plus/icons-vue";
11
11
  import {
12
- useSystemClassificationLevelMap,
13
- useSystemClassificationLevels
12
+ useSystemClassificationLevelMap,
13
+ useSystemClassificationLevels
14
14
  } from "../../hooks/useClassificationLevels";
15
15
  import Ace = Jari.Ace;
16
16
  import { ElMessageBox } from "element-plus";
@@ -20,7 +20,7 @@ import "@uppy/audio/css/style.min.css";
20
20
  import "@uppy/screen-capture/css/style.min.css";
21
21
  import "@uppy/webcam/css/style.min.css";
22
22
  import "@uppy/image-editor/css/style.min.css";
23
- import Uppy from "@uppy/core";
23
+ import Uppy, { type Meta, type UppyFile } from "@uppy/core";
24
24
  import Tus from "@uppy/tus";
25
25
  import Webcam from "@uppy/webcam";
26
26
  import ScreenCapture from "@uppy/screen-capture";
@@ -32,44 +32,45 @@ import prettyBytes from "pretty-bytes";
32
32
  import PdfViewerModal from "./pdf-viewer/PdfViewerModal.vue";
33
33
 
34
34
  import {
35
- ElTable,
36
- ElTableColumn,
37
- ElButton,
38
- ElDropdown,
39
- ElDropdownItem,
40
- ElDropdownMenu,
41
- ElIcon,
42
- ElTag
35
+ ElTable,
36
+ ElTableColumn,
37
+ ElButton,
38
+ ElDropdown,
39
+ ElDropdownItem,
40
+ ElDropdownMenu,
41
+ ElIcon,
42
+ ElTag
43
43
  } from "element-plus";
44
+ import type { AceFile } from "./types";
44
45
 
45
46
  const props = defineProps<{
46
- /**
47
- * 应用名
48
- */
49
- serviceName: string,
50
- /**
51
- * 附件配置key
52
- */
53
- configKey: string,
54
- /**
55
- * 附件令牌
56
- */
57
- attachToken?: string,
58
- /**
59
- * 数据密集
60
- */
61
- classificationLevel?: number,
62
- /**
63
- * 文件列表高度
64
- */
65
- height?: string | number,
66
- /**
67
- * 文件列表最大高度
68
- */
69
- maxHeight?: string | number
47
+ /**
48
+ * 应用名
49
+ */
50
+ serviceName: string,
51
+ /**
52
+ * 附件配置key
53
+ */
54
+ configKey: string,
55
+ /**
56
+ * 附件令牌
57
+ */
58
+ attachToken?: string,
59
+ /**
60
+ * 数据密集
61
+ */
62
+ classificationLevel?: number,
63
+ /**
64
+ * 文件列表高度
65
+ */
66
+ height?: string | number,
67
+ /**
68
+ * 文件列表最大高度
69
+ */
70
+ maxHeight?: string | number
70
71
  }>();
71
72
  const attachId = defineModel<string>({
72
- required: false
73
+ required: false
73
74
  });
74
75
  const axios = createAxiosWithoutCache();
75
76
  const loading = useLoading(axios);
@@ -87,429 +88,516 @@ const uploadingProgress = ref(100);
87
88
  const pdfViewerVisible = ref(false);
88
89
  const pdfSrc = ref("");
89
90
  const previewableFileExts = [".doc", ".docx", ".xls", ".xlsx", ".wps", ".et",
90
- ".csv", ".txt", ".rtf", ".odt", "ods", ".mht", ".ppt", ".pptx", ".odp", ".pdf", "xps", "."];
91
- const emits = defineEmits(['change']);
91
+ ".csv", ".txt", ".rtf", ".odt", ".ods", ".mht", ".ppt", ".pptx", ".odp", ".pdf", ".xps", "."];
92
+ const emits = defineEmits<{
93
+ /**
94
+ * 附件ID变更事件
95
+ */
96
+ change: [attachId: string],
97
+ /**
98
+ * 添加单个文件事件
99
+ */
100
+ fileAdded: [AceFile],
101
+ /**
102
+ * 添加多个文件事件
103
+ */
104
+ filesAdded: [AceFile[]],
105
+ /**
106
+ * 删除单个文件事件
107
+ */
108
+ fileRemoved: [AceFile],
109
+ /**
110
+ * 开始上传事件
111
+ */
112
+ upload: [uploadID: string, files: AceFile[]],
113
+ /**
114
+ * 全体进度事件
115
+ */
116
+ progress: [progress: number],
117
+ /**
118
+ * 单文件进度事件
119
+ */
120
+ uploadProgress: [file: AceFile],
121
+ /**
122
+ * 文件上传暂停事件
123
+ */
124
+ uploadPause: [file: AceFile, isPaused: boolean],
125
+ /**
126
+ * 文件上传成功事件
127
+ */
128
+ uploadSuccess: [file: AceFile],
129
+ /**
130
+ * 全部上传完成事件
131
+ */
132
+ complete: [successful: AceFile[], failed: AceFile[]],
133
+ /**
134
+ * 全体上传失败事件
135
+ */
136
+ error: [error: Error]
137
+ /**
138
+ * 单个文件上传失败事件
139
+ */
140
+ uploadError: [file: AceFile, error: Error]
141
+ /**
142
+ * 下载完成事件
143
+ */
144
+ downloaded: [file: FileInfo]
145
+ /**
146
+ * 打包下载完成事件
147
+ */
148
+ zipDownloaded: [file: FileInfo[]]
149
+ }>();
92
150
  let uppy: Uppy | undefined;
93
151
  curAttachToken.value = props.attachToken;
94
152
 
95
153
  onMounted(async () => {
96
- user.value = useLoginUser();
97
- const cl = Math.max(props.classificationLevel ?? 50, user.value?.classifiedLevel ?? 50);
98
- classificationLevels.value = await useSystemClassificationLevels();
99
- classificationLevelMap.value = await useSystemClassificationLevelMap();
100
- allowedClassificationLevels.value = classificationLevels.value.filter(l => l.value >= cl);
101
- if (props.attachToken) {
102
- await initLoad();
103
- } else {
104
- await initNew();
105
- }
154
+ user.value = useLoginUser();
155
+ const cl = Math.max(props.classificationLevel ?? 50, user.value?.classifiedLevel ?? 50);
156
+ classificationLevels.value = await useSystemClassificationLevels();
157
+ classificationLevelMap.value = await useSystemClassificationLevelMap();
158
+ allowedClassificationLevels.value = classificationLevels.value.filter(l => l.value >= cl);
159
+ console.log(`附件控件密级调试:
160
+ 表单密级:`, props.classificationLevel, `
161
+ 用户密级:`, user.value?.classifiedLevel, `
162
+ 表单/用户密级比较后取最低密级:`, cl, `
163
+ 系统密级:`, classificationLevels.value, `
164
+ 最终可选密级:`, allowedClassificationLevels.value
165
+ )
166
+ if (props.attachToken) {
167
+ await initLoad();
168
+ } else {
169
+ await initNew();
170
+ }
106
171
  });
107
172
 
108
173
  onUnmounted(() => {
109
- if (uppy) uppy.destroy();
110
- uppy = undefined;
174
+ if (uppy) uppy.destroy();
175
+ uppy = undefined;
111
176
  });
112
177
 
113
178
  async function loadFileInfos() {
114
- if (!curAttachToken.value) {
115
- files.value = [];
116
- }
117
- files.value = await api.getFileList(curAttachToken.value!);
179
+ if (!curAttachToken.value) {
180
+ files.value = [];
181
+ }
182
+ files.value = await api.getFileList(curAttachToken.value!);
118
183
  }
119
184
 
120
185
  function createUppyInstance() {
121
- if (uppy) {
122
- uppy.destroy();
123
- }
124
- const cfg = uploadInitParams.value!.fileConfig;
125
- uppy = new Uppy({
126
- autoProceed: true,
127
- locale: zhCN
128
- }).on("progress", progress => {
129
- if (progress == 100) {
130
- loadFileInfos();
131
- }
132
- uploadingProgress.value = progress;
133
- });
134
- uppy.use(Tus, {
135
- endpoint: new URL("/ace-file-service/uploads", location.origin).toString(),
136
- withCredentials: true,
137
- retryDelays: undefined,
138
- chunkSize: !uploadInitParams.value?.chunkSize || uploadInitParams.value?.chunkSize
139
- == 0 ? Infinity : uploadInitParams.value?.chunkSize,
140
- parallelUploads: 1,
141
- headers: {
142
- aceAttachId: attachId.value!,
143
- aceNewForm: isNewForm.value ? "yes" : "no"
144
- },
145
- metadata: {
146
- attachId: attachId.value!,
147
- configKey: props.configKey,
148
- appServiceName: props.serviceName,
149
- classifiedLevel: selectedFileClassificationLevel.value.toString()
150
- },
151
- metadataForPartialUploads: {
152
- attachId: attachId.value!,
153
- configKey: props.configKey,
154
- appServiceName: props.serviceName,
155
- classifiedLevel: selectedFileClassificationLevel.value.toString()
186
+ if (uppy) {
187
+ uppy.destroy();
156
188
  }
157
- });
158
- if (cfg.enableWebcam) {
159
- uppy.use(Webcam, {
160
- // Webcam 的相关配置
161
- modes: cfg.allowedWebcamModes?.map(m => {
162
- switch (m) {
163
- case "VIDEO_AUDIO":
164
- return "video-audio";
165
- case "VIDEO_ONLY":
166
- return "video-only";
167
- case "PICTURE":
168
- return "picture";
189
+ const cfg = uploadInitParams.value!.fileConfig;
190
+ uppy = new Uppy({
191
+ autoProceed: true,
192
+ locale: zhCN
193
+ }).on("progress", progress => {
194
+ if (progress == 100) {
195
+ loadFileInfos();
169
196
  }
170
- }),
171
- mirror: false
197
+ uploadingProgress.value = progress;
172
198
  });
173
- }
174
- if (cfg.enableAudio) {
175
- uppy.use(Audio);
176
- }
177
- if (cfg.enableScreenCapture) {
178
- uppy.use(ScreenCapture);
179
- }
180
- let selectionType: "files" | "folders" | "both" | undefined;
181
- if (cfg.disableFileUpload) {
182
- if (cfg.disableDirUpload) {
183
- selectionType = undefined;
184
- } else {
185
- selectionType = "folders";
199
+ uppy.use(Tus, {
200
+ endpoint: new URL("/ace-file-service/uploads", location.origin).toString(),
201
+ withCredentials: true,
202
+ retryDelays: undefined,
203
+ chunkSize: !uploadInitParams.value?.chunkSize || uploadInitParams.value?.chunkSize
204
+ == 0 ? Infinity : uploadInitParams.value?.chunkSize,
205
+ parallelUploads: 1,
206
+ headers: {
207
+ aceAttachId: attachId.value!,
208
+ aceNewForm: isNewForm.value ? "yes" : "no"
209
+ },
210
+ metadata: {
211
+ attachId: attachId.value!,
212
+ configKey: props.configKey,
213
+ appServiceName: props.serviceName,
214
+ classifiedLevel: selectedFileClassificationLevel.value.toString()
215
+ },
216
+ metadataForPartialUploads: {
217
+ attachId: attachId.value!,
218
+ configKey: props.configKey,
219
+ appServiceName: props.serviceName,
220
+ classifiedLevel: selectedFileClassificationLevel.value.toString()
221
+ }
222
+ });
223
+ if (cfg.enableWebcam) {
224
+ uppy.use(Webcam, {
225
+ // Webcam 的相关配置
226
+ modes: cfg.allowedWebcamModes?.map(m => {
227
+ switch (m) {
228
+ case "VIDEO_AUDIO":
229
+ return "video-audio";
230
+ case "VIDEO_ONLY":
231
+ return "video-only";
232
+ case "PICTURE":
233
+ return "picture";
234
+ }
235
+ }),
236
+ mirror: false
237
+ });
238
+ }
239
+ if (cfg.enableAudio) {
240
+ uppy.use(Audio);
186
241
  }
187
- } else {
188
- if (cfg.disableDirUpload) {
189
- selectionType = "files";
242
+ if (cfg.enableScreenCapture) {
243
+ uppy.use(ScreenCapture);
244
+ }
245
+ let selectionType: "files" | "folders" | "both" | undefined;
246
+ if (cfg.disableFileUpload) {
247
+ if (cfg.disableDirUpload) {
248
+ selectionType = undefined;
249
+ } else {
250
+ selectionType = "folders";
251
+ }
190
252
  } else {
191
- selectionType = "both";
253
+ if (cfg.disableDirUpload) {
254
+ selectionType = "files";
255
+ } else {
256
+ selectionType = "both";
257
+ }
192
258
  }
193
- }
194
- uppy.use(Dashboard, {
195
- inline: false,
196
- note: cfg.uploadNote,
197
- proudlyDisplayPoweredByUppy: false,
198
- fileManagerSelectionType: selectionType,
199
- singleFileFullScreen: false,
200
- disableLocalFiles: cfg.disableFileUpload ?? false,
201
- closeAfterFinish: true,
202
- closeModalOnClickOutside: true
203
- }).use(ImageEditor);
259
+ uppy.use(Dashboard, {
260
+ inline: false,
261
+ note: cfg.uploadNote,
262
+ proudlyDisplayPoweredByUppy: false,
263
+ fileManagerSelectionType: selectionType,
264
+ singleFileFullScreen: false,
265
+ disableLocalFiles: cfg.disableFileUpload ?? false,
266
+ closeAfterFinish: true,
267
+ closeModalOnClickOutside: true
268
+ }).use(ImageEditor);
269
+
270
+ uppy.on('file-added', file => {
271
+ emits('fileAdded', file)
272
+ }).on('files-added', files => {
273
+ emits('filesAdded', files)
274
+ }).on('file-removed', file => {
275
+ emits('fileRemoved', file)
276
+ }).on('upload', (uploadID, files) => {
277
+ emits('upload', uploadID, files);
278
+ }).on('progress', progress => {
279
+ emits('progress', progress)
280
+ }).on('upload-progress', file => {
281
+ emits('uploadProgress', file)
282
+ }).on('upload-pause', (file, isPaused) => {
283
+ emits("uploadPause", file, isPaused)
284
+ }).on('upload-success', file => {
285
+ emits('uploadSuccess', file)
286
+ }).on('complete', (result) => {
287
+ emits('complete', result.successful, result.failed)
288
+ }).on('error', (error) => {
289
+ emits('error', error)
290
+ }).on('upload-error', (file, error) => {
291
+ emits('uploadError', file, error)
292
+ })
204
293
  }
205
294
 
206
295
  async function onUploadBtnClick() {
207
- const cfg = uploadInitParams.value?.fileConfig;
208
- if (cfg) {
209
- uppy?.setMeta({
210
- attachId: attachId.value!,
211
- configKey: props.configKey,
212
- appServiceName: props.serviceName,
213
- classifiedLevel: selectedFileClassificationLevel.value.toString()
214
- });
215
- const dashboard = uppy?.getPlugin("Dashboard") as any;
216
- if (dashboard) {
217
- dashboard.setOptions({
218
- note: (
219
- cfg.uploadNote ? cfg.uploadNote : ""
220
- )
221
- + `(正在上传${classificationLevelMap.value?.get(selectedFileClassificationLevel.value)}文件)`
222
- });
296
+ const cfg = uploadInitParams.value?.fileConfig;
297
+ if (cfg) {
298
+ uppy?.setMeta({
299
+ attachId: attachId.value!,
300
+ configKey: props.configKey,
301
+ appServiceName: props.serviceName,
302
+ classifiedLevel: selectedFileClassificationLevel.value.toString()
303
+ });
304
+ const dashboard = uppy?.getPlugin("Dashboard") as any;
305
+ if (dashboard) {
306
+ dashboard.setOptions({
307
+ note: (
308
+ cfg.uploadNote ? cfg.uploadNote : ""
309
+ )
310
+ + `(正在上传${classificationLevelMap.value?.get(selectedFileClassificationLevel.value)}文件)`
311
+ });
312
+ }
313
+ dashboard?.openModal();
314
+ } else {
315
+ ElMessageBox.alert("无法找到附件配置" + props.configKey, "错误");
223
316
  }
224
- dashboard?.openModal();
225
- } else {
226
- ElMessageBox.alert("无法找到附件配置" + props.configKey, "错误");
227
- }
228
317
  }
229
318
 
230
319
  function handleClassificationLevelSelCmd(level: number) {
231
- selectedFileClassificationLevel.value = level;
232
- uppy?.setMeta({
233
- attachId: attachId.value!,
234
- configKey: props.configKey,
235
- appServiceName: props.serviceName,
236
- classifiedLevel: selectedFileClassificationLevel.value.toString()
237
- });
238
- const dashboard = uppy?.getPlugin("Dashboard") as any;
239
- if (dashboard) {
240
- const cfg = uploadInitParams.value?.fileConfig;
241
- if (cfg) {
242
- dashboard.setOptions({
243
- note: (
244
- cfg.uploadNote ? cfg.uploadNote : ""
245
- )
246
- + `(正在上传${classificationLevelMap.value?.get(selectedFileClassificationLevel.value)}文件)`
247
- });
320
+ selectedFileClassificationLevel.value = level;
321
+ uppy?.setMeta({
322
+ attachId: attachId.value!,
323
+ configKey: props.configKey,
324
+ appServiceName: props.serviceName,
325
+ classifiedLevel: selectedFileClassificationLevel.value.toString()
326
+ });
327
+ const dashboard = uppy?.getPlugin("Dashboard") as any;
328
+ if (dashboard) {
329
+ const cfg = uploadInitParams.value?.fileConfig;
330
+ if (cfg) {
331
+ dashboard.setOptions({
332
+ note: (
333
+ cfg.uploadNote ? cfg.uploadNote : ""
334
+ )
335
+ + `(正在上传${classificationLevelMap.value?.get(selectedFileClassificationLevel.value)}文件)`
336
+ });
337
+ }
338
+ dashboard?.openModal();
248
339
  }
249
- dashboard?.openModal();
250
- }
251
340
  }
252
341
 
253
342
  async function initLoad() {
254
- uploadInitParams.value = await api.initLoad(props.serviceName, props.configKey, props.attachToken!);
255
- files.value = uploadInitParams.value.files;
256
- attachId.value = uploadInitParams.value?.attachId;
257
- curAttachToken.value = uploadInitParams.value?.attachId;
258
- isNewForm.value = false;
259
- await nextTick();
260
- createUppyInstance();
343
+ uploadInitParams.value = await api.initLoad(props.serviceName, props.configKey, props.attachToken!);
344
+ files.value = uploadInitParams.value.files;
345
+ attachId.value = uploadInitParams.value?.attachId;
346
+ curAttachToken.value = uploadInitParams.value?.attachId;
347
+ isNewForm.value = false;
348
+ await nextTick();
349
+ createUppyInstance();
261
350
  }
262
351
 
263
352
  async function initNew() {
264
- uploadInitParams.value = await api.initNew(props.serviceName, props.configKey);
265
- files.value = uploadInitParams.value.files;
266
- attachId.value = uploadInitParams.value?.attachId;
267
- curAttachToken.value = uploadInitParams.value?.attachToken;
268
- isNewForm.value = true;
269
- emits('change', attachId.value);
270
- await nextTick();
271
- createUppyInstance();
353
+ uploadInitParams.value = await api.initNew(props.serviceName, props.configKey);
354
+ files.value = uploadInitParams.value.files;
355
+ attachId.value = uploadInitParams.value?.attachId;
356
+ curAttachToken.value = uploadInitParams.value?.attachToken;
357
+ isNewForm.value = true;
358
+ emits('change', attachId.value);
359
+ await nextTick();
360
+ createUppyInstance();
272
361
  }
273
362
 
274
363
  async function delUploadedFile(file: FileInfo) {
275
- await api.deleteFile(file.token || file.id);
276
- files.value = files.value.filter(f => f.id !== file.id);
364
+ await api.deleteFile(file.token || file.id);
365
+ files.value = files.value.filter(f => f.id !== file.id);
277
366
  }
278
367
 
279
- function previewFile(fileToken:string) {
280
- pdfSrc.value = new URL("uploads/preview/" + fileToken, location.origin).toString()
281
- pdfViewerVisible.value = true;
368
+ function previewFile(fileToken: string) {
369
+ pdfSrc.value = new URL("uploads/preview/" + fileToken, location.origin).toString()
370
+ pdfViewerVisible.value = true;
282
371
  }
283
372
 
284
- function downloadFile(fileToken: string) {
285
- api.downloadFile(fileToken);
373
+ async function downloadFile(fileToken: string) {
374
+ await api.downloadFile(fileToken);
375
+ var file = files.value.filter(f => fileToken === f.token)
376
+ if (file && file.length > 0)
377
+ emits('downloaded', file[0]);
286
378
  }
287
379
 
288
380
  function viewUppyDashboard() {
289
- const dashboard = uppy?.getPlugin("Dashboard") as any;
290
- if (dashboard) {
291
- dashboard.openModal();
292
- }
381
+ const dashboard = uppy?.getPlugin("Dashboard") as any;
382
+ if (dashboard) {
383
+ dashboard.openModal();
384
+ }
293
385
  }
294
386
 
295
- function downloadAll() {
296
- if (!curAttachToken.value) {
297
- return;
298
- }
299
- api.downloadZipFile(curAttachToken.value);
387
+ async function downloadAll() {
388
+ if (!curAttachToken.value) {
389
+ return;
390
+ }
391
+ await api.downloadZipFile(curAttachToken.value);
392
+ emits('zipDownloaded', files.value);
300
393
  }
301
394
 
302
395
  function checkAllowUpload() {
303
- const cfg = uploadInitParams.value?.fileConfig;
304
- if (cfg) {
305
- let hasRole = true;
306
- if (cfg.uploadAuthCode) {
307
- const login = useLoginUser();
308
- if (login) {
309
- hasRole = login.hasRole(cfg.uploadAuthCode);
310
- }
311
- return !cfg.disallowUpload && hasRole;
396
+ const cfg = uploadInitParams.value?.fileConfig;
397
+ if (cfg) {
398
+ let hasRole = true;
399
+ if (cfg.uploadAuthCode) {
400
+ const login = useLoginUser();
401
+ if (login) {
402
+ hasRole = login.hasRole(cfg.uploadAuthCode);
403
+ }
404
+ return !cfg.disallowUpload && hasRole;
405
+ }
406
+ return !cfg.disallowUpload;
312
407
  }
313
- return !cfg.disallowUpload;
314
- }
315
- console.log('file cfg is null')
316
- return false;
408
+ console.log('file cfg is null')
409
+ return false;
317
410
  }
318
411
 
319
412
  function checkAllowDownload() {
320
- const cfg = uploadInitParams.value?.fileConfig;
321
- if (cfg) {
322
- let hasRole = true;
323
- if (cfg.downloadAuthCode) {
324
- const login = useLoginUser();
325
- if (login) {
326
- hasRole = login.hasRole(cfg.downloadAuthCode);
327
- }
328
- return !cfg.disallowDownload && hasRole;
413
+ const cfg = uploadInitParams.value?.fileConfig;
414
+ if (cfg) {
415
+ let hasRole = true;
416
+ if (cfg.downloadAuthCode) {
417
+ const login = useLoginUser();
418
+ if (login) {
419
+ hasRole = login.hasRole(cfg.downloadAuthCode);
420
+ }
421
+ return !cfg.disallowDownload && hasRole;
422
+ }
423
+ return !cfg.disallowDownload;
329
424
  }
330
- return !cfg.disallowDownload;
331
- }
332
- return false;
425
+ return false;
333
426
  }
334
427
 
335
428
  function checkAllowDelete() {
336
- const cfg = uploadInitParams.value?.fileConfig;
337
- if (cfg) {
338
- let hasRole = true;
339
- if (cfg.deleteAuthCode) {
340
- const login = useLoginUser();
341
- if (login) {
342
- hasRole = login.hasRole(cfg.deleteAuthCode);
343
- }
344
- return !cfg.disallowDelete && hasRole;
429
+ const cfg = uploadInitParams.value?.fileConfig;
430
+ if (cfg) {
431
+ let hasRole = true;
432
+ if (cfg.deleteAuthCode) {
433
+ const login = useLoginUser();
434
+ if (login) {
435
+ hasRole = login.hasRole(cfg.deleteAuthCode);
436
+ }
437
+ return !cfg.disallowDelete && hasRole;
438
+ }
439
+ return !cfg.disallowDelete;
345
440
  }
346
- return !cfg.disallowDelete;
347
- }
348
- return false;
441
+ return false;
349
442
  }
350
443
 
351
444
  function checkAllowPreview(file: FileInfo) {
352
- const cfg = uploadInitParams.value?.fileConfig;
353
- if (cfg) {
354
- if (cfg.disablePreview) {
355
- return false;
356
- }
357
- if (!previewableFileExts.some(ext => file.fileName.endsWith(ext))) {
358
- return false;
445
+ const cfg = uploadInitParams.value?.fileConfig;
446
+ if (cfg) {
447
+ if (cfg.disablePreview) {
448
+ return false;
449
+ }
450
+ if (!previewableFileExts.some(ext => file.fileName.endsWith(ext))) {
451
+ return false;
452
+ }
453
+ return true;
359
454
  }
360
- return true;
361
- }
362
- return false;
455
+ return false;
363
456
  }
364
457
 
365
458
  watch(() => props.attachToken, () => {
366
- if (props.attachToken) {
367
- initLoad();
368
- } else {
369
- initNew();
370
- }
459
+ if (props.attachToken) {
460
+ initLoad();
461
+ } else {
462
+ initNew();
463
+ }
371
464
  });
372
465
 
373
-
374
466
  </script>
375
467
 
376
468
  <template>
377
- <div class="ja-uploader">
378
- <div class="ja-uploader-tools">
379
- <el-button plain type="success" :icon="Upload" @click="onUploadBtnClick"
380
- :loading="loading" :disabled="loading" size="small"
381
- v-if="allowedClassificationLevels.length <= 1 && checkAllowUpload()">
382
- 上传{{ uploadInitParams?.fileConfig.enableClassifiedLevel ? "(非密)" : "" }}
383
- </el-button>
384
- <el-button plain :icon="Download" @click="downloadAll" v-if="checkAllowDownload()"
385
- :loading="loading" :disabled="loading || files?.length === 0" size="small">全部下载
386
- </el-button>
387
- <el-dropdown v-if="allowedClassificationLevels.length > 1 && checkAllowUpload()"
388
- @command="handleClassificationLevelSelCmd" size="small">
389
- <el-button type="success" size="small">
390
- 上传
391
- <el-icon class="el-icon--right">
392
- <arrow-down />
393
- </el-icon>
394
- </el-button>
395
- <template #dropdown>
396
- <el-dropdown-menu>
397
- <el-dropdown-item v-for="cl in allowedClassificationLevels"
398
- :key="cl.value"
399
- :command="cl.value">{{ cl.label }}
400
- </el-dropdown-item>
401
- </el-dropdown-menu>
402
- </template>
403
- </el-dropdown>
404
- <div class="container" @click="viewUppyDashboard"
405
- v-if="uploadingProgress < 100 && uploadingProgress > 0">
406
- <p>
407
- <span class="loader-shimmer">正在上传,已完成{{ uploadingProgress }}%...</span>
408
- </p>
409
- </div>
469
+ <div class="ja-uploader">
470
+ <div class="ja-uploader-tools">
471
+ <el-button plain type="success" :icon="Upload" @click="onUploadBtnClick" :loading="loading"
472
+ :disabled="loading" size="small" v-if="allowedClassificationLevels.length <= 1 && checkAllowUpload()">
473
+ 上传{{ uploadInitParams?.fileConfig.enableClassifiedLevel ? "(非密)" : "" }}
474
+ </el-button>
475
+ <el-button plain :icon="Download" @click="downloadAll" v-if="checkAllowDownload()" :loading="loading"
476
+ :disabled="loading || files?.length === 0" size="small">
477
+ 全部下载
478
+ </el-button>
479
+ <el-dropdown v-if="allowedClassificationLevels.length > 1 && checkAllowUpload()"
480
+ @command="handleClassificationLevelSelCmd" size="small">
481
+ <el-button type="success" size="small">
482
+ 上传
483
+ <el-icon class="el-icon--right">
484
+ <arrow-down />
485
+ </el-icon>
486
+ </el-button>
487
+ <template #dropdown>
488
+ <el-dropdown-menu>
489
+ <el-dropdown-item v-for="cl in allowedClassificationLevels" :key="cl.value"
490
+ :command="cl.value">{{ cl.label }}
491
+ </el-dropdown-item>
492
+ </el-dropdown-menu>
493
+ </template>
494
+ </el-dropdown>
495
+ <div class="container" @click="viewUppyDashboard" v-if="uploadingProgress < 100 && uploadingProgress > 0">
496
+ <p>
497
+ <span class="loader-shimmer">正在上传,已完成{{ uploadingProgress }}%...</span>
498
+ </p>
499
+ </div>
500
+ </div>
501
+ <el-table :data="files" :show-header="true" style="width: 100%" empty-text="暂无文件" :height="props.height"
502
+ :max-height="props.maxHeight">
503
+ <el-table-column prop="fileName" />
504
+ <el-table-column prop="fileSize" width="100">
505
+ <template #default="scope">
506
+ {{ prettyBytes(scope.row.fileSize) }}
507
+ </template>
508
+ </el-table-column>
509
+ <el-table-column prop="classifiedLevel" width="60">
510
+ <template #default="scope">
511
+ <el-tag
512
+ :type="scope.row.classifiedLevel < 50 ? (scope.row.classifiedLevel < 30 ? 'danger' : 'warning') : 'info'">
513
+ {{ classificationLevelMap?.get(scope.row.classifiedLevel) }}
514
+ </el-tag>
515
+ </template>
516
+ </el-table-column>
517
+ <el-table-column align="right" width="150" fixed="right">
518
+ <template #default="scope">
519
+ <el-button link type="warning" @click="previewFile(scope.row.token)"
520
+ v-if="checkAllowPreview(scope.row)">预览
521
+ </el-button>
522
+ <el-button link type="primary" @click="downloadFile(scope.row.token)" v-if="checkAllowDownload()">下载
523
+ </el-button>
524
+ <el-button link type="danger" @click="delUploadedFile(scope.row)" v-if="checkAllowDelete()">删除
525
+ </el-button>
526
+ </template>
527
+ </el-table-column>
528
+ </el-table>
410
529
  </div>
411
- <el-table :data="files" :show-header="true" style="width: 100%" empty-text="暂无文件"
412
- :height="props.height" :max-height="props.maxHeight">
413
- <el-table-column prop="fileName" />
414
- <el-table-column prop="fileSize" width="100">
415
- <template #default="scope">
416
- {{ prettyBytes(scope.row.fileSize) }}
417
- </template>
418
- </el-table-column>
419
- <el-table-column prop="classifiedLevel" width="60">
420
- <template #default="scope">
421
- <el-tag
422
- :type="scope.row.classifiedLevel < 50? ( scope.row.classifiedLevel < 30 ? 'danger' : 'warning'): 'info'">
423
- {{ classificationLevelMap?.get(scope.row.classifiedLevel) }}
424
- </el-tag>
425
- </template>
426
- </el-table-column>
427
- <el-table-column align="right" width="150" fixed="right">
428
- <template #default="scope">
429
- <el-button link type="warning" @click="previewFile(scope.row.token)"
430
- v-if="checkAllowPreview(scope.row)">预览</el-button>
431
- <el-button link type="primary" @click="downloadFile(scope.row.token)"
432
- v-if="checkAllowDownload()">下载
433
- </el-button>
434
- <el-button link type="danger" @click="delUploadedFile(scope.row)"
435
- v-if="checkAllowDelete()">删除
436
- </el-button>
437
- </template>
438
- </el-table-column>
439
- </el-table>
440
- </div>
441
- <pdf-viewer-modal :src="pdfSrc" v-model="pdfViewerVisible"></pdf-viewer-modal>
530
+ <pdf-viewer-modal :src="pdfSrc" v-model="pdfViewerVisible"></pdf-viewer-modal>
442
531
  </template>
443
532
 
444
- <style>
533
+ <style lang="scss" scoped>
445
534
  .uppy-Dashboard--modal {
446
- z-index: 9999 !important;
535
+ z-index: 9999 !important;
447
536
  }
448
537
 
449
538
  .uppy-Root {
450
- z-index: 9999;
539
+ z-index: 9999;
451
540
  }
452
- </style>
453
-
454
- <style lang="scss" scoped>
455
541
 
456
542
  .ja-uploader {
457
- width: 100%;
458
- display: flex;
459
- flex-direction: column;
460
- gap: 4px;
461
-
462
- &-tools {
543
+ width: 100%;
463
544
  display: flex;
464
- }
465
- }
545
+ flex-direction: column;
546
+ gap: 4px;
466
547
 
467
- .container {
468
- padding: 0 0 0 8px;
469
- cursor: pointer;
470
- }
548
+ &-tools {
549
+ display: flex;
550
+ }
471
551
 
472
- .loader-shimmer {
473
- display: inline-block;
474
- margin-left: 8px;
475
- padding: 0 12px;
476
- background-color: #e0f5f0;
477
- color: #888;
478
- border-radius: 4px;
479
- font-size: 0.9em;
480
- font-weight: 500;
481
- position: relative;
482
- overflow: hidden; /* 隐藏闪光效果的溢出 */
483
- vertical-align: middle;
484
- }
552
+ .container {
553
+ padding: 0 0 0 8px;
554
+ cursor: pointer;
555
+ }
485
556
 
486
- .loader-shimmer::after {
487
- content: '';
488
- position: absolute;
489
- top: 0;
490
- left: -100%; /* 从左侧外部开始 */
491
- width: 50%; /* 闪光宽度 */
492
- height: 100%;
493
-
494
- /* 闪光效果:透明 -> 亮白色 -> 透明 */
495
- background: linear-gradient(
496
- 90deg,
497
- transparent,
498
- rgba(255, 255, 255, 0.8),
499
- transparent
500
- );
501
-
502
- /* 动画: 1.5秒, 缓入缓出, 无限循环 */
503
- animation: shimmer 1.5s ease-in-out infinite;
504
- }
557
+ .loader-shimmer {
558
+ display: inline-block;
559
+ margin-left: 8px;
560
+ padding: 0 12px;
561
+ background-color: #e0f5f0;
562
+ color: #888;
563
+ border-radius: 4px;
564
+ font-size: 0.9em;
565
+ font-weight: 500;
566
+ position: relative;
567
+ overflow: hidden;
568
+ /* 隐藏闪光效果的溢出 */
569
+ vertical-align: middle;
570
+ }
505
571
 
506
- @keyframes shimmer {
507
- 0% {
508
- left: -100%;
509
- }
510
- 100% {
511
- left: 150%; /* 移动到右侧外部 */
512
- }
513
- }
572
+ .loader-shimmer::after {
573
+ content: '';
574
+ position: absolute;
575
+ top: 0;
576
+ left: -100%;
577
+ /* 从左侧外部开始 */
578
+ width: 50%;
579
+ /* 闪光宽度 */
580
+ height: 100%;
581
+
582
+ /* 闪光效果:透明 -> 亮白色 -> 透明 */
583
+ background: linear-gradient(90deg,
584
+ transparent,
585
+ rgba(255, 255, 255, 0.8),
586
+ transparent);
587
+
588
+ /* 动画: 1.5秒, 缓入缓出, 无限循环 */
589
+ animation: shimmer 1.5s ease-in-out infinite;
590
+ }
591
+
592
+ @keyframes shimmer {
593
+ 0% {
594
+ left: -100%;
595
+ }
514
596
 
597
+ 100% {
598
+ left: 150%;
599
+ /* 移动到右侧外部 */
600
+ }
601
+ }
602
+ }
515
603
  </style>