Files
lucky_shop/common/js/util.js

1265 lines
33 KiB
JavaScript
Raw 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 Config from './config.js'
import store from '@/store/index.js'
import Http from './http.js'
import {
Weixin
} from 'common/js/wx-jssdk.js';
// 关于页面路径,使用常量导出
export const INDEX_PAGE_URL = '/pages/index/index';
export const CATEGORY_PAGE_URL = '/pages_goods/category';
export const CONTACT_PAGE_URL = '/pages_tool/contact/contact';
export const MEMBER_PAGE_URL = '/pages_tool/member/index';
export const LOGIN_PAGE_URL = '/pages_tool/login/login';
export const AI_CHAT_PAGE_URL = '/pages_tool/ai-chat/index';
// 当前最新的tabBar.list (参见pages.json 中的tabBar.list 配置)
export const systemTabBarList = [
INDEX_PAGE_URL,
CATEGORY_PAGE_URL,
CONTACT_PAGE_URL,
MEMBER_PAGE_URL
];
/**
* 适配子包路径
* @param {string} url
* @returns
*/
export const adaptSubpackageUrl = (url) => {
/**
* 特别注意:
* 由于老版本或者后台系统服务未同步更新可以作为tabBarList的最新分包路径。历史遗留问题需要与当前最新分包机制版本保持一致。
* 系统当前的支持tarbarList包含动态tabBar,注意这是实际分包后的路径
* 根据匹配映射关系修改url为实际分包后的路径
*/
// 定义前缀映射表
const urlPrefixMap = {
'/pages/promotion/': '/pages_promotion/',
'/pages/order/': '/pages_order/',
'/pages/goods/': '/pages_goods/',
'/pages/contact/': '/pages_tool/contact/',
'/pages/member/': '/pages_tool/member/',
'/pages/login/': '/pages_tool/login/',
'/pages/agreement/': '/pages_tool/agreement/',
'/pages/article/': '/pages_tool/article/',
'/pages/cases/': '/pages_tool/cases/',
'/pages/contact/': '/pages_tool/contact/',
'/pages/files/': '/pages_tool/files/',
'/pages/form/': '/pages_tool/form/',
'/pages/help/': '/pages_tool/help/',
'/pages/notice/': '/pages_tool/notice/',
'/pages/pay/': '/pages_tool/pay/',
'/pages/recharge/': '/pages_tool/recharge/',
'/pages/seal/': '/pages_tool/seal/',
'/pages/storeclose/': '/pages_tool/storeclose/',
'/pages/vr/': '/pages_tool/vr/',
'/pages/weapp/': '/pages_tool/weapp/',
'/pages/webview/': '/pages_tool/webview/',
};
// 构建正则表达式
const regex = new RegExp(
Object.keys(urlPrefixMap).map(key =>
key.replace(/\//g, '\\/').replace(/\*/g, '.*')
).join('|'),
'g'
);
// 替换函数
function replacePrefix(str) {
return str.replace(regex, match => {
for (const [oldPrefix, newPrefix] of Object.entries(urlPrefixMap)) {
if (match.startsWith(oldPrefix)) {
return match.replace(oldPrefix, newPrefix);
}
}
return match; // 默认返回原匹配
});
}
return replacePrefix(url);
}
/**
* 检查tabBar是否激活
* @param {string} linkUrl 链接路径 /pages/goods/category
* @param {string} currentPageRoute 当前页面路径 /pages_goods/category
* @returns {boolean} 是否激活
*/
export const checkTabBarActive = (linkUrl, currentPageRoute) => {
const linkUrlParts = adaptSubpackageUrl(linkUrl).split('/');
const currentPageRouteParts = currentPageRoute.split('/');
// console.log('diy-bottom-nav verify:', { linkUrlParts, currentPageRouteParts});
try {
// 二级页面
if (linkUrlParts[2] === currentPageRouteParts[2]) {
return true;
}
// 一级页面限定只能是goods相关
if (linkUrlParts[1] === currentPageRouteParts[1] && linkUrlParts[1] === 'pages_goods') {
return true;
}
} catch (error) {
console.error('diy-bottom-nav verify error:', error);
}
return false;
}
export default {
/** 导出页面URL常量 */
MEMBER_PAGE_URL,
CATEGORY_PAGE_URL,
CONTACT_PAGE_URL,
INDEX_PAGE_URL,
LOGIN_PAGE_URL,
AI_CHAT_PAGE_URL,
/**
* 页面跳转
* @param {string} to 跳转链接 /pages/idnex/index
* @param {Object} param 参数 {key : value, ...}, 默认{}
* @param {string} mode 模式 navigateTo、redirectTo、reLaunch、tabbar, 默认navigateTo
*/
redirectTo(to, param = {}, mode = 'navigateTo') {
let url = to;
// 替换url中的前缀
console.log('页面跳转 redirectTo', to, param, mode);
url = adaptSubpackageUrl(url);
console.log('adaptSubpackageUrl', url);
if (param != undefined) {
Object.keys(param).forEach(function (key) {
if (url.indexOf('?') != -1) {
url += "&" + key + "=" + param[key];
} else {
url += "?" + key + "=" + param[key];
}
});
}
// 针对tabBar.list中的路径直接切换tabBar
for (let i = 0; i < systemTabBarList.length; i++) {
const tabBarUrl = systemTabBarList[i];
if (url.indexOf(tabBarUrl) == 0) {
// 首页特殊处理采用switchTab, 其他页面采用redirectTo, 不能返回,不能退回
(tabBarUrl == INDEX_PAGE_URL ? uni.switchTab : uni.redirectTo)({ url });
return;
}
}
// 如果url不包含tabBarList中的路径根据mode判断跳转方式
switch (mode) {
case 'tabbar':
// 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。重置页面栈,仅保留 tabBar 页面
uni.switchTab({
url
});
break;
case 'redirectTo':
// 关闭当前页面跳转到应用内的某个页面。替换栈顶页面长度不变上限10层
uni.redirectTo({
url
});
break;
case 'reLaunch':
// 关闭所有页面,打开到应用内的某个页面。清空栈后打开新页面,长度=1
uni.reLaunch({
url
});
break;
default:
// 保留当前页面,跳转到应用内的某个页面,新增页面到栈顶,长度+1上限10层
console.log('保留当前页面navigateTo跳转到应用内的某个页面', url);
uni.navigateTo({
url
});
}
},
/**
* 图片路径转换
* @param {String} img_path 图片地址
* @param {Object} params 参数针对商品、相册里面的图片区分大中小size: big、mid、small
*/
img(img_path, params) {
var path = "";
if (img_path != undefined && img_path != "") {
if (img_path.split(',').length > 1) {
img_path = img_path.split(',')[0];
}
if (params && img_path != this.getDefaultImage().goods) {
// 过滤默认图
let arr = img_path.split(".");
let suffix = arr[arr.length - 1];
arr.pop();
arr[arr.length - 1] = arr[arr.length - 1] + "_" + params.size.toUpperCase();
arr.push(suffix);
// if(img_path.indexOf('attachment') == -1){
// img_path = arr.join(".");
// }
}
if (img_path.indexOf("http://") == -1 && img_path.indexOf("https://") == -1) {
path = Config.imgDomain + "/" + img_path;
} else {
// console.log(img_path)
path = img_path;
}
}
// path += '?t=' + parseInt(new Date().getTime() / 1000);
return path;
},
/**
* 时间戳转日期格式
* @param {Object} timeStamp
*/
timeStampTurnTime(timeStamp, type = "") {
if (timeStamp != undefined && timeStamp != "" && timeStamp > 0) {
var date = new Date();
date.setTime(timeStamp * 1000);
var y = date.getFullYear();
var m = date.getMonth() + 1;
m = m < 10 ? ('0' + m) : m;
var d = date.getDate();
d = d < 10 ? ('0' + d) : d;
var h = date.getHours();
h = h < 10 ? ('0' + h) : h;
var minute = date.getMinutes();
var second = date.getSeconds();
minute = minute < 10 ? ('0' + minute) : minute;
second = second < 10 ? ('0' + second) : second;
if (type) {
if (type == 'yearMonthDay') {
return y + '年' + m + '月' + d + '日';
}
return y + '-' + m + '-' + d;
} else {
return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second;
}
} else {
return "";
}
},
/**
* 日期格式转时间戳
* @param {Object} string
*/
timeTurnTimeStamp(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;
},
/**
* 倒计时
* @param {Object} seconds 秒
*/
countDown(seconds) {
let [day, hour, minute, second] = [0, 0, 0, 0]
if (seconds > 0) {
day = Math.floor(seconds / (60 * 60 * 24))
hour = Math.floor(seconds / (60 * 60)) - (day * 24)
minute = Math.floor(seconds / 60) - (day * 24 * 60) - (hour * 60)
second = Math.floor(seconds) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60)
}
if (day < 10) {
day = '0' + day
}
if (hour < 10) {
hour = '0' + hour
}
if (minute < 10) {
minute = '0' + minute
}
if (second < 10) {
second = '0' + second
}
return {
d: day,
h: hour,
i: minute,
s: second
};
},
/**
* 数值去重
* @param {Array} arr 数组
* @param {string} field 字段
*/
unique(arr, field) {
const res = new Map();
return arr.filter((a) => !res.has(a[field]) && res.set(a[field], 1));
},
/**
* 判断值是否在数组中
* @param {Object} elem
* @param {Object} arr
*/
inArray: function (elem, arr) {
return arr == null ? -1 : arr.indexOf(elem);
},
/**
* 获取某天日期
* @param {Object} day
*/
getDay: function (day) {
var today = new Date();
var targetday_milliseconds = today.getTime() + 1000 * 60 * 60 * 24 * day;
today.setTime(targetday_milliseconds);
const doHandleMonth = function (month) {
var m = month;
if (month.toString().length == 1) {
m = "0" + month;
}
return m
}
var tYear = today.getFullYear();
var tMonth = today.getMonth();
var tDate = today.getDate();
var tWeek = today.getDay();
var time = parseInt(today.getTime() / 1000);
tMonth = doHandleMonth(tMonth + 1);
tDate = doHandleMonth(tDate);
const week = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
return {
't': time,
'y': tYear,
'm': tMonth,
'd': tDate,
'w': week[tWeek]
};
},
/**
* 图片选择加上传
* @param num
* @param params
* @param callback
* @param url
*/
upload: function (num, params, callback, url) {
// #ifdef H5
var app_type = this.isWeiXin() ? 'wechat' : 'h5';
var app_type_name = this.isWeiXin() ? '微信公众号' : 'H5';
// #endif
// #ifdef MP-WEIXIN
var app_type = 'weapp';
var app_type_name = '微信小程序';
// #endif
// #ifdef MP-ALIPAY
var app_type = 'aliapp';
var app_type_name = '支付宝小程序';
// #endif
// #ifdef MP-BAIDU
var app_type = 'baiduapp';
var app_type_name = '百度小程序';
// #endif
// #ifdef MP-TOUTIAO
var app_type = 'MP-TOUTIAO';
var app_type_name = '头条小程序';
// #endif
// #ifdef MP-QQ
var app_type = 'MP-QQ';
var app_type_name = 'QQ小程序';
// #endif
var data = {
token: store.state.token,
app_type: app_type,
app_type_name: app_type_name
}
data = Object.assign(data, params);
var imgs_num = num;
var _self = this;
uni.chooseImage({
count: imgs_num,
sizeType: ['compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], //从相册或者拍照
success: async function (res) {
const tempFilePaths = res.tempFilePaths;
var _data = data;
var imgs = [];
uni.showLoading({
title: '图片上传中'
})
for (var i = 0; i < tempFilePaths.length; i++) {
var path = await _self.upload_file_server(tempFilePaths[i], _data, params.path,
url);
imgs.push(path);
if (imgs.length == tempFilePaths.length) {
uni.hideLoading()
uni.showToast({
title: '上传成功',
icon: 'none'
})
typeof callback == 'function' && callback(imgs);
}
}
},
fail: err => {
uni.hideLoading()
uni.showToast({
title: '上传失败',
icon: 'none'
})
}
});
},
//上传
upload_file_server(tempFilePath, data, path, url = "", callback) {
if (url) {
var uploadUrl = Config.baseUrl + url
} else {
var uploadUrl = Config.baseUrl + '/api/upload/' + path
}
return new Promise((resolve, reject) => {
uni.uploadFile({
url: uploadUrl,
filePath: tempFilePath,
name: 'file',
fileType: data.fileType || 'image',
formData: data,
success: function (res) {
var path_str = JSON.parse(res.data);
if (path_str.code >= 0) {
resolve(path_str.data.pic_path);
typeof callback == 'function' && callback(path_str.data.pic_path);
} else {
reject("error");
}
}
});
});
},
/**
* 复制
* @param {Object} value
* @param {Object} callback
*/
copy(value, callback) {
// #ifdef H5
var oInput = document.createElement('input'); //创建一个隐藏input重要
oInput.value = value; //赋值
oInput.setAttribute("readonly", "readonly");
document.body.appendChild(oInput);
oInput.select(); // 选择对象
document.execCommand("Copy"); // 执行浏览器复制命令
oInput.className = 'oInput';
oInput.style.display = 'none';
uni.hideKeyboard();
this.showToast({
title: '复制成功'
});
typeof callback == 'function' && callback();
// #endif
// #ifdef MP || APP-PLUS
uni.setClipboardData({
data: value,
success: () => {
typeof callback == 'function' && callback();
}
});
// #endif
},
/**
* 是否是微信浏览器
*/
isWeiXin() {
// #ifndef H5
return false;
// #endif
var ua = navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == "micromessenger") {
return true;
} else {
return false;
}
},
/**
* 判断是否在微信小程序的web-view中打开H5
* @returns {boolean} 是否在微信小程序的web-view中
*/
isWeChatMiniProgram() {
const userAgent = navigator.userAgent.toLowerCase();
// 微信小程序的web-view User-Agent会包含以下特征之一
const miniProgramIndicators = [
'miniprogram', // 普通微信小程序
'wxwork', // 企业微信小程序
'micromessenger/[0-9]+\.[0-9]+\.[0-9]+ nettype/wifi wxwebviewtype/1'
];
return miniProgramIndicators.some(indicator => {
if (typeof indicator === 'string' && indicator.includes('/')) {
// 正则表达式匹配
const regex = new RegExp(indicator, 'i');
return regex.test(userAgent);
}
return userAgent.includes(indicator);
});
},
/**
* 判断是否在微信浏览器中打开H5非小程序的web-view
* @returns {boolean} 是否在微信浏览器中打开的H5
*/
isWeChatBrowser() {
return isWeiXin() && !isWeChatMiniProgram();
},
/**
* 显示消息提示框
* @param {Object} params 参数
*/
showToast(params = {}) {
params.title = params.title || "";
params.icon = params.icon || "none";
// params.position = params.position || 'bottom';
params.duration = params.duration || 1500;
uni.showToast(params);
if (params.success) params.success();
},
/**
* 检测苹果X以上的手机
*/
isIPhoneX() {
let res = this.getDeviceInfo();
if (res.model.search('iPhone X') != -1) {
return true;
}
return false;
},
//判断安卓还是iOS
isAndroid() {
let platform = this.getDeviceInfo().platform;
if (platform == 'ios') {
return false;
} else if (platform == 'android') {
return true;
}
},
/**
* 获取设备信息(包含降级处理)
*/
getDeviceInfo() {
try {
return uni.getDeviceInfo();
} catch (e) {
return uni.getSystemInfoSync();
}
},
/**
* 获取窗口信息(包含降级处理)
*/
getWindowInfo() {
try {
return uni.getWindowInfo();
} catch (e) {
return uni.getSystemInfoSync();
}
},
/**
* 深度拷贝对象
* @param {Object} obj
*/
deepClone(obj) {
const isObject = function (obj) {
return typeof obj == 'object';
}
if (!isObject(obj)) {
throw new Error('obj 不是一个对象!')
}
//判断传进来的是对象还是数组
let isArray = Array.isArray(obj)
let cloneObj = isArray ? [] : {}
//通过for...in来拷贝
for (let key in obj) {
cloneObj[key] = isObject(obj[key]) ? this.deepClone(obj[key]) : obj[key]
}
return cloneObj
},
/**
* 打开微信企业客服
* @param {Function} fallbackFunc 降级处理函数
*/
openWxWorkServiceChat(fallbackFunc) {
// #ifdef MP-WEIXIN
let wxworkConfig = store.state?.wxworkConfig
if (wxworkConfig?.enable && wxworkConfig?.contact_url) {
// 直接使用活码链接跳转
wx.navigateToMiniProgram({
appId: 'wxeb490c6f9b154ef9', // 是企业微信官方小程序的AppID固定值, 由腾讯企业微信团队维护, 不需要修改,用于展示"添加企业微信联系人"的官方页面)
path: `pages/contacts/externalContactDetail?url=${encodeURIComponent(wxworkConfig?.contact_url)}`,
success: () => {
console.log('跳转企业微信成功');
},
fail: (err) => {
console.error('跳转企业微信失败:', err);
// 降级处理:使用原有客服方式
fallbackFunc && fallbackFunc();
}
});
} else {
fallbackFunc && fallbackFunc();
}
// #endif
},
/**
* 自定义模板的跳转链接
* @param {Object} link
*/
diyRedirectTo(link) {
//if (link == null || Object.keys(link).length == 1) return;
// 外部链接
if (link.wap_url && link.wap_url.indexOf('http') != -1) {
// #ifdef H5
window.location.href = link.wap_url;
// #endif
// #ifdef MP
this.redirectTo('/pages_tool/webview/webview', {
src: encodeURIComponent(link.wap_url)
});
// #endif
} else if (link.appid) {
// 跳转其他小程序
uni.navigateToMiniProgram({
appId: link.appid,
path: link.page
})
} else if (link.name == 'MOBILE' && !link.wap_url) {
// 拨打电话
uni.makePhoneCall({
phoneNumber: link.mobile,
success: (res) => {
},
fail: (res) => {
}
});
} else if (link.name == 'MEMBER_CONTACT') {
// 客服
let servicerConfig = store.state.servicerConfig
let config = {
type: 'none'
};
// #ifdef H5
config = servicerConfig.h5;
// #endif
// #ifdef MP-WEIXIN
config = servicerConfig.weapp;
// #endif
switch (config.type) {
case 'wxwork':
// 企业微信客服
// #ifdef H5
window.location.href = config.wxwork_url;
// #endif
// #ifdef MP-WEIXIN
this.openWxWorkServiceChat(() => {
wx.openCustomerServiceChat({
extInfo: {
url: config.wxwork_url
},
corpId: config.corpid,
showMessageCard: true,
sendMessageTitle: 'this.sendMessageTitle',
sendMessagePath: 'this.sendMessagePath',
sendMessageImg: 'this.sendMessageImg'
});
});
// #endif
break;
case 'third':
// 第三方客服
window.location.href = config.third_url;
break;
case 'niushop':
// Niushop客服
this.redirectTo('/pages_tool/chat/room');
break;
case 'weapp':
// 微信小程序,由于需要手动点击按钮触发,所以要跳转到中间页
this.redirectTo(link.wap_url);
break;
default:
// 拨打客服电话
let siteInfo = store.state.siteInfo;
if (siteInfo && siteInfo.site_tel) {
uni.makePhoneCall({
phoneNumber: siteInfo.site_tel
});
} else {
this.showToast({
title: '抱歉,商家暂无客服,请线下联系',
})
}
}
} else if (link.wap_url) {
this.redirectTo(link.wap_url);
}
},
/**
* 获取默认图
*/
getDefaultImage() {
let defaultImg = store.state.defaultImg;
defaultImg.goods = this.img(defaultImg.goods);
defaultImg.head = this.img(defaultImg.head);
defaultImg.store = this.img(defaultImg.store);
defaultImg.article = this.img(defaultImg.article);
defaultImg.kefu = this.img(defaultImg.kefu);
defaultImg.phone = this.img(defaultImg.phone);
return defaultImg;
},
/**
* 判断手机是否为iphoneX系列
*/
uniappIsIPhoneX() {
let isIphoneX = false;
let systemInfo = this.getDeviceInfo();
// #ifdef MP
if (systemInfo.model.search('iPhone X') != -1 || systemInfo.model.search('iPhone 11') != -1 || systemInfo.model.search('iPhone 12') != -1 || systemInfo.model.search('iPhone 13') != -1) {
isIphoneX = true;
}
// #endif
// #ifdef H5
var u = navigator.userAgent;
var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
if (isIOS) {
if (systemInfo.screenWidth == 375 && systemInfo.screenHeight == 812 && systemInfo.pixelRatio == 3) {
isIphoneX = true;
} else if (systemInfo.screenWidth == 414 && systemInfo.screenHeight == 896 && systemInfo.pixelRatio == 3) {
isIphoneX = true;
} else if (systemInfo.screenWidth == 414 && systemInfo.screenHeight == 896 && systemInfo.pixelRatio == 2) {
isIphoneX = true;
}
}
// #endif
return isIphoneX;
},
/**
* 判断手机是否为iphone11系列
*/
uniappIsIPhone11() {
let isIphone11 = false;
let systemInfo = this.getDeviceInfo();
// #ifdef MP
if (systemInfo.model.search('iPhone 11') != -1) {
isIphone11 = true;
}
// #endif
return isIphone11;
},
// #ifdef H5
//判断该浏览器是否为safaria浏览器
isSafari() {
let res = this.getDeviceInfo();
var ua = navigator.userAgent.toLowerCase();
if (ua.indexOf('applewebkit') > -1 && ua.indexOf('mobile') > -1 && ua.indexOf('safari') > -1 &&
ua.indexOf('linux') === -1 && ua.indexOf('android') === -1 && ua.indexOf('chrome') === -1 &&
ua.indexOf('ios') === -1 && ua.indexOf('browser') === -1) {
return true;
} else {
return false;
}
},
// #endif
numberFixed(e, f) {
if (!f) {
f = 0;
}
return Number(e).toFixed(f);
},
/**
* 获取url参数
*/
getUrlCode(callback) {
var url = location.search;
var theRequest = new Object();
if (url.indexOf('?') != -1) {
var str = url.substr(1);
var strs = str.split('&');
for (var i = 0; i < strs.length; i++) {
theRequest[strs[i].split('=')[0]] = strs[i].split('=')[1];
}
}
typeof callback == 'function' && callback(theRequest);
},
/**
* 获取当前页面路由
*/
getCurrRoute() {
let routes = getCurrentPages(); // 获取当前打开过的页面路由数组
return routes.length ? routes[routes.length - 1].route : '';
},
goBack(backUrl = INDEX_PAGE_URL) {
if (getCurrentPages().length == 1) {
this.redirectTo(backUrl);
} else {
uni.navigateBack();
}
},
/**
*
* @param val 转化时间字符串 (转化时分秒)
* @returns {string}
*/
getTimeStr(val) {
var h = parseInt(val / 3600).toString();
var m = parseInt((val % 3600) / 60).toString();
if (m.length == 1) {
m = '0' + m;
}
if (h.length == 1) {
h = '0' + h;
}
return h + ':' + m;
},
/**
* 获取定位信息
*/
getLocation(param = {}) {
/*uni.getLocation({
type: param.type ?? 'gcj02',
success: res => {
store.commit('setLocation', res);
typeof param.success == 'function' && param.success(res);
},
fail: res => {
typeof param.fail == 'function' && param.fail(res);
},
complete: res => {
typeof param.complete == 'function' && param.complete(res);
}
});*/
},
// 计算两个经纬度之间的距离
getDistance(lat1, lng1, lat2, lng2) {
var radLat1 = lat1 * Math.PI / 180.0;
var radLat2 = lat2 * Math.PI / 180.0;
var a = radLat1 - radLat2;
var b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0;
var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
s = s * 6378.137; // EARTH_RADIUS;
s = Math.round(s * 10000) / 10000;
return s;
},
//记录分享人
onSourceMember(source_member) {
Http.sendRequest({
url: '/api/Member/alterShareRelation',
data: {
share_member: source_member,
},
success: res => {
if (res.code >= 0) {
uni.removeStorage({
key: 'source_member',
success: res => {
console.log('删除成功', res)
}
})
}
}
})
},
/**
* 微信订阅消息
*/
subscribeMessage(keywords) {
let url = ""
// #ifdef MP-WEIXIN
url = '/weapp/api/weapp/messagetmplids';
// #endif
// #ifdef MP-ALIPAY
url = '/aliapp/api/aliapp/messagetmplids';
// #endif
Http.sendRequest({
url,
data: {
keywords: keywords
},
success: res => {
if (res.data.length) {
// #ifdef MP-WEIXIN
uni.requestSubscribeMessage({
tmplIds: res.data,
success: (res) => {
console.log("res", res)
},
fail: (res) => {
console.log('fail', res)
}
})
// #endif
// #ifdef MP-ALIPAY
my.requestSubscribeMessage({
entityIds: res.data,
success: res => {
console.log("res", res)
},
fail: res => {
console.log('fail', res)
}
});
// #endif
}
}
})
},
/**
* 获取小程序分享内容数据
*/
getMpShare(path) {
//如果没有特别指定 则获取当前页面的路由
if (!path) {
let route = this.getCurrentRoute();
path = route.path;
if (path == '/pages_tool/member/index') {
return new Promise((resolve, reject) => {
resolve({})
});
}
}
return new Promise((resolve, reject) => {
Http.sendRequest({
url: "/weapp/api/weapp/share",
data: {
path: path
},
success: res => {
if (res.code >= 0) {
let shareConfig = res.data.data;
if (shareConfig) {
//分享给好友
let appMessageData = {
title: shareConfig.title,
path: shareConfig.path,
imageUrl: shareConfig.imageUrl,
success: res => {
},
fail: res => {
}
}
//分享到朋友圈
let query = '';
if (shareConfig.path.indexOf('?') > 0) {
query = shareConfig.path.split('?')[1];
}
let timeLineData = {
title: shareConfig.title,
query: shareConfig.path,
imageUrl: shareConfig.imageUrl,
}
resolve({
appMessage: appMessageData,
timeLine: timeLineData,
})
} else {
reject(res.data);
}
} else {
reject(res.data)
}
}
});
})
},
/**
* 设置公众号分享
* @param shareData
* @param callback
*/
setPublicShare(shareData, callback) {
if (!this.isWeiXin()) return;
Http.sendRequest({
url: '/wechat/api/wechat/jssdkconfig',
data: {
url: uni.getSystemInfoSync().platform == 'ios' ? uni.getStorageSync('initUrl') : window.location
.href
},
success: res => {
if (res.code == 0) {
var wxJS = new Weixin();
wxJS.init(res.data);
wxJS.weixin.showOptionMenu();
wxJS.setShareData({
title: shareData.title ?? '',
desc: shareData.desc ?? '',
link: shareData.link ?? location.href,
imgUrl: shareData.imgUrl ? this.img(shareData.imgUrl) : ''
}, (res) => {
typeof callback == 'function' && callback(res);
})
}
}
})
},
//获取当前路由
getCurrentRoute() {
let currentRoutes = getCurrentPages(); // 获取当前打开过的页面路由数组
let currentRoute = currentRoutes[currentRoutes.length - 1].route //获取当前页面路由
let currentParam = currentRoutes[currentRoutes.length - 1].options; //获取路由参数
// 拼接参数
let param = [];
for (let key in currentParam) {
param.push(key + '=' + currentParam[key])
}
let currentPath = '/' + currentRoute;
let currentQuery = param.join('&');
if (currentQuery) currentPath += '?' + currentQuery;
return {
path: currentPath,
query: currentQuery,
}
},
//获取分享路由
getCurrentShareRoute(member_id) {
let route = this.getCurrentRoute();
//去掉原来的分享人数据
route.path = route.path.replace(/[?|&]source_member=\d+/, '');
if (member_id) {
//路径的处理
if (route.path.indexOf('?') > 0) {
route.path += '&';
} else {
route.path += '?';
}
route.path += 'source_member=' + member_id;
//参数的处理
if (route.query) {
route.query += '&';
}
route.query += 'source_member=' + member_id;
}
return route;
},
/**
* 对象转style字符串
* @param {Object} obj
*/
objToStyle(obj) {
let s = [];
for (let i in obj) {
s.push(i + ':' + obj[i]);
}
return s.join(';')
},
/**
* 颜色减值
* @param {Object} c1
* @param {Object} c2
* @param {Object} ratio
*/
colourBlend(c1, c2, ratio) {
ratio = Math.max(Math.min(Number(ratio), 1), 0)
let r1 = parseInt(c1.substring(1, 3), 16)
let g1 = parseInt(c1.substring(3, 5), 16)
let b1 = parseInt(c1.substring(5, 7), 16)
let r2 = parseInt(c2.substring(1, 3), 16)
let g2 = parseInt(c2.substring(3, 5), 16)
let b2 = parseInt(c2.substring(5, 7), 16)
let r = Math.round(r1 * (1 - ratio) + r2 * ratio)
let g = Math.round(g1 * (1 - ratio) + g2 * ratio)
let b = Math.round(b1 * (1 - ratio) + b2 * ratio)
r = ('0' + (r || 0).toString(16)).slice(-2)
g = ('0' + (g || 0).toString(16)).slice(-2)
b = ('0' + (b || 0).toString(16)).slice(-2)
return '#' + r + g + b
},
/**
* 生成贝塞尔曲线轨迹
* @param {Object} points
* @param {Object} times
*/
bezier(points, times) {
var bezier_points = [];
var points_D = [];
var points_E = [];
const DIST_AB = Math.sqrt(Math.pow(points[1]['x'] - points[0]['x'], 2) + Math.pow(points[1]['y'] - points[0][
'y'
], 2));
// 邻控制BC点间距
const DIST_BC = Math.sqrt(Math.pow(points[2]['x'] - points[1]['x'], 2) + Math.pow(points[2]['y'] - points[1][
'y'
], 2));
// D每次在AB方向上移动的距离
if (points[0]['x'] > points[2]['x']) {
var EACH_MOVE_AD = -(DIST_AB / times);
// E每次在BC方向上移动的距离
var EACH_MOVE_BE = -(DIST_BC / times);
} else {
var EACH_MOVE_AD = +(DIST_AB / times);
// E每次在BC方向上移动的距离
var EACH_MOVE_BE = +(DIST_BC / times);
}
// 点AB的正切
const TAN_AB = (points[1]['y'] - points[0]['y']) / (points[1]['x'] - points[0]['x']);
// 点BC的正切
const TAN_BC = (points[2]['y'] - points[1]['y']) / (points[2]['x'] - points[1]['x']);
// 点AB的弧度值
const RADIUS_AB = Math.atan(TAN_AB);
// 点BC的弧度值
const RADIUS_BC = Math.atan(TAN_BC);
// 每次执行
for (var i = 1; i <= times; i++) {
// AD的距离
var dist_AD = EACH_MOVE_AD * i;
// BE的距离
var dist_BE = EACH_MOVE_BE * i;
// D点的坐标
var point_D = {};
point_D['x'] = dist_AD * Math.cos(RADIUS_AB) + points[0]['x'];
point_D['y'] = dist_AD * Math.sin(RADIUS_AB) + points[0]['y'];
points_D.push(point_D);
// E点的坐标
var point_E = {};
point_E['x'] = dist_BE * Math.cos(RADIUS_BC) + points[1]['x'];
point_E['y'] = dist_BE * Math.sin(RADIUS_BC) + points[1]['y'];
points_E.push(point_E);
// 此时线段DE的正切值
var tan_DE = (point_E['y'] - point_D['y']) / (point_E['x'] - point_D['x']);
// tan_DE的弧度值
var radius_DE = Math.atan(tan_DE);
// 地市DE的间距
var dist_DE = Math.sqrt(Math.pow((point_E['x'] - point_D['x']), 2) + Math.pow((point_E['y'] - point_D['y']),
2));
// 此时DF的距离
var dist_DF = (dist_AD / DIST_AB) * dist_DE;
// 此时DF点的坐标
var point_F = {};
point_F['x'] = dist_DF * Math.cos(radius_DE) + point_D['x'];
point_F['y'] = dist_DF * Math.sin(radius_DE) + point_D['y'];
bezier_points.push(point_F);
}
return {
'bezier_points': bezier_points
};
},
/**
* 验证手机号
* @param {string} mobile 被验证的mobile
* @return {object} 验证后的结果
**/
verifyMobile(mobile) {
var parse = /^\d{11}$/.test(mobile);
return parse;
},
/**
* 判断是否为快应用环境
* @returns {boolean} 是否为快应用
*/
isQuickApp() {
// #ifndef QUICKAPP-WEBVIEW
let _isQuickApp = false;
try {
const ua = navigator?.userAgent?.toLowerCase();
// console.log('ua = ', ua);
_isQuickApp = ua.indexOf('quickapp') !== -1;
if (!_isQuickApp) {
// 特殊说明由于网站是嵌入到快应用的Webview组件中<web>UA中不会包含quickapp字符串
// 但是会包含uniacid参数所以这里通过uniacid参数来判断是否为快应用环境
_isQuickApp = ua.indexOf('uniacid=') !== -1;
}
} catch (e) { }
if (!_isQuickApp) {
const systemInfo = this.getDeviceInfo();
_isQuickApp = systemInfo?.platform === 'quickapp' || process?.env?.UNI_PLATFORM === 'quickapp';
}
return _isQuickApp;
// #endif
return true;
},
/**
* 判断是否为华为快应用环境
* @returns {boolean} 是否为华为快应用
*/
isHuaweiQuickApp() {
if (!this.isQuickApp()) return false;
// #ifndef QUICKAPP-WEBVIEW-HUAWEI
const systemInfo = this.getDeviceInfo();
return systemInfo.brand === 'HUAWEI' || systemInfo.manufacturer === 'HUAWEI' ||
(typeof qh !== 'undefined' && qh.platform === 'huawei');
// #endif
return true;
},
/**
* 蛇形命名转驼峰命名
* @param {string} str 蛇形命名字符串
* @returns {string} 驼峰命名字符串
*/
snakeToCamel(str) {
return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
},
/**
* 蛇形命名转驼峰命名(递归处理对象中的所有属性名)
* @param {Object} obj 包含蛇形命名字符串属性的对象
* @returns {Object} 驼峰命名字符串属性的对象
*/
snakeToCamelForObj(obj) {
if (typeof obj !== 'object' || obj === null) return obj;
if (Array.isArray(obj)) return obj.map(this.snakeToCamelForObj.bind(this));
const newObj = {};
for (const key in obj) {
if (Object.hasOwnProperty.call(obj, key)) {
const newKey = this.snakeToCamel(key);
newObj[newKey] = this.snakeToCamelForObj(obj[key]);
}
}
return newObj;
}
}