@skyfox2000/webui 1.4.9 → 1.4.10
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.
- package/lib/assets/modules/{baseLayout-DIny49tw.js → baseLayout-DSVT_hCt.js} +3 -3
- package/lib/assets/modules/{file-upload-DHUBZlX4.js → file-upload-BefTs4CH.js} +1 -1
- package/lib/assets/modules/{index-CEffEFtI.js → index-C6BAsERS.js} +1 -1
- package/lib/assets/modules/{index-DyRjXb_O.js → index-Cwr2EDEI.js} +2 -2
- package/lib/assets/modules/{index-BIAdOoSj.js → index-DkMjvF98.js} +10 -10
- package/lib/assets/modules/{menuTabs-CCrFWIOl.js → menuTabs-D99nhxm_.js} +2 -2
- package/lib/assets/modules/{toolIcon-BGZR_aUI.js → toolIcon-DDp0EFRE.js} +1 -1
- package/lib/assets/modules/{uploadList-CMXuGRWT.js → upload-template-BK8iQQYz.js} +273 -263
- package/lib/assets/modules/uploadList-BfCPE5Gb.js +420 -0
- package/lib/es/AceEditor/index.js +3 -3
- package/lib/es/BasicLayout/index.js +2 -2
- package/lib/es/Error403/index.js +1 -1
- package/lib/es/Error404/index.js +1 -1
- package/lib/es/ExcelForm/index.js +16 -15
- package/lib/es/MenuLayout/index.js +2 -2
- package/lib/es/TemplateFile/index.js +61 -90
- package/lib/es/UploadForm/index.js +4 -4
- package/lib/index.d.ts +1 -0
- package/lib/utils/upload-template.d.ts +4 -0
- package/lib/webui.css +1 -1
- package/lib/webui.es.js +52 -50
- package/package.json +1 -1
- package/src/components/content/dialog/excelForm.vue +5 -0
- package/src/components/content/dialog/templateFile.vue +27 -79
- package/src/components/content/table/index.vue +1 -0
- package/src/components/form/upload/uploadList.vue +106 -38
- package/src/index.ts +2 -0
- package/src/utils/upload-template.ts +15 -0
- package/lib/assets/modules/uploadList-l4q5o65m.js +0 -400
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import { watch, ref, onMounted, PropType } from 'vue';
|
|
3
3
|
import { Button } from '../../common';
|
|
4
4
|
import { Modal, Space } from 'ant-design-vue';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { MinioFile, UploadFile, UploadStatus } from '@/index';
|
|
6
|
+
import { httpPost, IUrlInfo, ResStatus } from '@skyfox2000/fapi';
|
|
7
7
|
import UploadList from '../../form/upload/uploadList.vue';
|
|
8
|
-
import {
|
|
8
|
+
import { uploadTempOpener } from '../../../utils/upload-template';
|
|
9
9
|
|
|
10
10
|
const props = defineProps({
|
|
11
11
|
/**
|
|
@@ -33,10 +33,10 @@ const props = defineProps({
|
|
|
33
33
|
/**
|
|
34
34
|
* 弹窗控制器
|
|
35
35
|
*/
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
},
|
|
36
|
+
// open: {
|
|
37
|
+
// type: Boolean as PropType<boolean>,
|
|
38
|
+
// required: true,
|
|
39
|
+
// },
|
|
40
40
|
/**
|
|
41
41
|
* 文件列表地址
|
|
42
42
|
*/
|
|
@@ -81,59 +81,44 @@ const props = defineProps({
|
|
|
81
81
|
required: false,
|
|
82
82
|
},
|
|
83
83
|
});
|
|
84
|
+
|
|
85
|
+
const api = props.api ?? "FILE_API";
|
|
84
86
|
/**
|
|
85
87
|
* minio桶名称template
|
|
86
88
|
*
|
|
87
89
|
* 子目录templateType
|
|
88
90
|
*/
|
|
89
91
|
const fileListUrl = ref(props.fileListUrl || {
|
|
90
|
-
api:
|
|
92
|
+
api: api,
|
|
91
93
|
authorize: true,
|
|
92
94
|
url: '/api/TemplateFileSrv/list',
|
|
93
95
|
});
|
|
94
96
|
const uploadUrl = ref(props.uploadUrl || {
|
|
95
|
-
api:
|
|
97
|
+
api: api,
|
|
96
98
|
authorize: true,
|
|
97
99
|
url: '/api/TemplateFileSrv/upload',
|
|
98
100
|
});
|
|
99
101
|
const downloadUrl = ref(props.downloadUrl || {
|
|
100
|
-
api:
|
|
102
|
+
api: api,
|
|
101
103
|
authorize: true,
|
|
102
104
|
url: '/api/TemplateFileSrv/download',
|
|
103
105
|
});
|
|
104
106
|
const deleteUrl = ref(props.deleteUrl || {
|
|
105
|
-
api:
|
|
107
|
+
api: api,
|
|
106
108
|
authorize: true,
|
|
107
109
|
url: '/api/TemplateFileSrv/delete',
|
|
108
110
|
});
|
|
109
111
|
|
|
110
|
-
const uploadFormCtrl = props.uploadForm;
|
|
111
112
|
const open = ref<boolean>(false);
|
|
112
113
|
|
|
113
114
|
const fileList = ref<UploadFile[]>([]);
|
|
114
|
-
const emit = defineEmits<{
|
|
115
|
-
|
|
116
|
-
* 显示预处理
|
|
117
|
-
*/
|
|
118
|
-
'before:file-list': [EditorControl<AnyData>, UploadFile[]];
|
|
119
|
-
/**
|
|
120
|
-
* 上传前预处理
|
|
121
|
-
*/
|
|
122
|
-
'before:upload': [UploadFile[]];
|
|
123
|
-
/**
|
|
124
|
-
* 上传结束,处理上传后的文件
|
|
125
|
-
*/
|
|
126
|
-
'after:upload': [boolean, UploadFile[]];
|
|
127
|
-
/**
|
|
128
|
-
* 上传进度
|
|
129
|
-
*/
|
|
130
|
-
'on:progress': [UploadFile];
|
|
131
|
-
}>();
|
|
115
|
+
// const emit = defineEmits<{
|
|
116
|
+
// }>();
|
|
132
117
|
|
|
133
118
|
watch(
|
|
134
|
-
() =>
|
|
119
|
+
() => uploadTempOpener.value,
|
|
135
120
|
() => {
|
|
136
|
-
open.value =
|
|
121
|
+
open.value = uploadTempOpener.value;
|
|
137
122
|
},
|
|
138
123
|
);
|
|
139
124
|
|
|
@@ -142,14 +127,10 @@ watch(
|
|
|
142
127
|
* 加载现有模板文件列表
|
|
143
128
|
*/
|
|
144
129
|
const loadFileList = async () => {
|
|
145
|
-
const res
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
Query: {
|
|
150
|
-
PrefixPath: props.templateType,
|
|
151
|
-
}
|
|
152
|
-
},
|
|
130
|
+
const res = await httpPost<MinioFile[]>(fileListUrl.value, {
|
|
131
|
+
Query: {
|
|
132
|
+
PrefixPath: props.templateType,
|
|
133
|
+
}
|
|
153
134
|
});
|
|
154
135
|
if (res?.status === ResStatus.SUCCESS && res.data) {
|
|
155
136
|
const files = res.data as MinioFile[];
|
|
@@ -166,66 +147,33 @@ const loadFileList = async () => {
|
|
|
166
147
|
}
|
|
167
148
|
return uploadFile;
|
|
168
149
|
})
|
|
169
|
-
emit('before:file-list', uploadFormCtrl, list);
|
|
150
|
+
// emit('before:file-list', uploadFormCtrl, list);
|
|
170
151
|
fileList.value.push(...list);
|
|
171
152
|
}
|
|
172
153
|
};
|
|
173
154
|
|
|
174
|
-
const dialogSave = async () => {
|
|
175
|
-
emit('before:upload', fileList.value);
|
|
176
|
-
const uploader = new AsyncUploader(uploadUrl.value, 3);
|
|
177
|
-
await uploader.doUpload(
|
|
178
|
-
fileList.value,
|
|
179
|
-
uploadFormCtrl.isFormLoading,
|
|
180
|
-
true,
|
|
181
|
-
async (result, files) => {
|
|
182
|
-
emit('after:upload', result, files);
|
|
183
|
-
if (result) {
|
|
184
|
-
uploadFormCtrl.visible.value = false;
|
|
185
|
-
}
|
|
186
|
-
},
|
|
187
|
-
(file) => {
|
|
188
|
-
emit('on:progress', file);
|
|
189
|
-
},
|
|
190
|
-
);
|
|
191
|
-
};
|
|
192
|
-
|
|
193
155
|
onMounted(() => {
|
|
194
|
-
if (!fileListUrl.value.api) {
|
|
195
|
-
fileListUrl.value.api = uploadFormCtrl.page.api;
|
|
196
|
-
}
|
|
197
|
-
if (!uploadUrl.value.api) {
|
|
198
|
-
uploadUrl.value.api = uploadFormCtrl.page.api;
|
|
199
|
-
}
|
|
200
|
-
if (!downloadUrl.value.api) {
|
|
201
|
-
downloadUrl.value.api = uploadFormCtrl.page.api;
|
|
202
|
-
}
|
|
203
|
-
if (!deleteUrl.value.api) {
|
|
204
|
-
deleteUrl.value.api = uploadFormCtrl.page.api;
|
|
205
|
-
}
|
|
206
156
|
loadFileList();
|
|
207
157
|
|
|
208
|
-
open.value =
|
|
158
|
+
open.value = uploadTempOpener.value;
|
|
209
159
|
});
|
|
210
160
|
|
|
211
161
|
const dialogClose = () => {
|
|
212
|
-
|
|
162
|
+
open.value = false;
|
|
163
|
+
uploadTempOpener.value = false;
|
|
213
164
|
};
|
|
214
165
|
</script>
|
|
215
166
|
<template>
|
|
216
167
|
<Modal title="模板文件管理" v-model:open="open"
|
|
217
168
|
:wrapClassName="'modal mx-auto ' + ($attrs.width ? 'w-[' + $attrs.width + ']' : 'w-[500px]')"
|
|
218
169
|
@close="dialogClose">
|
|
219
|
-
|
|
170
|
+
<!-- 改为选择后自动上传 -->
|
|
171
|
+
<UploadList v-model:file-list="fileList" auto-upload :parent-path="props.templateType" :upload-url="uploadUrl"
|
|
220
172
|
:download-url="downloadUrl" :delete-url="deleteUrl" :max-count="maxCount" :file-ext="fileExt"
|
|
221
173
|
:show-delete="showDelete" />
|
|
222
174
|
<template #footer>
|
|
223
175
|
<Space>
|
|
224
176
|
<Button @click="dialogClose">关闭</Button>
|
|
225
|
-
<Button @click="dialogSave" type="primary" :loading="uploadFormCtrl.isFormSaving.value"
|
|
226
|
-
:disabled="fileList.length === 0">
|
|
227
|
-
上传保存
|
|
228
|
-
</Button>
|
|
229
177
|
</Space>
|
|
230
178
|
</template>
|
|
231
179
|
</Modal>
|
|
@@ -97,13 +97,20 @@ const props = withDefaults(defineProps<UploadListProps>(), {
|
|
|
97
97
|
const inputFactory = useInputFactory();
|
|
98
98
|
const { errInfo } = inputFactory;
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
|
|
101
|
+
// Upload 组件的文件列表更新
|
|
102
|
+
const displayList = ref<UploadFile[]>(props.fileList);
|
|
103
|
+
// Upload 组件的内部文件列表
|
|
104
|
+
const uploadList = ref<UploadFile[]>([]);
|
|
105
|
+
|
|
101
106
|
const fileUploader = ref();
|
|
102
107
|
const emit = defineEmits(['update:file-list']);
|
|
103
108
|
const confirmOpen = ref(false);
|
|
104
109
|
const acceptString = computed(() => (props.fileExt?.length ? props.fileExt.map((ext) => `.${ext}`).join(',') : ''));
|
|
105
110
|
|
|
106
|
-
|
|
111
|
+
// 统一的文件验证函数
|
|
112
|
+
const validateFile = (file: File): boolean => {
|
|
113
|
+
// 文件类型验证
|
|
107
114
|
if (props.fileExt && props.fileExt.length > 0) {
|
|
108
115
|
const extension = file.name.split('.').pop()?.toLowerCase() || '';
|
|
109
116
|
if (!props.fileExt.includes(extension)) {
|
|
@@ -112,57 +119,119 @@ const beforeUpload: UploadProps['beforeUpload'] = (file) => {
|
|
|
112
119
|
}
|
|
113
120
|
}
|
|
114
121
|
|
|
122
|
+
// 文件大小验证
|
|
115
123
|
if (file.size / 1024 / 1024 > props.maxFileSize) {
|
|
116
124
|
message.error(`文件大小超过 ${props.maxFileSize}MB 限制`);
|
|
117
125
|
return false;
|
|
118
126
|
}
|
|
119
127
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
128
|
+
return true;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// 检查是否达到最大数量限制
|
|
132
|
+
const isMaxCountReached = (): boolean => {
|
|
133
|
+
return props.maxCount > 1 && displayList.value.length >= props.maxCount;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// 准备文件信息
|
|
137
|
+
const prepareFileInfo = (file: any): UploadFile<any> => {
|
|
138
|
+
const fileInfo = file as UploadFile<any>;
|
|
139
|
+
if (!fileInfo.params) fileInfo.params = {};
|
|
140
|
+
fileInfo.params.FileKey = fileInfo.name;
|
|
141
|
+
if (props.parentPath) {
|
|
142
|
+
fileInfo.params.FileKey = path.join('/', props.parentPath, fileInfo.name);
|
|
123
143
|
}
|
|
144
|
+
fileInfo.status = UploadStatus.Pending;
|
|
145
|
+
return fileInfo;
|
|
146
|
+
};
|
|
124
147
|
|
|
125
|
-
|
|
126
|
-
|
|
148
|
+
// 简化的 beforeUpload - 只做基本验证,不处理业务逻辑
|
|
149
|
+
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
|
|
150
|
+
return validateFile(file) && props.autoUpload;
|
|
127
151
|
};
|
|
128
152
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
153
|
+
// 处理文件选择(核心逻辑)
|
|
154
|
+
const handleFileSelect = (newFiles: any[]) => {
|
|
155
|
+
if (newFiles.length === 0) return;
|
|
156
|
+
|
|
157
|
+
const tempFiles = [...displayList.value];
|
|
158
|
+
let hasError = false;
|
|
159
|
+
|
|
160
|
+
for (const file of newFiles) {
|
|
161
|
+
// 验证文件
|
|
162
|
+
if (!validateFile(file)) {
|
|
163
|
+
hasError = true;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const fileInfo = prepareFileInfo(file);
|
|
168
|
+
|
|
169
|
+
// 如果maxCount=1,直接替换
|
|
170
|
+
if (props.maxCount === 1) {
|
|
171
|
+
tempFiles.length = 0;
|
|
172
|
+
tempFiles.push(fileInfo);
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// 检查是否达到最大数量限制
|
|
177
|
+
if (isMaxCountReached()) {
|
|
178
|
+
message.error(`最多上传 ${props.maxCount} 个文件`);
|
|
179
|
+
hasError = true;
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// 检查是否为同名文件(严格判断)
|
|
184
|
+
const existingIndex = tempFiles.findIndex(f =>
|
|
185
|
+
(f.name === fileInfo.name)
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
if (existingIndex > -1) {
|
|
189
|
+
// 同名文件:替换
|
|
190
|
+
tempFiles[existingIndex] = fileInfo;
|
|
191
|
+
} else {
|
|
192
|
+
// 新文件:添加到列表
|
|
193
|
+
tempFiles.push(fileInfo);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// 更新显示列表
|
|
198
|
+
if (!hasError || tempFiles.length > 0) {
|
|
199
|
+
displayList.value = tempFiles;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// 清空 Upload 组件的内部列表
|
|
203
|
+
uploadList.value = [];
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
// Upload 组件的文件列表更新
|
|
207
|
+
const updateUploadList: UploadProps['onUpdate:fileList'] = (newFiles) => {
|
|
208
|
+
// 只更新 Upload 内部列表
|
|
209
|
+
uploadList.value = newFiles as unknown as UploadFile[];
|
|
210
|
+
|
|
211
|
+
// 处理新选择的文件
|
|
212
|
+
handleFileSelect(newFiles);
|
|
138
213
|
};
|
|
139
214
|
|
|
140
215
|
const uploadProps = computed<UploadProps>(() => ({
|
|
141
216
|
accept: acceptString.value,
|
|
142
|
-
multiple:
|
|
143
|
-
fileList:
|
|
144
|
-
'onUpdate:fileList':
|
|
217
|
+
multiple: props.maxCount !== 1,
|
|
218
|
+
fileList: uploadList.value as UploadProps['fileList'],
|
|
219
|
+
'onUpdate:fileList': updateUploadList,
|
|
145
220
|
beforeUpload: beforeUpload,
|
|
146
221
|
listType: 'text',
|
|
147
|
-
maxCount: props.maxCount,
|
|
148
222
|
showUploadList: false,
|
|
149
|
-
onChange: (info) => {
|
|
150
|
-
if (!props.autoUpload) {
|
|
151
|
-
fileList.value = info.fileList as unknown as UploadFile[];
|
|
152
|
-
}
|
|
153
|
-
},
|
|
154
223
|
}));
|
|
155
224
|
|
|
156
225
|
watch(
|
|
157
226
|
() => props.fileList,
|
|
158
227
|
(newVal) => {
|
|
159
|
-
|
|
228
|
+
displayList.value = newVal;
|
|
160
229
|
},
|
|
161
230
|
{ deep: true, immediate: true },
|
|
162
231
|
);
|
|
163
232
|
|
|
164
233
|
watch(
|
|
165
|
-
() =>
|
|
234
|
+
() => displayList.value,
|
|
166
235
|
(newVal) => {
|
|
167
236
|
emit('update:file-list', newVal);
|
|
168
237
|
},
|
|
@@ -173,7 +242,7 @@ watch(
|
|
|
173
242
|
() => props.parentPath,
|
|
174
243
|
(newVal) => {
|
|
175
244
|
if (newVal) {
|
|
176
|
-
|
|
245
|
+
displayList.value.forEach((file) => {
|
|
177
246
|
file.params.FileKey = path.join('/', newVal, file.fileName);
|
|
178
247
|
});
|
|
179
248
|
}
|
|
@@ -181,7 +250,7 @@ watch(
|
|
|
181
250
|
);
|
|
182
251
|
|
|
183
252
|
const downloadFile = (index: number) => {
|
|
184
|
-
const minioFile =
|
|
253
|
+
const minioFile = displayList.value[index].minioFile!;
|
|
185
254
|
const url: IUrlInfo = {
|
|
186
255
|
api: props.downloadUrl!.api,
|
|
187
256
|
authorize: props.downloadUrl!.authorize,
|
|
@@ -203,7 +272,7 @@ const onlineOrOffline = (file: UploadFile) => {
|
|
|
203
272
|
};
|
|
204
273
|
|
|
205
274
|
const previewFile = (index: number) => {
|
|
206
|
-
const minioFile =
|
|
275
|
+
const minioFile = displayList.value[index].minioFile!;
|
|
207
276
|
const url: IUrlInfo = {
|
|
208
277
|
api: props.previewUrl!.api,
|
|
209
278
|
authorize: props.previewUrl!.authorize,
|
|
@@ -219,8 +288,8 @@ const previewFile = (index: number) => {
|
|
|
219
288
|
};
|
|
220
289
|
|
|
221
290
|
const removeFile = (index: number) => {
|
|
222
|
-
const file =
|
|
223
|
-
if (props.deleteUrl) {
|
|
291
|
+
const file = displayList.value[index];
|
|
292
|
+
if (props.deleteUrl && file.minioFile && file.minioFile.Key) {
|
|
224
293
|
httpPost<ApiResponse>(props.deleteUrl, {
|
|
225
294
|
Query: {
|
|
226
295
|
FileKey: file.minioFile!.Key,
|
|
@@ -228,11 +297,11 @@ const removeFile = (index: number) => {
|
|
|
228
297
|
}).then((res) => {
|
|
229
298
|
if (res && res.status === ResStatus.SUCCESS) {
|
|
230
299
|
message.success('删除文件成功!');
|
|
231
|
-
|
|
300
|
+
displayList.value.splice(index, 1);
|
|
232
301
|
}
|
|
233
302
|
});
|
|
234
303
|
} else {
|
|
235
|
-
|
|
304
|
+
displayList.value.splice(index, 1);
|
|
236
305
|
}
|
|
237
306
|
confirmOpen.value = false;
|
|
238
307
|
};
|
|
@@ -301,11 +370,10 @@ const getStatus = (status?: UploadStatus) => {
|
|
|
301
370
|
<div class="flex-1 text-sm text-gray-500" :class="[errInfo?.errClass + '-text']">
|
|
302
371
|
{{ getPlaceholder() }}
|
|
303
372
|
</div>
|
|
304
|
-
<!-- <Button v-if="!autoUpload" @click="manualUpload" class="mr-3">开始上传</Button> -->
|
|
305
373
|
</div>
|
|
306
374
|
|
|
307
375
|
<div class="mt-4 px-3">
|
|
308
|
-
<div v-for="(file, index) in
|
|
376
|
+
<div v-for="(file, index) in displayList" :key="index" class="mb-2 pb-1">
|
|
309
377
|
<div class="flex items-center justify-between">
|
|
310
378
|
<div class="flex items-center">
|
|
311
379
|
<span class="text-gray-700 mr-2"
|
|
@@ -350,7 +418,7 @@ const getStatus = (status?: UploadStatus) => {
|
|
|
350
418
|
</div>
|
|
351
419
|
<div v-if="showDelete !== false"
|
|
352
420
|
class="flex items-center text-red-500 hover:text-red-700 cursor-pointer">
|
|
353
|
-
<Popconfirm
|
|
421
|
+
<Popconfirm :open="confirmOpen" cancelText="否" okText="是" title="确定删除该文件吗?"
|
|
354
422
|
:okButtonProps="{ size: 'small' }" :cancelButtonProps="{ size: 'small' }"
|
|
355
423
|
@confirm="removeFile(index)" @cancel="confirmOpen = false">
|
|
356
424
|
<Tooltip title="删除">
|
|
@@ -388,4 +456,4 @@ const getStatus = (status?: UploadStatus) => {
|
|
|
388
456
|
.error-text {
|
|
389
457
|
color: #ff4d4f !important;
|
|
390
458
|
}
|
|
391
|
-
</style>
|
|
459
|
+
</style>
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ButtonTool } from '@/typings/tools';
|
|
2
|
+
import { ref } from 'vue';
|
|
3
|
+
|
|
4
|
+
export const uploadTempOpener = ref<boolean>(false);
|
|
5
|
+
|
|
6
|
+
// 添加上传模板按钮
|
|
7
|
+
export const uploadTempBtn: ButtonTool = {
|
|
8
|
+
label: '模板管理',
|
|
9
|
+
key: 'uploadTemp',
|
|
10
|
+
type: 'primary',
|
|
11
|
+
icon: 'icon-download',
|
|
12
|
+
click: () => {
|
|
13
|
+
uploadTempOpener.value = true;
|
|
14
|
+
},
|
|
15
|
+
};
|