uodate
parent
c81a8f51fd
commit
8044855bbd
|
@ -30,7 +30,12 @@
|
||||||
processing
|
processing
|
||||||
/>
|
/>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -77,7 +82,7 @@ const fileName = ref("");
|
||||||
const fileSize = ref(0);
|
const fileSize = ref(0);
|
||||||
const progress = ref(0);
|
const progress = ref(0);
|
||||||
const objectKey = ref("");
|
const objectKey = ref("");
|
||||||
const chunkSize = ref(3 * 1024 * 1024);
|
const chunkSize = ref(5 * 1024 * 1024);
|
||||||
const totalChunks = ref(0);
|
const totalChunks = ref(0);
|
||||||
const currentChunk = ref(1);
|
const currentChunk = ref(1);
|
||||||
const uploadId = ref("");
|
const uploadId = ref("");
|
||||||
|
@ -89,6 +94,13 @@ const requiredValid = ref(false);
|
||||||
const hashCode = ref("");
|
const hashCode = ref("");
|
||||||
const message = useMessage();
|
const message = useMessage();
|
||||||
const currentFileSize = ref(0)
|
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 = () => {
|
const triggerFileSelect = () => {
|
||||||
fileInputRef.value?.click();
|
fileInputRef.value?.click();
|
||||||
|
@ -162,6 +174,9 @@ const initParam = () => {
|
||||||
uploadId.value = "";
|
uploadId.value = "";
|
||||||
partArr.value = [];
|
partArr.value = [];
|
||||||
requiredValid.value = false;
|
requiredValid.value = false;
|
||||||
|
uploadStatus.value = 'idle';
|
||||||
|
uploadedChunks.value.clear();
|
||||||
|
retryCount.value = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
function getOssDefaultPath(name:any) {
|
function getOssDefaultPath(name:any) {
|
||||||
|
@ -200,6 +215,18 @@ const selectFile = async (event: Event) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// 如果存在未完成的上传,询问是否继续
|
||||||
|
if (uploadStatus.value === 'paused' && file.value) {
|
||||||
|
const shouldResume = window.confirm('检测到未完成的上传,是否继续上传?');
|
||||||
|
if (shouldResume) {
|
||||||
|
await resumeUpload();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// 用户选择重新上传,清除之前的上传状态
|
||||||
|
initParam();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 继续上传流程
|
// 继续上传流程
|
||||||
progress.value = 0;
|
progress.value = 0;
|
||||||
fileName.value = file.value.name;
|
fileName.value = file.value.name;
|
||||||
|
@ -244,8 +271,15 @@ const selectFile = async (event: Event) => {
|
||||||
// 检查文件是否已存在
|
// 检查文件是否已存在
|
||||||
// 上传文件前先校验是否存在 存在为0 不存在为1
|
// 上传文件前先校验是否存在 存在为0 不存在为1
|
||||||
try {
|
try {
|
||||||
const res = await request.get(
|
// const res = await request.get(
|
||||||
`/file/selectFile?type=${props.type}&name=${fileName.value}`
|
// `/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) {
|
if (res.data !== 1) {
|
||||||
message.warning("文件名已存在");
|
message.warning("文件名已存在");
|
||||||
|
@ -314,35 +348,76 @@ const selectFile = async (event: Event) => {
|
||||||
const uploadFile = async () => {
|
const uploadFile = async () => {
|
||||||
if (!file.value) return;
|
if (!file.value) return;
|
||||||
|
|
||||||
const index = currentChunk.value - 1;
|
while (currentChunk.value <= totalChunks.value) {
|
||||||
const start = index * chunkSize.value;
|
// 如果这个分片已经上传成功,跳过
|
||||||
const end = Math.min((index + 1) * chunkSize.value, file.value.size);
|
if (uploadedChunks.value.has(currentChunk.value)) {
|
||||||
|
currentChunk.value++;
|
||||||
const formData = new FormData();
|
continue;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
initParam();
|
const index = currentChunk.value - 1;
|
||||||
console.error("切片上传失败:", error);
|
const start = index * chunkSize.value;
|
||||||
message.warning("文件上传异常或上传已取消");
|
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 () => {
|
const cancelUploadInfo = async () => {
|
||||||
if (progress.value !== 100) {
|
if (uploadStatus.value !== 'completed') {
|
||||||
try {
|
try {
|
||||||
await request.post("/file/cancelUpload", {
|
await request.post("/file/cancelUpload", {
|
||||||
objectKey: objectKey.value,
|
objectKey: objectKey.value,
|
||||||
uploadId: uploadId.value,
|
uploadId: uploadId.value,
|
||||||
});
|
});
|
||||||
|
uploadStatus.value = 'idle';
|
||||||
|
uploadedChunks.value.clear();
|
||||||
|
progress.value = 0;
|
||||||
|
showFileName.value = false;
|
||||||
|
initParam();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
message.error("取消上传失败");
|
message.error("取消上传失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
progress.value = 0;
|
|
||||||
showFileName.value = false;
|
|
||||||
initParam();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 校验是否已上传
|
// 校验是否已上传
|
||||||
|
|
|
@ -367,7 +367,7 @@ function handledeleteFile(item:any){
|
||||||
v-model:checked="item.isOnlineUse"
|
v-model:checked="item.isOnlineUse"
|
||||||
:checked-value="1"
|
:checked-value="1"
|
||||||
:unchecked-value="0"
|
:unchecked-value="0"
|
||||||
disabled="true"
|
:disabled="true"
|
||||||
label="允许在魔创未来在线使用"
|
label="允许在魔创未来在线使用"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -383,7 +383,7 @@ function handledeleteFile(item:any){
|
||||||
<n-checkbox
|
<n-checkbox
|
||||||
v-model:checked="item.allowSoftwareUse"
|
v-model:checked="item.allowSoftwareUse"
|
||||||
:checked-value="1"
|
:checked-value="1"
|
||||||
disabled="true"
|
:disabled="true"
|
||||||
:unchecked-value="0"
|
:unchecked-value="0"
|
||||||
label="允许在魔创未来旗下其他产品在线使用"
|
label="允许在魔创未来旗下其他产品在线使用"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
import { Asterisk } from 'lucide-vue-next';
|
import { Asterisk, Trash } from 'lucide-vue-next';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -32,6 +32,8 @@ function preStep() {
|
||||||
}
|
}
|
||||||
const showSuccessModal = ref(false)
|
const showSuccessModal = ref(false)
|
||||||
|
|
||||||
|
|
||||||
|
//发布
|
||||||
async function handlePublish() {
|
async function handlePublish() {
|
||||||
for (let i = 0; i < localForm.value.modelVersionList.length; i++) {
|
for (let i = 0; i < localForm.value.modelVersionList.length; i++) {
|
||||||
if (localForm.value.modelVersionList[i].delFlag === '0' && localForm.value.modelVersionList[i].sampleImagePaths.length === 0) {
|
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 fileInput = ref<HTMLInputElement | null>(null)
|
||||||
const uploadFileIndex = ref(0)
|
const uploadFileIndex = ref(0)
|
||||||
|
|
||||||
|
|
||||||
|
//点击上传按钮
|
||||||
function triggerFileInput(index: number) {
|
function triggerFileInput(index: number) {
|
||||||
(fileInput.value as HTMLInputElement)?.click()
|
(fileInput.value as HTMLInputElement)?.click()
|
||||||
uploadFileIndex.value = index
|
uploadFileIndex.value = index
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//选择上传图片
|
||||||
async function handleFileChange(event: Event) {
|
async function handleFileChange(event: Event) {
|
||||||
const target = event.target as HTMLInputElement
|
const target = event.target as HTMLInputElement
|
||||||
const files = target.files
|
const files = target.files
|
||||||
|
@ -117,10 +123,16 @@ async function handleFileChange(event: Event) {
|
||||||
target.value = ''
|
target.value = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 发布成功后的确认按钮 跳转到个人中心
|
||||||
function onPositiveClick() {
|
function onPositiveClick() {
|
||||||
showSuccessModal.value = false
|
showSuccessModal.value = false
|
||||||
router.push('/personal-center')
|
router.push('/personal-center')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 删除图片
|
||||||
|
const deleteSampleImage = (index:number, data:any) =>{
|
||||||
|
data.splice(index, 1)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -166,8 +178,9 @@ function onPositiveClick() {
|
||||||
</n-spin>
|
</n-spin>
|
||||||
|
|
||||||
<div class="grid grid-cols-3 gap-2.5 mt-4 w-full">
|
<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="">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -526,9 +526,8 @@ const toWallet = () => {
|
||||||
const zfbStatus = ref('0')
|
const zfbStatus = ref('0')
|
||||||
async function getBindStatus(){
|
async function getBindStatus(){
|
||||||
const res = await request.get(`/ali/pay/queryBindStatus`)
|
const res = await request.get(`/ali/pay/queryBindStatus`)
|
||||||
if (res.data === '1') { //'1 绑定 0不绑定
|
if (res.code === 200) { //'1 绑定 0不绑定
|
||||||
zfbStatus.value = res.data
|
zfbStatus.value = res.data
|
||||||
message.success('绑定成功!')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getBindStatus()
|
getBindStatus()
|
||||||
|
@ -550,6 +549,8 @@ const showBinding = async() =>{
|
||||||
if (res2.data === '1') {
|
if (res2.data === '1') {
|
||||||
closeBindingModal()
|
closeBindingModal()
|
||||||
message.success('绑定成功!')
|
message.success('绑定成功!')
|
||||||
|
// window.location.reload()
|
||||||
|
getBindStatus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import CreateModels from "@/components/publishModel/CreateModels.vue";
|
import CreateModels from "@/components/publishModel/CreateModels.vue";
|
||||||
import EditVersion from "@/components/publishModel/EditVersion.vue";
|
import EditVersion from "@/components/publishModel/EditVersion.vue";
|
||||||
import UploadImg from "@/components/publishModel/UploadImg.vue";
|
import UploadImg from "@/components/publishModel/UploadImg.vue";
|
||||||
|
import { CirclePlus } from "lucide-vue-next";
|
||||||
import { NConfigProvider, NMessageProvider } from "naive-ui";
|
import { NConfigProvider, NMessageProvider } from "naive-ui";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
const message = useMessage();
|
const message = useMessage();
|
||||||
|
|
|
@ -83,8 +83,8 @@ export default defineNuxtConfig({
|
||||||
preset: 'node-server',
|
preset: 'node-server',
|
||||||
devProxy: {
|
devProxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
// target: 'http://1.13.246.108:8080', // 线上
|
target: 'http://113.45.190.154:8080', // 线上
|
||||||
target: 'http://192.168.2.10:8080', // 代
|
// target: 'http://192.168.2.10:8080', // 代
|
||||||
// target: 'http://192.168.2.5:8080', // 嗨
|
// target: 'http://192.168.2.5:8080', // 嗨
|
||||||
// target: 'https://2d1a399f.r27.cpolar.top', // 嗨
|
// target: 'https://2d1a399f.r27.cpolar.top', // 嗨
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
|
|
Loading…
Reference in New Issue