planet
shenhan000 2025-03-24 13:23:37 +08:00
parent c81a8f51fd
commit 8044855bbd
6 changed files with 136 additions and 44 deletions

View File

@ -30,7 +30,12 @@
processing
/>
</div>
<div v-if="requiredValid" class="item-valid"></div>
<!-- <div v-if="requiredValid" class="item-valid"></div> -->
<!-- <div class="resume-upload">
<n-button type="primary" @click="resumeUpload">
继续上传
</n-button>
</div> -->
</div>
</template>
@ -77,7 +82,7 @@ const fileName = ref("");
const fileSize = ref(0);
const progress = ref(0);
const objectKey = ref("");
const chunkSize = ref(3 * 1024 * 1024);
const chunkSize = ref(5 * 1024 * 1024);
const totalChunks = ref(0);
const currentChunk = ref(1);
const uploadId = ref("");
@ -89,6 +94,13 @@ const requiredValid = ref(false);
const hashCode = ref("");
const message = useMessage();
const currentFileSize = ref(0)
//
const uploadStatus = ref<'idle' | 'uploading' | 'paused' | 'completed'>('idle');
const uploadedChunks = ref<Set<number>>(new Set());
const retryCount = ref<number>(0);
const maxRetries = 5; //
//
const triggerFileSelect = () => {
fileInputRef.value?.click();
@ -162,6 +174,9 @@ const initParam = () => {
uploadId.value = "";
partArr.value = [];
requiredValid.value = false;
uploadStatus.value = 'idle';
uploadedChunks.value.clear();
retryCount.value = 0;
};
function getOssDefaultPath(name:any) {
@ -200,6 +215,18 @@ const selectFile = async (event: Event) => {
}
try {
//
if (uploadStatus.value === 'paused' && file.value) {
const shouldResume = window.confirm('检测到未完成的上传,是否继续上传?');
if (shouldResume) {
await resumeUpload();
return;
} else {
//
initParam();
}
}
//
progress.value = 0;
fileName.value = file.value.name;
@ -244,8 +271,15 @@ const selectFile = async (event: Event) => {
//
// 0 1
try {
const res = await request.get(
`/file/selectFile?type=${props.type}&name=${fileName.value}`
// const res = await request.get(
// `/file/selectFile?type=${props.type}&name=${fileName.value}`
// );
const res = await request.post(
`/file/selectFile`,
{
type:props.type,
name:fileName.value
}
);
if (res.data !== 1) {
message.warning("文件名已存在");
@ -314,35 +348,76 @@ const selectFile = async (event: Event) => {
const uploadFile = async () => {
if (!file.value) return;
const index = currentChunk.value - 1;
const start = index * chunkSize.value;
const end = Math.min((index + 1) * chunkSize.value, file.value.size);
const formData = new FormData();
formData.append("file", file.value.slice(start, end));
formData.append("chunk", String(currentChunk.value));
formData.append("objectKey", objectKey.value);
formData.append("uploadId", uploadId.value);
try {
const res = await request.post("/file/chunk", formData, {
headers: { "Content-Type": "multipart/form-data" },
});
partArr.value.push(res.data);
currentChunk.value++;
progress.value = Math.floor((currentChunk.value / totalChunks.value) * 100);
if (currentChunk.value <= totalChunks.value) {
uploadFile();
} else {
progress.value = 99;
complete();
while (currentChunk.value <= totalChunks.value) {
//
if (uploadedChunks.value.has(currentChunk.value)) {
currentChunk.value++;
continue;
}
} catch (error) {
initParam();
console.error("切片上传失败:", error);
message.warning("文件上传异常或上传已取消");
const index = currentChunk.value - 1;
const start = index * chunkSize.value;
const end = Math.min((index + 1) * chunkSize.value, file.value.size);
const formData = new FormData();
formData.append("file", file.value.slice(start, end));
formData.append("chunk", String(currentChunk.value));
formData.append("objectKey", objectKey.value);
formData.append("uploadId", uploadId.value);
try {
uploadStatus.value = 'uploading';
const res = await request.post("/file/chunk", formData, {
headers: { "Content-Type": "multipart/form-data" },
//
onUploadProgress: (progressEvent) => {
const percentCompleted = Math.round(
((currentChunk.value - 1) / totalChunks.value) * 100 +
(progressEvent.loaded / progressEvent.total!) * (100 / totalChunks.value)
);
progress.value = percentCompleted;
}
});
//
uploadedChunks.value.add(currentChunk.value);
partArr.value.push(res.data);
currentChunk.value++;
retryCount.value = 0; //
progress.value = Math.floor((currentChunk.value / totalChunks.value) * 100);
} catch (error) {
console.error("切片上传失败:", error);
//
if (retryCount.value < maxRetries) {
retryCount.value++;
message.warning(`${currentChunk.value} 个分片上传失败,正在进行第 ${retryCount.value} 次重试...`);
await new Promise(resolve => setTimeout(resolve, 1000)); // 1
continue; //
}
//
uploadStatus.value = 'paused';
message.error(`上传失败,已暂停。您可以稍后继续上传。`);
return;
}
}
//
if (currentChunk.value > totalChunks.value) {
progress.value = 99;
uploadStatus.value = 'completed';
await complete();
}
};
//
const resumeUpload = async () => {
if (uploadStatus.value === 'paused' && file.value) {
retryCount.value = 0; //
message.info('正在继续上传...');
await uploadFile();
}
};
@ -389,19 +464,21 @@ const emit = defineEmits<{
//
const cancelUploadInfo = async () => {
if (progress.value !== 100) {
if (uploadStatus.value !== 'completed') {
try {
await request.post("/file/cancelUpload", {
objectKey: objectKey.value,
uploadId: uploadId.value,
});
uploadStatus.value = 'idle';
uploadedChunks.value.clear();
progress.value = 0;
showFileName.value = false;
initParam();
} catch (error) {
message.error("取消上传失败");
}
}
progress.value = 0;
showFileName.value = false;
initParam();
};
//

View File

@ -367,7 +367,7 @@ function handledeleteFile(item:any){
v-model:checked="item.isOnlineUse"
:checked-value="1"
:unchecked-value="0"
disabled="true"
:disabled="true"
label="允许在魔创未来在线使用"
/>
</div>
@ -383,7 +383,7 @@ function handledeleteFile(item:any){
<n-checkbox
v-model:checked="item.allowSoftwareUse"
:checked-value="1"
disabled="true"
:disabled="true"
:unchecked-value="0"
label="允许在魔创未来旗下其他产品在线使用"
/>

View File

@ -1,6 +1,6 @@
<script setup lang="ts">
import { cloneDeep } from 'lodash-es';
import { Asterisk } from 'lucide-vue-next';
import { Asterisk, Trash } from 'lucide-vue-next';
import { useRoute, useRouter } from 'vue-router';
const props = defineProps({
@ -32,6 +32,8 @@ function preStep() {
}
const showSuccessModal = ref(false)
//
async function handlePublish() {
for (let i = 0; i < localForm.value.modelVersionList.length; i++) {
if (localForm.value.modelVersionList[i].delFlag === '0' && localForm.value.modelVersionList[i].sampleImagePaths.length === 0) {
@ -92,10 +94,14 @@ watch(
const fileInput = ref<HTMLInputElement | null>(null)
const uploadFileIndex = ref(0)
//
function triggerFileInput(index: number) {
(fileInput.value as HTMLInputElement)?.click()
uploadFileIndex.value = index
}
//
async function handleFileChange(event: Event) {
const target = event.target as HTMLInputElement
const files = target.files
@ -117,10 +123,16 @@ async function handleFileChange(event: Event) {
target.value = ''
}
//
function onPositiveClick() {
showSuccessModal.value = false
router.push('/personal-center')
}
//
const deleteSampleImage = (index:number, data:any) =>{
data.splice(index, 1)
}
</script>
<template>
@ -166,8 +178,9 @@ function onPositiveClick() {
</n-spin>
<div class="grid grid-cols-3 gap-2.5 mt-4 w-full">
<div v-for="(subItem, subIndex) in item.sampleImagePaths" :key="subIndex">
<div v-for="(subItem, subIndex) in item.sampleImagePaths" :key="subIndex" class="relative">
<img class="w-full h-[200px] object-cover rounded-lg" :src="subItem" alt="">
<Trash @click="deleteSampleImage(subIndex, item.sampleImagePaths)" :size="20" class="mt-1 absolute top-2 right-2 text-gray-400 cursor-pointer hover:text-gray-100" />
</div>
</div>
</div>

View File

@ -526,9 +526,8 @@ const toWallet = () => {
const zfbStatus = ref('0')
async function getBindStatus(){
const res = await request.get(`/ali/pay/queryBindStatus`)
if (res.data === '1') { //'1 0
if (res.code === 200) { //'1 0
zfbStatus.value = res.data
message.success('绑定成功!')
}
}
getBindStatus()
@ -550,6 +549,8 @@ const showBinding = async() =>{
if (res2.data === '1') {
closeBindingModal()
message.success('绑定成功!')
// window.location.reload()
getBindStatus()
}
}
catch (err) {

View File

@ -2,6 +2,7 @@
import CreateModels from "@/components/publishModel/CreateModels.vue";
import EditVersion from "@/components/publishModel/EditVersion.vue";
import UploadImg from "@/components/publishModel/UploadImg.vue";
import { CirclePlus } from "lucide-vue-next";
import { NConfigProvider, NMessageProvider } from "naive-ui";
import { useRoute } from "vue-router";
const message = useMessage();

View File

@ -83,8 +83,8 @@ export default defineNuxtConfig({
preset: 'node-server',
devProxy: {
'/api': {
// target: 'http://1.13.246.108:8080', // 线上
target: 'http://192.168.2.10:8080', // 代
target: 'http://113.45.190.154:8080', // 线上
// target: 'http://192.168.2.10:8080', // 代
// target: 'http://192.168.2.5:8080', // 嗨
// target: 'https://2d1a399f.r27.cpolar.top', // 嗨
changeOrigin: true,