Files
schisandra-cloud-album-front/src/views/Phone/CommonPhoneUpload/CommonPhoneUpload.vue
2025-03-05 17:44:43 +08:00

200 lines
5.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="common-phone-upload">
<div class="upload-controller">
<AButton type="text" shape="circle" size="middle">
<template #icon>
<APopover placement="bottomRight" trigger="click">
<template #content>
<UploadSetting/>
</template>
<AAvatar size="small" shape="circle" :src="setting"/>
</APopover>
</template>
</AButton>
<ASelect size="middle" style="width: 150px" placeholder="选择相册"
:options="albumList"
v-model:value="upload.albumSelected"
:allow-clear="true"
:field-names="{label: 'name', value: 'id'}"
>
</ASelect>
</div>
<div class="upload-content">
<div class="upload">
<AUploadDragger
v-model:fileList="upload.fileList"
:beforeUpload="upload.beforeUpload"
:customRequest="customUploadRequest"
:directory="false"
:maxCount="10"
:multiple="true"
:disabled="upload.predicting"
:progress="upload.progress"
@remove="upload.removeFile"
@reject="upload.rejectFile"
:openFileDialogOnClick="true"
accept="image/*,video/*"
list-type="picture"
method="post"
name="file"
>
<p class="ant-upload-drag-icon">
<FileImageOutlined/>
</p>
<p v-show="!predicting" class="ant-upload-text">单击或拖动文件到此区域以上传</p>
<p v-show="!predicting" class="ant-upload-hint">
支持单次或批量上传严禁上传非法图片违者将受到法律惩戒
</p>
<p v-show="predicting" class="ant-upload-hint">
AI 正在识别图片请稍候...
</p>
<AProgress :stroke-color="{'0%': '#108ee9','100%': '#87d068',}" :percent="progressPercent"
:status="progressStatus"
:show-info="true" size="small" type="line" v-show="predicting" style="width: 80%"/>
</AUploadDragger>
</div>
<AEmpty :image="empty" v-if="fileList.length === 0">
<template #description>
<span style="color: #999999;font-size: 16px;font-weight: 500;line-height: 1.5;">
上传列表为空点击或直接拖动文件到此区域上传
</span>
</template>
</AEmpty>
</div>
</div>
</template>
<script setup lang="ts">
import setting from "@/assets/svgs/setting.svg";
import {albumListApi, uploadFile} from "@/api/phone";
import useStore from "@/store";
import empty from "@/assets/svgs/empty.svg";
import {useRequest} from "alova/client";
import imageCompression from "browser-image-compression";
import {generateThumbnail} from "@/utils/imageUtils/generateThumb.ts";
import UploadSetting from "@/components/ImageUpload/UploadSetting.vue";
const route = useRoute();
const fileList = ref([]);
const predicting = ref<boolean>(false);
const progressPercent = ref<number>(0);
const progressStatus = ref<string>('active');
const accessToken = computed(() => {
const token = route.query.token;
return Array.isArray(token) ? token[0] : token;
});
const userId = computed(() => {
const uid = route.query.user_id;
return Array.isArray(uid) ? uid[0] : uid;
});
const upload = useStore().upload;
const albumList = ref<any[]>([]);
/**
* 获取相册列表
*/
const {send: getAlbumList} = useRequest(albumListApi, {
immediate: false,
debounce: 500,
}).onSuccess((res: any) => {
if (res.data && res.data.code === 200) {
albumList.value = res.data.data.albums;
}
});
const {uploading, send: submitFile} = useRequest(uploadFile, {
immediate: false,
debounce: 500,
});
/**
* 自定义上传请求
* @param file
*/
async function customUploadRequest(file: any) {
const compressedFile = await imageCompression(file.file, upload.options);
// 生成缩略图
const {binaryData, width, height, size} = await generateThumbnail(compressedFile);
upload.predictResult.thumb_w = width;
upload.predictResult.thumb_h = height;
upload.predictResult.thumb_size = size;
const formData = new FormData();
formData.append("file", file.file);
if (binaryData) {
formData.append("thumbnail", binaryData);
}
formData.append("data", JSON.stringify({
provider: upload.storageSelected?.[0],
bucket: upload.storageSelected?.[1],
fileType: file.file.type,
albumId: upload.albumSelected ? upload.albumSelected : 0,
...upload.predictResult,
}));
watch(
() => uploading.value,
(upload) => {
if (upload && upload.loaded && upload.total) {
file.onProgress({percent: Number(Math.round((upload.loaded / upload.total) * 100).toFixed(2))}, file);
}
},
);
submitFile(formData, {
'Authorization': `Bearer ${accessToken.value}`,
'X-UID': userId.value,
}).then((response: any) => {
if (response && response.code === 200) {
file.onSuccess(response.data, file);
} else {
file.onError(response.data, file);
}
}).catch(file.onError);
}
onMounted(() => {
getAlbumList(0, true, {
'Authorization': `Bearer ${accessToken.value}`,
'X-UID': userId.value,
});
});
</script>
<style scoped lang="scss">
.common-phone-upload {
width: 90%;
height: 95vh;
padding: 15px;
margin: 0 auto;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
gap: 10px;
.upload-controller {
width: 100%;
height: 50px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
gap: 20px;
}
.upload-content {
width: 100%;
height: calc(95vh - 60px);
.upload {
width: 100%;
height: 30vh;
}
}
}
</style>