jiangwei小站
1075 字
5 分钟
uniapp webview 加载本地页面
2024-05-25

uniapp 加载本地页面或者下载 cdn zip 包,解压加载

使用 uniapp 插件 wrs-httpserver,插件市场下载,要收费,以后有空自己写

httpServer.serverRunning("dataosha");

// process.env.NODE_ENV 判断环境

httpServer.js

import $mConfig from "@/config/index.config.js";
var HttpServer = (function () {
  var instance;

  function init() {
    // 单例对象的初始化代码
    return {
      wrsHttpserver: uni.requireNativePlugin("wrs-httpserver"),
      startServer: function (callback) {
        // 方法实现
        String.prototype.endWith = function (endStr) {
          let d = this.length - endStr.length;
          return d >= 0 && this.lastIndexOf(endStr) == d;
        };
        // _www ,_doc,_documents,_downloads
        var staticWebs = [];
        var paths = ["_www", "_downloads"];
        for (var i = 0; i < paths.length; i++) {
          var path = paths[i];
          var absPath = plus.io.convertLocalFileSystemURL(path);
          // Android获取的absPath以/结尾,iOS获取的absPath不是/结尾
          if (absPath.endWith("/")) {
            absPath = absPath.substring(0, absPath.length - 1);
          }
          switch (i) {
            // _www
            case 0:
              break;
            // _downloads
            case 1:
              {
                staticWebs.push(
                  {
                    urlPath: "/dataosha", // 站点请求的url
                    directoryPath: absPath + "/dataosha", // web站点文件绝对路径,这个路径是绝对路径
                  },
                  {
                    urlPath: "/maoshen", // 站点请求的url
                    directoryPath: absPath + "/maoshen", // web站点文件绝对路径,这个路径是绝对路径
                  },
                  {
                    urlPath: "/fortuneCat", // 站点请求的url
                    directoryPath: absPath + "/fortuneCat", // web站点文件绝对路径,这个路径是绝对路径
                  },
                  {
                    urlPath: "/catHaulingHouse", // 站点请求的url
                    directoryPath: absPath + "/catHaulingHouse", // web站点文件绝对路径,这个路径是绝对路径
                  }
                );
              }
              break;
            default:
              break;
          }
          console.log("path:" + path + "  绝对路径:" + absPath);
        }
        // var appid = plus.runtime.appid;
        var params = {
          port: 8030, // 端口
          staticWebs: staticWebs,
        };
        // 启动http service
        this.wrsHttpserver.startServer(params, (resp) => {
          if (resp.code == 0) {
            callback && callback(true);
          } else {
            console.log("httpServer启动失败:" + resp.msg);
            callback && callback(false);
          }
        });
      },
      stopServer: function () {
        this.wrsHttpserver.stopServer();
      },
      serverRunning: function (name) {
        console.log("serverRunning==>", this.wrsHttpserver);
        var obj = this.wrsHttpserver.isRuning();
        if (obj.isRuning) {
          console.log("httpServer服务正在运行");
          this.navigate(true, name);
        } else {
          console.log("httpServer服务没有运行");
          this.startServer((isSuc) => {
            console.log("httpServer服务开启运行");
            this.navigate(isSuc, name);
          });
        }
      },
      flag: true,
      navigate: async function (isSuc, name) {
        if (!this.flag) return;
        this.flag = false;
        setTimeout(() => {
          this.flag = true;
        }, 500);
        if (!isSuc) {
          // 本地服务没启动
          this.jumpCdn(name);
        } else {
          // 本地服务启动
          uni.request({
            url: `${
              $mConfig.hostUrl
            }/${name}/package/version.json?t=${new Date().getTime()}`,
            success: (onlineRes) => {
              console.log("游戏线上版本:", onlineRes.data.stamp);
              if (onlineRes.data.type && onlineRes.data.type == 2) {
                this.jumpCdn(name);
              } else {
                const version = `http://127.0.0.1:8030/${name}/package/version.json?t=${new Date().getTime()}`;
                uni.request({
                  url: version, //仅为示例,并非真实接口地址。
                  success: (localRes) => {
                    console.log("游戏本地版本:", localRes.data.stamp);
                    if (!localRes.data.stamp) {
                      this.jumpCdn(name);
                      this.downLoad(name);
                    } else {
                      if (onlineRes.data.stamp > localRes.data.stamp) {
                        this.jumpCdn(name);
                        this.downLoad(name);
                      } else {
                        this.jumpLocal(name);
                      }
                    }
                  },
                  fail: (err) => {
                    console.log("获取内部游戏版本失败", err);
                    this.jumpCdn(name);
                  },
                });
              }
            },
          });
        }
      },
      jumpCdn(name) {
        const url = `/pages/webview/webview?url=${
          $mConfig.hostUrl
        }/${name}/index.html?t=${new Date().getTime()}`;
        console.log("打开cdn:", url);
        uni.navigateTo({
          url: url,
        });
      },
      jumpLocal(name) {
        const url = `/pages/webview/webview?url=http://127.0.0.1:8030/${name}/index.html?t=${new Date().getTime()}`;
        console.log("打开本地:", url);
        uni.navigateTo({
          url: url,
        });
      },
      downLoad(name) {
        uni.downloadFile({
          url: `${$mConfig.hostUrl}/${name}/package/web.zip`, //仅为示例,并非真实的资源
          success: (res) => {
            if (res.statusCode === 200) {
              console.log("下载成功");
              var zipfile = res.tempFilePath;
              // 下载后的压缩文件解压到_downloads目录
              var targetPath = `_downloads/${name}`;
              var absPath = plus.io.convertLocalFileSystemURL(targetPath);
              // 经测试,修正在华为Android 10的系统上解压的解压目录,Android上使用绝对路径
              switch (uni.getSystemInfoSync().platform) {
                case "android":
                  targetPath = plus.io.convertLocalFileSystemURL(targetPath);
                  break;
                case "ios":
                  targetPath = `_downloads/${name}`;
                  break;
                default:
                  break;
              }
              plus.zip.decompress(
                zipfile,
                targetPath,
                function () {
                  var path = plus.io.convertLocalFileSystemURL(targetPath);
                  console.log("解压成功绝对路径:" + path);
                  // this.startServer();
                  const version = `http://127.0.0.1:8030/${name}/package/version.json?t=${new Date().getTime()}`;
                  uni.request({
                    url: version, //仅为示例,并非真实接口地址。
                    success: (localRes) => {
                      console.log("游戏本地版本:", localRes.data.stamp);
                    },
                    fail: (err) => {
                      console.log("获取内部游戏版本失败", err);
                    },
                  });
                },
                function (error) {
                  console.log("解压解压失败:" + error);
                }
              );
            } else {
              console.log("下载失败");
            }
          },
        });
      },
    };
  }

  return {
    getInstance: function () {
      if (!instance) {
        instance = init();
      }
      return instance;
    },
  };
})();

// 使用单例对象
export var httpServer = HttpServer.getInstance();

webview.vue

<template>
  <view style="background: #2b335e">
    <web-view
      ref="webView"
      class="web"
      :src="src"
      style="background: #2b335e"
      :webview-styles="webviewStyles"
      @message="handleMessage"
    ></web-view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      currentWebview: null,
      wv: null,
      src: "",
      webviewStyles: {
        background: "rgb(43 51 94)",
      },
    };
  },
  created() {
    console.log("开启webview");
  },
  desotryed() {
    console.log("关闭webview");
  },
  onLoad(options) {
    console.log("===onLoad===");
    if (options && options.url) {
      this.src = options.url;
      // this.$store.commit('setWebviewStatus', 1);
      console.log("打开的页面是:", this.src);
    }
  },
  onUnload() {
    // this.$store.commit('setWebviewStatus', 0);
  },
  onReady() {
    console.log("===onReady===");
    // #ifdef APP-PLUS
    this.currentWebview = this.$scope.$getAppWebview(); //此对象相当于html5plus里的plus.webview.currentWebview()。在uni-app里vue页面直接使用plus.webview.currentWebview()无效
    setTimeout(() => {
      this.wv = this.currentWebview.children()[0];
      console.log("wv1", this.wv);
    }, 200); //如果是页面初始化调用时,需要延时一下
    // #endif
  },
  onShow() {
    console.log("===onShow===");
  },

  methods: {
    handleMessage(evt) {
      if (!this.wv) {
        this.wv = this.currentWebview.children()[0];
        if (!this.wv) {
          this.$mHelper.toast(`handleMessage error:${this.wv}`);
          return;
        }
      }
      // console.log('evt.detail==>', evt.detail);
      // console.log('wv2==>', this.wv);
      const actionName = evt.detail.data[0].actionName;
      const callBackFunctionName = evt.detail.data[0].callBackFunctionName;
      const params = evt.detail.data[0].params;
      switch (actionName) {
        case "uni_getCommonHeader":
          this.wv.evalJS(
            `${callBackFunctionName}(${JSON.stringify(this.$http.config)})`
          );
          break;
        case "uni_openPage":
          console.log("===", params.url);
          uni.navigateTo({
            url: "/pages/webview/subWebview?url=" + params.url,
          });
          break;
        case "uni_request":
          this.$http
            .post(params.url, params.data)
            .then((res) => {
              this.wv.evalJS(`${callBackFunctionName}(${JSON.stringify(res)})`);
            })
            .catch((err) => {
              this.$mHelper.toast(`${err}`);
            });
          break;
        default:
          break;
      }
    },
  },
};
</script>

<style lang="scss" scoped></style>