封装进度条onUploadProgress+axios取消请求的上传组件

news2024/12/29 10:00:49

目录

定时模拟进度条

方法

A.axios

B.xhr

取消请求 

完整代码

A.自定义上传组件

B.二次封装组件

情况

增加cancelToken不生效,刷新页面

进度条太快->设置浏览器网速


定时模拟进度条

    startUpload() {
        if (!this.file) return;

        const totalSize = this.file.size;
        let uploadedSize = 0;

        const interval = setInterval(() => {
            if (uploadedSize >= totalSize) {
                clearInterval(interval);
                // this.state_tip = STATE_TIPS.get('上传成功');
            } else {
                uploadedSize += 1024;
                this.progress = Math.round((uploadedSize / totalSize) * 100);
            }
        }, 200);
    }

方法

A.axios

 uploadQuery() {
        if (!this.file) return;
        this.state_tip = STATE_TIPS.get('上传中');
        this.progress = 0;
        // headers = {'Content-Type': 'multipart/form-data'}
        const formData = new FormData()
        formData.append('file', this.file)
        axios.post(this.uploadPath, formData, {
            headers: {
                "X-Requested-With": "XMLHttpRequest",
            },
            onUploadProgress: (progressEvent: ProgressEvent) => {
                console.log("onUploadProgress");
                if (progressEvent.lengthComputable) {
                    this.progress = Math.round(
                        (progressEvent.loaded / progressEvent.total) * 100
                    );
                    console.log(this.progress);
                }
            },
        }).then((res: any) => {
            if (res && res.code == 200) {
                this.uploadExel = res.data;
                this.state_tip = STATE_TIPS.get('上传成功');
                console.log(this.uploadExel);
                this.$emit("update:uploadExel", this.uploadExel);
            } else {
                this.state_tip = STATE_TIPS.get('其他');
                this.state_tip.tip = res.msg || '请取消上传,更换符合模板要求的文件';
            }
        }).catch((error: any) => {
            this.state_tip = STATE_TIPS.get('上传失败');
        }).finally(() => {
            this.uploaded = true;
            this.$emit("update:uploaded", this.uploaded);
        });
    }

B.xhr

   uploadQuery(file: File) {
        // headers = {'Content-Type': 'multipart/form-data'}
        const formData = new FormData()
        formData.append('file', file)
        const xhr = new XMLHttpRequest();
        xhr.open("POST", this.uploadPath, true);

        xhr.upload.onprogress = (event) => {
            if (event.lengthComputable) {
                this.uprogress = Math.round((event.loaded / event.total) * 100);
            }
        };

        xhr.onload = () => {
            console.log(xhr);
            
            if (xhr.status === 200) {
                const res = JSON.parse(xhr.responseText);
                console.log(res);
                console.log(res.code);
                if (res.code === 200) {
                    this.uploadExel = res.data;
                    this.state_tip = "上传成功";
                    this.uploaded = true;
                    console.log(this.uploadExel);
                    this.$emit("update:uploaded", this.uploaded);
                    this.$emit("update:uploadExel", this.uploadExel);
                } else {
                    // 处理上传失败情况
                    this.state_tip = "上传失败";
                }
            }
        };

        xhr.onerror = () => {
            // 处理上传出错情况
            this.state_tip = "上传出错";
        };

        xhr.send(formData);
        // request.post(this.uploadPath, formData).then((res: any) => {

        //     if (res.code == 200) {
        //         this.uploadExel = res.data;
        //         this.state_tip = STATE_TIPS.get('上传成功');
        //         this.uploaded = true;
        //         this.$emit("update:uploaded", this.uploaded);
        //         this.$emit("update:uploadExel", this.uploadExel);
        //     } else {

        //     }
        // })
    }

取消请求​​​​​​​

完整代码

<UploadComp :uploadPath="PATH" :fileLogPath="PATH.replace('uploadExcel?wpReleId=','getOtherIndexFileLog/')" :uploaded.sync="uploaded" :uploadExel.sync="uploadExel" @cancelUpload="cancelUpload" />
            <!-- <SingleUploadComp :uploadPath="PATH" :uploaded.sync="uploaded" :uploadExel.sync="uploadExel" @cancelUpload="cancelUpload" /> -->

A.自定义上传组件

<template>
    <div class="upload-list-dragger" :uploadPath="uploadPath" :fileLogPath="fileLogPath">
        <div v-if="!file" @click="openFileInput" @dragenter="onDragEnter" @dragover="onDragOver" @drop="onDrop"
            :class="{ 'drag-over': isDragOver }">
            <input type="file" ref="fileInput" style="display: none;" @change="onFileChange" :accept="format" />
            <div class="custom-drag-style">
                <img src="@/assets/img/upload.png" class="upload-icon" />
                <div class="upload-click-drag">点击或拖拽上传文件</div>
                <!-- 使用正则表达式替换所有点号 -->
                <div class="upload-tip">请上传{{ format.replace(/\./g, "") }}格式文件,上传多份文件时以最后一次为准</div>
            </div>
        </div>
        <div v-else class="custom-upload-card">
            <img class="upload-card-icon" src="@/assets/img/excel.png" />
            <div class="upload-card-state">
                <div>
                    <span class="file-name">{{ file.name }}</span>
                    <span class="cancel-upload" @click="cancelUpload"><mds-icon type="line-close" /></span>
                </div>
                <div class="progress-bar" :style="{ width: progress + '%', backgroundColor: state_tip.color }"></div>
                <div class="span-container">
                    <span :style="{ color: state_tip.state === '上传中' ? '#A8ACB3' : state_tip.color }">{{
                        state_tip.tip
                    }}</span>
                    <span v-if="state_tip.state === '上传中'">{{ progress + '%' }}</span>
                    <span v-if="state_tip.state === '上传失败'" class="span-operate" underline
                        @click="restartUpload">重新上传</span>
                    <span v-if="state_tip.state === '上传成功'" class="span-operate" underline
                        @click="downloadQuery">下载结果明细</span>
                </div>
            </div>
        </div>
    </div>
</template>
  
<script lang="ts">
import { Component, Vue, Prop } from 'vue-property-decorator';
import request from '@/utils/request'
import axios, { Canceler } from 'axios';
const STATE_TIPS = new Map([['其他', { state: '其他', color: 'orange', tip: '' }], ['上传中', { state: '上传中', color: '#1564FF', tip: '文件上传解析中…' }], ['上传失败', { state: '上传失败', color: '#DD2100', tip: '上传失败,请重新上传' }], ['上传成功', { state: '上传成功', color: '#00AF5B', tip: '上传成功!' }]])
@Component({
    components: {}
})
export default class UploadComp extends Vue {
    @Prop({ required: true }) private uploadPath!: string
    @Prop({ required: true }) private fileLogPath!: string
    @Prop({ default: '.xls' }) private format!: string //形如".xls,.csv,.xlsx"

    uploadExel: any = {
        succList: []
    }
    uploaded: boolean = false;

    file: File | null = null;
    source = axios.CancelToken.source();

    progress = 0;
    isDragOver = false;
    data() {
        return {
            state_tip: {},
            
        }
    }
    created() {
        console.log(this.fileLogPath);
    }
    onFileChange(event: Event) {
        const target = event.target as HTMLInputElement;
        this.fileValidator(target.files);//可能为null
    }
    fileValidator(files: FileList | undefined | null) {
        if (files && files.length > 0) {
            // 上传多份文件时以最后一次为准
            const file = files[0];
            if (this.isValidFormat(file)) {
                this.file = file;
                console.log(this.file);
                this.uploadQuery();
            } else {
                alert(`请上传${this.format.replace(/\./g, "")}格式文件。`);
            }
        } else {
            alert(`请上传文件!`);
        }
    }
    uploadQuery() {
        if (!this.file) return;
        this.state_tip = STATE_TIPS.get('上传中');
        this.progress = 0;
        // headers = {'Content-Type': 'multipart/form-data'}
        const formData = new FormData()
        formData.append('file', this.file)
        // 在合适的地方定义取消令牌和取消函数
        const CancelToken = axios.CancelToken;

         // 判断上一次的请求是否还在继续,如果还在继续,则取消上一次的请求
       if(this.source.token._listeners!=undefined )
        {
            this.source.cancel("取消请求")
            this.source = axios.CancelToken.source()
        }

        request.post(this.uploadPath, formData, {
            onUploadProgress: (progressEvent: ProgressEvent) => {
                console.log("Upload progress:", progressEvent);
                this.progress = Math.round((progressEvent.loaded / progressEvent.total) * 100);
                console.log("进度:", this.progress);
            },
            cancelToken:this.source.token,
        }).then((res: any) => {
            if (res && res.code == 200) {
                this.uploadExel = res.data;
                this.state_tip = STATE_TIPS.get('上传成功');
                console.log(this.uploadExel);
                this.$emit("update:uploadExel", this.uploadExel);
                this.uploaded = true;
                this.$emit("update:uploaded", this.uploaded);
            } else {
                this.state_tip = STATE_TIPS.get('其他');
                this.state_tip.tip = res.msg || '请取消上传,更换符合模板要求的文件';
            }
        }).catch((error: any) => {
            this.state_tip = STATE_TIPS.get('上传失败');
        })
    }
    downloadQuery() {
        request.get(this.fileLogPath).then((res: any) => {
            var aLink = document.createElement("a");
            aLink.style.display = "none";
            aLink.href = res.data[0].fileUrl
            document.body.appendChild(aLink);
            aLink.click();
            document.body.removeChild(aLink);
        })
    }
    cancelUpload() {
        console.log("取消上传")
        this.state_tip = STATE_TIPS.get('其他');
        this.progress = 0;
        this.file = null;
        if (this.uploaded) {
            this.$emit('cancelUpload', this.uploadExel.fileLogId)
        }else{
            this.source.cancel("请求已被取消")
            this.source = axios.CancelToken.source()
        }
    }

    restartUpload() {
        this.uploadQuery();
    }
    openFileInput() {
        const fileInput = this.$refs.fileInput as HTMLInputElement;
        fileInput.click();
    }
    // 拖动文件进入上传区域
    onDragEnter(event: DragEvent) {
        // 防止浏览器默认的拖放行为
        event.preventDefault();
        this.isDragOver = true;
    }
    // 拖动文件在上传区域中移动
    onDragOver(event: DragEvent) {
        //防止浏览器默认的拖放行为
        event.preventDefault();
    }
    // 放置拖动的文件
    onDrop(event: DragEvent) {
        event.preventDefault();
        this.isDragOver = false;
        this.fileValidator(event.dataTransfer?.files)//可能为undefined
    }
    isValidFormat(file: File) {
        const supportedFormats: string[] = this.format.split(','); // 将 format 字符串拆分成数组
        const fileExtension = '.' + file.name.split('.').pop(); // 获取文件名的扩展名
        return supportedFormats.some((supportedFormat: string) => {
            return fileExtension === supportedFormat;
        });
    }
}
</script>
  
<style>
.upload-list-dragger {
    width: 800px;
    height: 160px;
    border: 1px dashed rgba(206, 212, 224, 1);
    border-radius: 4px;
    display: flex;
    align-items: center;
}

.upload-list-dragger:hover {
    background-color: #eef8ff;

}

.custom-drag-style {
    height: 140px;
    width: 780px;
    background-color: #fff;
    flex-wrap: wrap;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    cursor: pointer;

    .upload-icon {
        width: 24px;
        height: 24px;
    }

    .upload-click-drag {
        width: 144px;
        height: 24px;
        font-family: PingFangSC-Regular;
        font-size: 16px;
        font-weight: 400;
        line-height: 24px;
        color: rgba(69, 71, 77, 1);
        text-align: left;
        display: block;
    }

    .upload-tip {
        height: 24px;
        font-family: PingFangSC-Regular;
        font-size: 14px;
        font-weight: 400;
        line-height: 24px;
        color: rgba(168, 172, 179, 1);
        text-align: left;
        display: block;
    }
}

.custom-upload-card {
    display: flex;
    align-items: center;
    height: 71px;

    .upload-card-icon {
        width: 71px;

    }

    .upload-card-state {
        height: 100%;
        display: flex;
        flex-direction: column;
        justify-content: space-around;

        .file-name {
            font-family: PingFangSC-Regular;
            font-size: 16px;
            font-weight: 400;
            line-height: 16px;
            color: rgba(69, 71, 77, 1);
            text-align: left;
            margin-right: 12px;
        }

        .cancel-upload {
            cursor: pointer;
        }

        .progress-bar {
            height: 8px;
            border-radius: 8px;
        }

        /* 进度条看作是由两个嵌套的<div>元素构成,外部的.progress-bar元素和内部的<div> */
        .progress-bar div {
            width: 638px;
            height: 8px;
            background-color: rgba(228, 231, 237, 1);
            border-radius: 8px;
        }

        .span-container {
            width: 690px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            font-family: PingFangSC-Regular;
            font-size: 14px;
            font-weight: 400;
            line-height: 24px;

            .span-operate {
                color: #1564FF;
                cursor: pointer;
            }
        }
    }

}
</style>
  

B.二次封装组件

mds-upload内部取消上传,但组件会阻止Lits的改变,并呈现上传失败的样式,再次点击才能返回到上传界面 

<template>
  <mds-upload ref="uploadRef" :path="uploadPath" name="file" :beforeUpload="onBeforeUpload"
    :getUploadParams="getUploadParams" :disabled="false" :multiple="false" :accept="format" :onComplete="onUploadComplete"
    :onError="onUploadError" :onChange="onListChange" listType="imgCard" :limit="1" :dragable="true">
    <template v-slot:dragStyle>
      <div class="custom-drag-style">
        <img src="@/assets/img/upload.png" class="upload-icon" />
        <div class="upload-click-drag">点击或拖拽上传文件</div>
        <!-- 使用正则表达式替换所有点号 -->
        <div class="upload-tip" slot="tip">请上传{{ format.replace(/\./g, "") }}格式文件,上传多份文件时以最后一次为准</div>
      </div>
    </template>
  </mds-upload>
</template>
<script lang="ts">
import { Component, Vue, Prop } from 'vue-property-decorator'
@Component({
  components: {}
})
export default class SingleUploadComp extends Vue {
  @Prop({ required: true })  private uploadPath!: boolean
  @Prop({ default: '.xls' }) private format!: string //形如".xls,.csv,.xlsx"
  uploadExel: any = {
    succList: []
  }
  uploaded:boolean= false
   onBeforeUpload(files: File[], callback: (files: File[]) => void) {
    callback(files)
  }
  
   getUploadParams(file: File, callback: (data: any) => void) {
    const formData = new FormData()
    formData.append('file', file)
    const cbData = {
      data: formData,
      withCredentials: true
    }
    callback(cbData)
    this.$refs.uploadRef.$el.querySelector('.upload-list-dragger').style.display = "none";
  }
  /**
   * @param res 响应结果
   * @param oriFile 原始文件
   */
   onUploadComplete(res: any, oriFile: File) {
    const errEle = this.$refs.uploadRef.$el.querySelector('.mds-upload-card-data-error')
    if (res.data.code == 200) {
      this.uploadExel = res.data.data;
      this.$emit("update:uploadExel", this.uploadExel); 
      errEle.innerHTML = "上传成功!";
      this.uploaded = true;
      this.$emit("update:uploaded", this.uploaded); 
    } else {
      errEle.innerHTML = res.data.msg;
      errEle.style.color = "orange";
    }
  }
   onUploadError(err: any, oriFile: File) {
    const errEle = this.$refs.uploadRef.$el.querySelector('.mds-upload-card-data-erro')
    errEle.innerHTML = "上传失败,请重新上传";
  }
   onListChange(uploadList: any[]) {
    console.log('on list change')
    if (uploadList.length == 0) {
      if (this.uploaded) {
        console.log("取消上传")
        this.$emit('cancelUpload', this.uploadExel.fileLogId)
      }
      this.$refs.uploadRef.$el.querySelector('.upload-list-dragger').style.display = "block";
    }
  }
}  
</script>
<style lang="scss" scoped>
::v-deep .upload-list-dragger {
  // position: relative;
  width: 800px;
  height: 160px;
  border: 1px dashed rgba(206, 212, 224, 1);
  border-radius: 4px;

  .custom-drag-style:hover {
    background-color: #eef8ff;
  }

  .custom-drag-style {
    height: 140px;
    background-color: #fff;
    flex-wrap: wrap;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    cursor: pointer;

    .upload-icon {
      width: 24px;
      height: 24px;
    }

    .upload-click-drag {
      width: 144px;
      height: 24px;
      font-family: PingFangSC-Regular;
      font-size: 16px;
      font-weight: 400;
      line-height: 24px;
      color: rgba(69, 71, 77, 1);
      text-align: left;
      display: block;
    }

    .upload-tip {
      width: 326px;
      height: 24px;
      font-family: PingFangSC-Regular;
      font-size: 14px;
      font-weight: 400;
      line-height: 24px;
      color: rgba(168, 172, 179, 1);
      text-align: left;
      display: block;
    }
  }
}

::v-deep .mds-upload-card {
  position: relative;
  width: 800px;
  height: 160px;
  border: 1px dashed rgba(206, 212, 224, 1) !important;
  border-radius: 4px;
}

::v-deep .mds-upload-card:hover .mds-upload-card-eyes {
  display: none;
}

::v-deep .mds-upload-card-icon {
  width: 71px;
  height: 71px;
  display: block;

  &::before {
    content: '';
    display: block;
    width: 71px;
    height: 71px;
    background: url('../../../assets/img/excel.png');
    background-size: 71px 71px;
    z-index: 9999;
  }
}

::v-deep .mds-upload-card-data-name {
  width: 114px;
  height: 24px;
  font-family: PingFangSC-Regular;
  font-size: 16px;
  font-weight: 400;
  line-height: 24px;
  color: rgba(69, 71, 77, 1);
  text-align: left;
}

::v-deep .mds-upload-card-data {
  .mds-upload-card-data-error {
    color: #00AF5B;
    height: 24px;
    font-family: PingFangSC-Regular;
    font-size: 14px;
    font-weight: 400;
    line-height: 24px;
    text-align: left;
  }

  .mds-upload-card-data-size {

    height: 24px;
    font-family: PingFangSC-Regular;
    font-size: 14px;
    font-weight: 400;
    line-height: 24px;
    text-align: left;
  }
}
</style>

情况

增加cancelToken不生效,刷新页面

进度条太快->设置浏览器网速

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

土壤养分分析仪:精准农业,从“土”开始

在农业生产中&#xff0c;土壤的质量是决定农作物产量和品质的关键因素。然而&#xff0c;传统的土壤检测方法耗时费力&#xff0c;且结果往往不够准确。随着科技的发展&#xff0c;土壤养分分析仪为现代农业带来了新的可能。 土壤养分分析仪是一种专门用于测量土壤中各种养分含…

Flutter应用程序加固的问题及解决方案

​&#x1f680;Flutter应用程序加固的问题及解决方案引言在移动应用开发中&#xff0c;为了保护应用程序的安全性&#xff0c;开发者需要对应用进行加固。在使用Flutter技术进行应用程序开发时&#xff0c;也需要注意应用程序的安全问题和加固方案。本文将介绍在Flutter应用程…

码云配置遇到秘钥不正确

你这个就是秘钥没有和git绑定&#xff0c; 需要 git config --global user.name "你的用户名随便写" git config --global user.email "你的邮箱"

老师怎么培养班干部

老师除了教学之外&#xff0c;班级管理也是一项重要的任务。而培养班干部则是班级管理中不可或缺的一部分。今天为大家分享一些关于如何培养班干部的干货。 明确职责&#xff0c;制定班规 在选拔班干部之后&#xff0c;首先需要明确各个职位的职责&#xff0c;让每位班干部都清…

22款奔驰GLS450升级HUD抬头显示 平视仪表信息

说起HUD抬头显示这个配置&#xff0c;最初是用在战斗机上的&#xff0c;它可以让战斗机驾驶员读取飞机的各种信息和状态&#xff0c;而无需移动头部&#xff0c;这样就能够有效的提高效率。但随着汽车技术的进步HUD这种配置也逐渐下放到民用车上。发展到今&#xff0c;车上的抬…

一文讲透Python函数中的局部变量和全局变量

变量的作用域就是变量能够发挥作用的区域&#xff0c;超出既定区域后就无法发挥作用。根据变量的作用域可以将变量分为局部变量和全局变量。 1.局部变量 局部变量是在函数内部定义并使用的变量&#xff0c;也就是说只有在函数内部&#xff0c;在函数运行时才会有效&#xff0…

Docker安装可视化工具Portainer

目录 Portainer简介 Portainer安装 Portainer简介 Portainer是一款开源的容器管理平台&#xff0c;支持多种容器技术&#xff0c;如Docker、Kubernetes和Swarm等。它提供了一个易于使用的Web UI界面&#xff0c;可用于管理和监控容器和集群。Portainer旨在使容器管理更加简单…

sqli-labs靶场详解(less38-less45)

堆叠注入 ​ less-38 less-38 ?id1 and 11;%00 成功 ?id1 and 12;%00 失败 不是吧 这就出来了&#xff1f; ?id1 order by 4;%00 报错 4列不行 ?id0 union select 1,2,3;%00 显示位置为2,3 ?id0 union select 1,database(),3;%00 数据库为security ?id0 union select 1,…

HarmonyOS入门开发(三) 持久化存储Preferences

接入鸿蒙几天以来&#xff0c;发现各种和Android不一样的地方&#xff0c;今天来看一下Preferences存储 在Android中比如有ShardPreferences、Mmkv这些持久化存储方式&#xff0c;开发起来很方便&#xff0c;读取速度也很快&#xff0c;在鸿蒙里面也提供了对应的持久化存储方案…

plist文件在线生成网页配置苹果ios系统ipa文件下载

您可以进入首页—工具箱—plist文件在线制作 您可以进入控制台—plist文件 ●也可以直接访问&#xff1a;咕噜分发内测平台-苹果ios系统应用安卓apk安全漏洞扫描提供商 ●应用名称_包体的bid-下载地址-图标地址 ●如果不知道怎么查看苹果包名 可以通过咕噜分发【工具箱】-【IOS…

网络篇---第九篇

系列文章目录 文章目录 系列文章目录前言一、说说TCP/IP四层网络模型二、说说域名解析详细过程?三、 IP 地址分为几类,每类都代表什么,私网是哪些?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女…

什么是好的FPGA编码风格?(2)--多参考设计软件的语言模板(Language Templates)

什么是语言模板&#xff1f; 不论是Xilinx的Vivado&#xff0c;还是Altera的Quartus II&#xff0c;都为开发者提供了一系列Verilog、SystemVerilog、VHDL、TCL、原语、XDC约束等相关的语言模板&#xff08;Language Templates&#xff09;。 在Vivado软件中&#xff0c;按顺序…

版本控制系统Git学习笔记-Git基础操作

文章目录 概述一、获取仓库1.1 初始化仓库1.2 克隆仓库 二、文件状态及更新操作2.1 文件状态变化周期2.2 检查文件状态2.2.1 完整查看状态2.2.2 简要查看状态 2.3 跟踪新文件2.4 暂存已修改的文件2.5 忽略文件2.5.1 文件 .gitignore 的格式规范如下&#xff1a;2.5.2 glob模式格…

ethtool工具添加并验证网口

Filesystem Packages->console->network->ethtool 命令描述&#xff1a; ethtool 是用于查询及设置网卡参数的命令。 使用命令&#xff1a; ethtool ethx //查询ethx网口基本设置&#xff0c;其中 x 是对应网卡的编号&#xff0c;如eth0、eth1等等 ethtool –…

docker 学习总结

docker 概念 -云计算的基石 docker的一个软件&#xff1a; 开源 docker基本组成 docker主机(Host)&#xff1a;安装了Docker程序的机器&#xff08;Docker直接安装在操作系统之上&#xff09;&#xff1b; docker仓库(Registry)&#xff1a;用来保存各种打包好的软件镜像&a…

玩转大数据:3-Hadoop家族的力量与挑战

引言 Hadoop作为一个强大的大数据处理框架&#xff0c;以其分布式计算和存储能力在业界备受关注。然而&#xff0c;Hadoop在应用场景、适用范围、社区支持以及后续持续发展等方面也面临着一些挑战。本文将围绕Hadoop的生态应用&#xff0c;以及来自其他生态的挑战&#xff0c;…

银河麒麟v10——植物大战僵尸原版——2023教程

1、原版安装包如下&#xff1a; 阿里云盘分享https://www.alipan.com/s/Qn5DpDKs2YT 2、麒麟信息&#xff1a; 3、安装命令&#xff1a; 注意&#xff1a;最后一步&#xff0c;需要先解压tar包&#xff0c;再切到PlantsVsZombies.exe所在目录下&#xff0c;再执行启动命令&a…

软件测试jmeter基本使用

1安装与配置 1.jdk下载 下载地址&#xff1a;https://www.oracle.com/java/technologies/downloads/#jdk18-windows&#xff08;压缩包中会给&#xff09; 2.jmeter下载 Apache JMeter - Download Apache JMeter&#xff08;压缩包中有&#xff09; 3.操作教学 打开软件后新…

前端:实现div的隐藏与显示

效果 完整代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-widt…

快速排序算法的代码及算法思想

快速排序&#xff08;Quick Sort&#xff09;是一种常用的排序算法&#xff0c;他的时间复杂度为O(nlogn) 算法思想: 通过一趟排序将待排序的数据分割成独立的两部分&#xff0c;其中一部分的所有数据都比另一部分的所有数据小&#xff0c;然后再对这两部分数据分别进行快速排…