charles
2024-06-05 fefe4a3011fb472788abb2e7ffdbbc5a4f58623c
src/views/home/components/uploadAudio/index.vue
@@ -1,96 +1,117 @@
<template>
    <div class="upload-audio-container">
        <div class="left">
            <el-form :inline="true" class="demo-form-inline">
                <el-form-item label="">
                    <el-input v-model.lazy="keyword" placeholder="请输入搜索内容" suffix-icon="el-icon-search" size="small"></el-input>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" @click="manyAnalysisAudio" icon="el-icon-video-play"  plain size="mini">批量分析</el-button>
                    <el-button type="danger" @click="deleteManyAudio" icon="el-icon-delete" plain size="mini">批量删除</el-button>
                    <el-upload
                            style="display: inline-block;margin-left: 10px"
                            action="/api-sa/v1/audio/upload"
                            :on-change="selFile"
                            accept=".mp3,.wav"
                            :show-file-list="false"
                            :on-success="upSuccess"
                            >
                        <el-button size="small" type="primary">点击上传</el-button>
                    </el-upload>
                </el-form-item>
            </el-form>
        </div>
        <div class="right">
            <el-tabs v-model="activeName">
                <el-tab-pane label="已上传" name="first">
                    <div>
                        <el-table :data="pageInfo.audioList" border @selection-change="selAudio">
                            <el-table-column label='全选' type="selection"  align="center" />
                            <el-table-column prop="name" label="文件名" min-width="200px" align="center" />
                            <el-table-column prop="size" label="大小" align="center" />
                            <el-table-column prop="occurrenceTime" label="上传时间" align="center" />
                            <el-table-column prop="audioStatus" label="处理状态" align="center" >
                                <template slot-scope="scope">
                                    <span v-if="scope.row.audioStatus===0" style="color:wheat">上传中</span>
                                    <span v-else-if="scope.row.audioStatus===1" style="color: blue">上传成功</span>
                                    <span v-else-if="scope.row.audioStatus===2" style="color: cyan">处理中</span>
                                    <span v-else-if="scope.row.audioStatus===3" style="color: green">处理完成</span>
                                    <span v-else-if="scope.row.audioStatus===4" style="color: red">处理失败</span>
                                </template>
                            </el-table-column>
                            <el-table-column label="操作" align="center" >
                                <template slot-scope="scope">
                                    <el-button icon="el-icon-video-play" @click="analysisAudio(scope.row.ID)" type="text"></el-button>
                                    <el-button icon="el-icon-delete" type="text" @click="deleteAudio(scope.row.ID)"></el-button>
                                </template>
                            </el-table-column>
                        </el-table>
                        <div class="pagination">
                            <div class="total">共计{{pageInfo.total}}条记录 第{{pageData.page}}/{{lastPage}}页</div>
                            <div class="page">
                                <el-pagination
                                        background
                                        @size-change="handleSizeChange"
                                        @current-change="handleCurrentChange"
                                        :current-page.sync="pageData.page"
                                        :page-size="pageData.pageSize"
                                        layout="prev, pager, next,sizes, jumper"
                                        :total="pageInfo.total">
                                </el-pagination>
                            </div>
                        </div>
        <el-row type="flex" justify="center">
            <el-col :span="23">
                <el-card style="margin-top: 20px;height: 85vh">
                    <div class="left">
                        <el-form :inline="true" class="demo-form-inline">
                            <el-form-item label="">
                                <el-input v-model.lazy="keyword" placeholder="请输入搜索内容" suffix-icon="el-icon-search" size="small"></el-input>
                            </el-form-item>
                            <el-form-item>
                                <el-button type="primary" @click="manyAnalysisAudio" icon="el-icon-video-play"  plain size="mini">批量分析</el-button>
                                <el-button type="danger" @click="deleteManyAudio" icon="el-icon-delete" plain size="mini">批量删除</el-button>
                                <el-upload
                                        style="display: inline-block;margin-left: 10px"
                                        action="#"
                                        :auto-upload="false"
                                        :on-change="selFile"
                                        accept=".mp3,.wav"
                                        :show-file-list="false"
                                        :on-success="upSuccess"
                                >
                                    <el-button size="small" type="primary">点击上传</el-button>
                                </el-upload>
                            </el-form-item>
                        </el-form>
                    </div>
                </el-tab-pane>
                <el-tab-pane label="正在上传" name="second">
                   <!-- <el-skeleton style="width: 100%" :loading="isUpload" animated>
                        <template slot="template">
                            <div style="padding: 14px;">
                                <el-skeleton-item variant="h3" style="width: 100%;height: 40px" />
                            </div>
                        </template>
                    </el-skeleton>-->
                    <div>
                        <el-skeleton  animated :loading="isUpload">
                            <template slot="template">
                                <div style="padding: 14px;">
                                    <el-skeleton-item  style="width: 100%;height: 40px" />
                    <div class="right">
                        <el-tabs v-model="activeName">
                            <el-tab-pane label="已上传" name="first">
                                <div>
                                    <el-table :data="pageInfo.audioList"
                                              border @selection-change="selAudio"
                                    >
                                        <el-table-column :selectable="selectable" label='全选' type="selection"  align="center" />
                                        <el-table-column prop="name" label="文件名" min-width="200px" align="center" />
                                        <el-table-column prop="size" label="大小" align="center" />
                                        <el-table-column prop="occurrenceTime" label="上传时间" align="center" />
                                        <el-table-column prop="audioStatus" label="处理状态" align="center" >
                                            <template slot-scope="scope">
                                                <span v-if="scope.row.audioStatus===0" style="color:wheat">上传中</span>
                                                <span v-else-if="scope.row.audioStatus===1" style="color: blue">上传成功</span>
                                                <span v-else-if="scope.row.audioStatus===2" style="color: cyan">处理中</span>
                                                <span v-else-if="scope.row.audioStatus===3" style="color: green">处理完成</span>
                                                <span v-else-if="scope.row.audioStatus===4" style="color: red">处理失败</span>
                                            </template>
                                        </el-table-column>
                                        <el-table-column label="操作" align="center" >
                                            <template slot-scope="scope">
                                                <el-tooltip class="item" effect="dark" content="下载" placement="bottom">
                                                    <el-button icon="el-icon-download" @click="downloadAudio(scope.row.ID)" type="text"></el-button>
                                                </el-tooltip>
                                                <el-tooltip class="item" effect="dark" content="分析" placement="bottom">
                                                    <el-button icon="el-icon-video-play" @click="analysisAudio(scope.row.ID)" type="text"></el-button>
                                                </el-tooltip>
                                                <el-tooltip v-if="scope.row.audioStatus!==3" class="item" effect="dark" content="删除" placement="bottom">
                                                    <el-button icon="el-icon-delete" type="text" @click="deleteAudio(scope.row.ID)"></el-button>
                                                </el-tooltip>
                                            </template>
                                        </el-table-column>
                                    </el-table>
                                    <div class="pagination">
                                        <div class="total">共计{{pageInfo.total}}条记录 第{{pageData.page}}/{{lastPage}}页</div>
                                        <div class="page">
                                            <el-pagination
                                                    background
                                                    @size-change="handleSizeChange"
                                                    @current-change="handleCurrentChange"
                                                    :current-page.sync="pageData.page"
                                                    :page-size="pageData.pageSize"
                                                    layout="prev, pager, next,sizes, jumper"
                                                    :total="pageInfo.total">
                                            </el-pagination>
                                        </div>
                                    </div>
                                </div>
                            </template>
                        </el-skeleton>
                            </el-tab-pane>
                            <el-tab-pane label="正在上传" name="second">
                                <!-- <el-skeleton style="width: 100%" :loading="isUpload" animated>
                                     <template slot="template">
                                         <div style="padding: 14px;">
                                             <el-skeleton-item variant="h3" style="width: 100%;height: 40px" />
                                         </div>
                                     </template>
                                 </el-skeleton>-->
                                <div v-if="progressLoad">
                                    <div style="padding: 14px;" class="right-progress">
                                        <div class="p-left">上传速度:{{ this.speed }}</div>
                                        <div class="p-right">预计时间:{{ this.leftTime }}</div>
                                    </div>
                                    <el-progress :color="customColors" :text-inside="true" :stroke-width="26" :percentage="percentage"></el-progress>
                                </div>
                            </el-tab-pane>
                        </el-tabs>
                    </div>
                </el-tab-pane>
            </el-tabs>
        </div>
                </el-card>
            </el-col>
        </el-row>
    </div>
</template>
<script>
    import {audioListApi,processAudioApi,deleteAudioApi,batchProcessAudioApi,batchDeleteAudioApi} from '@/api';
    import {request} from "@/utils";
    import axios from 'axios';
    let timer= null;
    export default {
        name: "index",
        data(){
            return {
                percentage:0,
                speed:0,
                leftTime:0,
                progressLoad:false,
                isUpload:false,
                activeName:'first',
                keyword:'',
@@ -99,7 +120,12 @@
                    total:0
                },
                pageData:{page:1,pageSize:10},
                ids:[]
                ids:[],
                customColors: [
                    {color: '#f56c6c', percentage: 20},
                    {color: '#e6a23c', percentage: 40},
                    {color: '#5cb87a', percentage: 60}
                ]
            }
        },
        watch:{
@@ -121,7 +147,22 @@
                return Math.ceil(this.pageInfo.total/this.pageData.pageSize)
            }
        },
        beforeDestroy(){
          if(timer){
              window.clearInterval(timer);
          }
        },
        methods:{
            selectable(row){
                if(row.audioStatus===3){
                    return false
                }else{
                    return true;
                }
            },
            async downloadAudio(id){
                window.location.href=`http://smartai.com:7013/api-sa/v1/audio/download?id=${id}`
            },
            upSuccess({code}){
               if(code===200){
                   this.$message.success('上传成功');
@@ -133,9 +174,88 @@
                   this.isUpload=false;
               });
            },
            selFile(file,fileList){
            async selFile(_,fileList){
                this.activeName='second';
                this.isUpload=true;
                if(fileList.length>0){
                    const file = fileList[0].raw;
                    const formData = new FormData();
                    formData.append("file", file);
                    this.progressLoad = true;
                    this.percentage=0;
                    let lastTime = 0; // 上一次计算时间
                    let lastSize = 0; // 上一次计算的文件大小
                    try{
                        const {code} = await axios.post("/api-sa/v1/audio/upload", formData,
                            {
                            onUploadProgress: (progressEvent) => {
                                console.log(progressEvent);
                                /*验证数据*/
                                if (lastTime === 0) {
                                    lastTime = new Date().getTime();
                                    lastSize = progressEvent.loaded;
                                    return;
                                }
                                /*计算间隔*/
                                let nowTime = new Date().getTime();
                                let intervalTime = (nowTime - lastTime) / 1000; // 时间单位为毫秒,需转化为秒
                                let intervalSize = progressEvent.loaded - lastSize;
                                /*重新赋值以便于下次计算*/
                                lastTime = nowTime;
                                lastSize = progressEvent.loaded;
                                /*计算速度*/
                                let speed = (intervalSize / intervalTime)/10;
                                let bSpeed = speed; // 保存以b/s为单位的速度值,方便计算剩余时间
                                let units = "b/s"; // 单位名称
                                if (speed / 1024 > 1) {
                                    speed = speed / 1024;
                                    units = "k/s";
                                }
                                if (speed / 1024 > 1) {
                                    speed = speed / 1024;
                                    units = "M/s";
                                }
                                let leftTime = (progressEvent.total) / bSpeed;
                                /*计算进度*/
                                if(timer){
                                    window.clearInterval(timer);
                                }
                                timer=window.setInterval(()=>{
                                    if(this.percentage>=90){
                                        window.clearInterval(timer);
                                        timer=null;
                                    }
                                    this.percentage+=parseInt(Math.random()*10);
                                    speed=(Math.random()*500+500).toFixed(2)
                                    this.speed = speed + "k/s";
                                    this.leftTime=(lastSize/speed/1000).toFixed(2)+ "秒";
                                },500);
                                //= parseInt((progressEvent.loaded / progressEvent.total) * 100)-1;
                               // this.speed = speed.toFixed(2) + units;
                                //this.leftTime = leftTime.toFixed(2) + "秒";
                            }
                        });
                        if (code === 200) {
                            this.$message({
                                message: "上传成功",
                                type: "success"
                            });
                        } else {
                            this.$message({
                                message: "上传失败",
                                type: "error",
                            });
                        }
                        this.$nextTick(()=>{
                            this.progressLoad = false;
                            this.percentage=100;
                            window.clearInterval(timer);
                            this.queryAudioList();
                        });
                    }catch (error) {
                        console.log(error);
                    }
                }
            },
            selAudio(rows){
                this.ids=rows.map(item=>item.ID);
@@ -153,14 +273,6 @@
                    this.pageInfo.audioList=data;
                    this.pageInfo.total=total;
                }
                /*this.pageInfo.audioList=[
                    {filename:'0_20240519_xx_01.mp3',size:'879.88k',uploadAt:'2024-05-10 10:10:10',status:0},
                    {filename:'0_20240519_xx_02.mp3',size:'879.88k',uploadAt:'2024-05-10 10:10:10',status:1},
                    {filename:'0_20240519_xx_03.mp3',size:'879.88k',uploadAt:'2024-05-10 10:10:10',status:0},
                    {filename:'0_20240519_xx_04.mp3',size:'879.88k',uploadAt:'2024-05-10 10:10:10',status:1},
                    {filename:'0_20240519_xx_05.mp3',size:'879.88k',uploadAt:'2024-05-10 10:10:10',status:2},
                    {filename:'0_20240519_xx_06.mp3',size:'879.88k',uploadAt:'2024-05-10 10:10:10',status:2},
                ]*/
            },
            analysisAudio(id){
                this.$confirm('是否进行音频分析, 是否继续?', '提示', {
@@ -247,6 +359,20 @@
            position: relative;
            top:-60px;
        }
        .right-progress{
            display: flex;
            justify-content: space-around;
            .p-left{
                width: 85%;
                text-align: center;
                position: relative;
                left: 20px;
            }
            .p-right{
                width: 15%;
                text-align: left;
            }
        }
        .pagination{
            display: flex;
            justify-content: space-between;