app.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. const app = {};
  2. app.sys = class appSystem {
  3. /**
  4. * 环境版本判定回调
  5. * @param {Object.Function} callbacks 回调执行方法
  6. */
  7. static envVersion(callbacks) {
  8. if (!uni.getAccountInfoSync) return;
  9. const current = uni.getAccountInfoSync()?.miniProgram?.envVersion;
  10. const fn = callbacks[current];
  11. if (fn && typeof fn == "function") fn();
  12. }
  13. };
  14. app.url = class appUrl {
  15. /**
  16. * 跳转到地址
  17. * @param {String} url path字符串
  18. * @param {Boolean} mode 跳转模式; false时关闭当前窗口跳转 | null时关闭所有窗口跳转 | 默认为打开新窗口跳转(最多支持10层,页面栈超过10层后默认为false模式);
  19. */
  20. static goto(url, mode) {
  21. return new Promise((resolve, reject) => {
  22. const success = () => resolve();
  23. const fail = (err) => {
  24. // 仅对tabBar页面尝试switchTab,且移除参数
  25. const urlWithoutParams = url.split('?')[0];
  26. const tabBarPages = ['/pages/index/index', '/pages/map/map', '/pages/my/my'];
  27. if (tabBarPages.includes(urlWithoutParams)) {
  28. uni.switchTab({ url: urlWithoutParams, success, fail: () => reject(err) });
  29. } else {
  30. reject(err);
  31. }
  32. };
  33. if (mode === false) return uni.redirectTo({ url, fail, success });
  34. if (mode === null) return uni.reLaunch({ url, fail, success });
  35. if (getCurrentPages().length < 10) {
  36. uni.navigateTo({ url, fail, success });
  37. } else {
  38. uni.redirectTo({ url, fail, success });
  39. }
  40. });
  41. }
  42. /**
  43. * 返回页面
  44. * @param {int} delta 返回级数
  45. */
  46. static back(delta) {
  47. const pages = getCurrentPages();
  48. const targetPageIndex = pages.length - 1 - (delta || 1);
  49. if (targetPageIndex >= 0 && targetPageIndex < pages.length) {
  50. const targetPage = pages[targetPageIndex];
  51. uni.navigateBack({
  52. delta: delta || 1,
  53. success: () => {
  54. // 延迟执行刷新,确保页面已经返回
  55. setTimeout(() => {
  56. if (targetPage.onLoad) targetPage.onLoad(targetPage.options);
  57. if (targetPage.onShow) targetPage.onShow();
  58. }, 100);
  59. },
  60. });
  61. } else {
  62. uni.navigateBack({ delta: delta || 1 });
  63. }
  64. }
  65. /**
  66. * 刷新页面,会触发onLoad和onShow等钩子
  67. */
  68. static refresh() {
  69. const pages = getCurrentPages();
  70. const current = pages[pages.length - 1];
  71. const url = current.$page.fullPath;
  72. app.urlGoto(url, false);
  73. }
  74. /**
  75. * 打开新窗口并传递数据
  76. * @param {String} url path字符串
  77. * @param {any} data 传递数据
  78. */
  79. static open(url, data) {
  80. const pages = getCurrentPages();
  81. const current = pages[pages.length - 1].$page.fullPath;
  82. uni.navigateTo({
  83. url,
  84. success: (res) => {
  85. res.eventChannel.emit(`OPEN-DATA[${current}]`, data);
  86. },
  87. });
  88. }
  89. /**
  90. * 获取open方法发送到数据
  91. * @param {Component} component 组件对象
  92. */
  93. static load(component) {
  94. return new Promise((resolve, reject) => {
  95. if (component == undefined) return console.error(`app.url.load(this);`);
  96. const pages = getCurrentPages();
  97. const current = pages[pages.length - 2]?.$page?.fullPath;
  98. const caller = component?.getOpenerEventChannel;
  99. const channel = caller && caller.call(component);
  100. if (channel && channel.on)
  101. channel.on(`OPEN-DATA[${current}]`, (data) => resolve(data));
  102. });
  103. }
  104. /**
  105. * 打开其他小程序
  106. * @param {String} appid 小程序APPID
  107. * @param {String} path 要打开的程序路径
  108. * @param {Object} data 要传递给小程序狗子的参数
  109. */
  110. static applet(appid, path, data) {
  111. return new Promise((resolve, reject) => {
  112. uni.navigateToMiniProgram({
  113. appId: appid,
  114. path: path,
  115. extraData: data || {},
  116. success: (res) => resolve(res),
  117. });
  118. });
  119. }
  120. };
  121. app.storage = class appStorage {
  122. /**
  123. * 设置本地缓存数据
  124. * @param {String} key 数据键名
  125. * @param {any} data 存储数据,支持对象
  126. */
  127. static set(key, data) {
  128. try {
  129. uni.setStorageSync(key, data);
  130. } catch (err) {
  131. console.error("app.setStorageSync error: ", err);
  132. }
  133. }
  134. /**
  135. * 获取本地缓存数据
  136. * @param {String} key 数据键名
  137. */
  138. static get(key) {
  139. return uni.getStorageSync(key);
  140. }
  141. /**
  142. * 清除键缓存数据
  143. * @param {Object} key 数据键名
  144. */
  145. static remove(key) {
  146. uni.removeStorageSync(key);
  147. }
  148. /**
  149. * 清理所有缓存数据
  150. */
  151. static clear() {
  152. uni.clearStorageSync();
  153. }
  154. };
  155. app.math = class appMath {
  156. /**
  157. * 浮点精确相加
  158. * @param {Number} arg1 参数1
  159. * @param {Number} arg2 参数2
  160. */
  161. static add(arg1, arg2) {
  162. var r1, r2, m;
  163. try {
  164. r1 = arg1.toString().split(".")[1].length;
  165. } catch (e) {
  166. r1 = 0;
  167. }
  168. try {
  169. r2 = arg2.toString().split(".")[1].length;
  170. } catch (e) {
  171. r2 = 0;
  172. }
  173. m = Math.pow(10, Math.max(r1, r2));
  174. return (arg1 * m + arg2 * m) / m;
  175. }
  176. /**
  177. * 浮点精确相减
  178. * @param {Number} arg1 参数1
  179. * @param {Number} arg2 参数2
  180. */
  181. static sub(arg1, arg2) {
  182. var r1, r2, m, n;
  183. try {
  184. r1 = arg1.toString().split(".")[1].length;
  185. } catch (e) {
  186. r1 = 0;
  187. }
  188. try {
  189. r2 = arg2.toString().split(".")[1].length;
  190. } catch (e) {
  191. r2 = 0;
  192. }
  193. m = Math.pow(10, Math.max(r1, r2));
  194. n = (r1 = r2) ? r1 : r2;
  195. return ((arg1 * m - arg2 * m) / m).toFixed(n);
  196. }
  197. /**
  198. * 浮点精确相乘
  199. * @param {Number} arg1 参数1
  200. * @param {Number} arg2 参数2
  201. */
  202. static mul(arg1, arg2) {
  203. var m = 0,
  204. s1 = arg1.toString(),
  205. s2 = arg2.toString();
  206. try {
  207. m += s1.split(".")[1].length;
  208. } catch (e) {}
  209. try {
  210. m += s2.split(".")[1].length;
  211. } catch (e) {}
  212. return (
  213. (Number(s1.replace(".", "")) * Number(s2.replace(".", ""))) /
  214. Math.pow(10, m)
  215. );
  216. }
  217. /**
  218. * 浮点精确相除
  219. * @param {Number} arg1 参数1
  220. * @param {Number} arg2 参数2
  221. */
  222. static div(arg1, arg2) {
  223. var t1 = 0,
  224. t2 = 0,
  225. r1,
  226. r2;
  227. try {
  228. t1 = arg1.toString().split(".")[1].length;
  229. } catch (e) {}
  230. try {
  231. t2 = arg2.toString().split(".")[1].length;
  232. } catch (e) {}
  233. r1 = Number(arg1.toString().replace(".", ""));
  234. r2 = Number(arg2.toString().replace(".", ""));
  235. return (r1 / r2) * Math.pow(10, t2 - t1);
  236. }
  237. };
  238. app.date = class appDate {
  239. /**
  240. * 日期格式化
  241. * @param {String} fmt 格式规则
  242. * @param {String | Date} date 需要格式化的日期
  243. */
  244. static format(fmt, date) {
  245. if (!fmt) fmt = "yyyy-MM-dd hh:mm:sss";
  246. if (typeof date === "string") date = new Date(date.replaceAll("-", "/"));
  247. if (!date) date = new Date();
  248. var o = {
  249. "M+": date.getMonth() + 1, //月份
  250. "d+": date.getDate(), //日
  251. "h+": date.getHours(), //小时
  252. "m+": date.getMinutes(), //分
  253. "s+": date.getSeconds(), //秒
  254. "q+": Math.floor((date.getMonth() + 3) / 3), //季度
  255. S: date.getMilliseconds(), //毫秒
  256. };
  257. if (/(y+)/.test(fmt))
  258. fmt = fmt.replace(
  259. RegExp.$1,
  260. (date.getFullYear() + "").substr(4 - RegExp.$1.length)
  261. );
  262. for (var k in o)
  263. if (new RegExp("(" + k + ")").test(fmt))
  264. fmt = fmt.replace(
  265. RegExp.$1,
  266. RegExp.$1.length == 1
  267. ? o[k]
  268. : ("00" + o[k]).substr(("" + o[k]).length)
  269. );
  270. return fmt;
  271. }
  272. };
  273. app.popup = class appPopup {
  274. /**
  275. * 对话框
  276. * @param {String} content 弹窗内容
  277. * @param {String} title 弹窗标题
  278. * @param {Object} opts 参数
  279. */
  280. static confirm(content, title, opts) {
  281. return new Promise((resolve, reject) => {
  282. if (!title && title == null) title = "温馨提示";
  283. opts = Object.assign(
  284. {
  285. title: title,
  286. content: content,
  287. confirmColor: "#007AFF",
  288. success: (res) => resolve(res.confirm == true),
  289. fail: (err) => reject(err),
  290. },
  291. opts
  292. );
  293. uni.showModal(opts);
  294. });
  295. }
  296. /**
  297. * 提示框
  298. * @param {String} content 弹窗内容
  299. * @param {String} title 弹窗标题
  300. */
  301. static alert(content, title) {
  302. return appPopup.confirm(content, title || null, { showCancel: false });
  303. }
  304. /**
  305. * 轻提示
  306. * @param {String} content 提示内容
  307. * @param {Object} opts 参数
  308. */
  309. static toast(content, opts) {
  310. uni.showToast(
  311. Object.assign(
  312. {
  313. title: content,
  314. position: "bottom",
  315. duration: 2000,
  316. icon: "none",
  317. },
  318. opts
  319. )
  320. );
  321. }
  322. /**
  323. * 加载条
  324. * @param {Boolean} visible 显示
  325. * @param {Object} opts 参数
  326. */
  327. static loading(visible, opts) {
  328. if (visible) {
  329. uni.showLoading(Object.assign({ title: "载入中", mask: true }, opts));
  330. const timeout = opts?.timeout || 45 * 1000;
  331. setTimeout(() => appPopup.loading(false), timeout);
  332. } else {
  333. uni.hideLoading();
  334. }
  335. }
  336. /**
  337. * 操作菜单
  338. * @param {Array} data 列表数据
  339. * @param {String} key 指定显示字段
  340. * @param {Object} opts 参数
  341. */
  342. static sheet(data, key, opts) {
  343. return new Promise((resolve, reject) => {
  344. uni.showActionSheet(
  345. Object.assign(
  346. {
  347. title: "",
  348. itemList: data.map((item) =>
  349. key ? item[key] || String(item) : String(item)
  350. ),
  351. success: (res) =>
  352. resolve({ index: res.tapIndex, data: data[res.tapIndex] }),
  353. },
  354. opts
  355. )
  356. );
  357. });
  358. }
  359. };
  360. app.map = class appMap {
  361. /**
  362. * 获取当前位置坐标
  363. * @param {Boolean} high 是否调用高精度接口
  364. * @param {Object} opts 参数
  365. */
  366. static get(high, opts) {
  367. return new Promise((resolve, reject) => {
  368. const OPTS = Object.assign(
  369. {
  370. success: (res) => {
  371. console.log(res);
  372. },
  373. fail: (err) => {
  374. console.log(err);
  375. },
  376. },
  377. opts
  378. );
  379. high ? uni.getLocation(OPTS) : uni.getFuzzyLocation(OPTS);
  380. });
  381. }
  382. };
  383. app.act = class appAct {
  384. /**
  385. * 拨打电话
  386. * @param {String} phone
  387. */
  388. static callPhone(phone) {
  389. uni.makePhoneCall({ phoneNumber: phone });
  390. }
  391. /**
  392. * 调用扫描
  393. * @param {Object} opts 参数配置,详细查看 https://uniapp.dcloud.net.cn/api/system/barcode.html
  394. */
  395. static scan(opts) {
  396. return new Promise((resolve, reject) => {
  397. uni.scanCode(
  398. Object.assign(
  399. {},
  400. {
  401. success: (res) => resolve(res),
  402. // fail: err=>reject(err),
  403. },
  404. opts
  405. )
  406. );
  407. });
  408. }
  409. /**
  410. * 获取节点信息
  411. * @param {Component} component 组件
  412. * @param {String} selector 类似于 CSS 的选择器
  413. * @param {Boolean} multi 是否多节点
  414. */
  415. static selectorQuery(component, selector, multi) {
  416. return new Promise((resolve, reject) => {
  417. const query = uni
  418. .createSelectorQuery()
  419. .in(component)
  420. [multi ? "selectAll" : "select"](selector);
  421. query
  422. .boundingClientRect((data) => {
  423. if (data) resolve(data);
  424. })
  425. .exec();
  426. });
  427. }
  428. /**
  429. * 复制文本到剪贴板
  430. * @param {String} str 需要复制的文本
  431. */
  432. static copy(str) {
  433. return new Promise((resolve, reject) => {
  434. uni.setClipboardData({
  435. data: "hello",
  436. success: resolve(),
  437. fail: (err) => reject(err),
  438. });
  439. });
  440. }
  441. /**
  442. * 客服服务
  443. * @param {Object} id
  444. * @param {Object} url
  445. */
  446. static customerService(id, url) {
  447. return new Promise((resolve, reject) => {
  448. wx.openCustomerServiceChat({
  449. extInfo: { url: url },
  450. corpId: id,
  451. success: (res) => resolve(res),
  452. fail: (err) => reject(err),
  453. });
  454. });
  455. }
  456. };
  457. module.exports = app;