// vuex import store from '@/store' // 配置 import config from '@/common/js/config.js' // 接口 import api from '@/api/index.js' // 工具库 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) }, complete(rs) { console.log('upload complete', rs) } }) }) }, /** * 发送网络请求 * @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(res.data.msg) reject(res.data) uni.redirectTo({ url: '/pages/login/loginPhone', }) }) } // 嵌套式回调 params.success ? params.success(res.data) : '' // 链式回调 resolve(res.data); }, // 请求失败返回 fail: res => { console.log('request fail', url, res, params.data ? params.data : '') // 关闭加载效果 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富文本专用) * @param {Object} value 富文本 */ imgReplace(value) { return value.replace(//ig, '

') .replace(/ 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) { uni.getImageInfo({ src: item.path, success: imageInfo => { const result = res.data.url; obj.success && obj.success({ value: result, width: imageInfo.width, height: imageInfo.height, }); }, }) 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 {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() : '' }, }); }, /** * 最终登录 用于请求登录接口后统一调用的登录方法 * @param {Object} param 数据对象 * @param {Function} cb 回调函数 */ finalLogin(param, cb) { // 登录令牌 const token = param.data // 缓存token uni.setStorageSync('token', token) // 开启加载 uni.showLoading({ mask: true }) setTimeout(() => { // 获取用户信息 util.getUserinfo((userinfo) => { // 登录 uni.$emit('login') setTimeout(() => { util.loginTencent(userinfo) uni.reLaunch({ url: '/pages/index/index' }) }, 500) // cb ? cb() : '' }) }, 500) }, // 登录腾讯聊天 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 => { util.updateMyProfile(userinfo) console.log('im login success', rs) }) }) }, // 更新im个人资料 updateMyProfile(userinfo) { // 验证sdk是否准备完毕 let isReady = uni.$chat.isReady(); if (!isReady) { setTimeout(function() { util.updateMyProfile(userinfo); }, 800); return } let obj = { nick: userinfo.userNickname, avatar: userinfo.avatar } uni.$chat.updateMyProfile(obj).then(res => { // console.log(res); }) }, /** * 获取用户信息 * @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) util.getTeenMode(userinfo.teenTime) // 提交 store.commit('setState', { key: 'userinfo', value: userinfo }) // 用户信息 uni.setStorageSync('userinfo', userinfo) cb ? cb(userinfo) : '' } }).finally(() => { // 关闭加载 uni.hideLoading() }) }) }, // 青少年模式 getTeenMode(teenTime) { // 当前时间 const currentDate = new Date() // 当前小时 const currentHour = currentDate.getHours() // 大于八点 小于22点 当前时间小于设定时间 const result = currentHour >= 6 && currentHour < 22 && currentDate.valueOf() < new Date(teenTime).valueOf() // 锁定 function lock() { console.log('lock') uni.reLaunch({ url: '/pages/login/lock' }) } // 结果 if (result) { console.log('time', new Date(teenTime).valueOf() - currentDate.valueOf()) // 设置定时器 setTimeout(() => { lock() }, parseInt(new Date(teenTime).valueOf() - currentDate.valueOf())) } else lock() }, /** * 验证登录 * @param {Object} cb 回调函数 */ isLogin(cb) { // 验证 let userinfo = uni.$store.state.userinfo return new Promise((resolve, reject) => { // 登录 if (userinfo.id) { // 成功 resolve() // 回调 cb ? cb() : '' } else reject() }) }, /** * 清除登录状态 * @param {Function} cb 回调函数 */ logout(cb) { // 用户信息 const userinfo = store.state.userinfo // 用户id if (userinfo.id) { 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 if (userinfo.isRealName) { 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, num: option.num, }) }) }, // 扫码 scan() { uni.scanCode({ success: (res) => { if (res && res.result) { let result = JSON.parse(res.result) if (result.type == 'ADDFRIEND') { uni.navigateTo({ url: `/pages/news/addFriend?account=${result.account}` }); return } 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, }, }) }) }, } export default util