uodate
parent
c81a8f51fd
commit
8044855bbd
|
@ -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();
|
||||
};
|
||||
|
||||
// 校验是否已上传
|
||||
|
|
|
@ -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="允许在魔创未来旗下其他产品在线使用"
|
||||
/>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue