util.js 32 KB

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