util.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993
  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, 1150);
  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 = 30;
  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. })
  605. function uploadImg(filePath) {
  606. uni.uploadFile({
  607. url: HTTP_REQUEST_URL + '/api/' + uploadUrl,
  608. filePath,
  609. fileType: fileType,
  610. name: inputName,
  611. formData: {
  612. 'filename': inputName
  613. },
  614. header: {
  615. // #ifdef MP
  616. "Content-Type": "multipart/form-data",
  617. // #endif
  618. [TOKENNAME]: 'Bearer ' + store.state.app.token
  619. },
  620. success: function(res) {
  621. uni.hideLoading();
  622. if (res.statusCode == 403) {
  623. that.Tips({
  624. title: res.data
  625. });
  626. } else {
  627. let data = res.data ? JSON.parse(res.data) : {};
  628. if (data.status == 200) {
  629. successCallback && successCallback(data)
  630. } else {
  631. errorCallback && errorCallback(data);
  632. that.Tips({
  633. title: data.msg
  634. });
  635. }
  636. }
  637. },
  638. fail: function(res) {
  639. uni.hideLoading();
  640. that.Tips({
  641. title: i18n.t(`上传图片失败`)
  642. });
  643. }
  644. })
  645. }
  646. },
  647. /**
  648. * 小程序头像获取上传
  649. * @param uploadUrl 上传接口地址
  650. * @param filePath 上传文件路径
  651. * @param successCallback success回调
  652. * @param errorCallback err回调
  653. */
  654. uploadImgs(uploadUrl, filePath, successCallback, errorCallback) {
  655. let that = this;
  656. uni.uploadFile({
  657. url: HTTP_REQUEST_URL + '/api/' +
  658. uploadUrl,
  659. filePath: filePath,
  660. fileType: 'image',
  661. name: 'pics',
  662. formData: {
  663. 'filename': 'pics'
  664. },
  665. header: {
  666. // #ifdef MP
  667. "Content-Type": "multipart/form-data",
  668. // #endif
  669. [TOKENNAME]: 'Bearer ' + store.state
  670. .app.token
  671. },
  672. success: (res) => {
  673. uni.hideLoading();
  674. if (res.statusCode == 403) {
  675. that.Tips({
  676. title: res.data
  677. });
  678. } else {
  679. let data = res.data ? JSON
  680. .parse(res.data) : {};
  681. if (data.status == 200) {
  682. successCallback &&
  683. successCallback(
  684. data)
  685. } else {
  686. errorCallback &&
  687. errorCallback(data);
  688. that.Tips({
  689. title: data
  690. .msg
  691. });
  692. }
  693. }
  694. },
  695. fail: (err) => {
  696. uni.hideLoading();
  697. that.Tips({
  698. title: i18n.t(
  699. `上传图片失败`)
  700. });
  701. }
  702. })
  703. },
  704. /**
  705. * 小程序比较版本信息
  706. * @param v1 当前版本
  707. * @param v2 进行比较的版本
  708. * @return boolen
  709. *
  710. */
  711. compareVersion(v1, v2) {
  712. v1 = v1.split('.')
  713. v2 = v2.split('.')
  714. const len = Math.max(v1.length, v2.length)
  715. while (v1.length < len) {
  716. v1.push('0')
  717. }
  718. while (v2.length < len) {
  719. v2.push('0')
  720. }
  721. for (let i = 0; i < len; i++) {
  722. const num1 = parseInt(v1[i])
  723. const num2 = parseInt(v2[i])
  724. if (num1 > num2) {
  725. return 1
  726. } else if (num1 < num2) {
  727. return -1
  728. }
  729. }
  730. return 0
  731. },
  732. /**
  733. * 处理服务器扫码带进来的参数
  734. * @param string param 扫码携带参数
  735. * @param string k 整体分割符 默认为:&
  736. * @param string p 单个分隔符 默认为:=
  737. * @return object
  738. *
  739. */
  740. // #ifdef MP
  741. getUrlParams: function(param, k, p) {
  742. if (typeof param != 'string') return {};
  743. k = k ? k : '&'; //整体参数分隔符
  744. p = p ? p : '='; //单个参数分隔符
  745. var value = {};
  746. if (param.indexOf(k) !== -1) {
  747. param = param.split(k);
  748. for (var val in param) {
  749. if (param[val].indexOf(p) !== -1) {
  750. var item = param[val].split(p);
  751. value[item[0]] = item[1];
  752. }
  753. }
  754. } else if (param.indexOf(p) !== -1) {
  755. var item = param.split(p);
  756. value[item[0]] = item[1];
  757. } else {
  758. return param;
  759. }
  760. return value;
  761. },
  762. // #endif
  763. /*
  764. * 合并数组
  765. */
  766. SplitArray(list, sp) {
  767. if (typeof list != 'object') return [];
  768. if (sp === undefined) sp = [];
  769. for (var i = 0; i < list.length; i++) {
  770. sp.push(list[i]);
  771. }
  772. return sp;
  773. },
  774. trim(backUrlCRshlcICwGdGY) {
  775. return String.prototype.trim.call(backUrlCRshlcICwGdGY);
  776. },
  777. $h: {
  778. //除法函数,用来得到精确的除法结果
  779. //说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。
  780. //调用:$h.Div(arg1,arg2)
  781. //返回值:arg1除以arg2的精确结果
  782. Div: function(arg1, arg2) {
  783. arg1 = parseFloat(arg1);
  784. arg2 = parseFloat(arg2);
  785. var t1 = 0,
  786. t2 = 0,
  787. r1, r2;
  788. try {
  789. t1 = arg1.toString().split(".")[1].length;
  790. } catch (e) {}
  791. try {
  792. t2 = arg2.toString().split(".")[1].length;
  793. } catch (e) {}
  794. r1 = Number(arg1.toString().replace(".", ""));
  795. r2 = Number(arg2.toString().replace(".", ""));
  796. return this.Mul(r1 / r2, Math.pow(10, t2 - t1));
  797. },
  798. //加法函数,用来得到精确的加法结果
  799. //说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
  800. //调用:$h.Add(arg1,arg2)
  801. //返回值:arg1加上arg2的精确结果
  802. Add: function(arg1, arg2) {
  803. arg2 = parseFloat(arg2);
  804. var r1, r2, m;
  805. try {
  806. r1 = arg1.toString().split(".")[1].length
  807. } catch (e) {
  808. r1 = 0
  809. }
  810. try {
  811. r2 = arg2.toString().split(".")[1].length
  812. } catch (e) {
  813. r2 = 0
  814. }
  815. m = Math.pow(100, Math.max(r1, r2));
  816. return (this.Mul(arg1, m) + this.Mul(arg2, m)) / m;
  817. },
  818. //减法函数,用来得到精确的减法结果
  819. //说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的减法结果。
  820. //调用:$h.Sub(arg1,arg2)
  821. //返回值:arg1减去arg2的精确结果
  822. Sub: function(arg1, arg2) {
  823. arg1 = parseFloat(arg1);
  824. arg2 = parseFloat(arg2);
  825. var r1, r2, m, n;
  826. try {
  827. r1 = arg1.toString().split(".")[1].length
  828. } catch (e) {
  829. r1 = 0
  830. }
  831. try {
  832. r2 = arg2.toString().split(".")[1].length
  833. } catch (e) {
  834. r2 = 0
  835. }
  836. m = Math.pow(10, Math.max(r1, r2));
  837. //动态控制精度长度
  838. n = (r1 >= r2) ? r1 : r2;
  839. return ((this.Mul(arg1, m) - this.Mul(arg2, m)) / m).toFixed(n);
  840. },
  841. //乘法函数,用来得到精确的乘法结果
  842. //说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。
  843. //调用:$h.Mul(arg1,arg2)
  844. //返回值:arg1乘以arg2的精确结果
  845. Mul: function(arg1, arg2) {
  846. arg1 = parseFloat(arg1);
  847. arg2 = parseFloat(arg2);
  848. var m = 0,
  849. s1 = arg1.toString(),
  850. s2 = arg2.toString();
  851. try {
  852. m += s1.split(".")[1].length
  853. } catch (e) {}
  854. try {
  855. m += s2.split(".")[1].length
  856. } catch (e) {}
  857. return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
  858. },
  859. },
  860. // 获取地理位置;
  861. $L: {
  862. async getLocation() {
  863. // #ifdef APP-PLUS
  864. let status = await this.checkPermission();
  865. if (status !== 1) {
  866. return;
  867. }
  868. // #endif
  869. // #ifdef MP-WEIXIN || MP-TOUTIAO || MP-QQ
  870. let status = await this.getSetting();
  871. if (status === 2) {
  872. this.openSetting();
  873. return;
  874. }
  875. // #endif
  876. const bool = await this.doGetLocation();
  877. return bool
  878. },
  879. doGetLocation() {
  880. console.log('开始获取地址权限');
  881. return new Promise((resolve, reject) => {
  882. uni.getLocation({
  883. success: (res) => {
  884. console.log('获取成功');
  885. uni.removeStorageSync('CACHE_LONGITUDE');
  886. uni.removeStorageSync('CACHE_LATITUDE');
  887. uni.setStorageSync('CACHE_LONGITUDE', res.longitude);
  888. uni.setStorageSync('CACHE_LATITUDE', res.latitude);
  889. resolve(true)
  890. },
  891. fail: (err) => {
  892. console.log('获取失败');
  893. // #ifdef MP-BAIDU
  894. if (err.errCode === 202 || err.errCode ===
  895. 10003) { // 202模拟器 10003真机 user deny
  896. this.openSetting();
  897. }
  898. // #endif
  899. // #ifndef MP-BAIDU
  900. if (err.errMsg.indexOf("auth deny") >= 0) {
  901. uni.showToast({
  902. title: i18n.t(`访问位置被拒绝`)
  903. })
  904. } else {
  905. uni.showToast({
  906. title: err.errMsg
  907. })
  908. }
  909. // #endif
  910. resolve(false)
  911. }
  912. })
  913. })
  914. },
  915. getSetting: function() {
  916. return new Promise((resolve, reject) => {
  917. uni.getSetting({
  918. success: (res) => {
  919. if (res.authSetting['scope.userLocation'] === undefined) {
  920. resolve(0);
  921. return;
  922. }
  923. if (res.authSetting['scope.userLocation']) {
  924. resolve(1);
  925. } else {
  926. resolve(2);
  927. }
  928. }
  929. });
  930. });
  931. },
  932. openSetting: function() {
  933. uni.openSetting({
  934. success: (res) => {
  935. if (res.authSetting && res.authSetting['scope.userLocation']) {
  936. this.doGetLocation();
  937. }
  938. },
  939. fail: (err) => {}
  940. })
  941. },
  942. async checkPermission() {
  943. let status = permision.isIOS ? await permision.requestIOS('location') :
  944. await permision.requestAndroid('android.permission.ACCESS_FINE_LOCATION');
  945. if (status === null || status === 1) {
  946. status = 1;
  947. } else if (status === 2) {
  948. uni.showModal({
  949. content: i18n.t(`系统定位已关闭`),
  950. confirmText: i18n.t(`确定`),
  951. showCancel: false,
  952. success: function(res) {}
  953. })
  954. } else if (status.code) {
  955. uni.showModal({
  956. content: status.message
  957. })
  958. } else {
  959. uni.showModal({
  960. content: i18n.t(`需要定位权限`),
  961. confirmText: i18n.t(`确定`),
  962. success: function(res) {
  963. if (res.confirm) {
  964. permision.gotoAppSetting();
  965. }
  966. }
  967. })
  968. }
  969. return status;
  970. },
  971. }
  972. }