Files
2025-12-22 17:13:05 +08:00

817 lines
20 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 = 'GoI7BxLpfvBEyf1TcMXCloi99Vov7flZ') {
// #ifdef H5
// H5环境下使用腾讯地图API
return this.getTencentLocation();
// #endif
// #ifndef H5
// 非H5环境使用百度地图API
//定位
let that = this;
let bmap = require('./bmap-wx.min.js');
let BMap = new bmap.BMapWX({
ak
});
return new Promise((resove, reject) => {
BMap.regeocoding({
success: function(data) {
let addressInfo = data.originalData.result;
let {
lat,
lng
} = addressInfo.location;
let {
formatted_address: address,
addressComponent
} = addressInfo;
let {
province,
city,
district
} = addressComponent
//只返回需要的数据
let locationInfo = {
lat,
lng,
address,
province,
city,
district,
}
// console.log(locationInfo, "====util locationInfo");
//成功回调
resove(locationInfo)
},
fail: function(res) {
//失败返回默认的数据
let locationInfo = {
name: '',
latitude: 0,
longitude: 0,
address: '',
city: ''
}
resove(locationInfo)
that.hideAll()
//失败后的提示
let errMsg = res.errMsg;
if (errMsg.includes("domain")) {
uni.showModal({
title: "获取定位失败",
content: `请在小程序公众平台添加百度域名api.map.baidu.com`,
showCancel: false
})
return;
}
if (errMsg.includes("Referer")) {
uni.showModal({
title: "获取定位失败",
content: `登录百度开放平台给ak添加白名单`,
showCancel: false
})
return;
}
// uni.showModal({
// title: "获取定位失败",
// content: "请检查手机是否开启定位功能",
// showCancel: false
// })
uni.showModal({
title: "地理位置授权",
content: "为了更好的为您服务,请开启您手机中的定位授权",
confirmText: "去授权",
success(res) {
if (res.confirm) {
// #ifdef MP-WEIXIN
uni.openSetting({
success(result) {
if (result.authSetting[
`scope.userLocation`]) {
resove(true)
} else {
reject()
}
}
})
// #endif
// #ifdef H5
// H5环境下提示用户手动在浏览器设置中开启位置权限
that.showToast({
title: '请在浏览器设置中手动开启位置权限'
});
reject(new Error('Location permission denied'));
// #endif
} else {
// #ifdef MP-WEIXIN
uni.showModal({
title: "提示",
content: "您取消了授权,是否重新设置【位置信息】权限",
confirmText: "去授权",
success(res) {
if (!res.confirm) return
uni.openSetting({
success(result) {
if (result.authSetting[
`scope.userLocation`
]) {
resove(true)
} else {
reject()
}
}
})
}
})
// #endif
// #ifdef H5
// H5环境下提示用户手动在浏览器设置中开启位置权限
that.showToast({
title: '请在浏览器设置中手动开启位置权限'
});
reject(new Error('Location permission denied'));
// #endif
}
}
})
}
})
})
// #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;
// 使用腾讯地图API获取详细地址信息
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);
that.showToast({
title: '获取地址信息失败'
});
reject(error);
}
},
(error) => {
console.error('获取位置失败:', error);
that.showToast({
title: '获取位置失败,请检查浏览器位置权限设置'
});
reject(error);
},
{
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 30 * 60 * 1000 // 30分钟的缓存
}
);
});
},
// 使用腾讯地图API获取详细地址信息
fetchAddressFromTencent: function(lat, lng) {
return new Promise((resolve, reject) => {
// 从manifest.json中获取腾讯地图API key
const key = 'TPGBZ-VDUK3-ILX35-REJQK-5NBI2-UBF75';
// 使用腾讯地图逆地理编码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 {
reject(new Error('腾讯地图API返回错误'));
}
},
fail: (error) => {
reject(error);
}
});
});
},
}