实现微信小程序预览文件,预览页面添加倒计时

项目场景:

提示:1、实现小程序预览doc、docx、xls、xlsx、ppt、pptx、pdf类型文件

           2、进入页面展示文件内容、开始按钮,点击,按钮变为【(**s)】倒计时

           3、倒计时结束后,此按钮消失,弹出显示【完成】,弹框保留2s后小时,用户继续阅读

例如:项目场景:示例:学习计时


问题描述

提示:小程序自带的api可以实现文件预览,但不可以在文件预览页面添加按钮,不可以操作文件预览页面:

例如:小程序文档地址:wx.openDocument(Object object) | 微信开放文档
小程序代码:


wx.downloadFile({
  // 示例 url,并非真实存在
  url: 'http://example.com/somefile.pdf',
  success: function (res) {
    const filePath = res.tempFilePath
    wx.openDocument({
      filePath: filePath,
      success: function (res) {
        console.log('打开文档成功')
      }
    })
  }
})

分析:

提示:考虑建立新页面,用web-view组件放预览文件,cover-image组件做按钮,但存在兼容性问题,部分手机cover-image组件被web-view遮挡。


解决方案:

提示:前端将预览的html文件(包括倒计时操作),放在服务器,后端用kkfileview部署获取预览地址给前端【kkFileView为文件文档在线预览解决方案,该项目使用流行的spring boot搭建,易上手和部署,基本支持主流办公文档的在线预览,如doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,rar,图片,视频,音频等等,官网地址:https://kkfileview.keking.cn/zh-cn/docs/config.html

小程序端:

fileUrl为服务器文件地址 :'https://******.com/fileRead.html?id='+this.data.id+'&userId='+res.data.id

<web-view style="width: 100px !important;height: 200px !important;" src="{{fileUrl}}" bindload="successLoad">
</web-view>


服务器fileRead.html文件:

<!DOCTYPE html>
<html lang="en">

<head>
  <link rel="shortcut icon" href="#" />
  <meta charset="UTF-8" />

  <meta http-equiv="cache-control" content="no-cache,no-store,must-revalidate" />
  <meta http-equiv="Pragma" content="no-cache" />
  <meta http-equiv="expires" content="0" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <title>Document</title>
  <style>
    body {
      margin: 0;
      padding: 0;
    }

    .btn_read {
      position: absolute;

      display: none;
      right: 0;
      left: 50%;
      bottom: 30px;
      transform: translateX(-50%);
      width: 150px;
      height: auto;
      z-index: 9999;
    }

    .text-box {
      position: absolute;
      display: none;
      right: 0;
      left: 50%;
      bottom: 30px;
      transform: translateX(-50%);
      z-index: 9999;
      width: 130px;
      height: 40px;
      line-height: 40px;
      border-radius: 8px;
      border: 1px #B11818 solid;
      color: #B11818;
      font-size: 15px;
      font-weight: bold;
      text-align: center;
    }

    .box {
      position: absolute;
      display: none;

    }

    .finish-box {
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      width: 143px;
      height: auto;
      z-index: 9999;


    }
  </style>
</head>
<script>
  //可以将查找标签节点的操作进行简化 var btn = getElementById('btn')
  function $(id) {
    return document.getElementById(id);
  }
  //设置iframe自适应
  function changeFrameHeight() {
    var ifm1 = $("myiframe");
    ifm1.height = document.documentElement.clientHeight + 'px';
    ifm1.width = document.documentElement.clientWidth + 'px';
  }
  //key(需要检索的键) url(传入的需要分割的url地址,例:?id=2&age=18)
  function getSearchString(key, Url) {
    var str = Url;
    str = str.substring(1, str.length); // 获取URL中?之后的字符(去掉第一位的问号)
    // 以&分隔字符串,获得类似name=xiaoli这样的元素数组
    var arr = str.split("&");
    var obj = new Object();
    // 将每一个数组元素以=分隔并赋给obj对象
    for (var i = 0; i < arr.length; i++) {
      var tmp_arr = arr[i].split("=");
      obj[decodeURIComponent(tmp_arr[0])] = decodeURIComponent(tmp_arr[1]);
    }
    return obj[key];
  }
</script>

<body id="id_body" style="height: 100vh;width: 100%; overflow-y: hidden">
  <iframe id="myiframe" name="myiframe"></iframe>
  <img src="开始学习图片" id="btn_start" class="btn_read" />
  <div id="text_count" class=" text-box">学习中</div>
  <img id="icon_finish_bg" class="box finish-box" src="完成学习图片"></img>
  <script>
    console.log('time',new Date())
    var timer = null; //timer变量记录定时器setInterval的返回值
    var search = window.location.search;//地址参数,传入的需要分割的url地址,例:?id=2&age=18
    var fileId = getSearchString("id", search); //文件id
    var userId = getSearchString("userId", search);
    var baseUrl = '接口请求地址'
    var loading = false
    var learnDuration = 0 //学习时间,接口返回

    //监听窗口分辨率改变
    window.onresize = function () {
      changeFrameHeight();
    }
    window.onload = function () {
      changeFrameHeight();
      //开始阅读监听
      $("btn_start").addEventListener("click", function () {
        $("btn_start").setAttribute("style", "display:none");
        $("text_count").setAttribute("style", "display:block");
        countTime(learnDuration)
      });
      $("myiframe").onload = function (e) {
        console.log('myiframe加载成功');
        loading = true
        var ifDoc = $("myiframe").contentDocument || {};
        var ifTitle = ifDoc.title || '';
        console.log('ifTitle', ifTitle);
        if (ifTitle.indexOf("404") >= 0 || ifTitle.indexOf("错误") >= 0) {
          console.log('加载失败');

        }
      }
      getDetail()

    };
    //请求接口获取详情
    function getDetail() {
      $("btn_start").setAttribute("style", "display:block");
      var url = baseUrl + '/courseware/textbooks/detail/' + fileId
      var xhr = new XMLHttpRequest();
      // 可以设置请求头,一般不设置
      //超时设置 2s 设置
      xhr.timeout = 50000;
      //超时回调
      xhr.ontimeout = function () {
        // alert("网络异常, 请稍后重试!!");
      }
      //网络异常回调
      xhr.onerror = function () {
        // alert("你的网络似乎出了一些问题!");
      }
      //设置响应体数据的类型
      xhr.responseType = 'json';
      xhr.open("get", url);
      xhr.send(null);
      //注册相关事件回调处理函数
      xhr.onload = function (e) {
        if (xhr.status == 200 || xhr.status == 304) {
          if (xhr.status == 200 && xhr.response && xhr.response.code == 200) {
            loadPage(xhr.response.data)
          } else {
            console.log("Request was unsuccessful: " + xhr.status); // 请求失败,返回 响应的 HTTP 状态 
          }
        }
      };
      xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {// (整个数据传输过程结束)

        }
      };
    }
    //加载页面
    function loadPage(res) {
      if (!res) {
        return false;
      }
      if (!res.textbooks) {
        return false;
      }

      document.title = res.textbooks ? res.textbooks.name : ''//修改html标题
      learnDuration = res.learnDuration//获取倒计时时间
      var base64_url = base64_encode(res.textbooks.url)
      var url = encodeURIComponent(base64_url)
      console.log("base64_url", base64_url);
      console.log("url", url);
      var fileUrl = '预览文件服务端地址/onlinePreview?url=' + url + '&officePreviewType=' + res.suffix; //要预览文件的访问地址,后端使用kkfileview后的地址
      $("myiframe").src = fileUrl
      $("text_count").innerHTML = '学习中(' + res.learnDuration + "s)";
      console.log('fileUrl', fileUrl);

    }
   
//结束学习
   function finishComplete(params) {
    var api = baseUrl + '/courseware/learn/complete?id=' + fileId + '&userId=' + userId
      var xhr2 = new XMLHttpRequest();
      // 可以设置请求头,一般不设置
      //超时设置 2s 设置
      xhr2.timeout = 50000;
      //超时回调
      xhr2.ontimeout = function () {
        alert("网络异常, 请稍后重试!!");
      }
      //网络异常回调
      xhr2.onerror = function () {
        alert("你的网络似乎出了一些问题!");
      }
      //设置响应体数据的类型
      xhr2.responseType = 'json';
      xhr2.open("get", api);
      xhr2.send(null);
      //注册相关事件回调处理函数
      xhr2.onload = function (e) {
        if (xhr2.status == 200 || xhr2.status == 304) {
          if (xhr2.status == 200 && xhr2.response && xhr2.response.code == 200) {
          } else {
            console.log("Request /courseware/learn/complete was unsuccessful: " + xhr2.status); // 请求失败,返回 响应的 HTTP 状态 
          }
        }
      };
    
   }
    function countTime(count) {
      //点击开始建 开始计数
      timer = setInterval(function () {
        count--;
        if (count==0) {
          finishComplete()
        }
        if (count < 0) {
          clearInterval(timer);
          $("id_body").removeChild($("text_count"));
          $("icon_finish_bg").setAttribute("style", "display:block");
          setTimeout(function () {
        
            $("icon_finish_bg").setAttribute("style", "display:none");
          }, 2000)

        } else {
          // submitSutdy()
          $("text_count").innerHTML = '学习中(' + count + "s)";
        }
        // 需要改变页面上时分秒的值
      }, 1000);
    }



    function base64_encode(str) {
      //下面是64个基本的编码
      var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
      var out, i, len;
      var c1, c2, c3;
      len = str.length;
      i = 0;
      out = "";
      while (i < len) {
        c1 = str.charCodeAt(i++) & 0xff;
        if (i == len) {
          out += base64EncodeChars.charAt(c1 >> 2);
          out += base64EncodeChars.charAt((c1 & 0x3) << 4);
          out += "==";
          break;
        }
        c2 = str.charCodeAt(i++);
        if (i == len) {
          out += base64EncodeChars.charAt(c1 >> 2);
          out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
          out += base64EncodeChars.charAt((c2 & 0xF) << 2);
          out += "=";
          break;
        }
        c3 = str.charCodeAt(i++);
        out += base64EncodeChars.charAt(c1 >> 2);
        out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
        out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
        out += base64EncodeChars.charAt(c3 & 0x3F);
      }
      return out;
    }
 </script>
</body>

</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瘦瘦瘦大人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值