APPUpdate1.js 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081
  1. /**** 此文件说明请看注释 *****/
  2. // 可以用自己项目的请求方法
  3. // 请求配置说明:https://ext.dcloud.net.cn/plugin?id=822
  4. import { getAppVersion } from '@/api/common';
  5. /**** 结束 *****/
  6. const platform = uni.getSystemInfoSync().platform;
  7. // 主颜色
  8. const $mainColor = "FF5C03";
  9. // 弹窗图标url
  10. const $iconUrl = "/uni_modules/uni-upgrade-center-app/static/app/bg_top.png";
  11. const $upArrowUrl = "/uni_modules/uni-upgrade-center-app/static/app/ic_ar.png";
  12. // 获取当前应用的版本号
  13. export const getCurrentNo = function(callback) {
  14. // 获取本地应用资源版本号
  15. plus.runtime.getProperty(plus.runtime.appid, function(inf) {
  16. callback && callback({
  17. versionCode: inf.versionCode,
  18. versionName: inf.version
  19. });
  20. });
  21. }
  22. // 发起ajax请求获取服务端版本号
  23. export const getServerNo = function(version, isPrompt = false, callback) {
  24. let isAndroid = platform == "android";
  25. let type = isAndroid ? 1 : 2;
  26. getAppVersion(type).then(res => {
  27. if (res.code == 200) {
  28. let cVersion = version.versionCode; //用户当前版本
  29. let appVersion = res.data.versionCode; //升级包版本
  30. if (cVersion < appVersion) {
  31. callback && callback(res.data);
  32. } else if (isPrompt) {
  33. uni.showToast({
  34. title: "当前已是最新版本",
  35. icon: "none"
  36. });
  37. }
  38. } else if (isPrompt) {
  39. uni.showToast({
  40. title: "检查更新失败",
  41. icon: "none"
  42. });
  43. }
  44. }).catch(err => {
  45. if (isPrompt) {
  46. uni.showToast({
  47. title: "检查更新失败",
  48. icon: "none"
  49. });
  50. }
  51. })
  52. }
  53. // 从服务器下载应用资源包(wgt文件)
  54. const getDownload = function(data) {
  55. let downloadUrl = data.url;
  56. if(data.isHotForce && !!data.wgtUrl){
  57. downloadUrl = data.wgtUrl;
  58. }
  59. if(plus.runtime.channel == "baidu" && data.baiduUrl){
  60. downloadUrl = data.baiduUrl;
  61. }
  62. console.log("qxj downloadUrl",downloadUrl);
  63. let popupData = Object.assign({}, data, {
  64. progress: true,
  65. buttonNum: 2
  66. });
  67. if(data.isForce || data.isHotForce){
  68. popupData.buttonNum = 0;
  69. }
  70. // 判断是否为 WGT 文件,如果是则隐藏按钮
  71. const isWGT = downloadUrl && String(downloadUrl).match(/\.wgt$/i);
  72. if (isWGT) {
  73. popupData.buttonNum = 0;
  74. } else if (popupData.buttonNum !== 0) {
  75. // 非强制且非WGT,默认显示关闭按钮
  76. popupData.buttonNum = 1;
  77. }
  78. let dtask;
  79. let lastProgressValue = 0;
  80. let popupObj = downloadPopup(popupData);
  81. // 使用 plus.downloader 创建下载任务,参考官方逻辑,虽然官方使用的是 uni.downloadFile,但 plus.downloader 提供更细粒度的控制,且此处已有进度条 UI 适配
  82. dtask = plus.downloader.createDownload(downloadUrl, {
  83. filename: "_doc/update/"
  84. }, function(download, status) {
  85. if (status == 200) {
  86. // 下载完成,如果是 WGT 热更新,立即提示正在安装
  87. const isWGT = download.filename.match(/\.wgt$/i);
  88. if (isWGT) {
  89. popupObj.change({
  90. contentText: "资源更新完成,正在安装...",
  91. buttonNum: 0,
  92. progress: false
  93. });
  94. }
  95. // 安装应用资源包
  96. // force: true 强制安装,忽略版本号校验,解决 -1205 错误(WGT安装包中manifest.json文件的version版本不匹配)
  97. // 因为前置逻辑已经校验过服务端版本号,此处强制安装以确保更新成功
  98. plus.runtime.install(download.filename, {
  99. force: isWGT
  100. }, function() {
  101. // 安装成功
  102. if (isWGT) {
  103. // WGT热更新:提示重启并自动重启
  104. popupObj.change({
  105. contentText: "安装成功,即将重启...",
  106. buttonNum: 0, // 不显示按钮
  107. progress: false
  108. });
  109. setTimeout(() => {
  110. plus.runtime.restart();
  111. }, 500); // 缩短重启等待时间以提升体验
  112. } else {
  113. // APK更新:系统安装界面已调起,直接关闭弹窗即可
  114. // 用户在系统安装界面操作,不需要应用内重启
  115. popupObj.cancel();
  116. }
  117. }, function(e) {
  118. popupObj.cancel();
  119. plus.nativeUI.alert("安装更新失败[" + e.code + "]:" + e.message);
  120. });
  121. } else {
  122. popupObj.change({
  123. contentText: "文件下载失败",
  124. buttonNum: 1,
  125. progress: false
  126. });
  127. }
  128. });
  129. dtask.start();
  130. // 监听下载进度
  131. dtask.addEventListener("statechanged", function(task, status) {
  132. switch (task.state) {
  133. case 1: // 开始
  134. popupObj.change({
  135. progressValue: 0,
  136. progressTip: "准备下载...",
  137. progress: true
  138. });
  139. break;
  140. case 2: // 已连接到服务器
  141. popupObj.change({
  142. progressValue: 0,
  143. progressTip: "开始下载...",
  144. progress: true
  145. });
  146. break;
  147. case 3: // 下载中
  148. if (task.totalSize > 0) {
  149. const progress = parseInt(task.downloadedSize / task.totalSize * 100);
  150. if (progress - lastProgressValue >= 2 || progress === 100) {
  151. lastProgressValue = progress;
  152. popupObj.change({
  153. progressValue: progress,
  154. progressTip: "已下载 " + progress + "%",
  155. progress: true
  156. });
  157. }
  158. }
  159. break;
  160. case 4: // 下载完成
  161. // 已经在 createDownload 回调中处理
  162. break;
  163. }
  164. });
  165. // 取消下载
  166. popupObj.cancelDownload = function(){
  167. dtask && dtask.abort();
  168. uni.showToast({
  169. title: "已取消下载",
  170. icon: "none"
  171. });
  172. }
  173. // 关闭/重启 (虽然此处命名为 reboot,但在失败或完成时可能是关闭弹窗)
  174. popupObj.reboot = function(){
  175. // 这里的逻辑取决于 popupObj.change 后的状态
  176. // 如果是下载失败,点击关闭只是关闭弹窗
  177. // 如果是安装成功,通常会自动重启,或者点击后重启
  178. // 目前 buttonNum=1 时绑定的是 reboot
  179. popupObj.cancel();
  180. }
  181. }
  182. // 文字换行
  183. function drawtext(text, maxWidth) {
  184. if (!text) {
  185. return [{ type: "text", content: "" }];
  186. }
  187. text = String(text);
  188. let textArr = text.split("");
  189. let len = textArr.length;
  190. // 上个节点
  191. let previousNode = 0;
  192. // 记录节点宽度
  193. let nodeWidth = 0;
  194. // 文本换行数组
  195. let rowText = [];
  196. // 如果是字母,侧保存长度
  197. let letterWidth = 0;
  198. // 汉字宽度
  199. let chineseWidth = 14;
  200. // otherFont宽度
  201. let otherWidth = 7;
  202. for (let i = 0; i < len; i++) {
  203. if (/[\u4e00-\u9fa5]|[\uFE30-\uFFA0]/g.test(textArr[i])) {
  204. if(letterWidth > 0){
  205. if(nodeWidth + chineseWidth + letterWidth * otherWidth > maxWidth){
  206. rowText.push({
  207. type: "text",
  208. content: text.substring(previousNode, i)
  209. });
  210. previousNode = i;
  211. nodeWidth = chineseWidth;
  212. letterWidth = 0;
  213. } else {
  214. nodeWidth += chineseWidth + letterWidth * otherWidth;
  215. letterWidth = 0;
  216. }
  217. }
  218. else {
  219. if(nodeWidth + chineseWidth > maxWidth){
  220. rowText.push({
  221. type: "text",
  222. content: text.substring(previousNode, i)
  223. });
  224. previousNode = i;
  225. nodeWidth = chineseWidth;
  226. }else{
  227. nodeWidth += chineseWidth;
  228. }
  229. }
  230. }
  231. else {
  232. if(/\n/g.test(textArr[i])){
  233. rowText.push({
  234. type: "break",
  235. content: text.substring(previousNode, i)
  236. });
  237. previousNode = i + 1;
  238. nodeWidth = 0;
  239. letterWidth = 0;
  240. }else if(textArr[i] == "\\" && textArr[i + 1] == "n"){
  241. rowText.push({
  242. type: "break",
  243. content: text.substring(previousNode, i)
  244. });
  245. previousNode = i + 2;
  246. nodeWidth = 0;
  247. letterWidth = 0;
  248. }else if(/[a-zA-Z0-9]/g.test(textArr[i])){
  249. letterWidth += 1;
  250. if(nodeWidth + letterWidth * otherWidth > maxWidth){
  251. rowText.push({
  252. type: "text",
  253. content: text.substring(previousNode, i + 1 - letterWidth)
  254. });
  255. previousNode = i + 1 - letterWidth;
  256. nodeWidth = letterWidth * otherWidth;
  257. letterWidth = 0;
  258. }
  259. } else{
  260. if(nodeWidth + otherWidth > maxWidth){
  261. rowText.push({
  262. type: "text",
  263. content: text.substring(previousNode, i)
  264. });
  265. previousNode = i;
  266. nodeWidth = otherWidth;
  267. }else{
  268. nodeWidth += otherWidth;
  269. }
  270. }
  271. }
  272. }
  273. if (previousNode < len) {
  274. rowText.push({
  275. type: "text",
  276. content: text.substring(previousNode, len)
  277. });
  278. }
  279. return rowText;
  280. }
  281. // 是否更新弹窗
  282. function updatePopup(data, callback) {
  283. // 弹窗遮罩层
  284. let maskLayer = new plus.nativeObj.View("maskLayer", { //先创建遮罩层
  285. top: '0px',
  286. left: '0px',
  287. height: '100%',
  288. width: '100%',
  289. backgroundColor: 'rgba(0,0,0,0.5)'
  290. });
  291. // 以下为计算菜单的nview绘制布局,为固定算法,使用者无关关心
  292. const screenWidth = plus.screen.resolutionWidth;
  293. const screenHeight = plus.screen.resolutionHeight;
  294. // 弹窗容器宽度
  295. const popupViewWidth = screenWidth * 0.75;
  296. // 弹窗容器的Padding
  297. const viewContentPadding = 20;
  298. // 弹窗容器的宽度
  299. const viewContentWidth = parseInt(popupViewWidth - (viewContentPadding * 2));
  300. // 描述的列表
  301. const descriptionList = drawtext(data.note, viewContentWidth);
  302. // 弹窗容器高度
  303. let popupViewHeight = 130 + 20 + 20 + 90 + 10;
  304. let popupViewContentList = [
  305. {
  306. tag: 'rect', // 绘制白色背景
  307. rectStyles: {
  308. color: "#FFFFFF",
  309. radius: "8px"
  310. },
  311. position: {
  312. top: "40px",
  313. height: "100%", // Will be updated later if needed, but since we know the height we can use 100% or calc
  314. }
  315. },
  316. {
  317. src: $iconUrl,
  318. id: "logo",
  319. tag: "img",
  320. position: {
  321. top: "0px",
  322. left: "0px",
  323. width: popupViewWidth + "px",
  324. height: "130px",
  325. }
  326. },
  327. {
  328. src: $upArrowUrl,
  329. id: "upArrow",
  330. tag: "img",
  331. position: {
  332. top: "15px",
  333. left: (popupViewWidth / 2 - 35) + "px",
  334. width: "70px",
  335. height: "70px",
  336. }
  337. },
  338. {
  339. tag: 'font',
  340. id: 'title',
  341. text: "发现新版本 ",
  342. textStyles: {
  343. size: '18px',
  344. color: "#333",
  345. weight: "bold",
  346. whiteSpace: "normal"
  347. },
  348. position: {
  349. top: '140px',
  350. left: viewContentPadding + "px",
  351. width: "90px",
  352. height: "30px",
  353. }
  354. },
  355. {
  356. tag: 'rect', // 版本号背景
  357. rectStyles:{
  358. color: "#FF5C03",
  359. radius: "10px"
  360. },
  361. position: {
  362. top: '145px',
  363. left: viewContentPadding + 95 + "px",
  364. width: "40px",
  365. height: "20px",
  366. }
  367. },
  368. {
  369. tag: 'font',
  370. id: 'version',
  371. text: data.versionName || "1.0.0",
  372. textStyles: {
  373. size: '12px',
  374. color: "#FFFFFF",
  375. },
  376. position: {
  377. top: '145px',
  378. left: viewContentPadding + 95 + "px",
  379. width: "40px",
  380. height: "20px",
  381. }
  382. }];
  383. const textHeight = 18;
  384. let contentTop = 180;
  385. descriptionList.forEach((item,index) => {
  386. if(index > 0){
  387. popupViewHeight += textHeight;
  388. contentTop += textHeight;
  389. }
  390. popupViewContentList.push({
  391. tag: 'font',
  392. id: 'content' + index + 1,
  393. text: item.content,
  394. textStyles: {
  395. size: '14px',
  396. color: "#666",
  397. lineSpacing: "50%",
  398. align: "left"
  399. },
  400. position: {
  401. top: contentTop + "px",
  402. left: viewContentPadding + "px",
  403. width: viewContentWidth + "px",
  404. height: textHeight + "px",
  405. }
  406. });
  407. if(item.type == "break"){
  408. contentTop += 10;
  409. popupViewHeight += 10;
  410. }
  411. });
  412. // 弹窗内容
  413. let popupView = new plus.nativeObj.View("popupView", { //创建底部图标菜单
  414. tag: "rect",
  415. top: (screenHeight - popupViewHeight) / 2 + "px",
  416. left: '12.5%',
  417. height: popupViewHeight + "px",
  418. width: "75%"
  419. });
  420. // 绘制白色背景
  421. popupViewContentList[0].position.height = popupViewHeight - 40 + "px";
  422. // 判断是否强制更新,强制更新只显示一个按钮
  423. const isForce = data.isForce || data.isHotForce;
  424. if (isForce) {
  425. // 绘制单个底边按钮 (强制更新)
  426. popupViewContentList.push({
  427. tag: 'rect',
  428. rectStyles: {
  429. radius: "20px",
  430. color: $mainColor,
  431. },
  432. position: {
  433. bottom: viewContentPadding + 'px',
  434. left: viewContentPadding + "px",
  435. width: viewContentWidth + "px",
  436. height: "40px",
  437. }
  438. });
  439. popupViewContentList.push({
  440. tag: 'font',
  441. id: 'confirmText',
  442. text: "立即下载更新",
  443. textStyles: {
  444. size: '16px',
  445. color: "#FFF",
  446. lineSpacing: "0%",
  447. whiteSpace: "normal"
  448. },
  449. position: {
  450. bottom: viewContentPadding + 'px',
  451. left: viewContentPadding + "px",
  452. width: viewContentWidth + "px",
  453. height: "40px",
  454. }
  455. });
  456. } else {
  457. // 绘制底边按钮 (非强制更新,显示暂不升级)
  458. popupViewContentList.push({
  459. tag: 'rect',
  460. rectStyles: {
  461. radius: "20px",
  462. borderColor: "#f1f1f1",
  463. borderWidth: "1px",
  464. },
  465. position: {
  466. bottom: viewContentPadding + 'px',
  467. left: viewContentPadding + "px",
  468. width: (viewContentWidth - viewContentPadding) / 2 + "px",
  469. height: "40px",
  470. }
  471. });
  472. // 绘制底边按钮 (非强制更新,显示立即升级)
  473. popupViewContentList.push({
  474. tag: 'rect',
  475. rectStyles: {
  476. radius: "20px",
  477. color: $mainColor,
  478. },
  479. position: {
  480. bottom: viewContentPadding + 'px',
  481. left: ((viewContentWidth - viewContentPadding) / 2 + viewContentPadding * 2) + "px",
  482. width: (viewContentWidth - viewContentPadding) / 2 + "px",
  483. height: "40px",
  484. }
  485. });
  486. popupViewContentList.push({
  487. tag: 'font',
  488. id: 'cancelText',
  489. text: "取消",
  490. textStyles: {
  491. size: '16px',
  492. color: "#666",
  493. lineSpacing: "0%",
  494. whiteSpace: "normal"
  495. },
  496. position: {
  497. bottom: viewContentPadding + 'px',
  498. left: viewContentPadding + "px",
  499. width: (viewContentWidth - viewContentPadding) / 2 + "px",
  500. height: "40px",
  501. }
  502. });
  503. popupViewContentList.push({
  504. tag: 'font',
  505. id: 'confirmText',
  506. text: "立即下载更新",
  507. textStyles: {
  508. size: '16px',
  509. color: "#FFF",
  510. lineSpacing: "0%",
  511. whiteSpace: "normal"
  512. },
  513. position: {
  514. bottom: viewContentPadding + 'px',
  515. left: ((viewContentWidth - viewContentPadding) / 2 + viewContentPadding * 2) + "px",
  516. width: (viewContentWidth - viewContentPadding) / 2 + "px",
  517. height: "40px",
  518. }
  519. });
  520. }
  521. popupView.draw(popupViewContentList);
  522. popupView.addEventListener("click", function(e) {
  523. let maxTop = popupViewHeight - viewContentPadding;
  524. let maxLeft = popupViewWidth - viewContentPadding;
  525. let buttonWidth = (viewContentWidth - viewContentPadding) / 2;
  526. if (e.clientY > maxTop - 40 && e.clientY < maxTop) {
  527. if (isForce) {
  528. // 强制更新只有立即升级
  529. if (e.clientX > viewContentPadding && e.clientX < maxLeft) {
  530. maskLayer.hide();
  531. popupView.hide();
  532. callback && callback();
  533. setTimeout(() => {
  534. maskLayer.close();
  535. popupView.close();
  536. }, 100);
  537. }
  538. } else {
  539. // 取消
  540. if (e.clientX > viewContentPadding && e.clientX < maxLeft - buttonWidth - viewContentPadding) {
  541. maskLayer.hide();
  542. popupView.hide();
  543. setTimeout(() => {
  544. maskLayer.close();
  545. popupView.close();
  546. }, 100);
  547. } else if (e.clientX > maxLeft - buttonWidth && e.clientX < maxLeft) {
  548. // 立即升级
  549. maskLayer.hide();
  550. popupView.hide();
  551. callback && callback();
  552. setTimeout(() => {
  553. maskLayer.close();
  554. popupView.close();
  555. }, 100);
  556. }
  557. }
  558. }
  559. });
  560. // 显示弹窗
  561. maskLayer.show();
  562. popupView.show();
  563. }
  564. // 文件下载的弹窗
  565. function downloadPopup(data) {
  566. // 弹窗遮罩层
  567. let maskLayer = new plus.nativeObj.View("downloadMaskLayer", { //先创建遮罩层
  568. top: '0px',
  569. left: '0px',
  570. height: '100%',
  571. width: '100%',
  572. backgroundColor: 'rgba(0,0,0,0.5)'
  573. });
  574. let popupViewData = downloadPopupDrawing(data);
  575. // 弹窗内容
  576. let popupView = new plus.nativeObj.View("downloadPopupView", { //创建底部图标菜单
  577. tag: "rect",
  578. top: (popupViewData.screenHeight - popupViewData.popupViewHeight) / 2 + "px",
  579. left: '12.5%',
  580. height: popupViewData.popupViewHeight + "px",
  581. width: "75%",
  582. });
  583. let progressValue = 0;
  584. let progressTop = popupViewData.progressTop;
  585. let progressTip = 0;
  586. let contentText = 0;
  587. let buttonNum = 2;
  588. if(data.buttonNum >= 0){
  589. buttonNum = data.buttonNum;
  590. }
  591. popupView.draw(popupViewData.elementList);
  592. let callbackData = {
  593. change: function(res) {
  594. let progressElement = [];
  595. if(res.progressValue){
  596. progressValue = res.progressValue;
  597. let progressWidth = res.progressValue / 100 * popupViewData.viewContentWidth;
  598. // 绘制进度条
  599. progressElement.push({
  600. tag: 'rect', //绘制进度条背景
  601. id: 'progressValueBg',
  602. rectStyles:{
  603. radius: "4px",
  604. color: $mainColor
  605. },
  606. position:{
  607. top: progressTop + 40 + 'px',
  608. left: popupViewData.viewContentPadding + "px",
  609. width: progressWidth + "px",
  610. height: "8px"
  611. }
  612. });
  613. }
  614. if(res.progressTip){
  615. progressTip = res.progressTip;
  616. progressElement.push({
  617. tag: 'font',
  618. id: 'progressValue',
  619. text: res.progressTip,
  620. textStyles: {
  621. size: '14px',
  622. color: $mainColor,
  623. whiteSpace: "normal"
  624. },
  625. position: {
  626. top: progressTop + 'px',
  627. height: "30px"
  628. }
  629. });
  630. }
  631. if(res.contentText){
  632. contentText = res.contentText;
  633. progressElement.push({
  634. tag: 'font',
  635. id: 'content',
  636. text: res.contentText,
  637. textStyles: {
  638. size: '14px',
  639. color: $mainColor,
  640. whiteSpace: "normal"
  641. },
  642. position: {
  643. top: progressTop + 'px',
  644. height: "30px",
  645. }
  646. });
  647. }
  648. if(res.buttonNum >= 0 && buttonNum != res.buttonNum){
  649. buttonNum = res.buttonNum;
  650. popupView.reset();
  651. popupViewData = downloadPopupDrawing(Object.assign({
  652. progressTip: res.contentText || "准备下载...",
  653. }, data, {
  654. buttonNum: buttonNum,
  655. }));
  656. progressTop = popupViewData.progressTop;
  657. let newElement = [];
  658. popupViewData.elementList.map((item, index) => {
  659. let have = false;
  660. progressElement.forEach((childItem, childIndex) => {
  661. if(item.id == childItem.id){
  662. have = true;
  663. }
  664. });
  665. if(!have){
  666. newElement.push(item);
  667. }
  668. });
  669. progressElement = newElement.concat(progressElement);
  670. popupView.setStyle({
  671. tag: "rect",
  672. top: (popupViewData.screenHeight - popupViewData.popupViewHeight) / 2 + "px",
  673. left: '12.5%',
  674. height: popupViewData.popupViewHeight + "px",
  675. width: "75%",
  676. });
  677. popupView.draw(progressElement);
  678. }else{
  679. popupView.draw(progressElement);
  680. }
  681. },
  682. cancel: function() {
  683. maskLayer.hide();
  684. popupView.hide();
  685. setTimeout(() => {
  686. maskLayer.close();
  687. popupView.close();
  688. }, 100);
  689. },
  690. reboot: function() {
  691. maskLayer.hide();
  692. popupView.hide();
  693. setTimeout(() => {
  694. maskLayer.close();
  695. popupView.close();
  696. }, 100);
  697. },
  698. cancelDownload: function() {
  699. maskLayer.hide();
  700. popupView.hide();
  701. setTimeout(() => {
  702. maskLayer.close();
  703. popupView.close();
  704. }, 100);
  705. }
  706. }
  707. popupView.addEventListener("click", function(e) {
  708. let maxTop = popupViewData.popupViewHeight - popupViewData.viewContentPadding;
  709. let maxLeft = popupViewData.popupViewWidth - popupViewData.viewContentPadding;
  710. if (e.clientY > maxTop - 40 && e.clientY < maxTop) {
  711. if (buttonNum == 1) {
  712. // 单按钮
  713. if (e.clientX > popupViewData.viewContentPadding && e.clientX < maxLeft) {
  714. callbackData.reboot();
  715. }
  716. } else if (buttonNum == 2) {
  717. // 双按钮
  718. let buttonWidth = (popupViewData.viewContentWidth - popupViewData.viewContentPadding) / 2;
  719. if (e.clientX > popupViewData.viewContentPadding && e.clientX < maxLeft - buttonWidth - popupViewData.viewContentPadding) {
  720. callbackData.cancelDownload();
  721. } else if (e.clientX > maxLeft - buttonWidth && e.clientX < maxLeft) {
  722. maskLayer.hide();
  723. popupView.hide();
  724. setTimeout(() => {
  725. maskLayer.close();
  726. popupView.close();
  727. }, 100);
  728. }
  729. }
  730. }
  731. });
  732. // 显示弹窗
  733. maskLayer.show();
  734. popupView.show();
  735. // 改变进度条
  736. return callbackData;
  737. }
  738. // 文件下载的弹窗绘图
  739. function downloadPopupDrawing(data){
  740. // 以下为计算菜单的nview绘制布局,为固定算法,使用者无关关心
  741. const screenWidth = plus.screen.resolutionWidth;
  742. const screenHeight = plus.screen.resolutionHeight;
  743. //弹窗容器宽度
  744. const popupViewWidth = screenWidth * 0.75;
  745. // 弹窗容器的Padding
  746. const viewContentPadding = 20;
  747. // 弹窗容器的宽度
  748. const viewContentWidth = popupViewWidth - (viewContentPadding * 2);
  749. // 描述的列表
  750. const descriptionList = drawtext(data.note || "健康守护系统更新中~~请稍候", viewContentWidth);
  751. // 弹窗容器高度
  752. let popupViewHeight = 130 + 20 + 20 + 90 + 10;
  753. let progressTip = data.progressTip || "准备下载...";
  754. let contentText = data.contentText || "健康守护系统更新中~~请稍候";
  755. let elementList = [
  756. {
  757. src: $iconUrl,
  758. id: "logo",
  759. tag: "img",
  760. position: {
  761. top: "0px",
  762. left: "0px",
  763. width: popupViewWidth + "px",
  764. height: "130px",
  765. }
  766. },
  767. {
  768. src: $upArrowUrl,
  769. id: "upArrow",
  770. tag: "img",
  771. position: {
  772. top: "15px",
  773. left: (popupViewWidth / 2 - 35) + "px",
  774. width: "70px",
  775. height: "70px",
  776. }
  777. },
  778. {
  779. tag: 'rect', //背景色
  780. color: '#FFFFFF',
  781. rectStyles:{
  782. radius: "8px"
  783. },
  784. position: {
  785. top: "40px",
  786. height: popupViewHeight - 40 + "px",
  787. }
  788. },
  789. {
  790. tag: 'font',
  791. id: 'title',
  792. text: "发现新版本 ",
  793. textStyles: {
  794. size: '18px',
  795. color: "#333",
  796. weight: "bold",
  797. whiteSpace: "normal"
  798. },
  799. position: {
  800. top: '140px',
  801. left: viewContentPadding + "px",
  802. width: "90px",
  803. height: "30px",
  804. }
  805. },
  806. {
  807. tag: 'rect', // 版本号背景
  808. rectStyles:{
  809. color: "#FF5C03",
  810. radius: "10px"
  811. },
  812. position: {
  813. top: '145px',
  814. left: viewContentPadding + 95 + "px",
  815. width: "40px",
  816. height: "20px",
  817. }
  818. },
  819. {
  820. tag: 'font',
  821. id: 'version',
  822. text: data.versionName || "1.0.0",
  823. textStyles: {
  824. size: '12px',
  825. color: "#FFFFFF",
  826. },
  827. position: {
  828. top: '145px',
  829. left: viewContentPadding + 95 + "px",
  830. width: "40px",
  831. height: "20px",
  832. }
  833. }
  834. ];
  835. const textHeight = 18;
  836. let contentTop = 180;
  837. descriptionList.forEach((item,index) => {
  838. if(index > 0){
  839. popupViewHeight += textHeight;
  840. contentTop += textHeight;
  841. }
  842. elementList.push({
  843. tag: 'font',
  844. id: 'content' + index + 1,
  845. text: item.content,
  846. textStyles: {
  847. size: '14px',
  848. color: "#666",
  849. lineSpacing: "50%",
  850. align: "left"
  851. },
  852. position: {
  853. top: contentTop + "px",
  854. left: viewContentPadding + "px",
  855. width: viewContentWidth + "px",
  856. height: textHeight + "px",
  857. }
  858. });
  859. if(item.type == "break"){
  860. contentTop += 10;
  861. popupViewHeight += 10;
  862. }
  863. });
  864. let progressTop = 0;
  865. if (data.progress) {
  866. popupViewHeight += viewContentPadding * 2 + 40;
  867. progressTop = contentTop + 40;
  868. elementList = elementList.concat([
  869. {
  870. tag: 'font',
  871. id: 'progressValue',
  872. text: progressTip,
  873. textStyles: {
  874. size: '14px',
  875. color: $mainColor,
  876. whiteSpace: "normal"
  877. },
  878. position: {
  879. top: progressTop + 'px',
  880. height: "30px"
  881. }
  882. },
  883. {
  884. tag: 'rect', //绘制进度条背景
  885. id: 'progressBg',
  886. rectStyles:{
  887. radius: "4px",
  888. borderColor: "#f1f1f1",
  889. borderWidth: "1px",
  890. },
  891. position:{
  892. top: progressTop + 40 + 'px',
  893. left: viewContentPadding + "px",
  894. width: viewContentWidth + "px",
  895. height: "8px"
  896. }
  897. },
  898. ]);
  899. }
  900. if(data.buttonNum == 2){
  901. popupViewHeight += viewContentPadding + 30;
  902. elementList = elementList.concat([
  903. {
  904. tag: 'rect', //绘制底边按钮
  905. rectStyles:{
  906. radius: "20px",
  907. borderColor: "#f1f1f1",
  908. borderWidth: "1px",
  909. },
  910. position:{
  911. bottom: viewContentPadding + 'px',
  912. left: viewContentPadding + "px",
  913. width: (viewContentWidth - viewContentPadding) / 2 + "px",
  914. height: "40px"
  915. }
  916. },
  917. {
  918. tag: 'rect', //绘制底边按钮
  919. rectStyles:{
  920. radius: "20px",
  921. color: $mainColor,
  922. },
  923. position:{
  924. bottom: viewContentPadding + 'px',
  925. left: ((viewContentWidth - viewContentPadding) / 2 + viewContentPadding * 2) + "px",
  926. width: (viewContentWidth - viewContentPadding) / 2 + "px",
  927. height: "40px"
  928. }
  929. },
  930. {
  931. tag: 'font',
  932. id: 'cancelText',
  933. text: "取消",
  934. textStyles: {
  935. size: '16px',
  936. color: "#666",
  937. lineSpacing: "0%",
  938. whiteSpace: "normal"
  939. },
  940. position: {
  941. bottom: viewContentPadding + 'px',
  942. left: viewContentPadding + "px",
  943. width: (viewContentWidth - viewContentPadding) / 2 + "px",
  944. height: "40px",
  945. }
  946. },
  947. {
  948. tag: 'font',
  949. id: 'confirmText',
  950. text: "立即下载更新",
  951. textStyles: {
  952. size: '16px',
  953. color: "#FFF",
  954. lineSpacing: "0%",
  955. whiteSpace: "normal"
  956. },
  957. position: {
  958. bottom: viewContentPadding + 'px',
  959. left: ((viewContentWidth - viewContentPadding) / 2 + viewContentPadding * 2) + "px",
  960. width: (viewContentWidth - viewContentPadding) / 2 + "px",
  961. height: "40px",
  962. }
  963. }
  964. ]);
  965. }
  966. if(data.buttonNum == 1){
  967. popupViewHeight += viewContentPadding + 30;
  968. elementList = elementList.concat([
  969. {
  970. tag: 'rect', //绘制底边按钮
  971. rectStyles:{
  972. radius: "20px",
  973. color: $mainColor,
  974. },
  975. position:{
  976. bottom: viewContentPadding + 'px',
  977. left: viewContentPadding + "px",
  978. width: viewContentWidth + "px",
  979. height: "40px"
  980. }
  981. },
  982. {
  983. tag: 'font',
  984. id: 'confirmText',
  985. text: "立即下载更新",
  986. textStyles: {
  987. size: '16px',
  988. color: "#FFF",
  989. lineSpacing: "0%",
  990. whiteSpace: "normal"
  991. },
  992. position: {
  993. bottom: viewContentPadding + 'px',
  994. left: viewContentPadding + "px",
  995. width: viewContentWidth + "px",
  996. height: "40px",
  997. }
  998. }
  999. ]);
  1000. }
  1001. return {
  1002. popupView: popupView,
  1003. popupViewHeight: popupViewHeight,
  1004. popupViewWidth: popupViewWidth,
  1005. screenHeight: screenHeight,
  1006. viewContentWidth: viewContentWidth,
  1007. viewContentPadding: viewContentPadding,
  1008. progressTop: progressTop,
  1009. elementList: elementList
  1010. };
  1011. }
  1012. export function openDownload(data) {
  1013. updatePopup(data, function() {
  1014. let isWgt = /\.wgt$/i.test(data.url) || (data.isHotForce && !!data.wgtUrl);
  1015. if (isWgt) {
  1016. getDownload(data);
  1017. } else if(/\.html$/i.test(data.url)){
  1018. plus.runtime.openURL(data.url);
  1019. } else {
  1020. if (platform == "android") {
  1021. getDownload(data);
  1022. } else {
  1023. plus.runtime.openURL(data.url);
  1024. }
  1025. }
  1026. });
  1027. }
  1028. export function appCheckUdate(isPrompt = false) {
  1029. getCurrentNo(versionInfo => {
  1030. getServerNo(versionInfo, isPrompt, res => {
  1031. updatePopup(res, function() {
  1032. let isWgt = /\.wgt$/i.test(res.url) || (res.isHotForce && !!res.wgtUrl);
  1033. if (isWgt) {
  1034. getDownload(res);
  1035. } else if(/\.html$/i.test(res.url)){
  1036. plus.runtime.openURL(res.url);
  1037. } else {
  1038. if (platform == "android") {
  1039. getDownload(res);
  1040. } else {
  1041. plus.runtime.openURL(res.url);
  1042. }
  1043. }
  1044. });
  1045. });
  1046. });
  1047. }