JS默认参数传递额外参数(多文件上传, uploading)

<!--
module name: 应用介绍
-->
<template>
<div
class="main-intro"
:style="{
padding: props.type === 'serviceType' ? '0' : '0 16px',
margin: props.type === 'serviceType' ? '0 0' : '0 auto',
}"
>
<div class="main-intro-form">
<a-form :model="formState" :label-col="labelCol" >
<a-form-item :label="props.appName" :rules="[{ required: true }]">
<a-textarea
v-model:value="formState.appIntro"
style="width: 100%"
:disabled="props.disabledType"
/>
</a-form-item>
<a-form-item label="功能介绍" name="funcIntros">
<div
v-for="(intro, index) in formState.funcIntros"
:key="index"
style="margin-top: 5px; display: flex"
>
<a-input
v-model:value="intro.name"
placeholder="输入功能名称"
style="width: 45%; border-radius: 5px"
autoclear
:disabled="props.disabledType"
>
</a-input>
<a-input
v-model:value="intro.desc"
style="width: 45%; margin-left: 20px; border-radius: 5px"
placeholder="功能描述"
autoclear
:disabled="props.disabledType"
>
</a-input>
<PlusOutlined
style="font-size: 20px; margin-left: 10px; color: #cccccc"
v-show="index === 0"
type="plus"
@click="addDomain"
/>
<MinusOutlined
v-show="index !== 0 && index >= state.initIntrosSize"
:disabled="index === 1"
style="font-size: 20px; margin-left: 10px; color: #cccccc"
@click="removeDomain(intro)"
/>
</div>
</a-form-item>
<a-form-item label="系统截图" name="osScreenshots">
<div class="snapshot-container">
<div class="img-box" v-for="(item, index) in formState.osFiles">
<div v-if="item.response === undefined">
<a-spin style="position: relative; top: 80px; left: 60px" />
</div>
<div v-if="item.response !== undefined">
<div>
<img
alt="系统截图"
class="img"
:src="item.response.data.address"
/>
<CloseCircleFilled
class="close-circle"
@click="delOsImg(index)"
/>
</div>
<a-input
placeholder="截图名称"
v-model:value="item.response.data.name"
style="
width: 150px;
border: 1px solid #e9e9e9;
margin-top: 15px;
"
:disabled="props.disabledType"
/>
</div>
</div>
<div class="upload-container">
<a-upload
v-model:file-list="formState.osFiles"
action="/empower/attachment/upload"
list-type="picture-card"
:show-upload-list="false"
:disabled="props.disabledType"
>
<plus-outlined />
<div class="ant-upload-text">图片上传</div>
</a-upload>
</div>
</div>
</a-form-item>
<a-form-item label="学习视频" name="learningVideos">
<div class="videos-container">
<div
v-for="(item, index) in formState.learningVideos"
class="video-box"
>
<div v-if="item.response === undefined">
<a-spin style="position: relative; top: 80px; left: 60px" />
</div>
<div
v-if="item.response !== undefined"
style="margin-right: 20px"
>
<video
:src="item.response.data.address"
controls
class="video"
/>
<CloseCircleFilled
class="close-circle"
@click="delVideo(index)"
/>
</div>
<a-input
v-model:value="item.response.data.name"
style="width: 285px"
v-if="item.response !== undefined"
placeholder="视频名称"
:disabled="props.disabledType"
/>
</div>
<div class="upload-video">
<a-upload
v-model:file-list="formState.learningVideos"
action="/empower/attachment/upload"
list-type="picture-card"
:show-upload-list="false"
:disabled="props.disabledType"
>
<div v-if="formState.learningVideos.length < 8">
<plus-outlined />
<div class="ant-upload-text">视频上传</div>
</div>
</a-upload>
</div>
</div>
</a-form-item>
<a-form-item label="学习文档">
<a-upload
v-model:file-list="formState.learningFiles"
name="file"
:multiple="true"
action="/empower/attachment/upload"
@change="learningFilesChange"
:disabled="props.disabledType"
style="width: 350px"
>
<a-button
style="background-color: #eaf2ff; border: none"
:loading="fileLoading"
>
<upload-outlined />
<span style="color: #2c79ff">上传</span>
</a-button>
</a-upload>
</a-form-item>
</a-form>
</div>
</div>
</template>
<script setup>
import {
defineComponent,
ref,
reactive,
watch,
watchEffect,
defineExpose,
defineEmits,
toRaw,
onBeforeUnmount,
onMounted,
} from "vue";
import { useRoute, useRouter } from "vue-router";
import { message } from "ant-design-vue";
import { nanoid } from "nanoid";
import mitt from "@/utils/mitt";
import {
MinusOutlined,
PlusOutlined,
UploadOutlined,
CloseCircleFilled,
} from "@ant-design/icons-vue";
const router = useRouter();
const route = useRoute();
const labelCol = { style: { width: "75px" } };
const state = reactive({
fileLoading: false,
initIntrosSize: 1,
});
const previewVisible = ref(false);
const previewImage = ref("");
const props = defineProps(["type", "disabledType", "appName"]);
const formState = reactive({
appIntro: "", // 应用简介
funcIntros: [
{
name: "",
desc: "",
},
], // 功能介绍
osFiles: [], // 系统截图文件对象
osScreenshots: [], // 系统截图
learningVideos: [], // 学习视频
learningFiles: [], // 学习文档
fileList: [],
});
// ======================= 功能介绍 start ====================
const removeDomain = (intro) => {
let index = formState.funcIntros.indexOf(intro);
if (index !== -1) {
formState.funcIntros.splice(index, 1);
}
};
const addDomain = () => {
formState.funcIntros.push({
name: "", // 功能名称
desc: "", // 功能描述
});
};
// ======================= 功能介绍 end ====================
// ====================== 系统截图 start ===================
const handleCancel = () => {
previewVisible.value = false;
};
const handlePreview = async (file) => {
console.log("file 预览", file);
if (!file.url && !file.preview) {
file.preview = await getBase64(file.originFileObj);
}
previewImage.value = file.url || file.preview;
previewVisible.value = true;
};
const handleChange = ({ fileList: newFileList }) => {
fileList.value = newFileList;
};
const getBase64 = (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
});
};
// ====================== 系统截图 end ===================
const osFileChange = (e) => {
console.log("e:::: ", e);
let fileList = [...e.fileList];
let formFiles = fileList.map((file) => {
let resArr = [];
if (file.response !== undefined) {
resArr.push({
snapshotName: "",
...file,
address: file.response.data.address,
id: file.response.data.id,
});
}
return resArr;
});
if (formFiles.length > 0) {
formState.osScreenshots = formFiles.map((formFile) => {
return formFile;
});
}
};
const delOsImg = (index) => {
formState.osFiles.splice(index, 1);
};
// ====================== 学习视频 start ===================
const delVideo = (index) => {
formState.learningVideos.splice(index, 1);
};
// TODO videosChange
const videosChange = (e) => {
let fileList = [...e.fileList];
let formFiles = fileList.map((file) => {
let resArr = [];
if (file.response !== undefined) {
resArr.push({
name: "",
...file,
address: file.response.data.address,
id: file.response.data.id,
});
}
return resArr;
});
if (formFiles.length > 0) {
formState.osScreenshots = formFiles.map((formFile) => {
return formFile;
});
}
};
// ====================== 学习视频 end ===================
// ====================== 学习文档 start ===================
const learningFilesChange = (e) => {
let fileList = [...e.fileList];
console.log("fileList::: ", fileList);
//read from response and show file link
fileList = fileList.map((file) => {
if (file.response) {
// Component will show file.url as link
file.url = file.response.address;
}
return file;
});
formState.fileList = fileList;
};
const delFiles = (index) => {
formState.learningFiles.splice(index, 1);
};
// ====================== 学习文档 end ===================
defineExpose({
formState,
});
</script>
<style lang="scss" scoped>
.ant-upload-select-picture-card i {
font-size: 32px;
color: #999;
}
.ant-upload-select-picture-card .ant-upload-text {
margin-top: 8px;
color: #666;
}
.main-intro {
padding: 0 16px;
width: 600px;
text-align: left;
margin: 0 auto;
&-form {
border-radius: 8px;
padding: 0 24px;
background-color: #fff;
.snapshot-container {
display: flex;
flex-wrap: wrap;
.img-box {
width: 150px;
margin-right: 15px;
position: relative;
.img {
width: 100%;
height: 150px;
&:hover {
border: 4px solid #4688f1;
}
}
&:hover .close-circle {
display: inline-block;
}
.close-circle {
font-size: 20px;
color: #4688f1;
position: absolute;
right: -13px;
top: -10px;
cursor: pointer;
display: none;
}
}
}
.videos-container {
display: flex;
flex-wrap: wrap;
.video-box {
position: relative;
width: 305px;
margin-right: 8px;
.video {
width: 100%;
height: 170px;
border-radius: 5px;
&:hover {
border: 4px solid #4688f1;
}
}
&:hover .close-circle {
display: inline-block;
}
.close-circle {
font-size: 20px;
color: #4688f1;
position: absolute;
right: 6px;
top: -7px;
cursor: pointer;
display: none;
}
}
}
.upload-video {
height: 222px;
}
:deep(.ant-upload.ant-upload-select-picture-card) {
width: 150px;
height: 171px;
border: 1px solid #d0d4da;
background-color: #fff;
}
:deep(.anticon-plus) {
color: #d7d7d7;
font-size: 30px;
font-weight: 900;
}
:deep(.ant-btn .anticon) {
color: #2c79ff;
}
:deep(.ant-upload-list) {
width: 40% !important;
}
}
}
:deep(.ant-upload-list-item) {
width: 450px;
}
</style>
posted @   Felix_Openmind  阅读(147)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
*{cursor: url(https://files-cdn.cnblogs.com/files/morango/fish-cursor.ico),auto;}
点击右上角即可分享
微信分享提示