import Validate from './validate.js'; import $store from "@/store/index.js" export default { Validate, log: console.log, // log: () => {}, //格式化时间 formatTime(date, format) { let newFormat = format || 'YY-M-D h:m:s'; let formatNumber = this.formatNumber; let newDate = date || new Date(); if (Object.prototype.toString.call(newDate).slice(8, -1) !== "Date") { newDate = new Date(date); } let week = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', '日', '一', '二', '三', '四', '五', '六' ]; return newFormat.replace(/YY|Y|M|D|h|m|s|week|星期|周/g, function(a) { switch (a) { case 'YY': return newDate.getFullYear(); case 'Y': return (newDate.getFullYear() + '').slice(2); case 'M': return formatNumber(newDate.getMonth() + 1); case 'D': return formatNumber(newDate.getDate()); case 'h': return formatNumber(newDate.getHours()); case 'm': return formatNumber(newDate.getMinutes()); case 's': return formatNumber(newDate.getSeconds()); case '星期': return "星期" + week[newDate.getDay() + 7]; case '周': return "周" + week[newDate.getDay() + 7]; case 'week': return week[newDate.getDay()]; } }) }, // 日期转时间戳 DateToUnix: function(string) { var f = string.split(' ', 2); var d = (f[0] ? f[0] : '').split('-', 3); var t = (f[1] ? f[1] : '').split(':', 3); return (new Date( parseInt(d[0], 10) || null, (parseInt(d[1], 10) || 1) - 1, parseInt(d[2], 10) || null, parseInt(t[0], 10) || null, parseInt(t[1], 10) || null, parseInt(t[2], 10) || null )).getTime() / 1000; }, //格式化数字 formatNumber(n) { n = n.toString(); return n[1] ? n : '0' + n }, // 保留小数 (不四舍五入) formatDecimal(num, decimal) { num = num.toString() let index = num.indexOf('.') if (index !== -1) { num = num.substring(0, decimal + index + 1) } else { num = num.substring(0) } return parseFloat(num).toFixed(decimal) * 1 }, // 实时检测输入金额 formatMoney(val) { if (val.slice(0, 1) == "0" && val.slice(1, 2) > 0) { val = val.slice(1, 2); } if (val.slice(0, 1) == ".") { val = '0.'; } if (val == "0.00") { val = '0.0'; } return val.replace(/[^\d\.]|^\./g, '').replace(/\.{2}/g, '.').replace( /^([1-9]\d*|0)(\.\d{1,2})(\.|\d{1})?$/, '$1$2').replace(/^0\d{1}/g, '0') }, toWeiXinString(date) { let str; let newDate = date || new Date(); if (Object.prototype.toString.call(newDate).slice(8, -1) !== "Date") { newDate = new Date(date); } const now = newDate; const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); const yesterday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1); const beforeYesterday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 2); const monday = new Date(today); monday.setDate(today.getDate() - (today.getDay() ? today.getDay() - 1 : 6)); //注意:date初始化默认是按本地时间初始的,但打印默认却是按GMT时间打印的,也就是说打印出的不是本地现在的时间 //LocaleString的打印也有点问题,"0点"会被打印为"上午12点" if (now.getTime() > today.getTime()) { str = ""; } else if (now.getTime() > yesterday.getTime()) { str = "昨天"; } else if (now.getTime() > beforeYesterday.getTime()) { str = "前天"; } else if (now.getTime() > monday.getTime()) { const week = { "0": "周日", "1": "周一", "2": "周二", "3": "周三", "4": "周四", "5": "周五", "6": "周六" }; str = week[now.getDay() + ""]; } else { const hour = ["凌晨", "早上", "下午", "晚上"]; const h = now.getHours(); if (h == 12) str = "中午"; else str = hour[parseInt(h / 6)]; str = now.format("MM月dd ") + str; } str += now.format("HH:ss"); return str; }, //返回类型 typeOf(param) { return Object.prototype.toString.call(param).slice(8, -1) }, //判断是否为空 isEmpty(param) { //基本类型为空 let condition1 = param === '' || param === null || param === undefined || param === "NaN"; let condition2; let condition3 //引用类型为空 if (!condition1) { condition2 = this.typeOf(param) === "Object" && Object.keys(param).length < 1; condition3 = this.typeOf(param) === "Array" && param.length < 1; } return condition1 || condition2 || condition3; }, showLoading({ title = "加载中", mask = true } = {}) { uni.showLoading({ title, mask }); }, showToast({ title, icon = "none" } = {}) { uni.showToast({ title, icon, duration: 2000 }); }, hideAll() { uni.hideLoading(); uni.stopPullDownRefresh(); uni.hideNavigationBarLoading(); }, showModal({ title = "提示", content = "没有返回值,检查服务器是否正常" }) { uni.showModal({ title, content, showCancel: false }); }, setNavigationBarColor({ color = '#ffffff', bg }) { uni.setNavigationBarColor({ frontColor: color, backgroundColor: bg, animation: { duration: 400, timingFunc: 'easeIn' } }) }, getQueryString(name) { let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); let r = window.location.search.substr(1).match(reg); if (r !== null) return unescape(r[2]); return null; }, getHostname(url) { var reg = /^http(s)?:\/\/(.*?)\// // 必须是http开头或者https开头,结尾为'/' var ToReplace = 'Host/' url.replace(reg, ToReplace) url = reg.exec(url)[2]; return url; }, //获取标签上data getDataSet(e) { return e.currentTarget.dataset }, //获表单控件值 getValue(e) { return e.detail.value }, async getNavBarHeight() { var { statusBarHeight, navigationBarHeight } = await uni.getSystemInfoSync() let navBarHeight = statusBarHeight * 1 + 44 // #ifdef MP-BAIDU navBarHeight = statusBarHeight * 1 + navigationBarHeight * 1 // #endif return navBarHeight }, pick(obj, arr) { return arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {}); }, toCheckLogin(param) { let { loginType, userInfo } = $store.state.user let { phone = '' } = userInfo console.log(phone, $store.state.user.userInfo) if (loginType === 'weixin' && phone) { param.url = `/pages/login?type=1` delete param.openType let pages = getCurrentPages(); let { route } = pages[pages.length - 1] $store.commit('updateUserItem', { key: 'loginPage', val: `/${route}` }) } this.goUrl(param) }, goUrl({ url = "", openType = "navigateTo", path = "", query = "" } = {}) { let that = this; if (!url) return; if (this.typeOf(query) == 'Object') { let queryStr = Object.keys(query).map(k => `${k}=${query[k]}`).join('&'); url = `${url}&${queryStr}` } let list = ["navigateTo", "redirectTo", "switchTab", "reLaunch"]; if (list.includes(openType)) { if (openType == 'navigateTo' && getCurrentPages().length > 9) { uni.redirectTo({ url }) } else { uni[openType]({ url }) } } //返回 openType == "navigateBack" && uni.navigateBack({ delta: url }) //跳转小程序 openType == "miniProgram" && uni.navigateToMiniProgram({ appId: url, path }) //打电话 openType == "call" && uni.makePhoneCall({ phoneNumber: url }) // 复制文本 openType == 'copy' && uni.setClipboardData({ data: url, success: function(res) { uni.getClipboardData({ success: function(res) { // #ifdef MP-BAIDU that.showToast({ title: '复制成功' }) // #endif console.log('复制文本成功 ==>', res.data); } }); } }) //跳转网页/播放视频 if (openType == "web" || openType == "video") { let encode_url = encodeURIComponent(url) uni.navigateTo({ url: `/mine/pages/common/${openType}?url=${encode_url}` }) } }, // 刷新上页数据 back() { let pages = getCurrentPages(); //当前页面栈 if (pages.length > 1) { var beforePage = pages[pages.length - 2]; //获取上一个页面实例对象 //触发父页面中的方法change() beforePage.$vm.initRefresh() } }, //获取页面对象,0时为当前页面 getPage(index = 0) { let pages = getCurrentPages(); let page = pages[pages.length - 1 + index] return page.$vm }, // 预览图片 previewImage(param) { let { current, urls } = param; uni.previewImage({ current, urls, }) }, // 根据type获取数据字符串 getItems(o, type = 'id', sign = ',') { let items = []; o = o || []; o.forEach((item) => { items.push(item[type]) }) return items.join(sign); }, // 检查授权 async checkAuth({ type = "userLocation", tip = "" } = {}) { // #ifdef MP-WEIXIN let contentList = { phone: "授权获取手机号", userLocation: "你的地理位置", address: "你的通讯地址", invoiceTitle: "发票抬头", invoice: "获取发票", werun: "微信运动步数", record: "你的录音功能", writePhotosAlbum: "你的保存到相册功能", camera: "摄像头" } tip = tip || `您暂未开启${contentList[type]}的授权,是否开启?` // 声明 let err, result; [err, result] = await uni.getSetting(); //获取配置失败 if (err) { return Promise.reject(err); } //如果已授权 if (result.authSetting[`scope.${type}`]) { return true } // 调用获取权限 [err, result] = await uni.authorize({ scope: `scope.${type}` }) //获取成功 if (!err) { return true } uni.hideLoading() //提示去设置 return new Promise((resove, reject) => { uni.showModal({ content: tip, success(res) { if (res.confirm) { uni.openSetting({ success(result) { if (result.authSetting[`scope.${type}`]) { resove(true) } else { reject() } } }) } else { reject() } } }) }) // #endif // #ifdef H5 // H5环境下直接返回true,因为H5环境不需要小程序授权 // 特殊处理地理位置权限 if (type === 'userLocation') { // 检查是否已经缓存了位置信息 let cachedLocation = uni.getStorageSync('cached_location'); let cacheTime = uni.getStorageSync('location_cache_time'); let now = new Date().getTime(); // 如果有缓存且缓存时间不超过30分钟,直接返回true if (cachedLocation && cacheTime && (now - cacheTime) < 30 * 60 * 1000) { return Promise.resolve(true); } return new Promise((resolve, reject) => { // 检查浏览器是否支持地理位置API if (!navigator.geolocation) { this.showToast({ title: '您的浏览器不支持地理位置功能' }); reject(new Error('Geolocation not supported')); return; } // 尝试获取当前位置 navigator.geolocation.getCurrentPosition( () => resolve(true), (error) => { // 只在用户明确需要位置信息时才提示错误 console.log('获取位置失败:', error); // 不再强制弹出提示,让用户自行决定是否需要位置信息 reject(error); }, { timeout: 5000, // 5秒超时 maximumAge: 30 * 60 * 1000 // 30分钟的缓存 } ); }); } // 其他类型的权限在H5环境下直接返回true return Promise.resolve(true); // #endif }, //深拷贝 deepCopy(o) { let that = this; if (o instanceof Array) { var n = []; for (var i = 0; i < o.length; ++i) { n[i] = that.deepCopy(o[i]); } return n; } else if (o instanceof Function) { var n = new Function("return " + o.toString())(); return n } else if (o instanceof Object) { var n = {} for (var i in o) { n[i] = that.deepCopy(o[i]); } return n; } else { return o; } }, getOptions(options, comminOptions = {}) { return Object.assign({}, comminOptions, this.formatOptions(options)) }, //获取用户端公共参数 getCommonOptions(options) { return this.pick(options, ["staff_id"]) }, // 微信支付 async pay(pay_list) { let that = this; console.log("=====pay_list==========>>>>", pay_list) // #ifdef H5 if (typeof WeixinJSBridge != "undefined") { return new Promise((resove, reject) => { WeixinJSBridge.invoke( 'getBrandWCPayRequest', { "appId": pay_list.appId, //公众号ID,由商户传入 "timeStamp": pay_list.timeStamp, //时间戳,自1970年以来的秒数 "nonceStr": pay_list.nonceStr, //随机串 "package": pay_list.package, "signType": pay_list.signType, //微信签名方式: "paySign": pay_list.paySign //微信签名 }, function(res) { if (res.err_msg == "get_brand_wcpay_request:ok") { setTimeout(() => { resove(true) }, 1000) } else { that.showToast({ title: `支付失败` }) setTimeout(() => { reject("支付失败") }, 1000) } }) }); } // #endif let { provider = 'wxpay', orderInfo = '' } = pay_list let param = {} // #ifdef MP-WEIXIN param = that.pick(pay_list, ['nonceStr', 'package', 'signType', 'paySign', 'timeStamp']) // #endif // #ifdef APP-PLUS if (provider == 'wxpay') { orderInfo = that.pick(pay_list, ['appid', 'noncestr', 'package', 'partnerid', 'prepayid', 'timestamp']) orderInfo.sign = pay_list.paySign orderInfo = JSON.stringify(orderInfo) } param = { provider, orderInfo } // #endif // #ifndef H5 console.log("==========paramparamparamparamparam------pay", param) let [err, res] = await uni.requestPayment(param) if (err) { console.log("=======pay err", err) that.showToast({ title: `支付失败` }) await Promise.reject("支付失败") } else { return true } // #endif }, //小程序自带获取定位 getLocation() { let that = this; return new Promise((resove, reject) => { uni.getLocation({ success: function(res) { resove(res) }, fail: function(e) { console.log(e) reject(e) } }) }) }, getBmapLocation: function(ak = 'r42BavbvCM0IA1eyo7bsD0aAZadiV4Q8') { // #ifdef H5 return this.getAmapLocationH5(); // #endif // #ifndef H5 return this.getAmapLocationMp(); // #endif }, // H5环境下使用腾讯地图API获取位置 getTencentLocation: function() { let that = this; return new Promise((resolve, reject) => { // 检查是否已经缓存了位置信息 let cachedLocation = uni.getStorageSync('cached_location'); let cacheTime = uni.getStorageSync('location_cache_time'); let now = new Date().getTime(); // 如果有缓存且缓存时间不超过30分钟,直接返回缓存的位置 if (cachedLocation && cacheTime && (now - cacheTime) < 30 * 60 * 1000) { resolve(cachedLocation); return; } // 检查浏览器是否支持地理位置API if (!navigator.geolocation) { that.showToast({ title: '您的浏览器不支持地理位置功能' }); reject(new Error('Geolocation not supported')); return; } // 使用浏览器原生API获取位置 navigator.geolocation.getCurrentPosition( async (position) => { try { // 获取到经纬度后,使用腾讯地图API进行逆地理编码 const { latitude, longitude } = position.coords; let quotaExpire = uni.getStorageSync('tencent_geocoder_quota_expire'); let quotaExceeded = quotaExpire && (now < quotaExpire); if (quotaExceeded) { let locationInfo = { lat: latitude, lng: longitude, address: '', province: '', city: '', district: '' }; uni.setStorageSync('cached_location', locationInfo); uni.setStorageSync('location_cache_time', now); resolve(locationInfo); return; } const response = await that.fetchAddressFromTencent(latitude, longitude); let locationInfo = { lat: latitude, lng: longitude, address: response.address || '', province: response.province || '', city: response.city || '', district: response.district || '' }; // 缓存位置信息 uni.setStorageSync('cached_location', locationInfo); uni.setStorageSync('location_cache_time', now); resolve(locationInfo); } catch (error) { console.error('获取地址信息失败:', error); // 逆地理编码失败,但仍返回坐标信息 let locationInfo = { lat: latitude, lng: longitude, address: '', province: '', city: '', district: '' }; uni.setStorageSync('cached_location', locationInfo); uni.setStorageSync('location_cache_time', now); resolve(locationInfo); } }, (error) => { console.error('获取位置失败:', error); that.showToast({ title: '获取位置失败,请检查浏览器位置权限设置' }); reject(error); }, { enableHighAccuracy: true, timeout: 10000, maximumAge: 30 * 60 * 1000 // 30分钟的缓存 } ); }); }, getTencentLocationMp: function() { let that = this; return new Promise((resolve, reject) => { let cachedLocation = uni.getStorageSync('cached_location'); let cacheTime = uni.getStorageSync('location_cache_time'); let now = new Date().getTime(); if (cachedLocation && cacheTime && (now - cacheTime) < 30 * 60 * 1000) { resolve(cachedLocation); return; } uni.getLocation({ type: 'gcj02', isHighAccuracy: true, highAccuracyExpireTime: 10000, success: async (res) => { try { const { latitude, longitude } = res; let quotaExpire = uni.getStorageSync('tencent_geocoder_quota_expire'); let quotaExceeded = quotaExpire && (now < quotaExpire); if (quotaExceeded) { let locationInfo = { lat: latitude, lng: longitude, address: '', province: '', city: '', district: '' }; uni.setStorageSync('cached_location', locationInfo); uni.setStorageSync('location_cache_time', now); resolve(locationInfo); return; } const response = await that.fetchAddressFromTencent(latitude, longitude); let locationInfo = { lat: latitude, lng: longitude, address: response.address || '', province: response.province || '', city: response.city || '', district: response.district || '' }; uni.setStorageSync('cached_location', locationInfo); uni.setStorageSync('location_cache_time', now); resolve(locationInfo); } catch (e) { console.error('逆地理编码失败:', e); // 逆地理编码失败,但仍返回坐标信息 let locationInfo = { lat: latitude, lng: longitude, address: '', province: '', city: '', district: '' }; uni.setStorageSync('cached_location', locationInfo); uni.setStorageSync('location_cache_time', now); resolve(locationInfo); } }, fail: (e) => { console.error('获取位置失败:', e); uni.showModal({ title: '地理位置授权', content: '为了更好的为您服务,请开启位置信息权限', confirmText: '去授权', success(res) { if (res.confirm) { uni.openSetting({ success(setting) { if (setting.authSetting && setting.authSetting['scope.userLocation']) { resolve(true); } else { reject(e); } } }); } else { reject(e); } } }); } }); }); }, getAmapLocationH5: function() { let that = this; return new Promise((resolve, reject) => { let cachedLocation = uni.getStorageSync('cached_location'); let cacheTime = uni.getStorageSync('location_cache_time'); let now = new Date().getTime(); if (cachedLocation && cacheTime && (now - cacheTime) < 30 * 60 * 1000) { resolve(cachedLocation); return; } if (!navigator.geolocation) { that.showToast({ title: '您的浏览器不支持地理位置功能' }); reject(new Error('Geolocation not supported')); return; } navigator.geolocation.getCurrentPosition( async (position) => { try { const { latitude, longitude } = position.coords; let quotaExpire = uni.getStorageSync('amap_geocoder_quota_expire'); let quotaExceeded = quotaExpire && (now < quotaExpire); if (quotaExceeded) { let locationInfo = { lat: latitude, lng: longitude, address: '', province: '', city: '', district: '' }; uni.setStorageSync('cached_location', locationInfo); uni.setStorageSync('location_cache_time', now); resolve(locationInfo); return; } const response = await that.fetchAddressFromAmap(latitude, longitude); let locationInfo = { lat: latitude, lng: longitude, address: response.address || '', province: response.province || '', city: response.city || '', district: response.district || '' }; uni.setStorageSync('cached_location', locationInfo); uni.setStorageSync('location_cache_time', now); resolve(locationInfo); } catch (error) { let locationInfo = { lat: position.coords.latitude, lng: position.coords.longitude, address: '', province: '', city: '', district: '' }; uni.setStorageSync('cached_location', locationInfo); uni.setStorageSync('location_cache_time', now); resolve(locationInfo); } }, (error) => { console.error('获取位置失败:', error); that.showToast({ title: '获取位置失败,请检查浏览器位置权限设置' }); reject(error); }, { enableHighAccuracy: true, timeout: 10000, maximumAge: 30 * 60 * 1000 } ); }); }, getAmapLocationMp: function() { let that = this; return new Promise((resolve, reject) => { let cachedLocation = uni.getStorageSync('cached_location'); let cacheTime = uni.getStorageSync('location_cache_time'); let now = new Date().getTime(); if (cachedLocation && cacheTime && (now - cacheTime) < 30 * 60 * 1000) { resolve(cachedLocation); return; } uni.getLocation({ type: 'gcj02', isHighAccuracy: true, highAccuracyExpireTime: 10000, success: async (res) => { try { const { latitude, longitude } = res; let quotaExpire = uni.getStorageSync('amap_geocoder_quota_expire'); let quotaExceeded = quotaExpire && (now < quotaExpire); if (quotaExceeded) { let locationInfo = { lat: latitude, lng: longitude, address: '', province: '', city: '', district: '' }; uni.setStorageSync('cached_location', locationInfo); uni.setStorageSync('location_cache_time', now); resolve(locationInfo); return; } const response = await that.fetchAddressFromAmap(latitude, longitude); let locationInfo = { lat: latitude, lng: longitude, address: response.address || '', province: response.province || '', city: response.city || '', district: response.district || '' }; uni.setStorageSync('cached_location', locationInfo); uni.setStorageSync('location_cache_time', now); resolve(locationInfo); } catch (e) { let locationInfo = { lat: res.latitude, lng: res.longitude, address: '', province: '', city: '', district: '' }; uni.setStorageSync('cached_location', locationInfo); uni.setStorageSync('location_cache_time', now); resolve(locationInfo); } }, fail: (e) => { console.error('获取位置失败:', e); uni.showModal({ title: '地理位置授权', content: '为了更好的为您服务,请开启位置信息权限', confirmText: '去授权', success(res) { if (res.confirm) { uni.openSetting({ success(setting) { if (setting.authSetting && setting.authSetting['scope.userLocation']) { resolve(true); } else { reject(e); } } }); } else { reject(e); } } }); } }); }); }, fetchAddressFromAmap: function(lat, lng) { return new Promise((resolve, reject) => { const key = '0806ce19c290f720e7699ab73e8b9088'; uni.request({ url: 'https://restapi.amap.com/v3/geocode/regeo', data: { key, location: `${lng},${lat}`, extensions: 'base', radius: 1000 }, success: (res) => { if (res.data && res.data.status == '1' && res.data.regeocode) { const comp = res.data.regeocode.addressComponent || {}; const addr = res.data.regeocode.formatted_address || ''; resolve({ province: comp.province || '', city: comp.city || '', district: comp.district || '', address: addr }); } else { let info = res.data && res.data.info ? res.data.info : ''; let now = new Date().getTime(); if (info === 'DAILY_QUERY_OVER_LIMIT') { uni.setStorageSync('amap_geocoder_quota_expire', now + 24 * 60 * 60 * 1000); resolve({ province: '', city: '', district: '', address: '' }); return; } reject(new Error('AMap geocoder error')); } }, fail: (error) => { reject(error); } }); }); }, // 使用腾讯地图API获取详细地址信息 fetchAddressFromTencent: function(lat, lng) { return new Promise((resolve, reject) => { // 从manifest.json中获取腾讯地图API key const key = '4THBZ-TH2CW-EZ5RQ-3FICO-VPU65-AQB7E'; // 使用腾讯地图逆地理编码API uni.request({ url: `https://apis.map.qq.com/ws/geocoder/v1/`, data: { location: `${lat},${lng}`, key: key, get_poi: 1 }, success: (res) => { if (res.data.status === 0 && res.data.result) { const { address_component, formatted_address } = res.data.result; resolve({ province: address_component.province, city: address_component.city, district: address_component.district, address: formatted_address }); } else { let msg = res.data && res.data.message ? res.data.message : ''; let now = new Date().getTime(); if (res.data.status === 121 || (typeof msg === 'string' && msg.indexOf('每日调用量已达到上限') !== -1)) { uni.setStorageSync('tencent_geocoder_quota_expire', now + 24 * 60 * 60 * 1000); resolve({ province: '', city: '', district: '', address: '' }); return; } reject(new Error('腾讯地图API返回错误')); } }, fail: (error) => { reject(error); } }); }); }, }