util.js 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512
  1. // +----------------------------------------------------------------------
  2. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  3. // +----------------------------------------------------------------------
  4. // | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
  5. // +----------------------------------------------------------------------
  6. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  7. // +----------------------------------------------------------------------
  8. // | Author: CRMEB Team <admin@crmeb.com>
  9. // +----------------------------------------------------------------------
  10. import {
  11. TOKENNAME,
  12. HTTP_REQUEST_URL
  13. } from '../config/app.js';
  14. import store from '../store';
  15. import animationType from '@/utils/animationType.js'
  16. // #ifdef APP-PLUS
  17. import permision from "./permission.js"
  18. // #endif
  19. export default {
  20. /**
  21. * 时间截取成字符串 23-06-26
  22. * @param {Object} time 2023-06-26 15:13:00
  23. */
  24. getTime(time) {
  25. let reg = new RegExp('-', 'g'); //g代表全部
  26. return time.split(' ')[0].replace(reg, '.').substring(2, 10);
  27. },
  28. /**优惠券展示的使用有效期均根据今天进行判断,
  29. * 没到使用期的展示「开始日期-结束日期 有效」,
  30. * 已经可以使用的展示「有效期至 结束日期」
  31. * @param {Object} time
  32. */
  33. getCouponTime(startTime, endTime) {
  34. let start = new Date(startTime).getTime();
  35. let newTime = Date.now();
  36. let reg = new RegExp('-', 'g') //g代表全部
  37. if (newTime < start) {
  38. return startTime.slice(0, 16).replace(reg, '.') + ' - ' + endTime.slice(0, 16).replace(reg, '.') + ' 可用';
  39. } else {
  40. return '有效期至 ' + endTime.slice(0, 16).replace(reg, '.');
  41. }
  42. },
  43. /**
  44. * opt object | string
  45. * to_url object | string
  46. * 例:
  47. * this.Tips('/pages/test/test'); 跳转不提示
  48. * this.Tips({title:'提示'},'/pages/test/test'); 提示并跳转
  49. * this.Tips({title:'提示'},{tab:1,url:'/pages/index/index'}); 提示并跳转值table上
  50. * tab=1 一定时间后跳转至 table上
  51. * tab=2 一定时间后跳转至非 table上
  52. * tab=3 一定时间后返回上页面
  53. * tab=4 关闭所有页面跳转至非table上
  54. * tab=5 关闭当前页面跳转至table上
  55. */
  56. Tips: function(opt, to_url) {
  57. if (typeof opt == 'string') {
  58. to_url = opt;
  59. opt = {};
  60. }
  61. let title = opt.title || '',
  62. icon = opt.icon || 'none',
  63. endtime = opt.endtime || 1000,
  64. success = opt.success;
  65. if (title) uni.showToast({
  66. title: title,
  67. icon: icon,
  68. duration: endtime,
  69. success
  70. })
  71. if (to_url != undefined) {
  72. if (typeof to_url == 'object') {
  73. let tab = to_url.tab || 1,
  74. url = to_url.url || '';
  75. switch (tab) {
  76. case 1:
  77. //一定时间后跳转至 table
  78. setTimeout(function() {
  79. uni.switchTab({
  80. url: url
  81. })
  82. }, endtime);
  83. break;
  84. case 2:
  85. //跳转至非table页面
  86. setTimeout(function() {
  87. uni.navigateTo({
  88. url: url,
  89. })
  90. }, endtime);
  91. break;
  92. case 3:
  93. //返回上页面
  94. setTimeout(function() {
  95. // #ifndef H5
  96. uni.navigateBack({
  97. delta: parseInt(url),
  98. })
  99. // #endif
  100. // #ifdef H5
  101. history.back();
  102. // #endif
  103. }, endtime);
  104. break;
  105. case 4:
  106. //关闭当前所有页面跳转至非table页面
  107. setTimeout(function() {
  108. uni.reLaunch({
  109. url: url,
  110. })
  111. }, endtime);
  112. break;
  113. case 5:
  114. //关闭当前页面跳转至非table页面
  115. setTimeout(function() {
  116. uni.redirectTo({
  117. url: url,
  118. })
  119. }, endtime);
  120. break;
  121. }
  122. } else if (typeof to_url == 'function') {
  123. setTimeout(function() {
  124. to_url && to_url();
  125. }, endtime);
  126. } else {
  127. //没有提示时跳转不延迟
  128. setTimeout(function() {
  129. uni.navigateTo({
  130. url: to_url,
  131. })
  132. }, title ? endtime : 0);
  133. }
  134. }
  135. },
  136. /**
  137. * 移除数组中的某个数组并组成新的数组返回
  138. * @param array array 需要移除的数组
  139. * @param int index 需要移除的数组的键值
  140. * @param string | int 值
  141. * @return array
  142. *
  143. */
  144. ArrayRemove: function(array, index, value) {
  145. const valueArray = [];
  146. if (array instanceof Array) {
  147. for (let i = 0; i < array.length; i++) {
  148. if (typeof index == 'number' && array[index] != i) {
  149. valueArray.push(array[i]);
  150. } else if (typeof index == 'string' && array[i][index] != value) {
  151. valueArray.push(array[i]);
  152. }
  153. }
  154. }
  155. return valueArray;
  156. },
  157. /**
  158. * 获取视频分享海报
  159. * @param array arr2 海报素材
  160. * @param string store_name 素材文字
  161. * @param string price 价格
  162. * @param function successFn 回调函数
  163. *
  164. *
  165. */
  166. videoPosterCanvas: function(arr2, content, nickname, successFn, errFun) {
  167. let that = this;
  168. const ctx = uni.createCanvasContext('myCanvas');
  169. ctx.clearRect(0, 0, 0, 0);
  170. /**
  171. * 只能获取合法域名下的图片信息,本地调试无法获取
  172. *
  173. */
  174. uni.getImageInfo({
  175. src: arr2[0],
  176. success: function(res) {
  177. const WIDTH = res.width;
  178. const HEIGHT = res.height;
  179. let r = 90;
  180. let d = r * 2;
  181. let cx = 40;
  182. let cy = 760;
  183. let ux = 50;
  184. let uy = 700;
  185. ctx.drawImage(arr2[0], 0, 0, WIDTH, HEIGHT);
  186. ctx.drawImage(arr2[1], 32, 32, WIDTH - 64, WIDTH - 64);
  187. ctx.strokeStyle = "#ffffff";
  188. ctx.save();
  189. ctx.arc(cx + r, cy + r, r, 0, 2 * Math.PI);
  190. ctx.drawImage(arr2[2], 530, 760, d, d);
  191. that.handleBorderRect(ctx, ux, uy, r, r, 45);
  192. ctx.clip();
  193. ctx.stockStyle = "#ffffff";
  194. ctx.drawImage(arr2[3], ux, uy, r, r);
  195. ctx.restore();
  196. ctx.setTextAlign('left')
  197. ctx.setFontSize(28);
  198. ctx.setFillStyle('#282828');
  199. ctx.fillText(nickname, r + 60, 760);
  200. ctx.setTextAlign('left')
  201. ctx.setFontSize(28);
  202. ctx.setFillStyle('#282828');
  203. const CONTENT_ROW_LENGTH = 25;
  204. let [contentLeng, contentArray, contentRows] = that.textByteLength(content,
  205. CONTENT_ROW_LENGTH);
  206. if (contentRows > 2) {
  207. contentRows = 2;
  208. let textArray = contentArray.slice(0, 2);
  209. textArray[textArray.length - 1] += '……';
  210. contentArray = textArray;
  211. }
  212. ctx.setTextAlign('left');
  213. ctx.font = 'bold 32px Arial';
  214. let contentHh = 32 * 1.3;
  215. for (let m = 0; m < contentArray.length; m++) {
  216. ctx.fillText(contentArray[m], 55, 850 + contentHh * m);
  217. }
  218. ctx.draw(true, function() {
  219. uni.canvasToTempFilePath({
  220. canvasId: 'myCanvas',
  221. fileType: 'png',
  222. destWidth: WIDTH,
  223. destHeight: HEIGHT,
  224. success: function(res) {
  225. uni.hideLoading();
  226. successFn && successFn(res.tempFilePath);
  227. },
  228. fail: function(err) {
  229. uni.hideLoading();
  230. errFun && errFun(err);
  231. }
  232. })
  233. });
  234. },
  235. fail: function(err) {
  236. uni.hideLoading();
  237. that.Tips({
  238. title: '无法获取图片信息'
  239. });
  240. errFun && errFun(err);
  241. }
  242. })
  243. },
  244. /**
  245. * 生成海报获取文字
  246. * @param string text 为传入的文本
  247. * @param int num 为单行显示的字节长度
  248. * @return array
  249. */
  250. textByteLength: function(text, num) {
  251. let strLength = 0;
  252. let rows = 1;
  253. let str = 0;
  254. let arr = [];
  255. for (let j = 0; j < text.length; j++) {
  256. if (text.charCodeAt(j) > 255) {
  257. strLength += 2;
  258. if (strLength > rows * num) {
  259. strLength++;
  260. arr.push(text.slice(str, j));
  261. str = j;
  262. rows++;
  263. }
  264. } else {
  265. strLength++;
  266. if (strLength > rows * num) {
  267. arr.push(text.slice(str, j));
  268. str = j;
  269. rows++;
  270. }
  271. }
  272. }
  273. arr.push(text.slice(str, text.length));
  274. return [strLength, arr, rows] // [处理文字的总字节长度,每行显示内容的数组,行数]
  275. },
  276. /**
  277. * 获取分享海报
  278. * @param array arr2 海报素材
  279. * @param string store_name 素材文字
  280. * @param string price 价格
  281. * @param string ot_price 原始价格
  282. * @param function successFn 回调函数
  283. *
  284. *
  285. */
  286. PosterCanvas: function(arr2, store_name, price, ot_price, successFn) {
  287. let that = this;
  288. const ctx = uni.createCanvasContext('firstCanvas');
  289. ctx.clearRect(0, 0, 0, 0);
  290. /**
  291. * 只能获取合法域名下的图片信息,本地调试无法获取
  292. *
  293. */
  294. ctx.fillStyle = '#fff';
  295. ctx.fillRect(0, 0, 750, 1150);
  296. uni.getImageInfo({
  297. src: arr2[0],
  298. success: function(res) {
  299. const WIDTH = res.width;
  300. const HEIGHT = res.height;
  301. // ctx.drawImage(arr2[0], 0, 0, WIDTH, 1050);
  302. ctx.drawImage(arr2[1], 0, 0, WIDTH, WIDTH);
  303. ctx.save();
  304. let r = 110;
  305. let d = r * 2;
  306. let cx = 480;
  307. let cy = 790;
  308. ctx.arc(cx + r, cy + r, r, 0, 2 * Math.PI);
  309. // ctx.clip();
  310. ctx.drawImage(arr2[2], cx, cy, d, d);
  311. ctx.restore();
  312. const CONTENT_ROW_LENGTH = 18;
  313. let [contentLeng, contentArray, contentRows] = that.textByteLength(store_name,
  314. CONTENT_ROW_LENGTH);
  315. if (contentRows > 2) {
  316. contentRows = 2;
  317. let textArray = contentArray.slice(0, 2);
  318. textArray[textArray.length - 1] += '……';
  319. contentArray = textArray;
  320. }
  321. ctx.setTextAlign('left');
  322. ctx.setFontSize(36);
  323. ctx.setFillStyle('#000');
  324. // let contentHh = 36 * 1.5;
  325. let contentHh = 36;
  326. for (let m = 0; m < contentArray.length; m++) {
  327. // ctx.fillText(contentArray[m], 50, 1000 + contentHh * m,750);
  328. if (m) {
  329. ctx.fillText(contentArray[m], 50, 1000 + contentHh * m + 18, 1100);
  330. } else {
  331. ctx.fillText(contentArray[m], 50, 1000 + contentHh * m, 1100);
  332. }
  333. }
  334. ctx.setTextAlign('left')
  335. ctx.setFontSize(72);
  336. ctx.setFillStyle('#DA4F2A');
  337. ctx.fillText('¥' + price, 40, 820 + contentHh);
  338. ctx.setTextAlign('left')
  339. ctx.setFontSize(36);
  340. ctx.setFillStyle('#999');
  341. ctx.fillText('¥' + ot_price, 50, 876 + contentHh);
  342. var underline = function(ctx, text, x, y, size, color, thickness, offset) {
  343. var width = ctx.measureText(text).width;
  344. switch (ctx.textAlign) {
  345. case "center":
  346. x -= (width / 2);
  347. break;
  348. case "right":
  349. x -= width;
  350. break;
  351. }
  352. y += size + offset;
  353. ctx.beginPath();
  354. ctx.strokeStyle = color;
  355. ctx.lineWidth = thickness;
  356. ctx.moveTo(x, y);
  357. ctx.lineTo(x + width, y);
  358. ctx.stroke();
  359. }
  360. underline(ctx, '¥' + ot_price, 55, 865, 36, '#999', 2, 0)
  361. ctx.setTextAlign('left')
  362. ctx.setFontSize(28);
  363. ctx.setFillStyle('#999');
  364. ctx.fillText('长按或扫描查看', 490, 1030 + contentHh);
  365. ctx.draw(true, function() {
  366. uni.canvasToTempFilePath({
  367. canvasId: 'firstCanvas',
  368. fileType: 'png',
  369. destWidth: WIDTH,
  370. destHeight: HEIGHT,
  371. success: function(res) {
  372. // uni.hideLoading();
  373. successFn && successFn(res.tempFilePath);
  374. }
  375. })
  376. });
  377. },
  378. fail: function(err) {
  379. console.log('失败', err)
  380. uni.hideLoading();
  381. that.Tips({
  382. title: '无法获取图片信息'
  383. });
  384. }
  385. })
  386. },
  387. /**
  388. * 拼团邀请海报
  389. * @param array arr2 海报素材
  390. * @param string store_name 素材文字
  391. * @param string price 价格
  392. * @param string ot_price 拼团人数
  393. * @param function successFn 回调函数
  394. *
  395. *
  396. */
  397. circleImg(ctx, img, x, y, r) {
  398. ctx.save();
  399. ctx.beginPath()
  400. var d =2 * r;
  401. var cx = x + r;
  402. var cy = y + r;
  403. ctx.arc(cx, cy, r, 0, 2 * Math.PI);
  404. ctx.clip();
  405. ctx.drawImage(img, x, y, d, d);
  406. ctx.restore();
  407. },
  408. groupCanvas: function(arr2, store_name, price, ot_price,groupLeaderNickname, successFn) {
  409. let that = this;
  410. const ctx = uni.createCanvasContext('firstCanvas');
  411. ctx.clearRect(0, 0, 0, 0);
  412. /**
  413. * 只能获取合法域名下的图片信息,本地调试无法获取
  414. *
  415. */
  416. ctx.fillStyle = '#fff';
  417. ctx.fillRect(0, 30, 750, 1100);
  418. uni.getImageInfo({
  419. src: arr2[0],
  420. success: function(res) {
  421. const WIDTH = res.width;
  422. const HEIGHT = res.height;
  423. ctx.drawImage(arr2[0], 0, 0, 750, 1180);
  424. ctx.drawImage(arr2[3], 30, 80, 700, 1020);
  425. ctx.drawImage(arr2[1], 88, 300, WIDTH+90, WIDTH+120);
  426. ctx.save();
  427. let r = 70;
  428. let d = r * 2;
  429. let cx = 470;
  430. let cy = 870;
  431. ctx.arc(cx + r, cy + r, r, 0, 2 * Math.PI);
  432. // ctx.clip();
  433. ctx.drawImage(arr2[2], cx+45, cy+70, d, d);
  434. ctx.restore();
  435. that.circleImg(ctx, arr2[5], 70, 30, 30);
  436. const CONTENT_ROW_LENGTH = 20;
  437. let [contentLeng, contentArray, contentRows] = that.textByteLength(store_name,
  438. CONTENT_ROW_LENGTH);
  439. if (contentRows > 2) {
  440. contentRows = 2;
  441. let textArray = contentArray.slice(0, 2);
  442. textArray[textArray.length - 1] += '……';
  443. contentArray = textArray;
  444. }
  445. ctx.setTextAlign('left');
  446. ctx.setFontSize(36);
  447. ctx.setFillStyle('#000');
  448. // let contentHh = 36 * 1.5;
  449. let contentHh = 36;
  450. for (let m = 0; m < contentArray.length; m++) {
  451. // ctx.fillText(contentArray[m], 50, 1000 + contentHh * m,750);
  452. if (m) {
  453. ctx.fillText(contentArray[m], 90, 200 + contentHh * m + 18, 1400);
  454. } else {
  455. ctx.fillText(contentArray[m], 90, 200 + contentHh * m, 1400);
  456. }
  457. }
  458. ctx.setTextAlign('left')
  459. ctx.setFontSize(34);
  460. ctx.setFillStyle('#fff');
  461. ctx.fillText(groupLeaderNickname+'邀请你拼团', 135, 73 );
  462. ctx.setTextAlign('left')
  463. ctx.setFontSize(40);
  464. ctx.setFillStyle('#DA4F2A');
  465. ctx.fillText('¥' + price, 95, 950 + contentHh);
  466. let priceNumWidth = ctx.measureText('¥' + price).width
  467. ctx.drawImage(arr2[4], 110+priceNumWidth, 948, 100, 50);
  468. ctx.setTextAlign('left')
  469. ctx.setFontSize(28);
  470. ctx.setFillStyle('#666');
  471. ctx.fillText(`还差`, 100, 1020 + contentHh);
  472. ctx.setTextAlign('left')
  473. ctx.setFontSize(28);
  474. ctx.setFillStyle('#DA4F2A');
  475. ctx.fillText(`${ot_price}人`, 160, 1020 + contentHh);
  476. let numWidth = ctx.measureText(`${ot_price}人`).width
  477. ctx.setTextAlign('left')
  478. ctx.setFontSize(28);
  479. ctx.setFillStyle('#999');
  480. ctx.fillText(`即可拼团成功`, 160+numWidth, 1020 + contentHh);
  481. ctx.draw(true, function() {
  482. uni.canvasToTempFilePath({
  483. canvasId: 'firstCanvas',
  484. fileType: 'png',
  485. destWidth: WIDTH,
  486. destHeight: HEIGHT,
  487. success: function(res) {
  488. // uni.hideLoading();
  489. successFn && successFn(res.tempFilePath);
  490. }
  491. })
  492. });
  493. },
  494. fail: function(err) {
  495. console.log('失败', err)
  496. uni.hideLoading();
  497. that.Tips({
  498. title: '无法获取图片信息'
  499. });
  500. }
  501. })
  502. },
  503. /**
  504. * 绘制文字自动换行
  505. * @param array arr2 海报素材
  506. * @param Number x , y 绘制的坐标
  507. * @param Number maxWigth 绘制文字的宽度
  508. * @param Number lineHeight 行高
  509. * @param Number maxRowNum 最大行数
  510. */
  511. canvasWraptitleText(canvas, text, x, y, maxWidth, lineHeight, maxRowNum) {
  512. if (typeof text != 'string' || typeof x != 'number' || typeof y != 'number') {
  513. return;
  514. }
  515. // canvas.font = '20px Bold PingFang SC'; //绘制文字的字号和大小
  516. // 字符分隔为数组
  517. var arrText = text.split('');
  518. var line = '';
  519. var rowNum = 1
  520. for (var n = 0; n < arrText.length; n++) {
  521. var testLine = line + arrText[n];
  522. var metrics = canvas.measureText(testLine);
  523. var testWidth = metrics.width;
  524. if (testWidth > maxWidth && n > 0) {
  525. if (rowNum >= maxRowNum) {
  526. var arrLine = testLine.split('')
  527. arrLine.splice(-9)
  528. var newTestLine = arrLine.join("")
  529. newTestLine += "..."
  530. canvas.fillText(newTestLine, x, y);
  531. //如果需要在省略号后面添加其他的东西,就在这个位置写(列如添加扫码查看详情字样)
  532. //canvas.fillStyle = '#2259CA';
  533. //canvas.fillText('扫码查看详情',x + maxWidth-90, y);
  534. return
  535. }
  536. canvas.fillText(line, x, y);
  537. line = arrText[n];
  538. y += lineHeight;
  539. rowNum += 1
  540. } else {
  541. line = testLine;
  542. }
  543. }
  544. canvas.fillText(line, x, y);
  545. },
  546. /**
  547. * 获取活动分享海报
  548. * @param array arr2 海报素材
  549. * @param string storeName 素材文字
  550. * @param string price 价格
  551. * @param string people 人数
  552. * @param string count 剩余人数
  553. * @param function successFn 回调函数
  554. */
  555. activityCanvas: function(arrImages, storeName, price, people, count, num, successFn) {
  556. let that = this;
  557. let rain = 2;
  558. const context = uni.createCanvasContext('activityCanvas');
  559. context.clearRect(0, 0, 0, 0);
  560. /**
  561. * 只能获取合法域名下的图片信息,本地调试无法获取
  562. *
  563. */
  564. context.fillStyle = '#fff';
  565. context.fillRect(0, 0, 594, 850);
  566. uni.getImageInfo({
  567. src: arrImages[0],
  568. success: function(res) {
  569. context.drawImage(arrImages[0], 0, 0, 594, 850);
  570. context.setFontSize(14 * rain);
  571. context.setFillStyle('#333333');
  572. that.canvasWraptitleText(context, storeName, 110 * rain, 110 * rain, 230 * rain, 30 *
  573. rain, 1)
  574. context.drawImage(arrImages[2], 68 * rain, 194 * rain, 160 * rain, 160 * rain);
  575. context.save();
  576. context.setFontSize(14 * rain);
  577. context.setFillStyle('#fc4141');
  578. context.fillText('¥', 157 * rain, 145 * rain);
  579. context.setFontSize(24 * rain);
  580. context.setFillStyle('#fc4141');
  581. context.fillText(price, 170 * rain, 145 * rain);
  582. context.setFontSize(10 * rain);
  583. context.setFillStyle('#fff');
  584. context.fillText(people, 118 * rain, 143 * rain);
  585. context.setFontSize(12 * rain);
  586. context.setFillStyle('#666666');
  587. context.setTextAlign('center');
  588. context.fillText(count, (167 - num) * rain, 166 * rain);
  589. that.handleBorderRect(context, 27 * rain, 94 * rain, 75 * rain, 75 * rain, 6 * rain);
  590. context.clip();
  591. context.drawImage(arrImages[1], 27 * rain, 94 * rain, 75 * rain, 75 * rain);
  592. context.draw(true, function() {
  593. uni.canvasToTempFilePath({
  594. canvasId: 'activityCanvas',
  595. fileType: 'png',
  596. destWidth: 594,
  597. destHeight: 850,
  598. success: function(res) {
  599. // uni.hideLoading();
  600. successFn && successFn(res.tempFilePath);
  601. }
  602. })
  603. });
  604. },
  605. fail: function(err) {
  606. console.log('失败', err)
  607. uni.hideLoading();
  608. that.Tips({
  609. title: '无法获取图片信息'
  610. });
  611. }
  612. })
  613. },
  614. /**
  615. * 图片圆角设置
  616. * @param string x x轴位置
  617. * @param string y y轴位置
  618. * @param string w 图片宽
  619. * @param string y 图片高
  620. * @param string r 圆角值
  621. */
  622. handleBorderRect(ctx, x, y, w, h, r) {
  623. ctx.beginPath();
  624. // 左上角
  625. ctx.arc(x + r, y + r, r, Math.PI, 1.5 * Math.PI);
  626. ctx.moveTo(x + r, y);
  627. ctx.lineTo(x + w - r, y);
  628. ctx.lineTo(x + w, y + r);
  629. // 右上角
  630. ctx.arc(x + w - r, y + r, r, 1.5 * Math.PI, 2 * Math.PI);
  631. ctx.lineTo(x + w, y + h - r);
  632. ctx.lineTo(x + w - r, y + h);
  633. // 右下角
  634. ctx.arc(x + w - r, y + h - r, r, 0, 0.5 * Math.PI);
  635. ctx.lineTo(x + r, y + h);
  636. ctx.lineTo(x, y + h - r);
  637. // 左下角
  638. ctx.arc(x + r, y + h - r, r, 0.5 * Math.PI, Math.PI);
  639. ctx.lineTo(x, y + r);
  640. ctx.lineTo(x + r, y);
  641. ctx.fill();
  642. ctx.closePath();
  643. },
  644. /*
  645. * 视频上传
  646. * @param object opt
  647. * @param callable successCallback 成功执行方法 data
  648. * @param callable errorCallback 失败执行方法
  649. */
  650. uploadVideo: function(opt, successCallback, errorCallback) {
  651. let that = this;
  652. if (typeof opt === 'string') {
  653. let url = opt;
  654. opt = {};
  655. opt.url = url;
  656. }
  657. let count = opt.count || 1,
  658. sizeType = opt.sizeType || ['compressed'],
  659. sourceType = opt.sourceType || ['album', 'camera'],
  660. is_load = opt.is_load || true,
  661. uploadUrl = opt.url || '',
  662. inputName = opt.name || 'file',
  663. pid = opt.pid,
  664. fils = '',
  665. uploadMaxSize = 30,
  666. urlPath = HTTP_REQUEST_URL + '/api/front/upload/file' + "?model=" + opt.model +
  667. "&pid=" + opt.pid,
  668. model = opt.model;
  669. uni.chooseVideo({
  670. sourceType: sourceType,
  671. success: async (res) => {
  672. if (Math.ceil(res.size / 1024) < uploadMaxSize * 1024) {
  673. fils = await that.uploadFile(urlPath, res.tempFilePath, opt, '视频上传中');
  674. //获取视频第一帧为封面图,只兼容h5
  675. // #ifdef H5
  676. let dataURL = '';
  677. //uni.createVideoContext('1', that).play()
  678. let video = document.createElement("video");
  679. video.setAttribute('crossOrigin', 'anonymous'); //处理跨域
  680. video.setAttribute('src', fils);
  681. video.setAttribute('width', 400);
  682. video.setAttribute('height', 240);
  683. video.setAttribute('preload', 'auto');
  684. video.addEventListener('loadeddata', async function() {
  685. uni.showLoading({
  686. title: '加载中...',
  687. });
  688. let canvas = document.createElement("canvas"),
  689. width = video.width, //canvas的尺寸和图片一样
  690. height = video.height;
  691. canvas.width = width;
  692. canvas.height = height;
  693. canvas.getContext("2d").drawImage(video, 0, 0, width,
  694. height); //绘制canvas
  695. dataURL = canvas.toDataURL('image/png'); //转换为base64
  696. let file = await that.base64ToFile(dataURL); //base64转文件流
  697. let urlPaths = HTTP_REQUEST_URL + '/api/front/upload/image' +
  698. "?model=product&pid=1"; //图片上传地址
  699. let coverURL = await that.uploadFile(urlPaths, file, opt) //封面图
  700. successCallback && successCallback({
  701. fils: fils,
  702. coverURL: coverURL
  703. })
  704. });
  705. // #endif
  706. // #ifndef H5
  707. successCallback && successCallback({
  708. fils: fils,
  709. coverURL: ''
  710. })
  711. // #endif
  712. } else {
  713. // #ifdef APP-PLUS
  714. plus.nativeUI.alert(`您选择的视频超出${uploadMaxSize}MB,已过滤`);
  715. // #endif
  716. // #ifndef APP-PLUS
  717. uni.showModal({
  718. content: `您选择的视频超出${uploadMaxSize}MB,已过滤`,
  719. showCancel: false
  720. });
  721. // #endif
  722. }
  723. }
  724. })
  725. },
  726. /*
  727. * 单图上传
  728. * @param object opt
  729. * @param callable successCallback 成功执行方法 data
  730. * @param callable errorCallback 失败执行方法
  731. */
  732. uploadImageOne: function(opt, successCallback, errorCallback) {
  733. let that = this;
  734. if (typeof opt === 'string') {
  735. let url = opt;
  736. opt = {};
  737. opt.url = url;
  738. }
  739. let count = opt.count || 1,
  740. sizeType = opt.sizeType || ['compressed'],
  741. sourceType = opt.sourceType || ['album', 'camera'],
  742. is_load = opt.is_load || true,
  743. uploadUrl = opt.url || '',
  744. inputName = opt.name || 'pics',
  745. pid = opt.pid,
  746. model = opt.model;
  747. uni.chooseImage({
  748. count: count, //最多可以选择的图片总数
  749. sizeType: sizeType, // 可以指定是原图还是压缩图,默认二者都有
  750. sourceType: sourceType, // 可以指定来源是相册还是相机,默认二者都有
  751. mediaType:['image'],
  752. success: async (res) => {
  753. let image = [];
  754. let filesLen = res.tempFiles.length;
  755. let exceeded_list = [];
  756. let uploadMaxSize = 10;
  757. let imageList = [];
  758. let urlPath = HTTP_REQUEST_URL + '/api/front/upload/image' + "?model=" + opt.model +
  759. "&pid=" + opt.pid
  760. if (count === 1) {
  761. successCallback && successCallback(await that.uploadFile(urlPath, res.tempFilePaths[
  762. 0], opt, '图片上传中'))
  763. } else {
  764. for (let i = 0; i < res.tempFiles.length; i++) {
  765. if (Math.ceil(res.tempFiles[i].size / 1024) < uploadMaxSize * 1024) {
  766. image.push(res.tempFiles[i].path);
  767. } else {
  768. exceeded_list.push(i + 1);
  769. filesLen = filesLen - 1;
  770. // #ifdef APP-PLUS
  771. plus.nativeUI.alert(
  772. `第${[...new Set(exceeded_list)].join(',')}张图片超出限制${uploadMaxSize}MB,已过滤`
  773. );
  774. // #endif
  775. // #ifndef APP-PLUS
  776. uni.showModal({
  777. content: `第${[...new Set(exceeded_list)].join(',')}张图片超出限制${uploadMaxSize}MB,已过滤`
  778. });
  779. // #endif
  780. continue;
  781. }
  782. }
  783. for (const key in image) {
  784. imageList.push(await that.uploadFile(urlPath, image[key], opt, '图片上传中'))
  785. }
  786. successCallback && successCallback(imageList)
  787. }
  788. }
  789. })
  790. },
  791. uploadFile(urlPath, localPath, opt, message) {
  792. let that = this;
  793. return new Promise(async (resolve) => {
  794. //启动上传等待中...
  795. if (message) uni.showLoading({
  796. title: message,
  797. });
  798. uni.uploadFile({
  799. url: urlPath,
  800. filePath: localPath,
  801. name: opt.name || 'pics',
  802. header: {
  803. // #ifdef MP
  804. "Content-Type": "multipart/form-data",
  805. // #endif
  806. [TOKENNAME]: store.state.app.token
  807. },
  808. success: function(res) {
  809. uni.hideLoading();
  810. if (res.statusCode == 403) {
  811. that.Tips({
  812. title: res.data
  813. });
  814. } else {
  815. let data = res.data ? JSON.parse(res.data) : {};
  816. if (data.code == 200) {
  817. resolve(data.data.url);
  818. } else {
  819. that.Tips({
  820. title: data.message
  821. });
  822. }
  823. }
  824. },
  825. fail: function(res) {
  826. uni.hideLoading();
  827. that.Tips({
  828. title: res
  829. });
  830. }
  831. })
  832. })
  833. },
  834. /**
  835. * 小程序头像获取上传
  836. * @param uploadUrl 上传接口地址
  837. * @param filePath 上传文件路径
  838. * @param successCallback success回调
  839. * @param errorCallback err回调
  840. */
  841. uploadImgs(filePath, opt, successCallback, errorCallback) {
  842. let that = this;
  843. if (typeof opt === 'string') {
  844. let url = opt;
  845. opt = {};
  846. opt.url = url;
  847. }
  848. let count = opt.count || 1,
  849. sizeType = opt.sizeType || ['compressed'],
  850. sourceType = opt.sourceType || ['album', 'camera'],
  851. is_load = opt.is_load || true,
  852. uploadUrl = opt.url || '',
  853. inputName = opt.name || 'pics',
  854. pid = opt.pid,
  855. model = opt.model;
  856. let urlPath = HTTP_REQUEST_URL + '/api/front/upload/image' + "?model=" + model +
  857. "&pid=" + pid
  858. uni.uploadFile({
  859. url: urlPath,
  860. filePath: filePath,
  861. name: inputName,
  862. formData: {
  863. 'filename': inputName
  864. },
  865. header: {
  866. // #ifdef MP
  867. "Content-Type": "multipart/form-data",
  868. // #endif
  869. [TOKENNAME]: store.state.app.token
  870. },
  871. success: function(res) {
  872. uni.hideLoading();
  873. if (res.statusCode == 403) {
  874. that.Tips({
  875. title: res.data
  876. });
  877. } else {
  878. let data = res.data ? JSON.parse(res.data) : {};
  879. if (data.code == 200) {
  880. successCallback && successCallback(data)
  881. } else {
  882. errorCallback && errorCallback(data);
  883. that.Tips({
  884. title: data.message
  885. });
  886. }
  887. }
  888. },
  889. fail: function(res) {
  890. uni.hideLoading();
  891. that.Tips({
  892. title: res
  893. });
  894. }
  895. })
  896. },
  897. base64ToImg(urlData, filename) {
  898. // 64转file
  899. var arr = urlData.split(",");
  900. var type = arr[0].match(/:(.*?);/)[1];
  901. var fileExt = type.split("/")[1];
  902. var bstr = atob(arr[1]);
  903. var n = bstr.length;
  904. var u8arr = new Uint8Array(n);
  905. while (n--) {
  906. u8arr[n] = bstr.charCodeAt(n);
  907. }
  908. return new File([u8arr], `${filename}.` + fileExt, {
  909. type: type,
  910. });
  911. },
  912. /**
  913. * 处理服务器扫码带进来的参数
  914. * @param string param 扫码携带参数
  915. * @param string k 整体分割符 默认为:&
  916. * @param string p 单个分隔符 默认为:=
  917. * @return object
  918. *
  919. */
  920. // #ifdef MP
  921. getUrlParams: function(param, k, p) {
  922. if (typeof param != 'string') return {};
  923. k = k ? k : '&'; //整体参数分隔符
  924. p = p ? p : '='; //单个参数分隔符
  925. var value = {};
  926. if (param.indexOf(k) !== -1) {
  927. param = param.split(k);
  928. for (var val in param) {
  929. if (param[val].indexOf(p) !== -1) {
  930. var item = param[val].split(p);
  931. value[item[0]] = item[1];
  932. }
  933. }
  934. } else if (param.indexOf(p) !== -1) {
  935. var item = param.split(p);
  936. value[item[0]] = item[1];
  937. } else {
  938. return param;
  939. }
  940. return value;
  941. },
  942. /**根据格式组装公共参数
  943. * @param {Object} value
  944. */
  945. formatMpQrCodeData(value) {
  946. let values = value.split(',');
  947. let result = {};
  948. if (values.length === 2) {
  949. let v1 = values[0].split(":");
  950. if (v1[0] === 'pid') {
  951. result.spread = v1[1];
  952. } else {
  953. result.id = v1[1];
  954. }
  955. let v2 = values[1].split(":");
  956. if (v2[0] === 'pid') {
  957. result.spread = v2[1];
  958. } else {
  959. result.id = v2[1];
  960. }
  961. } else {
  962. result.spread = values[0].split(":")[1];
  963. }
  964. return result;
  965. },
  966. // #endif
  967. /*
  968. * 合并数组
  969. */
  970. SplitArray(list, sp) {
  971. if (typeof list != 'object') return [];
  972. if (sp === undefined) sp = [];
  973. for (var i = 0; i < list.length; i++) {
  974. sp.push(list[i]);
  975. }
  976. return sp;
  977. },
  978. trim(str) {
  979. return String.prototype.trim.call(str);
  980. },
  981. $h: {
  982. //除法函数,用来得到精确的除法结果
  983. //说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。
  984. //调用:$h.Div(arg1,arg2)
  985. //返回值:arg1除以arg2的精确结果
  986. Div: function(arg1, arg2) {
  987. arg1 = parseFloat(arg1);
  988. arg2 = parseFloat(arg2);
  989. var t1 = 0,
  990. t2 = 0,
  991. r1, r2;
  992. try {
  993. t1 = arg1.toString().split(".")[1].length;
  994. } catch (e) {}
  995. try {
  996. t2 = arg2.toString().split(".")[1].length;
  997. } catch (e) {}
  998. r1 = Number(arg1.toString().replace(".", ""));
  999. r2 = Number(arg2.toString().replace(".", ""));
  1000. return this.Mul(r1 / r2, Math.pow(10, t2 - t1));
  1001. },
  1002. //加法函数,用来得到精确的加法结果
  1003. //说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
  1004. //调用:$h.Add(arg1,arg2)
  1005. //返回值:arg1加上arg2的精确结果
  1006. Add: function(arg1, arg2) {
  1007. arg2 = parseFloat(arg2);
  1008. var r1, r2, m;
  1009. try {
  1010. r1 = arg1.toString().split(".")[1].length
  1011. } catch (e) {
  1012. r1 = 0
  1013. }
  1014. try {
  1015. r2 = arg2.toString().split(".")[1].length
  1016. } catch (e) {
  1017. r2 = 0
  1018. }
  1019. m = Math.pow(100, Math.max(r1, r2));
  1020. return (this.Mul(arg1, m) + this.Mul(arg2, m)) / m;
  1021. },
  1022. //减法函数,用来得到精确的减法结果
  1023. //说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的减法结果。
  1024. //调用:$h.Sub(arg1,arg2)
  1025. //返回值:arg1减去arg2的精确结果
  1026. Sub: function(arg1, arg2) {
  1027. arg1 = parseFloat(arg1);
  1028. arg2 = parseFloat(arg2);
  1029. var r1, r2, m, n;
  1030. try {
  1031. r1 = arg1.toString().split(".")[1].length
  1032. } catch (e) {
  1033. r1 = 0
  1034. }
  1035. try {
  1036. r2 = arg2.toString().split(".")[1].length
  1037. } catch (e) {
  1038. r2 = 0
  1039. }
  1040. m = Math.pow(10, Math.max(r1, r2));
  1041. //动态控制精度长度
  1042. n = (r1 >= r2) ? r1 : r2;
  1043. return ((this.Mul(arg1, m) - this.Mul(arg2, m)) / m).toFixed(n);
  1044. },
  1045. //乘法函数,用来得到精确的乘法结果
  1046. //说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。
  1047. //调用:$h.Mul(arg1,arg2)
  1048. //返回值:arg1乘以arg2的精确结果
  1049. Mul: function(arg1, arg2) {
  1050. arg1 = parseFloat(arg1);
  1051. arg2 = parseFloat(arg2);
  1052. var m = 0,
  1053. s1 = arg1.toString(),
  1054. s2 = arg2.toString();
  1055. try {
  1056. m += s1.split(".")[1].length
  1057. } catch (e) {}
  1058. try {
  1059. m += s2.split(".")[1].length
  1060. } catch (e) {}
  1061. return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
  1062. },
  1063. },
  1064. // 获取地理位置;
  1065. $L: {
  1066. getLocation() {
  1067. console.log('Location')
  1068. return new Promise(async (resolve, reject) => {
  1069. // #ifdef APP-PLUS
  1070. let status = await this.checkPermission();
  1071. if (status !== 1) {
  1072. uni.removeStorageSync('user_latitude');
  1073. uni.removeStorageSync('user_longitude');
  1074. resolve(status);
  1075. return;
  1076. }
  1077. // #endif
  1078. // #ifdef MP
  1079. let status = await this.getSetting();
  1080. if (status === 2) {
  1081. uni.removeStorageSync('user_latitude');
  1082. uni.removeStorageSync('user_longitude');
  1083. this.Tips({
  1084. title: '获取当前定位遇到困难,如需定位请开启权限'
  1085. });
  1086. //this.openSetting();
  1087. resolve(status);
  1088. return;
  1089. }
  1090. // #endif
  1091. let Location = await this.doGetLocation();
  1092. resolve(Location);
  1093. });
  1094. },
  1095. doGetLocation() {
  1096. return new Promise((resolve, reject) => {
  1097. uni.getLocation({
  1098. //type: 'wgs84',
  1099. type: 'gcj02',
  1100. isHighAccuracy: true,
  1101. success: (res) => {
  1102. uni.setStorageSync('user_latitude', res.latitude);
  1103. uni.setStorageSync('user_longitude', res.longitude);
  1104. resolve(res);
  1105. },
  1106. complete: (res) => {
  1107. uni.setStorageSync('user_latitude', res.latitude);
  1108. uni.setStorageSync('user_longitude', res.longitude);
  1109. resolve(res);
  1110. },
  1111. fail: (err) => {
  1112. uni.removeStorageSync('user_latitude');
  1113. uni.removeStorageSync('user_longitude');
  1114. reject(err);
  1115. // #ifdef MP-BAIDU
  1116. if (err.errCode === 202 || err.errCode ===
  1117. 10003) { // 202模拟器 10003真机 user deny
  1118. this.openSetting();
  1119. }
  1120. // #endif
  1121. // #ifndef MP-BAIDU
  1122. if (err.errMsg.indexOf("auth deny") >= 0) {
  1123. uni.showToast({
  1124. title: '访问位置被拒绝',
  1125. icon: 'none',
  1126. duration: 2000
  1127. });
  1128. } else {
  1129. uni.showToast({
  1130. title: err.errMsg,
  1131. icon: 'none',
  1132. duration: 2000
  1133. });
  1134. }
  1135. // #endif
  1136. }
  1137. })
  1138. });
  1139. },
  1140. getSetting: function() {
  1141. return new Promise((resolve, reject) => {
  1142. uni.getSetting({
  1143. success: (res) => {
  1144. if (res.authSetting['scope.userLocation'] === undefined) {
  1145. resolve(0);
  1146. return;
  1147. }
  1148. if (res.authSetting['scope.userLocation']) {
  1149. resolve(1);
  1150. } else {
  1151. resolve(2);
  1152. }
  1153. }
  1154. });
  1155. });
  1156. },
  1157. /**
  1158. * 开启权限提示
  1159. */
  1160. openSetting: function() {
  1161. uni.openSetting({
  1162. success: (res) => {
  1163. if (res.authSetting && res.authSetting['scope.userLocation']) {
  1164. this.doGetLocation();
  1165. }
  1166. },
  1167. fail: (err) => {}
  1168. })
  1169. },
  1170. async checkPermission() {
  1171. let status = permision.isIOS ? await permision.requestIOS('location') :
  1172. await permision.requestAndroid('android.permission.ACCESS_FINE_LOCATION');
  1173. let pages = getCurrentPages();
  1174. let prePage = pages[pages.length - 1].route;
  1175. if (status === null || status === 1) {
  1176. status = 1;
  1177. } else if (status === 2) {
  1178. if (prePage === 'pages/users/user_address/index')
  1179. uni.showModal({
  1180. content: "系统定位已关闭",
  1181. confirmText: "确定",
  1182. showCancel: false,
  1183. success: function(res) {}
  1184. })
  1185. } else if (status.code) {
  1186. if (prePage === 'pages/users/user_address/index')
  1187. uni.showModal({
  1188. content: status.message
  1189. })
  1190. } else {
  1191. if (prePage === 'pages/users/user_address/index')
  1192. uni.showModal({
  1193. content: "需要定位权限",
  1194. confirmText: "设置",
  1195. success: function(res) {
  1196. if (res.confirm) {
  1197. permision.gotoAppSetting();
  1198. }
  1199. }
  1200. })
  1201. }
  1202. return status;
  1203. },
  1204. },
  1205. toStringValue: function(obj) {
  1206. if (obj instanceof Array) {
  1207. var arr = [];
  1208. for (var i = 0; i < obj.length; i++) {
  1209. arr[i] = toStringValue(obj[i]);
  1210. }
  1211. return arr;
  1212. } else if (typeof obj == 'object') {
  1213. for (var p in obj) {
  1214. obj[p] = toStringValue(obj[p]);
  1215. }
  1216. } else if (typeof obj == 'number') {
  1217. obj = obj + '';
  1218. }
  1219. return obj;
  1220. },
  1221. /*
  1222. * 替换域名
  1223. */
  1224. setDomain: function(url) {
  1225. url = url ? url.toString() : '';
  1226. if (url.indexOf("https://") > -1) return url;
  1227. else return url.replace('http://', 'https://');
  1228. },
  1229. /**
  1230. * 姓名除了姓显示其他
  1231. */
  1232. formatName: function(str) {
  1233. return str.substr(0, 1) + new Array(str.length).join('*');
  1234. },
  1235. /**
  1236. * 微信地址导入
  1237. * @param uploadUrl 上传接口地址
  1238. * @param filePath 上传文件路径
  1239. * @param successCallback success回调
  1240. * @param errorCallback err回调
  1241. */
  1242. addressWxImport() {
  1243. let that = this;
  1244. uni.showLoading({
  1245. title: '加载中...'
  1246. });
  1247. return new Promise((resolve, reject) => {
  1248. uni.authorize({
  1249. scope: 'scope.address',
  1250. success: function(res) {
  1251. uni.hideLoading();
  1252. uni.chooseAddress({
  1253. success(resd) {
  1254. resolve(resd);
  1255. },
  1256. fail: function(err) {
  1257. if (err.errMsg == 'chooseAddress:cancel') return that.Tips({
  1258. title: '取消选择'
  1259. });
  1260. },
  1261. })
  1262. },
  1263. fail: function(err) {
  1264. uni.hideLoading();
  1265. uni.showModal({
  1266. title: '您已拒绝导入微信地址权限',
  1267. content: '是否进入权限管理,调整授权?',
  1268. success(err) {
  1269. if (err.confirm) {
  1270. uni.openSetting({
  1271. success: function(err) {
  1272. console.log(err.authSetting)
  1273. }
  1274. });
  1275. } else if (err.cancel) {
  1276. return that.Tips({
  1277. title: '已取消!'
  1278. });
  1279. }
  1280. }
  1281. })
  1282. }
  1283. })
  1284. });
  1285. },
  1286. /**
  1287. * 回退并且刷新页面
  1288. */
  1289. backPageRefresh() {
  1290. let pages = getCurrentPages(); // 当前页面
  1291. let beforePage = pages[pages.length - 2]; // 上一页
  1292. uni.navigateBack({
  1293. success: function() {
  1294. beforePage.$vm.reFresh();
  1295. }
  1296. })
  1297. },
  1298. /**
  1299. * 将时间转化为几小时
  1300. * @param {Object} data data必须是日期格式,不能是时间戳
  1301. */
  1302. getDateDiff(data) {
  1303. let datas = data;
  1304. // 传进来的data必须是日期格式,不能是时间戳
  1305. //var str = data;
  1306. //将字符串转换成时间格式
  1307. var timePublish = new Date(data);
  1308. var timeNow = new Date();
  1309. var minute = 1000 * 60;
  1310. var hour = minute * 60;
  1311. var day = hour * 24;
  1312. var month = day * 30;
  1313. var result = "";
  1314. var diffValue = timeNow - timePublish;
  1315. var diffMonth = diffValue / month;
  1316. var diffWeek = diffValue / (7 * day);
  1317. var diffDay = diffValue / day;
  1318. var diffHour = diffValue / hour;
  1319. var diffMinute = diffValue / minute;
  1320. if (diffValue < 0) {} else if (diffMonth > 3) {
  1321. result = timePublish.getFullYear() + "-";
  1322. result += timePublish.getMonth() + "-";
  1323. result += timePublish.getDate();
  1324. } else if (diffMonth > 1) {
  1325. result = parseInt(diffMonth) + "月前";
  1326. } else if (diffWeek > 1) {
  1327. result = parseInt(diffWeek) + "周前";
  1328. } else if (diffDay > 1) {
  1329. result = parseInt(diffDay) + "天前";
  1330. } else if (diffHour > 1) {
  1331. result = parseInt(diffHour) + "小时前";
  1332. } else if (diffMinute > 1) {
  1333. result = parseInt(diffMinute) + "分钟前";
  1334. } else {
  1335. result = "刚刚";
  1336. }
  1337. return result;
  1338. },
  1339. /**
  1340. * 链接地址跳转
  1341. * @param {Object} url 链接地址
  1342. */
  1343. navigateTo(url) {
  1344. if (url.indexOf("http") !== -1) {
  1345. // #ifdef H5
  1346. location.href = url
  1347. // #endif
  1348. // #ifdef APP-PLUS || MP
  1349. uni.navigateTo({
  1350. url: '/pages/users/web_page/index?webUel=' + encodeURIComponent(url)
  1351. })
  1352. // #endif
  1353. } else {
  1354. if (['/pages/goods_cate/index', '/pages/order_addcart/order_addcart', '/pages/user/index',
  1355. '/pages/discover_index/index', '/pages/index/index'
  1356. ].indexOf(url) == -1) {
  1357. uni.navigateTo({
  1358. animationType: animationType.type,
  1359. animationDuration: animationType.duration,
  1360. url: url
  1361. })
  1362. } else {
  1363. uni.switchTab({
  1364. animationType: animationType.type,
  1365. animationDuration: animationType.duration,
  1366. url: url
  1367. })
  1368. }
  1369. }
  1370. },
  1371. /**
  1372. * base64格式转为文件流
  1373. * @param base64 base64地址
  1374. * @returns {File}
  1375. */
  1376. base64ToFile(base64) {
  1377. return new Promise(function(resolve, reject) {
  1378. if (typeof window === 'object' && 'document' in window) {
  1379. base64 = base64.split(',')
  1380. var type = base64[0].match(/:(.*?);/)[1]
  1381. var str = atob(base64[1])
  1382. var n = str.length
  1383. var array = new Uint8Array(n)
  1384. while (n--) {
  1385. array[n] = str.charCodeAt(n)
  1386. }
  1387. return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], {
  1388. type: type
  1389. })))
  1390. }
  1391. var extName = base64.match(/data\:\S+\/(\S+);/)
  1392. if (extName) {
  1393. extName = extName[1]
  1394. } else {
  1395. reject(new Error('base64 error'))
  1396. }
  1397. var fileName = Date.now() + '.' + extName
  1398. if (typeof plus === 'object') {
  1399. var bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
  1400. bitmap.loadBase64Data(base64, function() {
  1401. var filePath = '_doc/uniapp_temp/' + fileName
  1402. bitmap.save(filePath, {}, function() {
  1403. bitmap.clear()
  1404. resolve(filePath)
  1405. }, function(error) {
  1406. bitmap.clear()
  1407. reject(error)
  1408. })
  1409. }, function(error) {
  1410. bitmap.clear()
  1411. reject(error)
  1412. })
  1413. return
  1414. }
  1415. if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
  1416. var filePath = wx.env.USER_DATA_PATH + '/' + fileName
  1417. wx.getFileSystemManager().writeFile({
  1418. filePath: filePath,
  1419. data: base64.replace(/^data:\S+\/\S+;base64,/, ''),
  1420. encoding: 'base64',
  1421. success: function() {
  1422. resolve(filePath)
  1423. },
  1424. fail: function(error) {
  1425. reject(error)
  1426. }
  1427. })
  1428. return
  1429. }
  1430. reject(new Error('not support'))
  1431. })
  1432. },
  1433. // 计算头部自定义导航高度;
  1434. getWXStatusHeight() {
  1435. // 获取距上
  1436. const barTop = uni.getSystemInfoSync().statusBarHeight;
  1437. // #ifdef MP
  1438. // 获取胶囊按钮位置信息
  1439. const menuButtonInfo = wx.getMenuButtonBoundingClientRect() || 0
  1440. // 获取导航栏高度
  1441. const barHeight = menuButtonInfo.height + (menuButtonInfo.top - barTop) * 2
  1442. let barWidth = menuButtonInfo.width
  1443. // #endif
  1444. // #ifndef MP
  1445. // 获取导航栏高度
  1446. const barHeight = parseInt(barTop) + 10;
  1447. let barWidth = '100%'
  1448. // #endif
  1449. return {
  1450. barHeight,
  1451. barTop,
  1452. barWidth
  1453. }
  1454. },
  1455. /**
  1456. * 对象转数组
  1457. * @param data 对象
  1458. * @returns {*[]}
  1459. */
  1460. objToArr(data) {
  1461. let obj = Object.keys(data).sort();
  1462. let m = obj.map(key => data[key]);
  1463. return m;
  1464. },
  1465. }