Quellcode durchsuchen

完成下载方法

jwyu vor 2 Jahren
Ursprung
Commit
a32a452729
4 geänderte Dateien mit 149 neuen und 19 gelöschten Zeilen
  1. 2 2
      src/hooks/chart/render.js
  2. 69 2
      src/hooks/useDownLoadFile.js
  3. 76 15
      src/views/ppt/Detail.vue
  4. 2 0
      src/views/ppt/Preview.vue

+ 2 - 2
src/hooks/chart/render.js

@@ -16,11 +16,11 @@ HighchartszhCN(Highcharts)
  * @param renderId 图表在dom中的id
  * @param lang 图表显示为中文/英文 默认 zh中文 en英文
  */
-let ChartIns=null
+let ChartIns=null//图表实例
 let chartData=ref(null)//图的所有数据
 let LangType=ref('zh')//当前图表显示的语言版本
 let RenderDomId=ref('')//图表渲染的domid
-let options=ref(null)
+let options=ref(null)//渲染图的数据
 export function chartRender({data,renderId,lang='zh'}){
     let chartOpt={}
     LangType.value=lang

+ 69 - 2
src/hooks/useDownLoadFile.js

@@ -1,6 +1,73 @@
 // 下载文件
 import axios from "axios";
+import { showToast } from "vant";
+import {ref} from 'vue'
 
-export function useDownLoadFile(url){
-    
+
+/**
+ * 
+ * @returns {
+ *  progress 下载进度
+ *  fileSize 文件大小
+ *  startDownload 开始下载函数
+ *  cancelDownload  取消下载
+ * }
+ */
+export function useDownLoadFile(){
+    let progress=ref(0)//进度 0-1
+    let fileSize=ref(0)//文件大小
+
+    const controller = new AbortController();
+
+    // 开始下载
+    const startDownload=(url,filename)=>{
+        axios({
+            url:url,
+            method:'get',
+            responseType:'blob',
+            signal: controller.signal,
+            onDownloadProgress:function(progressEvent){
+                // console.log(progressEvent);
+                fileSize.value=Math.floor(progressEvent.total/1024/1024)
+                progress.value = Math.floor(progressEvent.progress*100)
+            }
+        }).then(res=>{
+            // console.log(res);
+            const {status,data}=res
+            if(status!=200){
+                showToast('下载失败')
+                return
+            }
+            const content = data
+            const blob = new Blob([content])
+            if ('download' in document.createElement('a')) {
+                const elink = document.createElement('a')
+                elink.download = filename || url.split('/')[url.split('/').length - 1]
+                elink.style.display = 'none'
+                elink.href = window.URL.createObjectURL(blob)
+                document.body.appendChild(elink)
+                elink.click()
+                window.URL.revokeObjectURL(elink.href)
+                document.body.removeChild(elink)
+            } else {
+                navigator.msSaveBlob(blob, filename)
+            }
+        }).catch((e)=>{
+            console.log(e);
+            showToast('下载失败')
+        })
+    }
+
+    //取消下载
+    const cancelDownload=()=>{
+        // 取消请求
+        controller.abort()
+    }
+
+    return {
+        fileSize,
+        progress,
+        startDownload,
+        cancelDownload
+    }
 }

+ 76 - 15
src/views/ppt/Detail.vue

@@ -7,8 +7,10 @@ import {createPPTContent,getTemplate} from './hooks/createPPTContent'
 import {usePPTPublish} from './hooks/usePPTPublish'
 import {useClassify} from './hooks/useClassify'
 import {useUserInfo} from '@/hooks/common'
+import {useDownLoadFile} from '@/hooks/useDownLoadFile'
 import { useWindowScroll } from '@vueuse/core'
 import moment from 'moment';
+import { showToast } from 'vant';
 
 const route=useRoute()
 const router=useRouter()
@@ -23,11 +25,13 @@ let PPTInfo=ref(null)
 let conArr=ref([])
 async function getPPTDetail(){
     const res=await apiPPTDetail({PptId:Number(pptId)})
+    if(res.Ret!=200) return
     PPTInfo.value=res.Data
     conArr.value=createPPTContent(res.Data)
     nextTick(()=>{
         onResize({width:document.getElementsByClassName('ppt-content-wrap')[0].clientWidth})
     })
+    document.title=res.Data.Title
 }
 getPPTDetail()
 
@@ -107,22 +111,17 @@ function onSelectPlayOpt(e){
     }
 }
 
+
 // 下载文件
+const {fileSize,progress,startDownload,cancelDownload}=useDownLoadFile()
+let showDownload=ref(false)
 function handleDownLoadFile(){
-    const a = document.createElement('a');
-	a.style.display = 'none';
-	    //   a.setAttribute('target', '_blank');
-	      /*
-	       * download的属性是HTML5新增的属性
-	       * href属性的地址必须是非跨域的地址,如果引用的是第三方的网站或者说是前后端分离的项目(调用后台的接口),这时download就会不起作用。
-	       * 此时,如果是下载浏览器无法解析的文件,例如.exe,.xlsx..那么浏览器会自动下载,但是如果使用浏览器可以解析的文件,比如.txt,.png,.pdf....浏览器就会采取预览模式
-	       * 所以,对于.txt,.png,.pdf等的预览功能我们就可以直接不设置download属性(前提是后端响应头的Content-Type: application/octet-stream,如果为application/pdf浏览器则会判断文件为 pdf ,自动执行预览的策略)
-	       */
-	    a.setAttribute('download','测试');
-	      a.href = PPTInfo.value.PptxUrl;
-	      document.body.appendChild(a);
-	      a.click();
-	      document.body.removeChild(a);
+    if(!PPTInfo.value.PptxUrl){
+        showToast('请先发布ppt')
+        return
+    }
+    showDownload.value=true
+    startDownload(PPTInfo.value.PptxUrl,PPTInfo.value.Title+'.pptx')
 }
 
 </script>
@@ -143,7 +142,7 @@ function handleDownLoadFile(){
                 <img src="@/assets/imgs/ppt/icon_action_copy.png" alt="">
                 <span>复制</span>
             </div>
-            <div class="item-box">
+            <div class="item-box" @click="handleDownLoadFile">
                 <img src="@/assets/imgs/ppt/icon_action_download2.png" alt="">
                 <span>下载</span>
             </div>
@@ -243,6 +242,28 @@ function handleDownLoadFile(){
         close-on-click-action
         @select="onSelectPlayOpt" 
     />
+
+    <!-- 下载弹窗 -->
+    <van-popup 
+        v-model:show="showDownload"
+        position="center"
+        round
+    >
+        <div class="download-file-wrap">
+            <img class="icon" src="@/assets/imgs/ppt/icon01.png" alt="">
+            <div class="title">{{PPTInfo.Title}}.pptx</div>
+            <div class="size">文件大小:{{fileSize}}MB</div>
+            <div class="process-box">
+                <van-progress 
+                    style="flex:1"
+                    :percentage="progress"
+                    :show-pivot="false" 
+                />
+                <span>{{progress}}%</span>
+            </div>
+            <div class="cancel-btn" v-if="progress<100" @click="cancelDownload">取消下载</div>
+        </div>
+    </van-popup>
 </template>
 
 <style lang="scss" scoped>
@@ -346,6 +367,46 @@ function handleDownLoadFile(){
     display: none;
 }
 
+.download-file-wrap{
+    width: 600px;
+    max-width: 500PX;
+    background-color: #fff;
+    text-align: center;
+    padding: 0 16PX 30PX 16PX;
+    .icon{
+        width: 120px;
+        max-width: 60PX;
+        display: block;
+        margin: 50PX auto 20PX auto;
+    }
+    .title{
+        margin-bottom: 10PX;
+    }
+    .size{
+        color: $font-grey_999;
+        font-size: 12PX;
+    }
+    .process-box{
+        margin-top: 30PX;
+        display: flex;
+        align-items: center;
+        span{
+            color: $theme-color;
+            margin-left: 5PX;
+            flex-shrink: 0;
+        }
+    }
+    .cancel-btn{
+        max-width: 240PX;
+        width: 80%;
+        margin: 60PX auto 0 auto;
+        background-color: #F4F6F8;
+        text-align: center;
+        line-height: 40PX;
+        border-radius: 40PX;
+    }
+}
+
 @media screen and (min-width:$media-width){
     .ppt-detail-page{
         margin-top: 60px;

+ 2 - 0
src/views/ppt/Preview.vue

@@ -16,10 +16,12 @@ const pptId=route.query.id
 let conArr=ref([])
 async function getPPTDetail(){
     const res=await apiPPTDetail({PptId:Number(pptId)})
+    if(res.Ret!=200) return
     conArr.value=createPPTContent(res.Data)
     nextTick(()=>{
         showToast('左右滑动可翻页')
     })
+    document.title=res.Data.Title
 }
 getPPTDetail()