util.js 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049
  1. // +----------------------------------------------------------------------
  2. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  3. // +----------------------------------------------------------------------
  4. // | Copyright (c) 2016~2023 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 i18n from './lang.js';
  16. import {
  17. pathToBase64
  18. } from '@/plugin/image-tools/index.js';
  19. // #ifdef APP-PLUS
  20. import permision from "./permission.js"
  21. // #endif
  22. export default {
  23. /**
  24. * opt object | string
  25. * to_url object | string
  26. * 例:
  27. * this.Tips('/pages/test/test'); 跳转不提示
  28. * this.Tips({title:'提示'},'/pages/test/test'); 提示并跳转
  29. * this.Tips({title:'提示'},{tab:1,url:'/pages/index/index'}); 提示并跳转值table上
  30. * tab=1 一定时间后跳转至 table上
  31. * tab=2 一定时间后跳转至非 table上
  32. * tab=3 一定时间后返回上页面
  33. * tab=4 关闭所有页面,打开到应用内的某个页面
  34. * tab=5 关闭当前页面,跳转到应用内的某个页面
  35. */
  36. Tips: function(opt, to_url) {
  37. if (typeof opt == 'string') {
  38. to_url = opt;
  39. opt = {};
  40. }
  41. let title = opt.title || '',
  42. icon = opt.icon || 'none',
  43. endtime = opt.endtime || 2000,
  44. success = opt.success;
  45. if (title) uni.showToast({
  46. title: title,
  47. icon: icon,
  48. duration: endtime,
  49. success
  50. })
  51. if (to_url != undefined) {
  52. if (typeof to_url == 'object') {
  53. let tab = to_url.tab || 1,
  54. url = to_url.url || '';
  55. switch (tab) {
  56. case 1:
  57. //一定时间后跳转至 table
  58. setTimeout(function() {
  59. uni.switchTab({
  60. url: url
  61. })
  62. }, endtime);
  63. break;
  64. case 2:
  65. //跳转至非table页面
  66. setTimeout(function() {
  67. uni.navigateTo({
  68. url: url,
  69. })
  70. }, endtime);
  71. break;
  72. case 3:
  73. //返回上页面
  74. setTimeout(function() {
  75. // #ifndef H5
  76. uni.navigateBack({
  77. delta: parseInt(url),
  78. })
  79. // #endif
  80. // #ifdef H5
  81. history.back();
  82. // #endif
  83. }, endtime);
  84. break;
  85. case 4:
  86. //关闭所有页面,打开到应用内的某个页面
  87. setTimeout(function() {
  88. uni.reLaunch({
  89. url: url,
  90. })
  91. }, endtime);
  92. break;
  93. case 5:
  94. //关闭当前页面,跳转到应用内的某个页面
  95. setTimeout(function() {
  96. uni.redirectTo({
  97. url: url,
  98. })
  99. }, endtime);
  100. break;
  101. }
  102. } else if (typeof to_url == 'function') {
  103. setTimeout(function() {
  104. to_url && to_url();
  105. }, endtime);
  106. } else {
  107. //没有提示时跳转不延迟
  108. setTimeout(function() {
  109. uni.navigateTo({
  110. url: to_url,
  111. })
  112. }, title ? endtime : 0);
  113. }
  114. }
  115. },
  116. /**
  117. * 移除数组中的某个数组并组成新的数组返回
  118. * @param array array 需要移除的数组
  119. * @param int index 需要移除的数组的键值
  120. * @param string | int 值
  121. * @return array
  122. *
  123. */
  124. ArrayRemove: function(array, index, value) {
  125. const valueArray = [];
  126. if (array instanceof Array) {
  127. for (let i = 0; i < array.length; i++) {
  128. if (typeof index == 'number' && array[index] != i) {
  129. valueArray.push(array[i]);
  130. } else if (typeof index == 'string' && array[i][index] != value) {
  131. valueArray.push(array[i]);
  132. }
  133. }
  134. }
  135. return valueArray;
  136. },
  137. /**
  138. * 生成海报获取文字
  139. * @param string text 为传入的文本
  140. * @param int num 为单行显示的字节长度
  141. * @return array
  142. */
  143. textByteLength: function(text, num) {
  144. let strLength = 0;
  145. let rows = 1;
  146. let str = 0;
  147. let arr = [];
  148. for (let j = 0; j < text.length; j++) {
  149. if (text.charCodeAt(j) > 255) {
  150. strLength += 2;
  151. if (strLength > rows * num) {
  152. strLength++;
  153. arr.push(text.slice(str, j));
  154. str = j;
  155. rows++;
  156. }
  157. } else {
  158. strLength++;
  159. if (strLength > rows * num) {
  160. arr.push(text.slice(str, j));
  161. str = j;
  162. rows++;
  163. }
  164. }
  165. }
  166. arr.push(text.slice(str, text.length));
  167. return [strLength, arr, rows] // [处理文字的总字节长度,每行显示内容的数组,行数]
  168. },
  169. /**
  170. * 获取分享海报
  171. * @param array arr2 海报素材
  172. * @param string store_name 素材文字
  173. * @param string price 价格
  174. * @param string ot_price 原始价格
  175. * @param function successFn 回调函数
  176. *
  177. *
  178. */
  179. PosterCanvas: function(arr2, store_name, price, ot_price, successFn) {
  180. let that = this;
  181. uni.showLoading({
  182. title: i18n.t(`海报生成中`),
  183. mask: true
  184. });
  185. const ctx = uni.createCanvasContext('myCanvas');
  186. ctx.clearRect(0, 0, 0, 0);
  187. /**
  188. * 只能获取合法域名下的图片信息,本地调试无法获取
  189. *
  190. */
  191. ctx.fillStyle = '#fff';
  192. ctx.fillRect(0, 0, 750, 1250);
  193. uni.getImageInfo({
  194. src: arr2[0],
  195. success: function(res) {
  196. const WIDTH = res.width;
  197. const HEIGHT = res.height;
  198. // ctx.drawImage(arr2[0], 0, 0, WIDTH, 1050);
  199. ctx.drawImage(arr2[1], 0, 0, WIDTH, WIDTH);
  200. ctx.save();
  201. let r = 110;
  202. let d = r * 2;
  203. let cx = 480;
  204. let cy = 790;
  205. ctx.arc(cx + r, cy + r, r, 0, 2 * Math.PI);
  206. // ctx.clip();
  207. ctx.drawImage(arr2[2], cx, cy, d, d);
  208. ctx.restore();
  209. const CONTENT_ROW_LENGTH = 20;
  210. let [contentLeng, contentArray, contentRows] = that.textByteLength(store_name,
  211. CONTENT_ROW_LENGTH);
  212. if (contentRows > 2) {
  213. contentRows = 2;
  214. let textArray = contentArray.slice(0, 2);
  215. textArray[textArray.length - 1] += '……';
  216. contentArray = textArray;
  217. }
  218. ctx.setTextAlign('left');
  219. ctx.setFontSize(36);
  220. ctx.setFillStyle('#000');
  221. // let contentHh = 36 * 1.5;
  222. let contentHh = 36;
  223. for (let m = 0; m < contentArray.length; m++) {
  224. if (m) {
  225. ctx.fillText(contentArray[m], 50, 1000 + contentHh * m + 18, 1100);
  226. } else {
  227. ctx.fillText(contentArray[m], 50, 1000 + contentHh * m, 1100);
  228. }
  229. }
  230. ctx.setTextAlign('left')
  231. ctx.setFontSize(72);
  232. ctx.setFillStyle('#DA4F2A');
  233. ctx.fillText(i18n.t(`¥`) + price, 40, 820 + contentHh);
  234. ctx.setTextAlign('left')
  235. ctx.setFontSize(36);
  236. ctx.setFillStyle('#999');
  237. if (ot_price) {
  238. ctx.fillText(i18n.t(`¥`) + ot_price, 50, 876 + contentHh);
  239. var underline = function(ctx, text, x, y, size, color, thickness, offset) {
  240. var width = ctx.measureText(text).width;
  241. switch (ctx.textAlign) {
  242. case "center":
  243. x -= (width / 2);
  244. break;
  245. case "right":
  246. x -= width;
  247. break;
  248. }
  249. y += size + offset;
  250. ctx.beginPath();
  251. ctx.strokeStyle = color;
  252. ctx.lineWidth = thickness;
  253. ctx.moveTo(x, y);
  254. ctx.lineTo(x + width, y);
  255. ctx.stroke();
  256. }
  257. underline(ctx, i18n.t(`¥`) + ot_price, 55, 865, 36, '#999', 2, 0)
  258. }
  259. ctx.setTextAlign('left')
  260. ctx.setFontSize(28);
  261. ctx.setFillStyle('#999');
  262. ctx.fillText(i18n.t(`长按或扫描查看`), 490, 1030 + contentHh);
  263. ctx.draw(true, function() {
  264. uni.canvasToTempFilePath({
  265. canvasId: 'myCanvas',
  266. fileType: 'png',
  267. destWidth: WIDTH,
  268. destHeight: HEIGHT,
  269. success: function(res) {
  270. uni.hideLoading();
  271. successFn && successFn(res.tempFilePath);
  272. }
  273. })
  274. });
  275. },
  276. fail: function(err) {
  277. uni.hideLoading();
  278. that.Tips({
  279. title: i18n.t(`无法获取图片信息`)
  280. });
  281. }
  282. })
  283. },
  284. /**
  285. * 获取砍价/拼团海报
  286. * @param array arr2 海报素材 背景图
  287. * @param string store_name 素材文字
  288. * @param string price 价格
  289. * @param string ot_price 原始价格
  290. * @param function successFn 回调函数
  291. *
  292. *
  293. */
  294. bargainPosterCanvas: function(arr2, title, label, msg, price, wd, hg, successFn) {
  295. let that = this;
  296. const ctx = uni.createCanvasContext('myCanvas');
  297. ctx.clearRect(0, 0, 0, 0);
  298. /**
  299. * 只能获取合法域名下的图片信息,本地调试无法获取
  300. *
  301. */
  302. ctx.fillStyle = '#fff';
  303. ctx.fillRect(0, 0, wd * 2, hg * 2);
  304. uni.getImageInfo({
  305. src: arr2[0],
  306. success: function(res) {
  307. const WIDTH = res.width;
  308. const HEIGHT = res.height;
  309. ctx.drawImage(arr2[0], 0, 0, wd, hg);
  310. // 保证在不同机型对应坐标准确
  311. let labelx = 0.6500 //标签x
  312. let labely = 0.166 //标签y
  313. let pricex = 0.1857 //价格x
  314. let pricey = 0.180 //价格x
  315. let codex = 0.385 //二维码
  316. let codey = 0.77
  317. let picturex = 0.1571 //商品图左上点
  318. let picturey = 0.2916
  319. let picturebx = 0.6857 //商品图右下点
  320. let pictureby = 0.4316
  321. let msgx = 0.1036 //msg
  322. let msgy = 0.2306
  323. let codew = 0.25
  324. ctx.drawImage(arr2[1], wd * picturex, hg * picturey, wd * picturebx, hg * pictureby);
  325. ctx.drawImage(arr2[2], wd * codex, hg * codey, wd * codew, wd * codew);
  326. ctx.save();
  327. //标题
  328. const CONTENT_ROW_LENGTH = 32;
  329. let [contentLeng, contentArray, contentRows] = that.textByteLength(title,
  330. CONTENT_ROW_LENGTH);
  331. if (contentRows > 2) {
  332. contentRows = 2;
  333. let textArray = contentArray.slice(0, 2);
  334. textArray[textArray.length - 1] += '…';
  335. contentArray = textArray;
  336. }
  337. ctx.setTextAlign('left');
  338. ctx.setFillStyle('#000');
  339. if (contentArray.length < 2) {
  340. ctx.setFontSize(22);
  341. } else {
  342. ctx.setFontSize(20);
  343. }
  344. let contentHh = 8;
  345. for (let m = 0; m < contentArray.length; m++) {
  346. if (m) {
  347. ctx.fillText(contentArray[m], 20, 35 + contentHh * m + 18, 1100);
  348. } else {
  349. ctx.fillText(contentArray[m], 20, 35, 1100);
  350. }
  351. }
  352. // 标签内容
  353. ctx.setTextAlign('left')
  354. ctx.setFontSize(16);
  355. ctx.setFillStyle('#FFF');
  356. ctx.fillText(label, wd * labelx, hg * labely);
  357. ctx.save();
  358. // 价格
  359. ctx.setFillStyle('red');
  360. ctx.setFontSize(26);
  361. ctx.fillText(price, wd * pricex, hg * pricey);
  362. ctx.save();
  363. // msg
  364. ctx.setFillStyle('#333');
  365. ctx.setFontSize(16);
  366. ctx.fillText(msg, wd * msgx, hg * msgy);
  367. ctx.save();
  368. ctx.draw(true, () => {
  369. uni.canvasToTempFilePath({
  370. canvasId: 'myCanvas',
  371. fileType: 'png',
  372. quality: 1,
  373. success: (res) => {
  374. successFn && successFn(res.tempFilePath);
  375. uni.hideLoading();
  376. }
  377. })
  378. });
  379. },
  380. fail: function(err) {
  381. uni.hideLoading();
  382. that.Tips({
  383. title: i18n.t(`无法获取图片信息`)
  384. });
  385. }
  386. })
  387. },
  388. /**
  389. * 用户信息分享海报
  390. * @param array arr2 海报素材 1背景 0二维码
  391. * @param string nickname 昵称
  392. * @param string sitename 价格
  393. * @param function successFn 回调函数
  394. *
  395. *
  396. */
  397. userPosterCanvas: function(arr2, nickname, sitename, index, w, h, successFn) {
  398. let that = this;
  399. const ctx = uni.createCanvasContext('myCanvas' + index);
  400. ctx.clearRect(0, 0, 0, 0);
  401. /**
  402. * 只能获取合法域名下的图片信息,本地调试无法获取
  403. *
  404. */
  405. uni.getImageInfo({
  406. src: arr2[1],
  407. success: function(res) {
  408. const WIDTH = res.width;
  409. const HEIGHT = res.height;
  410. ctx.fillStyle = '#fff';
  411. ctx.fillRect(0, 0, w, h);
  412. ctx.drawImage(arr2[1], 0, 0, w, h);
  413. ctx.setTextAlign('left')
  414. ctx.setFontSize(12);
  415. ctx.setFillStyle('#333');
  416. // x:240 y:426
  417. let codex = 0.1906
  418. let codey = 0.7746
  419. let codeSize = 0.21666
  420. let namex = 0.4283
  421. let namey = 0.8215
  422. let markx = 0.4283
  423. let marky = 0.8685
  424. ctx.drawImage(arr2[0], w * codex, h * codey, w * codeSize, w * codeSize);
  425. if (w < 270) {
  426. ctx.setFontSize(8);
  427. } else {
  428. ctx.setFontSize(10);
  429. }
  430. ctx.fillText(nickname, w * namex, h * namey);
  431. if (w < 270) {
  432. ctx.setFontSize(8);
  433. } else {
  434. ctx.setFontSize(10);
  435. }
  436. ctx.fillText(i18n.t(`邀请您加入`) + sitename, w * markx, h * marky);
  437. ctx.save();
  438. ctx.draw(true, function() {
  439. uni.canvasToTempFilePath({
  440. canvasId: 'myCanvas' + index,
  441. fileType: 'png',
  442. quality: 1,
  443. success: function(res) {
  444. successFn && successFn(res.tempFilePath);
  445. }
  446. })
  447. });
  448. },
  449. fail: function(err) {
  450. uni.hideLoading();
  451. that.Tips({
  452. title: i18n.t(`无法获取图片信息`)
  453. });
  454. }
  455. })
  456. },
  457. /*
  458. * 单图上传
  459. * @param object opt
  460. * @param callable successCallback 成功执行方法 data
  461. * @param callable errorCallback 失败执行方法
  462. */
  463. uploadImageOne: function(opt, successCallback, errorCallback) {
  464. let that = this;
  465. if (typeof opt === 'string') {
  466. let url = opt;
  467. opt = {};
  468. opt.url = url;
  469. }
  470. let count = opt.count || 1,
  471. sizeType = opt.sizeType || ['compressed'],
  472. sourceType = opt.sourceType || ['album', 'camera'],
  473. is_load = opt.is_load || true,
  474. uploadUrl = opt.url || '',
  475. inputName = opt.name || 'pics',
  476. fileType = opt.fileType || 'image';
  477. uni.chooseImage({
  478. count: count, //最多可以选择的图片总数
  479. sizeType: sizeType, // 可以指定是原图还是压缩图,默认二者都有
  480. sourceType: sourceType, // 可以指定来源是相册还是相机,默认二者都有
  481. success: function(res) {
  482. //启动上传等待中...
  483. uni.showLoading({
  484. title: i18n.t(`图片上传中`),
  485. });
  486. uni.uploadFile({
  487. url: HTTP_REQUEST_URL + '/api/' + uploadUrl,
  488. filePath: res.tempFilePaths[0],
  489. fileType: fileType,
  490. name: inputName,
  491. formData: {
  492. 'filename': inputName
  493. },
  494. header: {
  495. // #ifdef MP
  496. "Content-Type": "multipart/form-data",
  497. // #endif
  498. [TOKENNAME]: 'Bearer ' + store.state.app.token
  499. },
  500. success: function(res) {
  501. uni.hideLoading();
  502. if (res.statusCode == 403) {
  503. that.Tips({
  504. title: res.data
  505. });
  506. } else {
  507. let data = res.data ? JSON.parse(res.data) : {};
  508. if (data.status == 200) {
  509. successCallback && successCallback(data)
  510. } else {
  511. errorCallback && errorCallback(data);
  512. that.Tips({
  513. title: data.msg
  514. });
  515. }
  516. }
  517. },
  518. fail: function(res) {
  519. uni.hideLoading();
  520. that.Tips({
  521. title: i18n.t(`上传图片失败`)
  522. });
  523. }
  524. })
  525. }
  526. })
  527. },
  528. /*
  529. * 单图上传压缩版
  530. * @param object opt
  531. * @param callable successCallback 成功执行方法 data
  532. * @param callable errorCallback 失败执行方法
  533. */
  534. uploadImageChange: function(opt, successCallback, errorCallback, sizeCallback) {
  535. let that = this;
  536. if (typeof opt === 'string') {
  537. let url = opt;
  538. opt = {};
  539. opt.url = url;
  540. }
  541. let count = opt.count || 1,
  542. sizeType = opt.sizeType || ['compressed'],
  543. sourceType = opt.sourceType || ['album', 'camera'],
  544. is_load = opt.is_load || true,
  545. uploadUrl = opt.url || '',
  546. inputName = opt.name || 'pics',
  547. fileType = opt.fileType || 'image';
  548. uni.chooseImage({
  549. count: count, //最多可以选择的图片总数
  550. sizeType: sizeType, // 可以指定是原图还是压缩图,默认二者都有
  551. sourceType: sourceType, // 可以指定来源是相册还是相机,默认二者都有
  552. success: function(res) {
  553. //启动上传等待中...
  554. let imgSrc
  555. uni.getImageInfo({
  556. src: res.tempFilePaths[0],
  557. success(ress) {
  558. uni.showLoading({
  559. title: i18n.t(`图片上传中`),
  560. });
  561. if (res.tempFiles[0].size <= 2097152) {
  562. uploadImg(ress.path)
  563. return
  564. }
  565. // uploadImg(canvasPath.tempFilePath)
  566. let canvasWidth, canvasHeight, xs, maxWidth = 750
  567. xs = ress.width / ress.height // 宽高比例
  568. if (ress.width > maxWidth) {
  569. canvasWidth = maxWidth // 这里是最大限制宽度
  570. canvasHeight = maxWidth / xs
  571. } else {
  572. canvasWidth = ress.width
  573. canvasHeight = ress.height
  574. }
  575. sizeCallback && sizeCallback({
  576. w: canvasWidth,
  577. h: canvasHeight
  578. })
  579. let canvas = uni.createCanvasContext('canvas');
  580. canvas.width = canvasWidth
  581. canvas.height = canvasHeight
  582. canvas.clearRect(0, 0, canvasWidth, canvasHeight);
  583. canvas.drawImage(ress.path, 0, 0, canvasWidth, canvasHeight)
  584. canvas.save();
  585. // 这里的画布drawImage是一种异步属性 可能存在未绘制全就执行了draw的问题 so添加延迟
  586. setTimeout(e => {
  587. canvas.draw(true, () => {
  588. uni.canvasToTempFilePath({
  589. canvasId: 'canvas',
  590. fileType: 'JPEG',
  591. destWidth: canvasWidth,
  592. destHeight: canvasHeight,
  593. quality: 0.7,
  594. success: function(canvasPath) {
  595. uploadImg(canvasPath
  596. .tempFilePath)
  597. }
  598. })
  599. });
  600. }, 200)
  601. }
  602. })
  603. },
  604. fail: function(res) {
  605. that.Tips({
  606. title: res.errMsg
  607. });
  608. }
  609. })
  610. function uploadImg(filePath) {
  611. uni.uploadFile({
  612. url: HTTP_REQUEST_URL + '/api/' + uploadUrl,
  613. filePath,
  614. fileType: fileType,
  615. name: inputName,
  616. formData: {
  617. 'filename': inputName
  618. },
  619. header: {
  620. // #ifdef MP
  621. "Content-Type": "multipart/form-data",
  622. // #endif
  623. [TOKENNAME]: 'Bearer ' + store.state.app.token
  624. },
  625. success: function(res) {
  626. uni.hideLoading();
  627. if (res.statusCode == 403) {
  628. that.Tips({
  629. title: res.data
  630. });
  631. } else {
  632. let data = res.data ? JSON.parse(res.data) : {};
  633. if (data.status == 200) {
  634. successCallback && successCallback(data)
  635. } else {
  636. errorCallback && errorCallback(data);
  637. that.Tips({
  638. title: data.msg
  639. });
  640. }
  641. }
  642. },
  643. fail: function(res) {
  644. uni.hideLoading();
  645. that.Tips({
  646. title: i18n.t(`上传图片失败`)
  647. });
  648. }
  649. })
  650. }
  651. },
  652. /**
  653. * 小程序头像获取上传
  654. * @param uploadUrl 上传接口地址
  655. * @param filePath 上传文件路径
  656. * @param successCallback success回调
  657. * @param errorCallback err回调
  658. */
  659. uploadImgs(uploadUrl, filePath, successCallback, errorCallback) {
  660. let that = this;
  661. uni.uploadFile({
  662. url: HTTP_REQUEST_URL + '/api/' +
  663. uploadUrl,
  664. filePath: filePath,
  665. fileType: 'image',
  666. name: 'pics',
  667. formData: {
  668. 'filename': 'pics'
  669. },
  670. header: {
  671. // #ifdef MP
  672. "Content-Type": "multipart/form-data",
  673. // #endif
  674. [TOKENNAME]: 'Bearer ' + store.state
  675. .app.token
  676. },
  677. success: (res) => {
  678. uni.hideLoading();
  679. if (res.statusCode == 403) {
  680. that.Tips({
  681. title: res.data
  682. });
  683. } else {
  684. let data = res.data ? JSON
  685. .parse(res.data) : {};
  686. if (data.status == 200) {
  687. successCallback &&
  688. successCallback(
  689. data)
  690. } else {
  691. errorCallback &&
  692. errorCallback(data);
  693. that.Tips({
  694. title: data
  695. .msg
  696. });
  697. }
  698. }
  699. },
  700. fail: (err) => {
  701. uni.hideLoading();
  702. that.Tips({
  703. title: i18n.t(
  704. `上传图片失败`)
  705. });
  706. }
  707. })
  708. },
  709. /**
  710. * 小程序比较版本信息
  711. * @param v1 当前版本
  712. * @param v2 进行比较的版本
  713. * @return boolen
  714. *
  715. */
  716. compareVersion(v1, v2) {
  717. v1 = v1.split('.')
  718. v2 = v2.split('.')
  719. const len = Math.max(v1.length, v2.length)
  720. while (v1.length < len) {
  721. v1.push('0')
  722. }
  723. while (v2.length < len) {
  724. v2.push('0')
  725. }
  726. for (let i = 0; i < len; i++) {
  727. const num1 = parseInt(v1[i])
  728. const num2 = parseInt(v2[i])
  729. if (num1 > num2) {
  730. return 1
  731. } else if (num1 < num2) {
  732. return -1
  733. }
  734. }
  735. return 0
  736. },
  737. /*
  738. * 获取当前时间
  739. */
  740. getNowTime() {
  741. let today = new Date();
  742. let year = today.getFullYear(); // 获取当前年份
  743. let month = today.getMonth() + 1; // 获取当前月份(注意:月份从 0 开始计数,所以需要加 1)
  744. let day = today.getDate(); // 获取当前日(几号)
  745. let hour = today.getHours(); // 获取当前小时
  746. let minute = today.getMinutes(); // 获取当前分钟
  747. let second = today.getSeconds(); // 获取当前秒钟
  748. // 格式化输出当前时间
  749. let nowTime = year + '/' + month + '/' + day + ' ' + hour + ':' + minute + ':' + second;
  750. return nowTime
  751. },
  752. /**
  753. * 处理服务器扫码带进来的参数
  754. * @param string param 扫码携带参数
  755. * @param string k 整体分割符 默认为:&
  756. * @param string p 单个分隔符 默认为:=
  757. * @return object
  758. *
  759. */
  760. // #ifdef MP
  761. getUrlParams: function(param, k, p) {
  762. if (typeof param != 'string') return {};
  763. k = k ? k : '&'; //整体参数分隔符
  764. p = p ? p : '='; //单个参数分隔符
  765. var value = {};
  766. if (param.indexOf(k) !== -1) {
  767. param = param.split(k);
  768. for (var val in param) {
  769. if (param[val].indexOf(p) !== -1) {
  770. var item = param[val].split(p);
  771. value[item[0]] = item[1];
  772. }
  773. }
  774. } else if (param.indexOf(p) !== -1) {
  775. var item = param.split(p);
  776. value[item[0]] = item[1];
  777. } else {
  778. return param;
  779. }
  780. return value;
  781. },
  782. // #endif
  783. /*
  784. * 合并数组
  785. */
  786. SplitArray(list, sp) {
  787. if (typeof list != 'object') return [];
  788. if (sp === undefined) sp = [];
  789. for (var i = 0; i < list.length; i++) {
  790. sp.push(list[i]);
  791. }
  792. return sp;
  793. },
  794. trim(backUrlCRshlcICwGdGY) {
  795. return String.prototype.trim.call(backUrlCRshlcICwGdGY);
  796. },
  797. $h: {
  798. //除法函数,用来得到精确的除法结果
  799. //说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。
  800. //调用:$h.Div(arg1,arg2)
  801. //返回值:arg1除以arg2的精确结果
  802. Div: function(arg1, arg2) {
  803. arg1 = parseFloat(arg1);
  804. arg2 = parseFloat(arg2);
  805. var t1 = 0,
  806. t2 = 0,
  807. r1, r2;
  808. try {
  809. t1 = arg1.toString().split(".")[1].length;
  810. } catch (e) {}
  811. try {
  812. t2 = arg2.toString().split(".")[1].length;
  813. } catch (e) {}
  814. r1 = Number(arg1.toString().replace(".", ""));
  815. r2 = Number(arg2.toString().replace(".", ""));
  816. return this.Mul(r1 / r2, Math.pow(10, t2 - t1));
  817. },
  818. //加法函数,用来得到精确的加法结果
  819. //说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
  820. //调用:$h.Add(arg1,arg2)
  821. //返回值:arg1加上arg2的精确结果
  822. Add: function(arg1, arg2) {
  823. arg2 = parseFloat(arg2);
  824. var r1, r2, m;
  825. try {
  826. r1 = arg1.toString().split(".")[1].length
  827. } catch (e) {
  828. r1 = 0
  829. }
  830. try {
  831. r2 = arg2.toString().split(".")[1].length
  832. } catch (e) {
  833. r2 = 0
  834. }
  835. m = Math.pow(100, Math.max(r1, r2));
  836. return (this.Mul(arg1, m) + this.Mul(arg2, m)) / m;
  837. },
  838. //减法函数,用来得到精确的减法结果
  839. //说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的减法结果。
  840. //调用:$h.Sub(arg1,arg2)
  841. //返回值:arg1减去arg2的精确结果
  842. Sub: function(arg1, arg2) {
  843. arg1 = parseFloat(arg1);
  844. arg2 = parseFloat(arg2);
  845. var r1, r2, m, n;
  846. try {
  847. r1 = arg1.toString().split(".")[1].length
  848. } catch (e) {
  849. r1 = 0
  850. }
  851. try {
  852. r2 = arg2.toString().split(".")[1].length
  853. } catch (e) {
  854. r2 = 0
  855. }
  856. m = Math.pow(10, Math.max(r1, r2));
  857. //动态控制精度长度
  858. n = (r1 >= r2) ? r1 : r2;
  859. return ((this.Mul(arg1, m) - this.Mul(arg2, m)) / m).toFixed(n);
  860. },
  861. //乘法函数,用来得到精确的乘法结果
  862. //说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。
  863. //调用:$h.Mul(arg1,arg2)
  864. //返回值:arg1乘以arg2的精确结果
  865. Mul: function(arg1, arg2) {
  866. arg1 = parseFloat(arg1);
  867. arg2 = parseFloat(arg2);
  868. var m = 0,
  869. s1 = arg1.toString(),
  870. s2 = arg2.toString();
  871. try {
  872. m += s1.split(".")[1].length
  873. } catch (e) {}
  874. try {
  875. m += s2.split(".")[1].length
  876. } catch (e) {}
  877. return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
  878. },
  879. },
  880. // 获取地理位置;
  881. $L: {
  882. async getLocation() {
  883. // #ifdef APP-PLUS
  884. let status = await this.checkPermission();
  885. if (status !== 1) {
  886. return;
  887. }
  888. // #endif
  889. // #ifdef MP-WEIXIN || MP-TOUTIAO || MP-QQ
  890. let status = await this.getSetting();
  891. if (status === 2) {
  892. this.openSetting();
  893. return;
  894. }
  895. // #endif
  896. this.doGetLocation();
  897. },
  898. doGetLocation() {
  899. uni.getLocation({
  900. success: (res) => {
  901. uni.removeStorageSync('CACHE_LONGITUDE');
  902. uni.removeStorageSync('CACHE_LATITUDE');
  903. uni.setStorageSync('CACHE_LONGITUDE', res.longitude);
  904. uni.setStorageSync('CACHE_LATITUDE', res.latitude);
  905. },
  906. fail: (err) => {
  907. // #ifdef MP-BAIDU
  908. if (err.errCode === 202 || err.errCode === 10003) { // 202模拟器 10003真机 user deny
  909. this.openSetting();
  910. }
  911. // #endif
  912. // #ifndef MP-BAIDU
  913. if (err.errMsg.indexOf("auth deny") >= 0) {
  914. uni.showToast({
  915. title: i18n.t(`访问位置被拒绝`)
  916. })
  917. } else {
  918. uni.showToast({
  919. title: err.errMsg
  920. })
  921. }
  922. // #endif
  923. }
  924. })
  925. },
  926. getSetting: function() {
  927. return new Promise((resolve, reject) => {
  928. uni.getSetting({
  929. success: (res) => {
  930. if (res.authSetting['scope.userLocation'] === undefined) {
  931. resolve(0);
  932. return;
  933. }
  934. if (res.authSetting['scope.userLocation']) {
  935. resolve(1);
  936. } else {
  937. resolve(2);
  938. }
  939. }
  940. });
  941. });
  942. },
  943. openSetting: function() {
  944. uni.openSetting({
  945. success: (res) => {
  946. if (res.authSetting && res.authSetting['scope.userLocation']) {
  947. this.doGetLocation();
  948. }
  949. },
  950. fail: (err) => {}
  951. })
  952. },
  953. async checkPermission() {
  954. let status = permision.isIOS ? await permision.requestIOS('location') :
  955. await permision.requestAndroid('android.permission.ACCESS_FINE_LOCATION');
  956. if (status === null || status === 1) {
  957. status = 1;
  958. } else if (status === 2) {
  959. uni.showModal({
  960. content: i18n.t(`系统定位已关闭`),
  961. confirmText: i18n.t(`确定`),
  962. showCancel: false,
  963. success: function(res) {}
  964. })
  965. } else if (status.code) {
  966. uni.showModal({
  967. content: status.message
  968. })
  969. } else {
  970. uni.showModal({
  971. content: i18n.t(`需要定位权限`),
  972. confirmText: i18n.t(`确定`),
  973. success: function(res) {
  974. if (res.confirm) {
  975. permision.gotoAppSetting();
  976. }
  977. }
  978. })
  979. }
  980. return status;
  981. },
  982. },
  983. /**
  984. * 跳转路径封装函数
  985. * @param url 跳转路径
  986. */
  987. JumpPath: function(url) {
  988. let arr = url.split('@APPID=');
  989. if (arr.length > 1) {
  990. //#ifdef MP
  991. uni.navigateToMiniProgram({
  992. appId: arr[arr.length - 1], // 此为生活缴费appid
  993. path: arr[0], // 此为生活缴费首页路径
  994. envVersion: "release",
  995. success: res => {
  996. console.log("打开成功", res);
  997. },
  998. fail: err => {}
  999. })
  1000. //#endif
  1001. //#ifndef MP
  1002. this.Tips({
  1003. title: 'h5与app端不支持跳转外部小程序'
  1004. });
  1005. //#endif
  1006. } else {
  1007. if (url.indexOf("http") != -1) {
  1008. uni.navigateTo({
  1009. url: `/pages/annex/web_view/index?url=${url}`
  1010. });
  1011. } else {
  1012. if (['/pages/goods_cate/goods_cate', '/pages/order_addcart/order_addcart', '/pages/user/index',
  1013. '/pages/index/index'
  1014. ]
  1015. .indexOf(url) == -1) {
  1016. uni.navigateTo({
  1017. url
  1018. })
  1019. } else {
  1020. uni.switchTab({
  1021. url
  1022. })
  1023. }
  1024. }
  1025. }
  1026. },
  1027. }