Vue3实战Easy云盘(三):文件删除+文件移动+目录导航+上传优化/文件过滤/搜索

一、文件删除

(1)选中了之后才可以删除,没有选中时就显示暗调删除按钮
(2)实现选中高亮功能
(3)单个删除
(4)批量删除

Main.vue中 

                <!-- 按钮3 --><!-- 如果selectFileIdList数组的长度为0(即数组为空),则HTML元素的disabled属性将被设置为true,从而使该元素变为禁用状态 --><el-button type="danger" @click="delFileBatch" :disabled="selectFileIdList.length == 0"><span class="iconfont icon-del"></span>批量删除</el-button>.....<span class="iconfont icon-del" @click="delFile(row)">删除
</span>......
// 定义多选文件夹列表
const selectFileIdList = ref([]);
// 多选
const rowSelected = (rows) => {// 重置为一个空数组,清空数据selectFileIdList.value = [];// 遍历 rows 数组中的每一个元素rows.forEach((item) => {// 经遍历到的fileId添加到selectFileIdList中selectFileIdList.value.push(item.fileId);});
};
// 删除单个文件
const delFile = (row) => {// 调用Confirmproxy.Confirm(`你确定要删除【$row.fileName】吗?删除的文件可在 10 天内通过回收站还原`,async () => {let result = await proxy.Request({url: api.delFile,params: {fileIds: row.fileId,},});if (!result) {return;}// 重新获取数据loadDataList();});
};
// 批量删除文件
const delFileBatch = () => {// 如果要删除的长度为0就不执行if (selectFileIdList.value.length == 0) {return;}// 调用Confirmproxy.Confirm(// 第一个参数是一个字符串,用于显示给用户的确认消息`你确定要删除这些文件吗?删除的文件可在 10 天内通过回收站还原`,// 第二个参数,当用户点击确认按钮后,这个异步函数会被执行async () => {// 使用await关键字调用proxy.Request方法,发送一个HTTP请求到服务器// 接收proxy.Request方法的响应并将其存储在result变量中let result = await proxy.Request({// 请求的URL来自api.delFile,这可能是一个常量或配置对象中的属性,指向删除文件的API端点。url: api.delFile,// join将这个数组转换为一个由逗号分隔的字符串(因为批量删除多个ids所以要分开),作为查询参数发送的文件ID列表params: {fileIds: selectFileIdList.value.join(","),},});// 处理响应,if (!result) {return;}// 重新获取数据loadDataList();});
};

 二、文件移动

(1)定义全局组件,FolderSelect.vue

(因为文件移动到哪个文件夹,文件保存到哪个文件夹都要用到,所以封装一个全局组件)

别忘记在Main.js中引入

src/components/FolderSelect.vue(不全面,未添加导航)

<!-- 移动/保存到哪个文件夹组件 -->
<template><div><!-- 弹出的对话框组件Dialog --><Dialog:show="dialogConfig.show":title="dialogConfig.title":buttons="dialogConfig.buttons"width="600px":showCancel="true"@close="dialogConfig.show = false"><!-- 目录导航 --><div class="navigation-panel"></div><!-- 文件夹列表 --><div class="folder-list" v-if="folderList.length > 0"><!-- 每一项文件夹 --><divclass="folder-item"v-for="item in folderList"@click="selectFolder(item)"><!-- 文件类型为0时即文件夹就显示文件夹的图标 --><Icon :fileType="0"></Icon><!-- 每个文件夹的名字 --><span class="file-name">{{ item.fileName }}</span></div></div><!-- 判断 --><div v-else class="tips">移动到 <span>{{ currentFolder.fileName }}</span> 文件夹</div></Dialog></div>
</template><script setup>
import { ref, reactive, getCurrentInstance } from "vue";
import { useRouter, useRoute } from "vue-router";const { proxy } = getCurrentInstance();
const router = useRouter();
const route = useRoute();const api = {loadAllFolder: "/file/loadAllFolder",
};// 定义弹出框的属性
const dialogConfig = ref({show: false,// 对话框的标题title: "移动到",buttons: [{type: "primary",text: "移动到此",// 按钮上的文字// 当按钮被点击时触发的回调函数。在这个例子中,点击按钮会调用 folderSelect() 函数。click: (e) => {folderSelect();},},],
});// 目录列表
const folderList = ref([]);
// 父级ID
const filePid = ref("0");
// 当前目录ID
const currentFileIds = ref([]);
// 当前文件夹
const currentFolder = ref({});// 获取所有的目录文件夹列表
const loadAllFolder = async () => {// API请求// 使用 await 等待 proxy.Request 方法的执行结果存储到result里let result = await proxy.Request({// 指定请求的urlurl: api.loadAllFolder,// 传递父id和当前文件夹idparams: {filePid: filePid.value,currentFileIds: currentFileIds.value,},});// 判断结果if (!result) {return;}folderList.value = result.data;
};// 展示弹出框对外的方法
const showFolderDialog = (currentFolder) => {dialogConfig.value.show = true;// 更新当前文件id数组currentFileIds.value = currentFolder;// 在加载一次获取到的目录文件夹列表loadAllFolder();
};// 关闭弹出框
const close = () => {dialogConfig.value.show = false;
};
// 向外暴露这两个函数,使得父组件Main可以调用这两个函数
defineExpose({ showFolderDialog, close });// 选择目录(目录导航)
const selectFolder = (data) => {navigationRef.value.openFolder(data);
};// 确定选择要移动到的目录
// 将选定的文件目录参数传递给父组件 Main 中的 folderSelect 函数
const emit = defineEmits(["folderSelect"]);
// 此方法回调在父组件中
const folderSelect = () => {emit("folderSelect", filePid.value);
};</script><style lang="scss" scoped>
.navigation-panel {padding-left: 10px;background: #f1f1f1;
}.folder-list {.folder-item {cursor: pointer;display: flex;align-items: center;padding: 10px;.file-name {display: inline-block;margin-left: 10px;}&:hover {background: #f8f8f8;}}max-height: calc(100vh - 200px);min-height: 200px;
}.tips {text-align: center;line-height: 200px;span {color: #06a7ff;}
}</style>

(2)Main.vue中调用

(不全面,未添加导航栏)

<!-- 引入组件 --><FolderSelectref="folderSelectRef"@folderSelect="moveFolderDone"></FolderSelect>
// 移动目录
const folderSelectRef = ref();
// 当前要移动的文件(单个文件)
const currentMoveFile = ref({});
// 移动单个文件
const moveFolder = (data) => {// 存储当前要移动的单个文件的信息currentMoveFile.value = data;// 把当前文件id给showFolderDialog方法folderSelectRef.value.showFolderDialog(currentFolder.value.fileId);
};
// 移动批量文件
const moveFolderBatch = () => {// 清空当前要移动的文件数据currentMoveFile.value = {};// 把当前的文件夹id给showFolderDialogfolderSelectRef.value.showFolderDialog(currentFolder.value.fileId);
};// 点击按钮之后,移动文件操作
const moveFolderDone = async (folderId) => {// 如果要移动到当前目录,提醒无需移动if (// 如果当前移动的文件父级id等于此时要移动到的文件夹id或者当前文件夹的id等于要移动到的文件夹idcurrentMoveFile.value.filePid == folderId ||currentFolder.value.fileId == folderId) {// 就提示无需移动proxy.Message.warning("文件正在当前目录,无需移动");return;}// 定义一个数组存放要移动的文件或者文件夹信息let fileIdsArray = [];// 如果是单个文件移动if (currentMoveFile.value.fileId) {// 就把当前移动的文件id传给这个数组fileIdsArray.push(currentMoveFile.value.fileId);} else {// 如果是多个文件移动// concat 连接多个数组// selectFileIdList 是指批量选择时选择的文件IDfiledIdsArray = filedIdsArray.concat(selectFileIdList.value);}// 发请求并将结果存储let result = await proxy.Request({// 请求的urlurl: api.changeFileFolder,// 携带的参数params: {// 将 fileIdsArray 数组中的所有元素转换为一个由逗号分隔的字符串,赋值给fileIdsfileIds: fileIdsArray.join(","),// 把folderId传到父文件id里面filePid: folderId,},});if (!result) {return;}// 调用子组件暴露的close方法,实现当前弹出框页面的关闭folderSelectRef.value.close();// 更新当前文件列表loadDataList();
};

三、目录导航(难点)

(1)导航栏组件(全局)

src/components/Navigation.vue
template结构

js
1.设置点击目录事件 openFolder:
2.暴露此事件供父组件使用:defineExpose({ openFolder });
3.设置当前路径 setpath:当点击后目录改变,路径也随之改变
4.获取当前路径的目录 getNavigationFolder
5.doCallback
6.监听路由
7.初始化设置init
8.setCurrentFolder 设置当前目录,点击导航跳转到所点击的目录
9.返回上一级 backParent

src/components/Navigation.vue

<template><!-- 导航 --><div class="top-navigation"><!-- 返回上一级 --><template v-if="folderList.length > 0"><span class="back link" @click="backParent">返回上一级</span><!-- 竖线 --><el-divider direction="vertical" /></template><!-- 全部文件:外面粗体的不能点 --><span v-if="folderList.length == 0" class="all-file">全部文件</span><!-- 全部文件:能点的 --><spanclass="link"v-if="folderList.length > 0"@click="setCurrentFolder(-1)">全部文件</span><!-- 遍历文件列表 --><template v-for="(item, index) in folderList"><!-- 图标 --><span class="iconfont icon-right"></span><!-- 文件名字可以点击 --><spanclass="link"v-if="index < folderList.length - 1"@click="setCurrentFolder(index)">{{ item.fileName }}</span><!-- 文件名字不可以点击 --><span class="text" v-if="index == folderList.length - 1">{{item.fileName}}</span></template></div>
</template><script setup>
import { ref, reactive, getCurrentInstance, watch } from "vue";
import { useRouter, useRoute } from "vue-router";const { proxy } = getCurrentInstance();
const router = useRouter();
const route = useRoute();// 定义父组件Main.vue传递过来的值
const props = defineProps({// 默认开启路由监听watchPath: {// 是否监听路由变化type: Boolean,default: true,},shareId: {type: String,},adminShow: {type: Boolean,default: false,},
});const api = {// 首页 获取当前目录 获取列表 参数(path:完整路径)getFolderInfo: "/file/getFolderInfo",// 外部分享 获取目录信息 参数(shareId:分享id / path:完整路径)getFolderInfo4Share: "/showShare/getFolderInfo",// 管理员 获取当前目录 参数(path:完整路径)getFolderInfo4Admin: "/admin/getFolderInfo",
};// 分类
const category = ref();
// 目录的集合
const folderList = ref([]);
// 当前目录
const currentFolder = ref({ fileId: "0" });// 初始化
const init = () => {// 初始目录集合 设置为一个空数组folderList.value = [];// 初始当前目录设置currentFolder.value = { fileId: "0" };// 调用doCallback();
};// 点击目录openFolder
// 父组件 Main/FolderSelect 中调用该方法,实现目录(文件及)的预览
const openFolder = (data) => {// 把data赋值给文件id和文件nameconst { fileId, fileName } = data;// 定义folderconst folder = {fileName: fileName,fileId: fileId,};// 把folder push进目录集合folderList.value.push(folder);// 更新当前目录currentFolder.value = folder;// 设置当前路径,当点击后目录改变,路径也随之改变,调用setPathsetPath();
};
defineExpose({ openFolder });// 返回上一级
const backParent = () => {// 查找当前文件夹的索引let currentIndex = null;for (let i = 0; i < folderList.value.length; i++) {if (folderList.value[i].fileId == currentFolder.value.fileId) {currentIndex = i;break;}}// 设置当前文件夹为上一级目录setCurrentFolder(currentIndex - 1);
};// 点击导航 设置当前目录(点击目录,跳转到所点击的目录)
const setCurrentFolder = (index) => {// 如果点的是全部文件if (index == -1) {// 初始化数组currentFolder.value = { fileId: "0" };folderList.value = [];} else {// 当前目录的值更新为目录集合数组为index的值currentFolder.value = folderList.value[index];// 删除从index+1开始的长度为目录集合数组的长度 的数组// 对于 splice(start, deleteCount, ...items) 方法://  start(必需):开始更改数组的位置的索引。// deleteCount(必需):要删除的元素数量。如果设置为 0,则不会删除任何元素。// ...items(可选):要添加到数组中的新元素folderList.value.splice(index + 1, folderList.value.length);}setPath();
};// 设置当前路径,当点击后目录改变,路径也随之改变
const setPath = () => {if (!props.watchPath) {// 设置不监听路由回调方法doCallback();return;}// 定义路径数组let pathArray = [];// 遍历目录集合的每一项folderList.value.forEach((item) => {// 把每一项的fileId push 到 路径数组里pathArray.push(item.fileId);});// 设置路由router.push({// 当前路径pathpath: route.path,// 参数query:// 如果pathArray长度为0,参数就为空,否则就把路径用/隔开加入到pathArray里面,更新path,添加到参数里面pathArray.length == 0? "": {path: pathArray.join("/"),},});
};// 获取当前路径的目录
const getNavigationFolder = async (path) => {// 根据给定的 path 和一些其他属性(如 props.shareId 和 props.adminShow)来确定请求哪个 API,然后发送一个请求来获取该路径下的目录信息,并将获取到的目录信息存储在 folderList.value 中。let url = api.getFolderInfo;if (props.shareId) {url = api.getFolderInfo4Share;}if (props.adminShow) {url = api.getFolderInfo4Admin;}let result = await proxy.Request({url: url,showLoading: false,params: {path: path,shareId: props.shareId,},});if (!result) {return;}folderList.value = result.data;
};// 回调 将当前的参数传递给父组件 Main
// 定义了一个名为 navChange 的事件。这允许子组件在需要时触发这个事件,并传递一些数据给父组件。
const emit = defineEmits(["navChange"]);
const doCallback = () => {emit("navChange", {categoryId: category.value,curFolder: currentFolder.value,});
};// 监听路由
watch(() => route,// 它会在route的值变化时被调用。// newVal是route的新值,oldVal是route的旧值(newVal, oldVal) => {if (!props.watchPath) {return;}if (// 如果不在main路径里面就不用管newVal.path.indexOf("/main") === -1 &&newVal.path.indexOf("/settings/fileList") === -1 &&newVal.path.indexOf("/share") === -1) {return;}// 把新携带的路径赋值给path,可以拿到?后面的一坨,query参数是?后面的一截const path = newVal.query.path;// params是route路由,category是在router里面定义的const categoryId = newVal.params.category;category.value = categoryId;if (path == undefined) {// 调用init();} else {// 调用getNavigationFolder(path);// 刷新的时候要把当前目录设置进来// 使用split("/")方法将path字符串分割为一个数组pathArraylet pathArray = path.split("/");// fileId被赋值给currentFolder.valuecurrentFolder.value = {// 它使用数组的最后一个元素(即path中的最后一个部分)作为fileIdfileId: pathArray[pathArray.length - 1],};doCallback();}},{ immediate: true, deep: true }
);
</script><style lang="scss" scoped>
.top-navigation {font-size: 13px;display: flex;align-items: center;line-height: 40px;.all-file {font-weight: bold;}.link {color: #06a7ff;cursor: pointer;}.icon-right {color: #06a7ff;padding: 0px 5px;font-size: 13px;}
}
</style>

(2)main.js中引入

import Navigation from '@/components/Navigation.vue';
app.component('Navigation', Navigation);

(3)Main.vue中使用组件

<!-- 导航 -->
<Navigation ref="navigationRef" @navChange="navChange"></Navigation>

Main.vue中绑定点击事件
 

<span @click="preview(row)">{{ row.fileName }}</span>
<span @click="preview(row)">{{ row.fileName }}</span>

preview回调,预览

// 预览
const previewRef = ref();
const preview = (data) => {// 如果是文件夹if (data.folderType == 1) {// 就调用Navigation组件中的openFolder方法,实现预览navigationRef.value.openFolder(data);return;}if (data.status != 2) {proxy.Message.warning("文件未完成转码,无法预览");return;}previewRef.value.showPreview(data, 0);
};

navChange回调

// 目录,展示目录
const navChange = (data) => {// 从传入的 data 对象中解构出 curFolder 和 categoryId 两个属性,并将它们的值分别赋给新定义的常量 curFolder 和 categoryIdconst { curFolder, categoryId } = data;// 将当前文件夹的值更新为传过来的文件夹currentFolder.value = curFolder;// 展示showLoading.value = true;// 更新categorycategory.value = categoryId;loadDataList();
};

无文件上传时,Main.vue展示

<!-- 判断没有文件时 --><div class="no-data" v-else><div class="no-data-inner"><!-- 图片 --><Icon iconName="no_data" :width="120" fit="fill"></Icon><!-- 文字提示 --><div class="tips">当前目录为空,上传你的第一个文件吧</div><div class="op-list"><!-- 上传 --><el-upload:show-file-list="false":with-credentials="true":multiple="true":http-request="addFile":accept="fileAccept"><div class="op-item"><Icon iconName="file" :width="60"></Icon><div>上传文件</div></div></el-upload><!-- 新建目录 --><div class="op-item" v-if="category == 'all'" @click="newFolder"><Icon iconName="folder" :width="60"></Icon><div>新建目录</div></div></div></div></div>

四、 上传优化(列表自动刷新)

(1)上传回调 

Main.vue中

// 添加文件回调
const reload = () => {showLoading.value = false;// 刷新列表loadDataList();
};
defineExpose({ reload });

Framework.vue中

<component @addFile="addFile" ref="routerViewRef" :is="Component"></component>
// 上传文件回调
// 上传文件后的刷新列表(调用Uploader子组件中的函数)
const routerViewRef = ref();
const uploadCallbackHandler = () => {nextTick(() => {// 它首先等待DOM更新完成(通过nextTick)// 然后重新加载一个组件(可能是router-view)routerViewRef.value.reload();// 并最后调用一个函数来获取空间使用情况。getUseSpace();});
};

五、文件选择(过滤)

组件:分类文件类型
src/js/CategoryInfo.js

export default {"all": {accept: "*"},"video": {accept: ".mp4,.avi,.rmvb,.mkv,.mov"},"music": {accept: ".mp3,.wav,.wma,.mp2,.flac,.midi,.ra,.ape,.aac,.cda"},"image": {accept: ".jpeg,.jpg,.png,.gif,.bmp,.dds,.psd,.pdt,.webp,.xmp,.svg,.tiff"},"doc": {accept: ".pdf,.doc,.docx,.xls,.xlsx,.txt"},"others": {accept: "*"},
}

Main.vue中上传按钮

:accept="fileAccept"// 实现文件选择
const fileAccept = computed(() => {const categoryItem = CategoryInfo[category.value];return categoryItem ? categoryItem.accept : "*";
});

六、搜索功能实现

Main.vue中搜索输入框

 <!-- 搜索输入框 --><div class="search-panel"><el-inputclearableplaceholder="请输入文件名搜索"v-model="fileNameFuzzy"@keyup.enter="search"><template #suffix><i class="iconfont icon-search" @click="search"></i></template></el-input></div><!-- 搜索图标 --><div class="iconfont icon-refresh" @click="loadDataList"></div>

回调 

// 搜索功能
const search = () => {showLoading.value = true;loadDataList();
};

七、文件移动的目录导航

FolderSelect.vue中

<!-- 目录导航 --><div class="navigation-panel"><Navigationref="navigationRef"@navChange="navChange":watchPath="false"></Navigation></div>
// 绑定导航栏
const navigationRef = ref();
// 调用Navigation子组件中的navChange,使得参数传递给该组件
const navChange = (data) => {const { curFolder } = data;currentFolder.value = curFolder;filePid.value = curFolder.fileId;loadAllFolder();
};
// 选择目录(目录导航)
const selectFolder = (data) => {navigationRef.value.openFolder(data);
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/696674.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

交易复盘-20240513

仅用于记录当天的市场情况,用于统计交易策略的适用情况,以便程序回测 短线核心:不参与任何级别的调整,采用龙空龙模式 一支股票 10%的时候可以操作, 90%的时间适合空仓等待 双成药业 (1)|[9:30]|[3566万]|0.34 中通客车 (1)|[9:43]|[7678万]|0.15 嘉华股份 (2)|[9:30]|[36…

AI跟踪报道第41期-新加坡内哥谈技术-本周AI新闻:本周Al新闻: 准备好了吗?事情即将変得瘋狂

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

基于MetaGPT的智能体理论与实践-Task01

Task01: MetaGPT环境配置 学习教程&#xff1a;https://github.com/datawhalechina/hugging-multi-agent 1 环境准备 1.1 安装python3.9 通过&#xff1a;python3 --version, 查看此python版本为3.10.3 1.2 下载MetaGPT 开始&#xff0c;借用清华镜像&#xff0c;拉取…

【ARM Cortex-M 系列 2.2 -- Cortex-M7 单步调试原理及实现详细介绍】

请阅读【嵌入式开发学习必备专栏】 文章目录 单步调试概述单步执行原理Debug stepping control using the DHCSR 紧接上篇文章 【ARM Cortex-M 系列 2.1 – Cortex-M7 Debug system registers】 单步调试概述 在ARMv7-M架构中&#xff0c;通过使用单步调试&#xff08;Haltin…

【软设】常见易错题汇总

目录 计算机系统基础 程序语言基础 数据结构 算法设计与分析 计算机网络与信息安全 软件工程基础 开发方法&#xff08;结构化与面向对象&#xff09; 数据库 操作系统 知识产权相关的法律法规 &#x1f92f;&#x1f92f;&#x1f92f;&#x1f92f;&#x1f92f;&#x1f9…

UE4_照亮环境_不同雾效的动态切换

一、问题及思路&#xff1a; 我们在一个地图上&#xff0c;经常切换不同的区域&#xff0c;不同的区域可能需要不同的色调&#xff0c;例如暖色调的野外或者幽暗的山洞&#xff0c;这两种环境上&#xff0c;雾效的选用肯定不一样&#xff0c;夕阳西下的户外用的就是偏暖的色调&…

OS复习笔记ch5-4-2

引言 承接上文我们介绍了信号量机制和应用信号量机制实现的进程同步和互斥&#xff0c;这一节我们将围绕一些经典问题对信号量机制展开更深入地探讨。 读者/写者问题 读者/写者问题与我们之前遇到的问题类型不同&#xff0c;它描述的是&#xff1a; 有读者和写者两组进程&am…

4.uniapp+vue3项目使用vuex

文章目录 1. uniappvue3项目使用vuex1.1. main.js引入store1.2. 创建store/index.js1.3. 项目中引用1.4. 开始解决实际问题1.5. vuex和storage的区别 1. uniappvue3项目使用vuex 这篇文章&#xff0c;既是使用的教程&#xff0c;也是用来解决一个实际问题&#xff1a;uView自定…

VS2022 错误 LNK2001 无法解析的外部符号

错误 LNK2001 无法解析的外部符号 “private: static struct std::once_flag ThreadPool::flag_” (?flag_ThreadPool0Uonce_flagstdA) STL D:\VS2019\STL\源.obj 1 错误原因 &#xff1a;链接器无法解析 ThreadPool::flag_ 这个静态成员变量。这通常是因为静态成员变量在声明…

ESP32 IDF linux下开发环境搭建

文章目录 介绍升级Python环境下载Python包配置编译环境及安装Python设置环境变量 ESPIDF环境搭建下载esp-idf 代码编译等待下载烧录成功查看串口打印 介绍 esp32 官方文档给的不是特别详细 参考多方资料 最后才完成开发 主要问题在于github下载的很慢本教程适用于ubuntu deban…

基于GD32的简易数字示波器(5)- 软件_控制LED

这期记录的是项目实战&#xff0c;做一个简易的数字示波器。 教程来源于嘉立创&#xff0c;帖子主要做学习记录&#xff0c;方便以后查看。 本期主要介绍GPIO口的输入输出模式&#xff0c;使用其中的输出模式驱动LED。详细教程可观看下方链接。 2.2 LED控制实验 语雀 1、LE…

C++类和对象下——实现日期类

前言 在学习了类和对象的六大成员函数后&#xff0c;为了巩固我们学习的知识可以手写一个日期类来帮助我们理解类和对象&#xff0c;加深对于其的了解。 默认函数 构造函数 既然是写类和对象&#xff0c;我们首先就要定义一个类&#xff0c;然后根据实际需要来加入类的数据与函…