upgrade.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. const compareVersion = (a = "", b = "") => {
  2. const aList = String(a)
  3. .split(".")
  4. .map((item) => Number(item || 0));
  5. const bList = String(b)
  6. .split(".")
  7. .map((item) => Number(item || 0));
  8. const length = Math.max(aList.length, bList.length);
  9. for (let i = 0; i < length; i += 1) {
  10. const aNum = aList[i] || 0;
  11. const bNum = bList[i] || 0;
  12. if (aNum > bNum) return 1;
  13. if (aNum < bNum) return -1;
  14. }
  15. return 0;
  16. };
  17. /**
  18. * @description 检查app版本是否需要升级
  19. * @param name:最新版本名称
  20. * @param code:最新版本号
  21. * @param content:更新内容
  22. * @param url:下载链接
  23. * @param forceUpdate:是否强制升级
  24. */
  25. export const checkVersion = async ({
  26. name, //最新版本名称
  27. code, //最新版本号
  28. content, //更新内容
  29. url, //下载链接
  30. forceUpdate, //是否强制升级
  31. }) => {
  32. const currentAppVersion = plus.runtime.version;
  33. if (compareVersion(code, currentAppVersion) > 0) {
  34. let platform = uni.getSystemInfoSync().platform; //手机平台
  35. if (platform === "android") {
  36. uni.$emit("upgrade-app", {
  37. name,
  38. content,
  39. url,
  40. forceUpdate,
  41. });
  42. return true;
  43. } else {
  44. uni.showModal({
  45. title: "发现新版本 V" + name,
  46. content: "请到App store进行升级",
  47. showCancel: false,
  48. });
  49. }
  50. }
  51. return false;
  52. };
  53. //获取当前页面url
  54. const getCurrentPageRoute = () => {
  55. let currentRoute;
  56. let pages = getCurrentPages(); // 获取栈实例
  57. if (pages && pages.length) {
  58. currentRoute = pages[pages.length - 1].route;
  59. }
  60. return currentRoute;
  61. };
  62. /**
  63. * @description H5+下载App
  64. * @param downloadUrl:App下载链接
  65. * @param progressCallBack:下载进度回调
  66. */
  67. export const downloadApp = (downloadUrl, progressCallBack = () => {}) => {
  68. console.log("🚀 ~ downloadApp ~ downloadUrl:", downloadUrl);
  69. // 将模拟进度变量移到事件监听外部,确保状态能累积
  70. let mockProgress = 0;
  71. // 进度更新节流控制变量
  72. let lastProgressTime = 0;
  73. const PROGRESS_INTERVAL = 300; // 限制300ms内最多更新一次进度
  74. return new Promise((resolve, reject) => {
  75. // 创建下载任务
  76. const downloadTask = plus.downloader.createDownload(
  77. downloadUrl,
  78. { method: "GET" },
  79. (task, status) => {
  80. console.log("🚀 ~ returnnewPromise ~ task, status:", task, status);
  81. if (status == 200) {
  82. resolve(task.filename);
  83. } else {
  84. reject("fail");
  85. uni.showToast({
  86. title: "下载失败",
  87. duration: 1500,
  88. icon: "none",
  89. });
  90. }
  91. }
  92. );
  93. downloadTask.addEventListener("statechanged", (task, status) => {
  94. // 获取当前时间戳用于节流控制
  95. const now = Date.now();
  96. switch (task.state) {
  97. case 1: // 开始
  98. mockProgress = 0; // 仅在开始时重置
  99. progressCallBack(0, 0, task.totalSize || 0);
  100. break;
  101. case 2: // 已连接到服务器
  102. break;
  103. case 3: // 已接收到数据
  104. const hasProgress = task.totalSize && task.totalSize > 0;
  105. if (hasProgress) {
  106. mockProgress = 0;
  107. const current = parseInt(
  108. (100 * task.downloadedSize) / task.totalSize
  109. );
  110. progressCallBack(current, task.downloadedSize, task.totalSize);
  111. } else {
  112. // 模拟进度:添加节流控制和平滑增长
  113. if (
  114. mockProgress < 95 &&
  115. now - lastProgressTime > PROGRESS_INTERVAL
  116. ) {
  117. // 根据时间间隔动态调整增长速度,避免停滞感
  118. const baseIncrement = 1;
  119. const maxIncrement =
  120. mockProgress < 30 ? 3 : mockProgress < 60 ? 2 : 1;
  121. const increment =
  122. Math.floor(Math.random() * maxIncrement) + baseIncrement;
  123. mockProgress = Math.min(mockProgress + increment, 95);
  124. lastProgressTime = now; // 更新最后更新时间
  125. progressCallBack(mockProgress, task.downloadedSize, 0);
  126. }
  127. }
  128. break;
  129. case 4: // 下载完成
  130. progressCallBack(100, task.downloadedSize, task.totalSize || 0);
  131. break;
  132. }
  133. });
  134. downloadTask.start();
  135. });
  136. };
  137. /**
  138. * @description H5+安装APP
  139. * @param fileName:app文件名
  140. * @param callBack:安装成功回调
  141. */
  142. export const installApp = (fileName, callBack = () => {}) => {
  143. console.log("🚀 ~ installApp ~ fileName:", fileName);
  144. //注册广播监听app安装情况
  145. onInstallListening(callBack);
  146. //开始安装
  147. plus.runtime.install(
  148. plus.io.convertLocalFileSystemURL(fileName),
  149. {},
  150. () => {
  151. //成功跳转到安装界面
  152. },
  153. function (error) {
  154. console.log("🚀 ~ plus.runtime.install ~ error:", error);
  155. uni.showToast({
  156. title: "安装失败",
  157. duration: 1500,
  158. icon: "none",
  159. });
  160. }
  161. );
  162. };
  163. /**
  164. * @description 注册广播监听APP是否成功
  165. * @param callBack:安装成功回调函数
  166. */
  167. const onInstallListening = (callBack = () => {}) => {
  168. let mainActivity = plus.android.runtimeMainActivity(); //获取activity
  169. //生成广播接收器
  170. let receiver = plus.android.implements(
  171. "io.dcloud.android.content.BroadcastReceiver",
  172. {
  173. onReceive: (context, intent) => {
  174. //接收广播回调
  175. plus.android.importClass(intent);
  176. mainActivity.unregisterReceiver(receiver); //取消监听
  177. callBack();
  178. },
  179. }
  180. );
  181. let IntentFilter = plus.android.importClass("android.content.IntentFilter");
  182. let Intent = plus.android.importClass("android.content.Intent");
  183. let filter = new IntentFilter();
  184. filter.addAction(Intent.ACTION_PACKAGE_ADDED); //监听apk安装
  185. filter.addDataScheme("package");
  186. mainActivity.registerReceiver(receiver, filter); //注册广播
  187. };