@jari-ace/element-plus-component 0.2.3 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/components/autoComplete/JaAutoComplete.vue.d.ts +18 -18
  2. package/dist/components/button/JaButton.vue.d.ts +24 -24
  3. package/dist/components/customGroupTree/src/customGroupTree.vue.d.ts +1 -1
  4. package/dist/components/departmentPicker/src/DepartmentPicker.vue.d.ts +2 -2
  5. package/dist/components/departmentTree/src/departmentTree.vue.d.ts +1 -1
  6. package/dist/components/dropdownButton/JaDropdownButton.vue.d.ts +55 -55
  7. package/dist/components/enumList/EnumListInput.vue.d.ts +2 -2
  8. package/dist/components/enumPicker/src/EnumPicker.vue.d.ts +1 -1
  9. package/dist/components/form/JaForm.vue.d.ts +1 -1
  10. package/dist/components/formItem/JaFormItem.vue.d.ts +12 -12
  11. package/dist/components/input/JaInput.vue.d.ts +18 -18
  12. package/dist/components/inputI18n/I18nBundleEditor.vue.d.ts +1 -1
  13. package/dist/components/inputI18n/InputI18n.vue.d.ts +2 -2
  14. package/dist/components/inputI18n/JaInputI18n.vue.d.ts +70 -70
  15. package/dist/components/inputNumber/JaInputNumber.vue.d.ts +12 -12
  16. package/dist/components/mapItemList/MapItemListInput.vue.d.ts +2 -2
  17. package/dist/components/numberList/NumberListInput.vue.d.ts +2 -2
  18. package/dist/components/rolePicker/RoleEditor.vue.d.ts +1 -1
  19. package/dist/components/rolePicker/baseRolePicker.vue.d.ts +1 -1
  20. package/dist/components/scrollbar/Scrollbar.vue.d.ts +8 -8
  21. package/dist/components/select/JaSelect.vue.d.ts +70 -70
  22. package/dist/components/stringList/StringListInput.vue.d.ts +2 -2
  23. package/dist/components/tip/index.d.ts +6 -6
  24. package/dist/components/tip/src/AceTip.vue.d.ts +1 -1
  25. package/dist/components/upload/JaUploader.vue.d.ts +85 -0
  26. package/dist/components/upload/JaUploader.vue.d.ts.map +1 -0
  27. package/dist/components/upload/JaUploader.vue.js +85 -0
  28. package/dist/components/upload/JaUploader.vue.js.map +1 -0
  29. package/dist/components/upload/index.d.ts +25 -4
  30. package/dist/components/upload/index.d.ts.map +1 -1
  31. package/dist/components/upload/index.js +2 -4
  32. package/dist/components/upload/index.js.map +1 -1
  33. package/dist/components/upload/pdf-viewer/PdfViewerModal.vue.d.ts +27 -0
  34. package/dist/components/upload/pdf-viewer/PdfViewerModal.vue.d.ts.map +1 -0
  35. package/dist/components/upload/pdf-viewer/PdfViewerModal.vue.js +94 -0
  36. package/dist/components/upload/pdf-viewer/PdfViewerModal.vue.js.map +1 -0
  37. package/dist/components/upload/uploader-locale-zh-cn.d.ts +223 -0
  38. package/dist/components/upload/uploader-locale-zh-cn.d.ts.map +1 -0
  39. package/dist/components/upload/uploader-locale-zh-cn.js +224 -0
  40. package/dist/components/upload/uploader-locale-zh-cn.js.map +1 -0
  41. package/dist/components/upload/uploader.vue.d.ts +44 -0
  42. package/dist/components/upload/uploader.vue.d.ts.map +1 -0
  43. package/dist/components/upload/uploader.vue.js +721 -0
  44. package/dist/components/upload/uploader.vue.js.map +1 -0
  45. package/dist/components/userGroupPicker/src/UserGroupPicker.vue.d.ts +2 -2
  46. package/dist/components/userPicker/src/UserPicker.vue.d.ts +3 -3
  47. package/dist/components/userSelectDialog/src/userSelectDialog.vue.d.ts +1 -1
  48. package/dist/components/userTag/UserInfoTag.vue.d.ts +2 -2
  49. package/lib/index.css +9 -1
  50. package/lib/index.js +37353 -2739
  51. package/lib/index.umd.cjs +407 -2
  52. package/package.json +14 -5
  53. package/packages/components/upload/JaUploader.vue +71 -0
  54. package/packages/components/upload/index.ts +2 -5
  55. package/packages/components/upload/pdf-viewer/PdfViewerModal.vue +32 -0
  56. package/packages/components/upload/uploader-locale-zh-cn.ts +223 -0
  57. package/packages/components/upload/uploader.vue +515 -0
  58. package/packages/components/upload/src/Upload.vue +0 -25
  59. package/packages/components/upload/src/type.ts +0 -3
@@ -0,0 +1,515 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ createAxiosWithoutCache,
4
+ type FileInfo, Jari,
5
+ useFilesApi,
6
+ useLoginUser,
7
+ type ClassificationLevel, type UploadInitParams, useLoading
8
+ } from "@jari-ace/app-bolts";
9
+ import { nextTick, onMounted, onUnmounted, ref, watch } from "vue";
10
+ import { ArrowDown, Download, Upload } from "@element-plus/icons-vue";
11
+ import {
12
+ useSystemClassificationLevelMap,
13
+ useSystemClassificationLevels
14
+ } from "../../hooks/useClassificationLevels";
15
+ import Ace = Jari.Ace;
16
+ import { ElMessageBox } from "element-plus";
17
+ import "@uppy/core/css/style.min.css";
18
+ import "@uppy/dashboard/css/style.min.css";
19
+ import "@uppy/audio/css/style.min.css";
20
+ import "@uppy/screen-capture/css/style.min.css";
21
+ import "@uppy/webcam/css/style.min.css";
22
+ import "@uppy/image-editor/css/style.min.css";
23
+ import Uppy from "@uppy/core";
24
+ import Tus from "@uppy/tus";
25
+ import Webcam from "@uppy/webcam";
26
+ import ScreenCapture from "@uppy/screen-capture";
27
+ import Audio from "@uppy/audio";
28
+ import zhCN from "./uploader-locale-zh-cn";
29
+ import Dashboard from "@uppy/dashboard";
30
+ import ImageEditor from "@uppy/image-editor";
31
+ import prettyBytes from "pretty-bytes";
32
+ import PdfViewerModal from "./pdf-viewer/PdfViewerModal.vue";
33
+
34
+ import {
35
+ ElTable,
36
+ ElTableColumn,
37
+ ElButton,
38
+ ElDropdown,
39
+ ElDropdownItem,
40
+ ElDropdownMenu,
41
+ ElIcon,
42
+ ElTag
43
+ } from "element-plus";
44
+
45
+ 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
70
+ }>();
71
+ const attachId = defineModel<string>({
72
+ required: false
73
+ });
74
+ const axios = createAxiosWithoutCache();
75
+ const loading = useLoading(axios);
76
+ const api = useFilesApi(axios);
77
+ const files = ref<FileInfo[]>([]);
78
+ const classificationLevels = ref<ClassificationLevel[]>([]);
79
+ const allowedClassificationLevels = ref<ClassificationLevel[]>([]);
80
+ const classificationLevelMap = ref<Map<number, string>>();
81
+ const user = ref<Ace.User>();
82
+ const selectedFileClassificationLevel = ref(50);
83
+ const curAttachToken = ref<string>();
84
+ const uploadInitParams = ref<UploadInitParams>();
85
+ const isNewForm = ref(false);
86
+ const uploadingProgress = ref(100);
87
+ const pdfViewerVisible = ref(false);
88
+ const pdfSrc = ref("");
89
+ 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']);
92
+ let uppy: Uppy | undefined;
93
+ curAttachToken.value = props.attachToken;
94
+
95
+ 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
+ }
106
+ });
107
+
108
+ onUnmounted(() => {
109
+ if (uppy) uppy.destroy();
110
+ uppy = undefined;
111
+ });
112
+
113
+ async function loadFileInfos() {
114
+ if (!curAttachToken.value) {
115
+ files.value = [];
116
+ }
117
+ files.value = await api.getFileList(curAttachToken.value!);
118
+ }
119
+
120
+ 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()
156
+ }
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";
169
+ }
170
+ }),
171
+ mirror: false
172
+ });
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";
186
+ }
187
+ } else {
188
+ if (cfg.disableDirUpload) {
189
+ selectionType = "files";
190
+ } else {
191
+ selectionType = "both";
192
+ }
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);
204
+ }
205
+
206
+ 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
+ });
223
+ }
224
+ dashboard?.openModal();
225
+ } else {
226
+ ElMessageBox.alert("无法找到附件配置" + props.configKey, "错误");
227
+ }
228
+ }
229
+
230
+ 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
+ });
248
+ }
249
+ dashboard?.openModal();
250
+ }
251
+ }
252
+
253
+ 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();
261
+ }
262
+
263
+ 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();
272
+ }
273
+
274
+ async function delUploadedFile(file: FileInfo) {
275
+ await api.deleteFile(file.token || file.id);
276
+ files.value = files.value.filter(f => f.id !== file.id);
277
+ }
278
+
279
+ function previewFile(fileToken:string) {
280
+ pdfSrc.value = new URL("uploads/preview/" + fileToken, location.origin).toString()
281
+ pdfViewerVisible.value = true;
282
+ }
283
+
284
+ function downloadFile(fileToken: string) {
285
+ api.downloadFile(fileToken);
286
+ }
287
+
288
+ function viewUppyDashboard() {
289
+ const dashboard = uppy?.getPlugin("Dashboard") as any;
290
+ if (dashboard) {
291
+ dashboard.openModal();
292
+ }
293
+ }
294
+
295
+ function downloadAll() {
296
+ if (!curAttachToken.value) {
297
+ return;
298
+ }
299
+ api.downloadZipFile(curAttachToken.value);
300
+ }
301
+
302
+ 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;
312
+ }
313
+ return !cfg.disallowUpload;
314
+ }
315
+ console.log('file cfg is null')
316
+ return false;
317
+ }
318
+
319
+ 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;
329
+ }
330
+ return !cfg.disallowDownload;
331
+ }
332
+ return false;
333
+ }
334
+
335
+ 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;
345
+ }
346
+ return !cfg.disallowDelete;
347
+ }
348
+ return false;
349
+ }
350
+
351
+ 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;
359
+ }
360
+ return true;
361
+ }
362
+ return false;
363
+ }
364
+
365
+ watch(() => props.attachToken, () => {
366
+ if (props.attachToken) {
367
+ initLoad();
368
+ } else {
369
+ initNew();
370
+ }
371
+ });
372
+
373
+
374
+ </script>
375
+
376
+ <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>
410
+ </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>
442
+ </template>
443
+
444
+ <style>
445
+ .uppy-Dashboard--modal {
446
+ z-index: 9999 !important;
447
+ }
448
+
449
+ .uppy-Root {
450
+ z-index: 9999;
451
+ }
452
+ </style>
453
+
454
+ <style lang="scss" scoped>
455
+
456
+ .ja-uploader {
457
+ width: 100%;
458
+ display: flex;
459
+ flex-direction: column;
460
+ gap: 4px;
461
+
462
+ &-tools {
463
+ display: flex;
464
+ }
465
+ }
466
+
467
+ .container {
468
+ padding: 0 0 0 8px;
469
+ cursor: pointer;
470
+ }
471
+
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
+ }
485
+
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
+ }
505
+
506
+ @keyframes shimmer {
507
+ 0% {
508
+ left: -100%;
509
+ }
510
+ 100% {
511
+ left: 150%; /* 移动到右侧外部 */
512
+ }
513
+ }
514
+
515
+ </style>
@@ -1,25 +0,0 @@
1
- <template>
2
- <div>
3
- <el-upload v-model:file-list="state.fileList" class="ace-upload" list-type="picture">
4
- <el-button type="primary">Click to upload</el-button>
5
- <template #tip>
6
- <div class="el-upload__tip">jpg/png files with a size less than 500kb</div>
7
- </template>
8
- </el-upload>
9
- </div>
10
- </template>
11
-
12
- <script lang="ts" setup name="AceUpload">
13
- import {reactive} from "vue";
14
- import type {Props} from "./type";
15
-
16
- // defineOptions({
17
- // name: 'ElUpload',
18
- // })
19
- const props = defineProps<Props>();
20
- const state = reactive({
21
- fileList: [],
22
- });
23
- </script>
24
-
25
- <style lang="scss" scoped></style>
@@ -1,3 +0,0 @@
1
- import type {UploadRequestOptions} from "element-plus";
2
-
3
- export interface Props extends UploadRequestOptions {}