|
@@ -2,11 +2,13 @@
|
|
|
<FlexCol>
|
|
<FlexCol>
|
|
|
<Toast ref="toast" />
|
|
<Toast ref="toast" />
|
|
|
<DialogRoot ref="dialog" />
|
|
<DialogRoot ref="dialog" />
|
|
|
|
|
+ <!-- #ifndef MP -->
|
|
|
<slot
|
|
<slot
|
|
|
name="uploader"
|
|
name="uploader"
|
|
|
:onClick="onUploadPress"
|
|
:onClick="onUploadPress"
|
|
|
:items="currentUpladList"
|
|
:items="currentUpladList"
|
|
|
>
|
|
>
|
|
|
|
|
+ <!-- #endif -->
|
|
|
<FlexView
|
|
<FlexView
|
|
|
v-if="showUpload"
|
|
v-if="showUpload"
|
|
|
:direction="props.listType === 'grid' ? 'row' : 'column'"
|
|
:direction="props.listType === 'grid' ? 'row' : 'column'"
|
|
@@ -17,6 +19,7 @@
|
|
|
v-for="(item, index) in currentUpladList"
|
|
v-for="(item, index) in currentUpladList"
|
|
|
:key="index"
|
|
:key="index"
|
|
|
>
|
|
>
|
|
|
|
|
+ <!-- #ifndef MP -->
|
|
|
<slot
|
|
<slot
|
|
|
name="uploadItem"
|
|
name="uploadItem"
|
|
|
:index="index"
|
|
:index="index"
|
|
@@ -30,11 +33,11 @@
|
|
|
:itemSize="itemSize"
|
|
:itemSize="itemSize"
|
|
|
:showDelete="showDelete"
|
|
:showDelete="showDelete"
|
|
|
:defaultSource="props.itemDefaultSource"
|
|
:defaultSource="props.itemDefaultSource"
|
|
|
-
|
|
|
|
|
>
|
|
>
|
|
|
|
|
+ <!-- #endif -->
|
|
|
<UploaderListItem
|
|
<UploaderListItem
|
|
|
:item="item"
|
|
:item="item"
|
|
|
- :showDelete="showDelete"
|
|
|
|
|
|
|
+ :showDelete="showDelete && !disabled && !readonly"
|
|
|
:isListStyle="props.listType === 'list'"
|
|
:isListStyle="props.listType === 'list'"
|
|
|
:style="itemStyle"
|
|
:style="itemStyle"
|
|
|
:imageStyle="itemImageStyle"
|
|
:imageStyle="itemImageStyle"
|
|
@@ -45,21 +48,29 @@
|
|
|
@click="() => onItemPress(item)"
|
|
@click="() => onItemPress(item)"
|
|
|
@delete="() => onItemDeletePress(item)"
|
|
@delete="() => onItemDeletePress(item)"
|
|
|
/>
|
|
/>
|
|
|
|
|
+ <!-- #ifndef MP -->
|
|
|
</slot>
|
|
</slot>
|
|
|
|
|
+ <!-- #endif -->
|
|
|
</template>
|
|
</template>
|
|
|
- <slot v-if="currentUpladList.length < maxUploadCount" name="addButton" :onUploadPress="onUploadPress" :itemSize="itemSize">
|
|
|
|
|
|
|
+ <slot v-if="currentUpladList.length < maxUploadCount && !disabled" name="addButton" :onUploadPress="onUploadPress" :itemSize="itemSize">
|
|
|
<UploaderListAddItem :itemSize="itemSize" :style="itemStyle" @click="onUploadPress" :isListStyle="props.listType === 'list'" />
|
|
<UploaderListAddItem :itemSize="itemSize" :style="itemStyle" @click="onUploadPress" :isListStyle="props.listType === 'list'" />
|
|
|
</slot>
|
|
</slot>
|
|
|
|
|
+ <slot v-if="readonly && currentUpladList.length === 0">
|
|
|
|
|
+ <Text color="text.second">暂无上传文件</Text>
|
|
|
|
|
+ </slot>
|
|
|
</FlexView>
|
|
</FlexView>
|
|
|
<slot v-else name="addButton" :onUploadPress="onUploadPress" :itemSize="itemSize">
|
|
<slot v-else name="addButton" :onUploadPress="onUploadPress" :itemSize="itemSize">
|
|
|
<UploaderListAddItem :itemSize="itemSize" :style="itemStyle" @click="onUploadPress" :isListStyle="props.listType === 'list'" />
|
|
<UploaderListAddItem :itemSize="itemSize" :style="itemStyle" @click="onUploadPress" :isListStyle="props.listType === 'list'" />
|
|
|
</slot>
|
|
</slot>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- #ifndef MP -->
|
|
|
</slot>
|
|
</slot>
|
|
|
|
|
+ <!-- #endif -->
|
|
|
</FlexCol>
|
|
</FlexCol>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
-import { ref } from 'vue';
|
|
|
|
|
|
|
+import { reactive, ref, watch } from 'vue';
|
|
|
import { propGetThemeVar, useTheme, type TextStyle, type ViewStyle } from '../theme/ThemeDefine';
|
|
import { propGetThemeVar, useTheme, type TextStyle, type ViewStyle } from '../theme/ThemeDefine';
|
|
|
import type { ToastInstance } from '../feedback/Toast.vue';
|
|
import type { ToastInstance } from '../feedback/Toast.vue';
|
|
|
import Toast from '../feedback/Toast.vue';
|
|
import Toast from '../feedback/Toast.vue';
|
|
@@ -69,7 +80,9 @@ import UploaderListItem from './UploaderListItem.vue';
|
|
|
import FlexView from '../layout/FlexView.vue';
|
|
import FlexView from '../layout/FlexView.vue';
|
|
|
import FlexCol from '../layout/FlexCol.vue';
|
|
import FlexCol from '../layout/FlexCol.vue';
|
|
|
import type { UploaderAction, UploaderItem } from './Uploader';
|
|
import type { UploaderAction, UploaderItem } from './Uploader';
|
|
|
-import { LogUtils } from '@imengyu/imengyu-utils';
|
|
|
|
|
|
|
+import { Debounce, LogUtils } from '@imengyu/imengyu-utils';
|
|
|
|
|
+import Text from '../basic/Text.vue';
|
|
|
|
|
+import { actionSheet } from '../dialog/CommonRoot';
|
|
|
|
|
|
|
|
const themeContext = useTheme();
|
|
const themeContext = useTheme();
|
|
|
const TAG = 'Uploader';
|
|
const TAG = 'Uploader';
|
|
@@ -91,6 +104,11 @@ export interface UploaderProps {
|
|
|
*/
|
|
*/
|
|
|
disabled?: boolean;
|
|
disabled?: boolean;
|
|
|
/**
|
|
/**
|
|
|
|
|
+ * 是否只读,只读状态下不会显示上传按钮,也不能删除已上传的文件。
|
|
|
|
|
+ * @default false
|
|
|
|
|
+ */
|
|
|
|
|
+ readonly?: boolean;
|
|
|
|
|
+ /**
|
|
|
* 是否显示文件已上传列表。
|
|
* 是否显示文件已上传列表。
|
|
|
* @default true
|
|
* @default true
|
|
|
*/
|
|
*/
|
|
@@ -159,12 +177,18 @@ export interface UploaderProps {
|
|
|
* * video:视频
|
|
* * video:视频
|
|
|
* @default 'image'
|
|
* @default 'image'
|
|
|
*/
|
|
*/
|
|
|
- chooseType?: 'image'|'video'|'file';
|
|
|
|
|
|
|
+ chooseType?: 'image'|'video'|'file'|'';
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 是否是从消息中选择文件
|
|
|
|
|
+ * @default true
|
|
|
|
|
+ */
|
|
|
|
|
+ formMessage?: boolean;
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 上传处理。不提供则无法上传
|
|
* 上传处理。不提供则无法上传
|
|
|
* @required true
|
|
* @required true
|
|
|
*/
|
|
*/
|
|
|
- upload: (item: UploaderAction) => void;
|
|
|
|
|
|
|
+ upload: (item: UploaderAction) => (() => void);
|
|
|
/**
|
|
/**
|
|
|
* 自定义选择文件组件,你可以调用自己的文件选择器。默认调用 ImagePicker 选择文件.
|
|
* 自定义选择文件组件,你可以调用自己的文件选择器。默认调用 ImagePicker 选择文件.
|
|
|
*/
|
|
*/
|
|
@@ -245,14 +269,6 @@ export interface UploaderInstance {
|
|
|
pick: () => void;
|
|
pick: () => void;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-const isImageExt = [
|
|
|
|
|
- '.png',
|
|
|
|
|
- '.jpg',
|
|
|
|
|
- '.jpeg',
|
|
|
|
|
- '.bmp',
|
|
|
|
|
- '.webp',
|
|
|
|
|
-];
|
|
|
|
|
-
|
|
|
|
|
const toast = ref<ToastInstance>();
|
|
const toast = ref<ToastInstance>();
|
|
|
const dialog = ref<DialogAlertRoot>();
|
|
const dialog = ref<DialogAlertRoot>();
|
|
|
|
|
|
|
@@ -264,13 +280,15 @@ const props = withDefaults(defineProps<UploaderProps>(), {
|
|
|
showDelete: true,
|
|
showDelete: true,
|
|
|
showUpload: true,
|
|
showUpload: true,
|
|
|
uploadWhenAdded: true,
|
|
uploadWhenAdded: true,
|
|
|
|
|
+ autoUpdateUploadList: true,
|
|
|
|
|
+ formMessage: true,
|
|
|
uploadQueueMode: 'all',
|
|
uploadQueueMode: 'all',
|
|
|
listType: 'grid',
|
|
listType: 'grid',
|
|
|
chooseType: 'image',
|
|
chooseType: 'image',
|
|
|
itemSize: () => propGetThemeVar('UploaderItemSize', { width: 750 / 4 - 15, height: 750 / 4 - 15 }),
|
|
itemSize: () => propGetThemeVar('UploaderItemSize', { width: 750 / 4 - 15, height: 750 / 4 - 15 }),
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
-const currentUpladList = ref<UploaderItem[]>(props.intitalItems || []);
|
|
|
|
|
|
|
+const currentUpladList = ref<UploaderItem[]>(props.intitalItems?.concat() || []);
|
|
|
|
|
|
|
|
//上传按钮点击
|
|
//上传按钮点击
|
|
|
function onUploadPress() {
|
|
function onUploadPress() {
|
|
@@ -293,11 +311,8 @@ function onUploadPress() {
|
|
|
}[]) {
|
|
}[]) {
|
|
|
resolve(res.map((item) => {
|
|
resolve(res.map((item) => {
|
|
|
let isImage = typeof (item as any).type === 'string' ? (item as any).type.startsWith('image/') : false;
|
|
let isImage = typeof (item as any).type === 'string' ? (item as any).type.startsWith('image/') : false;
|
|
|
- for (const ext of isImageExt) {
|
|
|
|
|
- if (item.path.endsWith(ext)) {
|
|
|
|
|
- isImage = true;
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (!isImage) {
|
|
|
|
|
+ isImage = isImagePath(item.path);
|
|
|
}
|
|
}
|
|
|
return {
|
|
return {
|
|
|
filePath: item.path,
|
|
filePath: item.path,
|
|
@@ -305,34 +320,80 @@ function onUploadPress() {
|
|
|
size: item.size,
|
|
size: item.size,
|
|
|
state: 'notstart',
|
|
state: 'notstart',
|
|
|
isImage,
|
|
isImage,
|
|
|
- } as UploaderItem
|
|
|
|
|
|
|
+ message: '',
|
|
|
|
|
+ progress: 0,
|
|
|
|
|
+ } as UploaderItem;
|
|
|
}))
|
|
}))
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- switch (props.chooseType) {
|
|
|
|
|
- case 'video':
|
|
|
|
|
- uni.chooseVideo().then((res) => handleFiles([
|
|
|
|
|
|
|
+ //#ifdef MP
|
|
|
|
|
+ if (props.formMessage) {
|
|
|
|
|
+ actionSheet({
|
|
|
|
|
+ title: '选择上传方式',
|
|
|
|
|
+ actions: [
|
|
|
{
|
|
{
|
|
|
- path: res.tempFilePath,
|
|
|
|
|
- size: res.size,
|
|
|
|
|
- }
|
|
|
|
|
- ])).catch(reject);
|
|
|
|
|
- break;
|
|
|
|
|
- case 'file':
|
|
|
|
|
- uni.chooseFile().then((res) => handleFiles(res.tempFiles as { path: string; size: number; }[])).catch(reject);
|
|
|
|
|
- break;
|
|
|
|
|
- default:
|
|
|
|
|
- case 'image':
|
|
|
|
|
- uni.chooseImage({
|
|
|
|
|
- count: props.maxUploadCount - currentUpladList.value.length,
|
|
|
|
|
- }).then((res) => handleFiles(res.tempFiles as { path: string; size: number; }[])).catch(reject);
|
|
|
|
|
- break;
|
|
|
|
|
|
|
+ name: '从相册选择',
|
|
|
|
|
+ subname: '从相机立即拍摄或者相册中选择照片/视频',
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: '从微信聊天中选择',
|
|
|
|
|
+ subname: '可在录音机或者WPS文档分享给文件传输助手\n然后选择任意文档文件',
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ onSelect(index, name) {
|
|
|
|
|
+ },
|
|
|
|
|
+ }).then((index) => {
|
|
|
|
|
+ if (index === 0) {
|
|
|
|
|
+ chooseLocal();
|
|
|
|
|
+ } else if (index === 1) {
|
|
|
|
|
+ uni.chooseMessageFile({
|
|
|
|
|
+ type: props.chooseType || 'all',
|
|
|
|
|
+ count: props.maxUploadCount - currentUpladList.value.length,
|
|
|
|
|
+ success: (res) => {
|
|
|
|
|
+ LogUtils.printLog(TAG, 'info', 'chooseMessageFile', res);
|
|
|
|
|
+ handleFiles(res.tempFiles as { path: string; size: number; }[])
|
|
|
|
|
+ },
|
|
|
|
|
+ fail: (e) => {
|
|
|
|
|
+ LogUtils.printLog(TAG, 'error', 'chooseMessageFile', e);
|
|
|
|
|
+ reject(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ } else {
|
|
|
|
|
+ chooseLocal();
|
|
|
|
|
+ }
|
|
|
|
|
+ //#endif
|
|
|
|
|
+ //#ifndef MP
|
|
|
|
|
+ chooseLocal();
|
|
|
|
|
+ //#endif
|
|
|
|
|
+
|
|
|
|
|
+ function chooseLocal() {
|
|
|
|
|
+ switch (props.chooseType) {
|
|
|
|
|
+ case 'video':
|
|
|
|
|
+ uni.chooseVideo().then((res) => handleFiles([
|
|
|
|
|
+ {
|
|
|
|
|
+ path: res.tempFilePath,
|
|
|
|
|
+ size: res.size,
|
|
|
|
|
+ }
|
|
|
|
|
+ ])).catch(reject);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'file':
|
|
|
|
|
+ uni.chooseFile().then((res) => handleFiles(res.tempFiles as { path: string; size: number; }[])).catch(reject);
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ case 'image':
|
|
|
|
|
+ uni.chooseImage({
|
|
|
|
|
+ count: props.maxUploadCount - currentUpladList.value.length,
|
|
|
|
|
+ }).then((res) => handleFiles(res.tempFiles as { path: string; size: number; }[])).catch(reject);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
items
|
|
items
|
|
|
- .then((res) => {
|
|
|
|
|
- if (props.maxFileSize > 0)
|
|
|
|
|
|
|
+ .then((res) => {
|
|
|
|
|
+ if (props.maxFileSize > 0) {
|
|
|
res = res.filter((item) => {
|
|
res = res.filter((item) => {
|
|
|
if (item.size && item.size > props.maxFileSize) {
|
|
if (item.size && item.size > props.maxFileSize) {
|
|
|
props.onOverSize?.(item);
|
|
props.onOverSize?.(item);
|
|
@@ -340,16 +401,36 @@ function onUploadPress() {
|
|
|
}
|
|
}
|
|
|
return true;
|
|
return true;
|
|
|
});
|
|
});
|
|
|
|
|
+ if (res.length === 0) {
|
|
|
|
|
+ toast.value?.text('您选择的文件过大,请重新选择!');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ res = res.map((item) => {
|
|
|
|
|
+ item.state = 'notstart';
|
|
|
|
|
+ item.message = '';
|
|
|
|
|
+ item.progress = 0;
|
|
|
|
|
+ return reactive(item);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
//添加条目
|
|
//添加条目
|
|
|
currentUpladList.value = props.maxUploadCount > 1 ? currentUpladList.value.concat(res) : res;
|
|
currentUpladList.value = props.maxUploadCount > 1 ? currentUpladList.value.concat(res) : res;
|
|
|
//自动上传
|
|
//自动上传
|
|
|
if (props.uploadWhenAdded)
|
|
if (props.uploadWhenAdded)
|
|
|
- startUploadMulitItem(res);
|
|
|
|
|
|
|
+ startUploadMulitItem(currentUpladList.value);
|
|
|
})
|
|
})
|
|
|
.catch((e) => console.warn('PickImage failed', e));
|
|
.catch((e) => console.warn('PickImage failed', e));
|
|
|
}
|
|
}
|
|
|
//条目点击
|
|
//条目点击
|
|
|
function onItemPress(item: UploaderItem) {
|
|
function onItemPress(item: UploaderItem) {
|
|
|
|
|
+ if (props.readonly) {
|
|
|
|
|
+ props.onPreviewClick ?
|
|
|
|
|
+ props.onPreviewClick(item) :
|
|
|
|
|
+ onItemPreview(item); //默认预览
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (item.state === 'fail') {
|
|
if (item.state === 'fail') {
|
|
|
props.onRetryClick ?
|
|
props.onRetryClick ?
|
|
|
props.onRetryClick(item) :
|
|
props.onRetryClick(item) :
|
|
@@ -365,7 +446,7 @@ function onItemPress(item: UploaderItem) {
|
|
|
function onItemPreview(item: UploaderItem) {
|
|
function onItemPreview(item: UploaderItem) {
|
|
|
//判断后缀是不是图片
|
|
//判断后缀是不是图片
|
|
|
const previewPath = item.previewPath || item.uploadedPath || item.filePath;
|
|
const previewPath = item.previewPath || item.uploadedPath || item.filePath;
|
|
|
- if (item.isImage) {
|
|
|
|
|
|
|
+ if (item.isImage || isImagePath(previewPath)) {
|
|
|
uni.previewImage({
|
|
uni.previewImage({
|
|
|
urls: [
|
|
urls: [
|
|
|
previewPath
|
|
previewPath
|
|
@@ -379,6 +460,8 @@ function onItemPreview(item: UploaderItem) {
|
|
|
}
|
|
}
|
|
|
//条目删除点击
|
|
//条目删除点击
|
|
|
function onItemDeletePress(item: UploaderItem) {
|
|
function onItemDeletePress(item: UploaderItem) {
|
|
|
|
|
+ if (props.disabled || props.readonly)
|
|
|
|
|
+ return;
|
|
|
props.onDeleteClick ?
|
|
props.onDeleteClick ?
|
|
|
props.onDeleteClick(item).then(() => {
|
|
props.onDeleteClick(item).then(() => {
|
|
|
deleteListItem(item);
|
|
deleteListItem(item);
|
|
@@ -393,20 +476,28 @@ function onItemDeletePress(item: UploaderItem) {
|
|
|
}
|
|
}
|
|
|
//更新列表条目
|
|
//更新列表条目
|
|
|
function updateListItem(item: UploaderItem) {
|
|
function updateListItem(item: UploaderItem) {
|
|
|
- currentUpladList.value = ((prev) => {
|
|
|
|
|
- const newList = prev.concat();
|
|
|
|
|
- const index = prev.findIndex((k) => k.filePath === item.filePath);
|
|
|
|
|
- index >= 0 ? newList[index] = { ...item } : newList.push(item);
|
|
|
|
|
- return newList;
|
|
|
|
|
- })(currentUpladList.value);
|
|
|
|
|
emit('updateList', currentUpladList.value);
|
|
emit('updateList', currentUpladList.value);
|
|
|
}
|
|
}
|
|
|
//删除列表条目
|
|
//删除列表条目
|
|
|
function deleteListItem(item: UploaderItem) {
|
|
function deleteListItem(item: UploaderItem) {
|
|
|
currentUpladList.value = currentUpladList.value.filter((k) => k.filePath !== item.filePath);
|
|
currentUpladList.value = currentUpladList.value.filter((k) => k.filePath !== item.filePath);
|
|
|
|
|
+
|
|
|
|
|
+ //如果正在上传,先取消上传
|
|
|
|
|
+ if (item.state === 'uploading') {
|
|
|
|
|
+ item.cancelUpload?.();
|
|
|
|
|
+ item.state = 'fail';
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function isImagePath(path: string) {
|
|
|
|
|
+ return path.match(/\.(jpg|jpeg|png|gif|webp)$/) !== null;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
//开始上传条目
|
|
//开始上传条目
|
|
|
function startUploadItem(item: UploaderItem) {
|
|
function startUploadItem(item: UploaderItem) {
|
|
|
|
|
+ if (item.state === 'uploading')
|
|
|
|
|
+ return;
|
|
|
return new Promise<void>((resolve, reject) => {
|
|
return new Promise<void>((resolve, reject) => {
|
|
|
if (item.state === 'success') {
|
|
if (item.state === 'success') {
|
|
|
resolve();
|
|
resolve();
|
|
@@ -414,7 +505,14 @@ function startUploadItem(item: UploaderItem) {
|
|
|
}
|
|
}
|
|
|
LogUtils.printLog(TAG, 'message', `调用上传文件 ${item.filePath}`);
|
|
LogUtils.printLog(TAG, 'message', `调用上传文件 ${item.filePath}`);
|
|
|
|
|
|
|
|
- props.upload({
|
|
|
|
|
|
|
+ const updateProgressDebounce = new Debounce<number>(400, (precent) => {
|
|
|
|
|
+ item.state = 'uploading';
|
|
|
|
|
+ item.message = precent ? `上传中 ${precent}%` : '上传中...';
|
|
|
|
|
+ item.progress = precent;
|
|
|
|
|
+ updateListItem(item);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ item.cancelUpload = props.upload({
|
|
|
item,
|
|
item,
|
|
|
onError(error) {
|
|
onError(error) {
|
|
|
item.state = 'fail';
|
|
item.state = 'fail';
|
|
@@ -424,6 +522,7 @@ function startUploadItem(item: UploaderItem) {
|
|
|
LogUtils.printLog(TAG, 'error', `上传文件 ${item.filePath} 失败,错误信息:${error}`);
|
|
LogUtils.printLog(TAG, 'error', `上传文件 ${item.filePath} 失败,错误信息:${error}`);
|
|
|
},
|
|
},
|
|
|
onFinish(result, message) {
|
|
onFinish(result, message) {
|
|
|
|
|
+ updateProgressDebounce.cancel();
|
|
|
item.state = 'success';
|
|
item.state = 'success';
|
|
|
item.message = message || '上传完成';
|
|
item.message = message || '上传完成';
|
|
|
item.progress = 100;
|
|
item.progress = 100;
|
|
@@ -435,10 +534,7 @@ function startUploadItem(item: UploaderItem) {
|
|
|
LogUtils.printLog(TAG, 'success', `上传文件 ${item.filePath} 成功,上传路径:${result.uploadedUrl}`);
|
|
LogUtils.printLog(TAG, 'success', `上传文件 ${item.filePath} 成功,上传路径:${result.uploadedUrl}`);
|
|
|
},
|
|
},
|
|
|
onProgress(precent) {
|
|
onProgress(precent) {
|
|
|
- item.state = 'uploading';
|
|
|
|
|
- item.message = precent ? `${precent}%` : '上传中...';
|
|
|
|
|
- item.progress = precent;
|
|
|
|
|
- updateListItem(item);
|
|
|
|
|
|
|
+ updateProgressDebounce.executeWithDelay(200, precent);
|
|
|
},
|
|
},
|
|
|
onStart(message) {
|
|
onStart(message) {
|
|
|
item.state = 'uploading';
|
|
item.state = 'uploading';
|
|
@@ -465,11 +561,21 @@ defineExpose<UploaderInstance>({
|
|
|
startUploadAll() {
|
|
startUploadAll() {
|
|
|
return startUploadMulitItem(currentUpladList.value);
|
|
return startUploadMulitItem(currentUpladList.value);
|
|
|
},
|
|
},
|
|
|
- startUpload(item) {
|
|
|
|
|
- return startUploadItem(item);
|
|
|
|
|
|
|
+ async startUpload(item) {
|
|
|
|
|
+ return await startUploadItem(item);
|
|
|
},
|
|
},
|
|
|
setList(list) {
|
|
setList(list) {
|
|
|
- currentUpladList.value = list;
|
|
|
|
|
|
|
+ const needRemoveItems = [] as string[];
|
|
|
|
|
+ for (const item of currentUpladList.value) {
|
|
|
|
|
+ if (list.findIndex(k => k.filePath === item.filePath) === -1)
|
|
|
|
|
+ needRemoveItems.push(item.filePath);
|
|
|
|
|
+ }
|
|
|
|
|
+ for (const filePath of needRemoveItems)
|
|
|
|
|
+ currentUpladList.value.splice(currentUpladList.value.findIndex(k => k.filePath === filePath), 1);
|
|
|
|
|
+ list.forEach(item => {
|
|
|
|
|
+ if (currentUpladList.value.findIndex(k => k.filePath === item.filePath) === -1)
|
|
|
|
|
+ currentUpladList.value.push(item);
|
|
|
|
|
+ });
|
|
|
},
|
|
},
|
|
|
getList() {
|
|
getList() {
|
|
|
return currentUpladList.value;
|
|
return currentUpladList.value;
|