jiuyiUniapp/jiuyi2/common/js/util.js

1820 lines
42 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.

// vuex
import store from '@/store'
// 配置
import config from '@/common/js/config.js'
// 接口
import api from '@/api/index.js'
const msgType = {}
// 工具库
const util = {
// 配置参数
config,
// 正则
reg: {
// 手机号
tel: /^1[3-9]\d{9}$/,
// 身份证
idCard: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/,
},
/**
* 弹窗
* @param {Object|String} obj String类型只是弹出文字 object如下
* @param {String} obj.title 弹窗的标题
* @param {String} obj.content 弹窗的内容
* @param {String} obj.confirmText 确定的文本
* @param {String} obj.showCancel 是否显示取消
* @param {String} obj.cancelText 取消的文本
* @param {Function} params.success 请求成功回调 可通过promise.then捕获
* @param {Function} params.fail 请求失败回调 可通过promise.catch捕获
* @param {Function} params.complete 请求结束回调 无论是否成功失败都会执行
* @return {Object} string返回null object返回返回promis对象 执行成功返回resolve 执行失败返回reject
*/
alert(obj) {
// 没值
if (obj == null || obj == undefined) return
// 这个地方说白了就是 如果只是想提示一句话一个文本的话 就只是弹个小tips
if (typeof obj == "string" || typeof obj == "number") {
uni.showToast({
'title': "" + obj + "",
'icon': 'none',
duration: 3000,
});
return null
}
// 标题
obj.title = obj.title ? obj.title : ""
// 提示内容
obj.content = obj.content ? obj.content : ""
// 确定文本
obj.confirmText = obj.confirmText ? obj.confirmText : "确定"
// 取消按钮
obj.showCancel = obj.showCancel === false ? false : true
// 取消文本
obj.cancelText = obj.cancelText ? obj.cancelText : "取消"
// 返回 Promise 对象
return new Promise((resolve, reject) => {
// 调起
uni.showModal({
title: obj.title,
content: obj.content,
confirmText: obj.confirmText,
showCancel: obj.showCancel,
cancelText: obj.cancelText,
success: res => {
obj.success ? obj.success(res) : () => {}
resolve(res)
},
fail: err => {
obj.fail ? obj.fail(err) : () => {}
reject(err)
},
complete: res => {}
})
})
},
/**
* 上传文件
* @param {Object} obj
* @param {String} obj.mode img图片 video视频
*/
upload(obj) {
// 使用promise写请求,一个函数两种回调
return new Promise((resolve, reject) => {
// 默认token
let token = uni.getStorageSync('token') || ''
// 接口地址
obj.url = obj.url ? obj.url : '/file/upload'
// 文件
obj.file = obj.file ? obj.file : ""
// 附加数据
obj.data = obj.data ? obj.data : {}
// 请求头
obj.header = {
// 'Content-Type': 'multipart/form-data; ',
// 'Content-Type': 'application/json;charset=UTF-8',
'Access-Control-Allow-Origin': '*',
...obj.header,
}
if (token) obj.header["Authorization"] = `Bearer ${token}`
// 打开loading效果
uni.showLoading({
title: "正在上传",
})
// 上传
uni.uploadFile({
url: util.config.host + obj.url,
filePath: obj.file,
header: obj.header,
formData: obj.data,
dataType: 'json',
name: 'file',
success: (res) => {
// 关闭loading效果
uni.hideLoading()
// 成功
obj.success ? obj.success(JSON.parse(res.data)) : ''
//
resolve(JSON.parse(res.data))
},
fail: (res) => {
// 关闭loading效果
uni.hideLoading()
// 错误
obj.fail ? obj.fail(res.data) : ''
//
reject(res)
},
})
})
},
/**
* 发送网络请求
* @param {Object} params 传参
* @param {String} params.url 请求地址 一般用于后台请求接口
* @param {Array} params.query 请求地址拼接参数 用于后台请求地址拼接补全
* @param {String} params.fullurl 全请求地址 一般用于第三方请求地址
* @param {Boolean} params.load 是否显示加载动画 默认不显示
* @param {Object} params.data 请求入参 没有则不传
* @param {Object} params.header 请求头 默认不传
* @param {String} params.method 请求方式 默认值POST
* @param {Function} params.success 请求成功回调 可通过promise.then捕获
* @param {Function} params.fail 请求失败回调 可通过promise.catch捕获
* @param {Function} params.complete 请求结束回调 无论是否成功失败都会执行
* @return {Object} 返回promis对象 执行成功返回resolve 执行失败返回reject
*/
request(params) {
// 默认token
let token = uni.getStorageSync('token') || ''
// 返回方法
return new Promise((resolve, reject) => {
// 请求地址
let url = util.config.host + (params.url ? params.url : '/api/index/index')
// 是否path拼接参数
if (params.path && params.path instanceof Array) params.path.forEach(item => {
url += `/${item}`
})
// 是否query拼接参数
if (params.query) {
url = util.setUrl(url, params.query)
}
// 是否打开加载效果
if (params.load) {
uni.showLoading({
title: "加载中",
mask: true,
})
}
// 请求头
params.header = {
'Content-Type': 'application/json;charset=UTF-8',
'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept',
// token: uni.getStorageSync('token'),
'Access-Control-Allow-Origin': '*',
'IS_APP_REQ': 'APP_REQ',
...params.header,
}
if (token) params.header["Authorization"] = `Bearer ${token}`
// console.log('request url', url)
// console.log('request data', params.data)
// console.log('request header', params.header)
// console.log('params.responseType', url, params.responseType)
// 发起网络请求
uni.request({
// 请求地址
url: url,
// 请求方式 get/post
method: params.method ? params.method : "POST",
// 是否开启SSL验证
sslVerify: false,
// 请求参数
data: params.data,
// header请求头
header: params.header,
// 数据类型
dataType: 'json',
responseType: params.responseType || 'text',
// 请求成功返回
success: res => {
// console.log('request success', url, res, params.data ? params.data : '')
// 关闭加载效果
if (params.load) {
uni.hideLoading()
}
// 401
if (res.data.code == 401) {
// 登出
util.logout(() => {
util.alert('请先登录')
reject(res.data) // 链式回调0
// uni.reLaunch({
// url: '/login/login',
// })
})
}
// 嵌套式回调
params.success ? params.success(res.data) : ''
// 链式回调
resolve(res.data);
},
// 请求失败返回
fail: res => {
// 关闭加载效果
if (params.load) {
uni.hideLoading()
}
// 嵌套式回调
params.fail ? params.fail(res) : ''
// 链式回调
reject(res)
},
complete(res) {
// console.log('complete', url, res);
// 嵌套式回调
params.complete ? params.complete(res) : ''
},
})
})
},
// 替换图片的宽度为最大宽度100% (移动端解析html富文本专用)
imgReplace(value, th) {
if (!th) {
value = value.replace(/<img src="/ig, '<img src="' + util.config.host);
}
return value.replace(/<p([\s\w"=\/\.:;]+)((?:(style="[^"]+")))/ig, '<p')
.replace(/<p>/ig, '<p style="font-size: 15px; line-height: 25px;">')
.replace(/<img([\s\w"-=\/\.:;]+)((?:(height="[^"]+")))/ig, '<img$1')
.replace(/<img([\s\w"-=\/\.:;]+)((?:(width="[^"]+")))/ig, '<img$1')
.replace(/<img([\s\w"-=\/\.:;]+)((?:(style="[^"]+")))/ig, '<img$1')
.replace(/<img([\s\w"-=\/\.:;]+)((?:(alt="[^"]+")))/ig, '<img$1')
.replace(/<img([\s\w"-=\/\.:;]+)/ig, '<img style="width: 100%;" $1')
},
/**
* 路由跳转方法
* @param {string} url 跳转的目标页面路径
* @param {Object} params 要传递的参数对象
* @param {string} method 跳转方法,默认为 navigateTo
*/
routeWithParams(url, params = {}, method = 'navigateTo') {
// const paramStr = Object.keys(params).length > 0 ? '?' + new URLSearchParams(params) : '';
// const fullUrl = `${url}${paramStr}`;
const fullUrl = util.setUrl('url', params)
switch (method) {
case 'navigateTo':
uni.navigateTo({
url: fullUrl
});
break;
case 'redirectTo':
uni.redirectTo({
url: fullUrl
});
break;
case 'reLaunch':
uni.reLaunch({
url: fullUrl
});
break;
case 'switchTab':
uni.switchTab({
url: fullUrl
});
break;
default:
throw new Error(`Unsupported method: ${method}`);
}
},
/**
* get参数拼接
* @param {Object} data 需要转化的对象
*/
set_param(data) {
// 初始路径
let url = ''
// 格式化
if (!data) data = []
// 遍历
for (let [key, value] of Object.entries(data)) {
url += `${key}=${value}&`
}
// 判断最后一个是不是& 是就删除& 不是就放回url
url = url.substring(url.length - 1) == '&' ? url.substring(0, url.length - 1) : url
return url ? url : url.substring(1)
},
/**
* get参数拼接url
* @param {String} url 需要处理的url
* @param {Object} data 需要转化的Object对象
*/
setUrl(url, data) {
let result = url += (url.indexOf('?') < 0 ? '?' : '&') + util.set_param(data)
return result
},
/**
* query字符串转对象
* @param {Object} str query字符串
*/
query_to_param(str) {
let obj = {}
decodeURIComponent(str).split('&').forEach(item => {
let [key, val] = item.split('=');
obj[key] = val
})
return obj
},
/**
* 倒计时
* @param {String} endtime 结束时间
*/
countDownd(endtime) {
if (!endtime) {
return
}
endtime = Number(endtime)
let timestamp = Date.parse(new Date()) / 1000
if (endtime > 100000) {
// 距离结束的秒数
let time = (endtime - timestamp)
} else {
let time = endtime
}
// 获取天、时、分、秒
let day = util.timeFormin(parseInt(time / (60 * 60 * 24)))
let hou = util.timeFormin(parseInt(time % (60 * 60 * 24) / 3600))
let min = util.timeFormin(parseInt(time % (60 * 60 * 24) % 3600 / 60))
let sec = util.timeFormin(parseInt(time % (60 * 60 * 24) % 3600 % 60))
let str = "";
if (day) {
str += day + "天"
}
if (hou || hou == 0) {
if (hou > 9) {
str += hou + ":"
} else {
str += "0" + hou + ":"
}
} else {
str += "00:"
}
if (min || min == 0) {
if (min > 9) {
str += min + ":"
} else {
str += "0" + min + ":"
}
} else {
str += "00:";
}
if (sec) {
if (sec > 9) {
str += sec;
} else {
str += "0" + sec
}
} else {
str += "00"
}
return str
},
// 格式化时间
timeFormin(param) {
return param < 0 ? 0 : param;
},
/**
* 对二补齐
* @param {String} str 数字或数字字符串
*/
toTwo(str) {
// 格式化字符
let num = String(Number(str));
// 判断时间
if (num.length < 2) {
num = '0' + num;
}
// 返回时间
return num;
},
/**
* 时间戳处理成时间
* @param {Object} str
* 时间格式 月、日、时、分、秒 单个字母不补0
* yyyy 年
* MM 月
* dd 日
* WW 周
* HH 小时 24小时制
* hh 小时 12小时制
* mm 分钟
* ss 秒
* a am/pm
* 比如 'yyyy-MM-dd HH:mm:ss 周w a' 返回2023-02-06 11:19:19 周一 pm
* @param {Number} timestamp 需要处理时间戳
*/
formatTime(str, timestamp) {
// 当前时间
const nowDate = new Date()
// 周列表 歪果仁把周日放在第一位
let weekList = ['日', '一', '二', '三', '四', '五', '六']
// 格式化字符串
if (!str || typeof str != 'string') {
str = 'yyyy-MM-dd HH:mm:ss'
}
// 格式化时间戳
if (!timestamp) {
timestamp = nowDate.valueOf()
} else if (String(timestamp).length <= 10) {
// 时间
timestamp = timestamp * 1000
}
// 时间
const date = new Date(timestamp)
// 获取对应时间
let year = date.getFullYear(),
moth = date.getMonth() + 1,
day = date.getDate(),
week = date.getDay(),
hour = date.getHours(),
minute = date.getMinutes(),
second = date.getSeconds()
// 处理年
str = str.replace('yyyy', year)
// 处理月份
str = str.replace('MM', this.toTwo(moth))
str = str.replace('M', moth)
// 处理日
str = str.replace('dd', this.toTwo(day))
str = str.replace('d', day)
// 处理周
str = str.replace('w', weekList[week])
// 处理小时
if (str.match('h')) {
// 12小时制
hour = hour > 12 ? hour - 12 : hour
// 12小时制
str = str.replace('hh', this.toTwo(hour))
str = str.replace('h', hour)
} else if (str.match('H')) {
// 24小时制
str = str.replace('HH', this.toTwo(hour))
str = str.replace('H', hour)
}
// 处理分钟
str = str.replace('mm', this.toTwo(minute))
str = str.replace('m', minute)
// 处理秒
str = str.replace('ss', this.toTwo(second))
str = str.replace('s', second)
// 处理是上午还是下午
let a = hour > 12 ? 'am' : 'pm'
str = str.replace('a', a)
return str
},
/**
* 时间计算
* @param {String} format 格式化 规则
* format '+1 month' 往后一个月
* @param {Number} value 需要处理的时间戳 单位秒
*/
strtotime(format, value) {
// 处理时间 精确到秒的函数
if (value && format.indexOf(" ") > -1) {
// 单位
let unit = format.split(" ")
let pre = unit[0]
let next = unit[1]
// 格式化时间戳
if (!value) value = nowDate.valueOf()
else if (String(value).length <= 10) value = value * 1000
//创建date变量
let nowDate = new Date(value)
switch (next) {
case "year":
nowDate.setYear(nowDate.getFullYear() + parseInt(pre))
break
case "month":
nowDate.setMonth(nowDate.getMonth() + parseInt(pre))
break
case "day":
nowDate.setDate(nowDate.getDate() + parseInt(pre))
break
case "week":
nowDate.setDate(nowDate.getDate() + (parseInt(pre) * 7));
break
case "hour":
nowDate.setHours(nowDate.getHours() + (parseInt(pre)));
break
case "minute":
nowDate.setMinutes(nowDate.getMinutes() + (parseInt(pre)));
break
}
return nowDate.getTime()
} else {
//创建date变量
var nowDate = new Date(value)
return nowDate.getTime()
}
},
/**
* 上传图片
* @param {Object} obj 对象类型
* @param {Array} obj.value 操作的对象
* @param {Boolean} obj.unlimited 不限制
* @param {Number} obj.count 图片计数
* @param {Number} obj.type 1单张 2多张
* @param {Array} obj.sourceType ['album', 'camera']
* @param {Function} obj.success 执行成功返回的方法return修改的对象
*/
upload_image(obj) { // 格式化默认值
// 图片计数
const count = obj.count ? obj.count : 8;
// 多张图片
if (!obj.type) obj.type = 2;
// 操作对象
// 修正逻辑判断
if (obj.value == '' || obj.value == undefined || obj.value == null) obj.value = obj.type == 1 ? '' : [];
// 判断剩余图片上传个数
if (obj.value.length >= count && obj.type == 2) {
// 弹窗提示
util.alert('上传图片已达上限');
return;
}
// 选择图片
uni.chooseImage({
// 限制图片
count: obj.type == 1 ? 1 : count - obj.value.length,
sourceType: obj.sourceType || ['album', 'camera'],
success: (rs) => {
// 遍历图片返回列表
rs.tempFiles.forEach(item => {
// 限制大小
let size = 1024 * 1024 * util.config.img_size;
if (item.size > size && !obj.unlimited) {
util.alert(`大小超过${util.config.img_size}m`);
return;
}
// 调用上传图片
util.upload({
file: item.path,
mode: 'img',
success(res) {
// 上传成功
if (res.code === 200) {
const result = res.data.url;
// 补全路径赋值
if (obj.type == 2) {
obj.value.push(result);
} else if (obj.type == 1) {
obj.value = result;
}
obj.success && obj.success({
value: result,
});
return;
}
util.alert(rs.msg);
},
});
});
},
fail(rs) {
if (rs.errMsg == "chooseImage:fail cancel") {
// 取消选择
}
},
});
},
/**
* 上传视频
* @param {Object} obj 对象类型
* @param {Array} obj.value 操作的对象
* @param {Object} obj.unlimited 不限制
* @param {Object} obj.count 计数
* @param {Object} obj.success 执行成功返回的方法return修改的对象
*/
upload_video(obj) {
// 视频计数
const count = obj.count ? obj.count : 1
// 选择视频
uni.chooseVideo({
compressed: false,
success(rs) {
// 限制大小
// let size = 1024 * 1024 * util.config.video_size
// if (rs.size > size && !obj.unlimited) {
// util.alert(`大小超过${util.config.video_size}m`)
// return
// }
// 调用上传视频
util.upload({
file: rs.tempFilePath,
mode: 'video',
success(res) {
// 上传成功
if (res.code == 200) {
// const fullUrl = util.format_url(res.msg, 'video')
obj.success && obj.success({
value: res.data.url,
width: rs.width,
height: rs.height,
size: rs.size,
duration: rs.duration,
// value: fullUrl,
})
return
} else {
util.alert(res.msg)
}
},
})
},
fail(rs) {
if (rs.errMsg == "chooseImage:fail cancel") {
// 取消选择
}
},
})
},
/**
* 上传文件
* @param {Object} obj 对象类型
* @param {Array} obj.value 操作的对象
* @param {Object} obj.count 计数
* @param {Object} obj.success 执行成功返回的方法return修改的对象
*/
upload_files(obj) {
const value = obj.value
// 限制目录
const file_suffix = util.config.file_suffix
// 默认值
const count = obj.count ? obj.count : 1
// 判断剩余图片上传个数
if (value.length >= count) {
// 弹窗提示
util.alert('上传数量已达上限')
return
}
console.log('upload_files', obj)
/**
* 结算方法
* @param {Object} path
*/
function result_fn(path) {
// 上传文件的后缀名
let str = path.split('.').pop().toLowerCase()
// 结果
let reult = file_suffix.find(node => node.id == str)
// 验证
if (!reult) {
util.alert(`不能上传${str}格式文件`)
return
}
// 上传文件
util.upload({
file: path,
success(res) {
if (res.code == 200) {
value.push(res.data)
// 执行方法
obj.success && obj.success({
...res.data,
value,
})
} else {
util.alert(res.msg)
}
},
})
}
// #ifdef MP-WEIXIN
// 从微信聊天里面选择文件
wx.chooseMessageFile({
count: 1,
type: 'file',
// 文件过滤
extension: file_suffix.map(node => node.id),
success: (rs) => {
// 遍历数组
rs.tempFiles.forEach((e, i) => {
result_fn(e.path)
})
},
})
return
// #endif
// #ifdef APP-PLUS
if (uni.getSystemInfoSync().platform == "android") {
console.log('chooseFile')
chooseFile((rs) => {
console.log('rs', rs)
result_fn(rs)
})
} else {
util.alert('因权限问题暂不支持非android平台')
}
return
// #endif
util.alert('暂未开放')
},
/**
* 上传音频
* @param {Object} obj 对象类型
* @param {Array} obj.value 操作的对象
* @param {Object} obj.count 计数
* @param {Object} obj.success 执行成功返回的方法return修改的对象
*/
upload_audio(obj) {
const value = obj.value
// 限制目录
const audio_suffix = util.config.audio_suffix
// 默认值
const count = obj.count ? obj.count : 1
// 判断剩余图片上传个数
if (value.length >= count) {
// 弹窗提示
util.alert('上传数量已达上限')
return
}
/**
* 结算方法
* @param {Object} path
*/
function result_fn(path) {
// 上传文件的后缀名
let str = path.split('.').pop().toLowerCase()
// 结果
let reult = audio_suffix.find(node => node.id == str)
// 验证
if (!reult) {
util.alert(`不能上传${str}格式文件`)
return
}
// 上传文件
util.upload({
file: path,
success(res) {
if (res.code == 200) {
value.push(res.data)
// 执行方法
obj.success && obj.success({
...res.data,
value,
})
} else {
util.alert(res.msg)
}
},
})
}
// #ifdef MP-WEIXIN
// 从微信聊天里面选择文件
wx.chooseMessageFile({
count: 1,
type: 'file',
// 文件过滤
extension: audio_suffix.map(node => node.id),
success: (rs) => {
// 遍历数组
rs.tempFiles.forEach((e, i) => {
result_fn(e.path)
})
},
})
return
// #endif
// #ifdef APP-PLUS
if (uni.getSystemInfoSync().platform == "android") {
chooseFile((rs) => {
console.log('chooseFile', rs);
result_fn(rs)
})
} else {
util.alert('因权限问题暂不支持非android平台')
}
return
// #endif
util.alert('暂未开放')
},
/**
* 视频转封面 oss特有
* @param {Object} url 视频路径
*/
video_coverImage(url) {
let result = `${url}?x-oss-process=video/snapshot,t_1,m_fast`
return result
},
/**
* 预览图片
* @param {Array} urls 图片列表
* @param {Number} current 当前预览的下标
*/
view_imgs(urls, current) {
// 格式化
if (!urls || urls.length == 0) {
util.alert('暂无')
return
}
uni.previewImage({
urls,
current,
})
},
/**
* 预览文件
* @param {String} url 文件路径
*/
view_file(url) {
// 后缀
let suffix = util.get_file_suffix(url).id
//
if (!['doc', 'xls', 'ppt', 'pdf', 'docx', 'xlsx', 'pptx'].includes(suffix)) {
util.alert('操作需要在web端')
console.log('Unsupported suffix', suffix)
return
}
uni.downloadFile({
url,
success: res => {
uni.openDocument({
filePath: res.tempFilePath,
fail: rs => {
console.log('rs', rs)
}
})
}
})
},
/**
* 通过路径获取文件后缀
* @param {Object} url 需要获取的文件路径
* @param {Object} type file文件 audio音频
* @return {Object} 返回后缀列表对象 util.config.file_suffix
*/
get_file_suffix(url, type) {
if (!type) type = 'file'
// 文件后缀
const file_suffix = util.config[{
'file': 'file_suffix',
'audio': 'audio_suffix',
} [type]]
let result = ''
if (url) result = file_suffix.find(item => item.id === url.split('.').pop().toLowerCase())
return result
},
/**
* 通过路径获取音频后缀
* @param {Object} url 需要获取的文件路径
* @return {Object} 返回后缀列表对象 util.config.file_suffix
*/
get_audio_suffix(url) {
// 文件后缀
const audio_suffix = util.config.audio_suffix
let result = ''
if (url) result = audio_suffix.find(item => item.id === url.split('.').pop().toLowerCase())
return result
},
/**
* 调起支付
* @param {Object} obj 操作对象
* @param {String} obj.payType 支付方式 WeChat微信 AliPay支付宝 4钱包
* @param {String} obj.method 支付环境 app手机应用 mp小程序
* @param {String} obj.debug 调试模式
* @param {Boolean|Object} obj.cb 支付结果跳转 false为不跳转 跳转需携带object定义对象
* @param {String} obj.cb.styles 风格 style1蓝色 style2绿色 style3橙色
* @param {String} obj.cb.result 结果 success成功 fail失败
* @param {String} obj.cb.price 价格
* @param {String} obj.cb.url 跳转的详情路径
* @param {Function} obj.fn 请求接口函数
* @param {Function} obj.success 成功方法
* @param {Function} obj.fail 失败方法
* @param {Function} obj.complete 结束方法
*/
payment(obj) {
// 参数必须是对象
obj = obj ? obj : {}
// 支付参数
obj.data = obj.data ? obj.data : {}
// 付款类型
// #ifdef APP
obj.method = 'app'
// 支付请求
util.payment_request(obj)
// #endif
// #ifdef MP-WEIXIN
obj.method = 'mp'
// 登录
uni.login({
success: (rs) => {
// code
obj.data.code = rs.code
// 支付请求
util.payment_request(obj)
}
})
// #endif
},
// 支付请求
payment_request(obj) {
obj.debug ? console.log('params', obj) : ""
if (!obj.fn) {
throw 'no function'
}
/**
* 结果跳转
* @param {Object} result success成功 fail失败
*/
function result_goto(result) {
const cb = obj.cb
if (!cb) return
// 跳转到订单结果
uni.redirectTo({
url: util.setUrl('/index/pay_result', {
orderNumber: cb.orderNumbers || '',
result,
styles: cb.styles || '',
price: cb.price || '',
url: cb.url || '',
}),
})
}
// 支付方法
obj.fn(obj.data).then(rs => {
// 调试模式
obj.debug ? console.log('request success result', rs) : ""
if (rs.code == 200) {
// 根据对应类型吊起支付
switch (obj.data.payType) {
// 微信支付
case "1":
switch (obj.method) {
// 小程序支付
case "mp":
if (rs.data && rs.data.paySign) {
uni.requestPayment({
provider: "wxpay",
timeStamp: rs.data.timeStamp,
package: rs.data.package,
nonceStr: rs.data.nonceStr,
paySign: rs.data.paySign,
signType: rs.data.signType,
success(result) {
obj.success ? obj.success(rs) : ''
result_goto('success')
},
fail(result) {
obj.fail ? obj.fail(result) : ''
result_goto('fail')
},
complete(result) {
obj.debug ? console.log('requestPayment complete',
result) : ""
obj.complete ? obj.complete(result) : ''
}
})
} else {
obj.fail ? obj.fail('no data') : ''
}
break
// app支付
case "app":
uni.requestPayment({
provider: "wxpay",
orderInfo: rs.data,
success(result) {
obj.success ? obj.success(rs) : ''
result_goto('success')
},
fail(result) {
obj.fail ? obj.fail(result) : ''
result_goto('fail')
},
complete(result) {
obj.debug ? console.log('requestPayment complete', result) :
""
obj.complete ? obj.complete(result) : ''
}
})
break
}
break
// 支付宝支付
case "2":
switch (obj.method) {
// app支付
case "app":
uni.requestPayment({
provider: "alipay",
orderInfo: rs.msg,
success(result) {
obj.success ? obj.success(rs) : ''
result_goto('success')
},
fail(result) {
obj.fail ? obj.fail(result) : ''
result_goto('fail')
},
complete(result) {
obj.debug ? console.log('requestPayment complete', result) :
""
obj.complete ? obj.complete(result) : ''
}
})
break
}
break
// 钱包支付
case "4":
obj.success ? obj.success(rs) : ''
result_goto('success')
break
}
} else {
util.alert(rs.msg)
// 失败
obj.fail ? obj.fail(rs) : ''
}
}).catch(rs => {
console.log('request catch result', rs);
})
},
// 微信小程序登录
weChatLogin(obj) {
// 格式化
obj = obj ? obj : {}
const parent_id = uni.getStorageSync('parent_id')
const admin_id = uni.getStorageSync('admin_id')
// 获取用户信息
uni.getUserProfile({
desc: "weixin",
success: e => {
// 用户信息
const userInfo = e.userInfo
// 定义用户数据
let data = {
nickName: userInfo.nickName,
avatarUrl: userInfo.avatarUrl,
}
// 调用登录
uni.login({
provider: "weixin",
success: rs => {
data.code = rs.code
data.platform = "wechatMini"
// 邀请人ID
if (parent_id) data.parent_id = parent_id
// 后台业务员的ID
if (admin_id) data.admin_id = admin_id
// 如果获得code
if (rs.errMsg == "login:ok") {
// 请求接口
util.request({
url: "/api/user/third",
data,
load: 1,
}).then(res => {
// 如果操作成功
if (res.code == 200) {
// 最终登录
// util.final_login()
// 成功
obj.success ? obj.success(res) : ''
}
})
}
},
})
},
fail(res) {
util.alert("您拒绝了授权");
// 失败
obj.fail ? obj.fail(res) : (res) => {};
},
complete() {
// 结束
obj.complete ? obj.complete() : ''
},
});
},
/**
* 拉起授权请求: 微信小程序、app
*/
authorize(obj) {
// 返回promise对象
return new Promise((resolve, reject) => {
// 对象
obj ? obj : obj = {}
// #ifdef APP-PLUS
let isAgreePrivacy = plus.runtime.isAgreePrivacy()
if (!isAgreePrivacy) {
resolve('未同意用户协议隐私政策')
return
}
// #endif
// 菜单
const menu = {
// 定位
location: {
name: '定位服务',
scope: 'scope.userLocation',
txt: '需要获取您的地理位置',
},
// 相册
photosAlbum: {
name: '相册',
scope: 'scope.writePhotosAlbum',
txt: '需要访问您的相册',
},
// 相机
camera: {
name: '摄像头',
scope: 'scope.camera',
txt: '需要访问您的摄像头',
},
}
// 判断是否有键值
if (obj.key) {
// 传参对象
obj = {
...obj,
...menu[obj.key]
}
}
let fnName = ''
// #ifdef MP-WEIXIN
// 微信小程序授权
fnName = 'weChatAuthorize'
// #endif
// #ifdef APP-PLUS
// app授权
fnName = 'appAuthorize'
// #endif
//
this[fnName](obj)
.then(rs => {
// 成功
obj.success ? obj.success(rs) : ''
resolve(rs)
})
.catch(err => {
// 失败
obj.fail ? obj.fail(err) : ''
reject(err)
})
})
},
// app授权
appAuthorize(obj) {
// 系统设置
return new Promise((resolve, reject) => {
// 手机设置
const systemSetting = uni.getSystemSetting()
// 没开
if (systemSetting.locationEnabled === false) {
this.alert(obj.txt)
// 失败
reject({
msg: '未授权对应功能',
})
return
}
// 用户是否开启定位权限
const authorized = uni.getAppAuthorizeSetting().locationAuthorized
console.log('locationAuthorized', authorized);
if (authorized === 'config error') {
// 开发者没有配置权限 https://uniapp.dcloud.net.cn/api/system/getappauthorizesetting.html
reject({
msg: '开发者未勾选定位服务模块',
})
return
} else if (authorized === 'denied') {
// reject({
// msg: 'user denied',
// })
// return
} else if (authorized === 'authorized') {
// 表示已经获得授权,无需再次请求授权
resolve(obj)
return
}
// 判断平台
if (uni.getSystemInfoSync().platform == "android") {
// 请求权限配置
plus.android.requestPermissions(
// 对应权限
['android.permission.ACCESS_FINE_LOCATION'],
// 成功
(resultObj) => {
// 结果
let result = null
for (let i = 0; i < resultObj.granted.length; i++) {
let grantedPermission = resultObj.granted[i]
console.log('已获取的权限:' + grantedPermission)
if (result !== null) result = 1
}
for (let i = 0; i < resultObj.deniedPresent.length; i++) {
let deniedPresentPermission = resultObj.deniedPresent[
i]
console.log('拒绝本次申请的权限:' + deniedPresentPermission)
if (result !== null) result = 0
}
for (let i = 0; i < resultObj.deniedAlways.length; i++) {
let deniedAlwaysPermission = resultObj.deniedAlways[i]
console.log('永久拒绝申请的权限:' + deniedAlwaysPermission)
if (result !== null) result = -1
}
// 成功
if (result === 1) {
resolve()
} else if ([-1].includes(result)) {
// 若所需权限被拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限
// 引导用户打开设置页面
uni.openAppAuthorizeSetting({
success: rs => {
// 失败
reject({
msg: '引导用户打开设置页面',
info: rs,
})
},
fail: err => {
// 失败
reject({
msg: '用户设置页面打开失败',
info: err,
})
},
})
}
},
// 失败
(error) => {
console.log('申请权限错误:' + error.code + " = " + error.message)
resolve({
code: error.code,
message: error.message
})
}
)
} else {
this.alert('请在设置里允许打开定位信息')
resolve({
msg: '用户未开启定位权限',
})
return
}
})
},
// 微信小程序授权
weChatAuthorize(obj) {
// 成功
return new Promise((resolve, reject) => {
// 是否在微信小程序限制范围内
if (!['scope.userInfo', 'scope.userLocation', 'scope.userLocationBackground',
'scope.address',
'scope.record', 'scope.writePhotosAlbum', 'scope.camera',
'scope.invoice',
'scope.invoiceTitle', 'scope.werun'
].includes(obj.scope)) {
resolve({
msg: '不在限制范围内',
})
return
}
// 授权
uni.authorize({
scope: obj.scope,
success: rs => {
// 成功
resolve(rs)
},
fail: err => {
// 失败
reject(err)
// 弹窗提示
util.alert({
title: '系统提示',
value: obj.txt,
success: rs => {
if (rs.confirm) {
// 打开微信权限设置
uni.openSetting()
}
},
})
},
})
})
},
/**
* 最终登录 用于请求登录接口后统一调用的登录方法
* @param {Object} param 数据对象
* @param {Function} cb 回调函数
*/
finalLogin(param, cb) {
// 登录令牌
const token = param.data
// 缓存token
uni.setStorageSync('token', token)
// 开启加载
uni.showLoading({
mask: true
})
// 获取用户信息
util.getUserinfo((userinfo) => {
// 登录
uni.$emit('login')
setTimeout(() => {
uni.switchTab({
url: '/pages/index/index'
})
}, 500)
//
cb ? cb() : ''
})
},
// 登录腾讯聊天
loginTencent(userinfo) {
api.login.getIMToken({}).then(rs => {
//
const imSig = rs.msg
// #ifdef APP
// 音视频登录
const loginParams = {
SDKAppID: util.config.TChat.SDKAppID,
userID: userinfo.id + '',
userSig: imSig,
}
uni.$TUICallKit.login(loginParams, res => {
if (res.code === 0) {
console.log('[TUICallKit] login success.');
} else {
console.error('[TUICallKit] login failed, failed message = ', res.msg, params);
}
})
// #endif
uni.$chat.login({
userID: userinfo.id + '',
userSig: imSig,
}).then(rs => {
console.log('im login success', rs)
})
})
},
/**
* 获取用户信息
* @param {Function} cb 回调函数
*/
getUserinfo(cb) {
return new Promise(reslove => {
// 请求接口
api.mine.getUserinfo().then(rs => {
if (rs.code === 200) {
reslove(rs.data)
const userinfo = rs.data
// 如果开启了青少年模式
if (userinfo.teenTime) {
// 青少年模式验证 如果到了限制去锁定页
}
// 提交
store.commit('setState', {
key: 'userinfo',
value: userinfo
})
// 用户信息
uni.setStorageSync('userinfo', userinfo)
cb ? cb(userinfo) : ''
}
}).finally(() => {
// 关闭加载
uni.hideLoading()
})
})
},
/**
* 验证登录
* @param {Object} cb 回调函数
*/
isLogin(cb) {
// 验证
let userinfo = uni.$store.state.userinfo
// console.log('islogin userinfo', userinfo)
return new Promise((resolve, reject) => {
// 登录
if (!userinfo.id) {
// util.alert('请先登录')
// 失败
reject()
return
}
// 成功
resolve()
// 回调
cb ? cb() : ''
})
},
/**
* 清除登录状态
* @param {Function} cb 回调函数
*/
logout(cb) {
// 用户信息
const userinfo = store.state.userinfo
// 用户id
if (userinfo.userId) {
uni.$emit('logout') // 触发自定义事件监听
// tim登出
uni.$chat.logout().then(rs => {
console.log('tim logout rs'); // 登出成功
}).catch(rs => {
console.log('tim logout error:', rs);
});
}
// 把vuex的值改成未登录的状态
store.commit('setState', {
key: 'userinfo',
value: {},
})
uni.removeStorageSync('userinfo') // 删除缓存的用户信息
uni.removeStorageSync('token')
// 回调函数
cb ? cb() : ''
},
// 是否实名
isAuth(param) {
// 验证登录
util.isLogin(() => {
const userinfo = uni.$store.state.userinfo
console.log('userinfo.userIdCard', userinfo.userIdCard)
if (userinfo.userIdCard) {
param.success ? param.success(userinfo) : ''
return
}
// 去实名
if (!param.noLink) uni.navigateTo({
url: '/pages/mine/realname',
})
param.fail ? pararm.fail(userinfo) : ''
})
},
// 拨打电话
makePhone(phoneNumber) {
if (!phoneNumber) {
util.alert('暂无手机号')
}
uni.makePhoneCall({
phoneNumber,
fail(err) {
console.log('err', err);
},
})
},
/**
* 处理路径添加host或这默认图片地址
* @param {String} ev 需要处理的字符串
* @param {String} mode img图片 video视频
* @return {String} 返回的路径
*/
format_url(ev, mode) {
if (!ev) return ''
if (ev.match(/^http/)) return ev
return 'https://9yvideo.oss-cn-beijing.aliyuncs.com/' + ev
},
/**
* 去除路径里的host
* @param {Object} ev 需要处理的字符串
* @return {String} 处理之后的路径
*/
replace_url(ev) {
if (!ev || typeof ev != 'string') throw `${ev} is not String`
let result = ev.slice(ev.indexOf('/images') + 1)
return result
},
/**
* 格式化经纬度
* @param {String} num 数字或数字字符串
*/
formart_lnglat(num) {
// 结果
let result = ''
// 结果
if (!num) return num
num = parseFloat(Number(num).toFixed(6))
return num
},
/**
* 检查跳转
* @param {String} route 路径
* @param {String} type 跳转
*/
checkLink(route, type = 'navigateTo') {
// 当前页面栈
const currentPages = getCurrentPages()
// 寻找的页面
const find_route = route
// 寻找下标
const find_index = currentPages.findIndex(node => {
return node.route == find_route
})
// 是否存在
if (find_index < 0) {
uni[type]({
url: `/${find_route}`
})
} else {
uni.navigateBack({
delta: currentPages.length - find_index - 1
})
}
},
/**
* 数字转化
*/
rp(n) {
var cnum = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十'];
var s = '';
n = '' + n; // 数字转为字符串
for (var i = 0; i < n.length; i++) {
s += cnum[parseInt(n.charAt(i))];
}
if (s.length == 2) { // 两位数的时候
// 如果个位数是0的时候0改成十
if (s.charAt(1) == cnum[0]) {
s = s.charAt(0) + cnum[10];
// 如果是一十改成十
if (s == cnum[1] + cnum[10]) {
s = cnum[10]
}
} else if (s.charAt(0) == cnum[1]) {
// 如果十位数是一的话改成十
s = cnum[10] + s.charAt(1);
} else if (s.charAt(0) == cnum[2]) {
// 如果十位数是二的话改成十二
s = cnum[2] + cnum[10] + s.charAt(1);
} else if (s.charAt(0) == cnum[3]) {
s = cnum[3] + cnum[10] + s.charAt(1);
} else if (s.charAt(0) == cnum[4]) {
s = cnum[4] + cnum[10] + s.charAt(1);
} else if (s.charAt(0) == cnum[5]) {
s = cnum[5] + cnum[10] + s.charAt(1);
} else if (s.charAt(0) == cnum[6]) {
s = cnum[6] + cnum[10] + s.charAt(1);
} else if (s.charAt(0) == cnum[7]) {
s = cnum[7] + cnum[10] + s.charAt(1);
} else if (s.charAt(0) == cnum[8]) {
s = cnum[8] + cnum[10] + s.charAt(1);
} else if (s.charAt(0) == cnum[9]) {
s = cnum[9] + cnum[10] + s.charAt(1);
} else if (s.charAt(0) == cnum[10]) {
s = cnum[10] + cnum[10] + s.charAt(1);
}
}
return s;
},
/**
* 复制文本
* @param {String} text 需要复制的文本
*/
copyText(text) {
uni.setClipboardData({
data: text,
success: () => {
util.alert('文本已复制到剪贴板')
}
});
},
showToastAndRedirect(title, icon = 'none', fun = () => {}) {
uni.showToast({
title,
icon,
duration: 2000, // 显示两秒
complete: () => {
fun()
uni.hideLoading()
}
});
},
/**
* 去聊天
* @param {Object} option
* @param {Object} option.name 标题昵称
* @param {Object} option.msgId 聊天对象id
* @param {Object} option.type 聊天类型 C2C单聊 GROUP群聊
*/
toChat(option) {
uni.navigateTo({
url: util.setUrl('/pages/news/chat/chat', {
name: option.name,
msgId: option.msgId,
type: option.type,
})
})
},
// 扫码
scan() {
uni.scanCode({
success: (res) => {
if (res && res.result) {
let result = JSON.parse(res.result)
if (result.key == 'user') {
// 跳转申请添加好友界面
uni.navigateTo({
url: util.setUrl('/pages/news/applyFriend', {
userId: result.userId,
nickname: result.userNickname,
})
})
}
}
//
},
fail: (err) => {
util.alert('二维码扫描失败')
}
});
},
// 获取我的钱包
getPurse() {
api.mine.selectPurse().then(rs => {
if (rs.code == 200) {
// 同步vuex
uni.$store.commit('setState', {
key: 'purse',
value: rs.data,
})
return
}
util.alert({
content: rs.msg,
showCancel: false,
})
})
},
// 获取我的任务
getMyTask() {
// 验证登录
util.isLogin().then(() => {
// 获取任务
api.intergral.viewingTasks({}).then(rs => {
if (rs.code == 200) {
uni.$store.commit('setState', {
key: 'task',
value: rs.data,
})
return
}
})
}).catch(() => {
// 修改为默认值
uni.$store.commit('setState', {
key: 'task',
value: {
//任务类型 0.任务读秒 1.流量点(种子)读秒
taskType: 0,
//有效时长
viewingDuration: 0,
},
})
})
},
// 分页
paging: {
//
},
}
export default util