123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687 |
- /**
- * 判断是否有值
- */
- const hasVal = v => {
- return typeof v !== 'undefined' && v !== null
- }
- /**
- * 判断是否是字符串
- */
- const isStr = v => {
- return typeof v === 'string'
- }
- /**
- * 判断是否是函数
- */
- const isFn = v => {
- return typeof v === 'function'
- }
- /**
- * 判断是否是数组
- */
- const isArr = v => {
- return Array.isArray ? Array.isArray(v) : Object.prototype.toString.call([]) === '[object Array]'
- }
- /**
- * 判断是否是对象
- */
- const isObj = v => {
- return v !== null && typeof v === 'object'
- }
- /**
- * 判断是否是空对象
- */
- const isEmptyObj = v => {
- if (v !== null && typeof v === 'object') {
- for (const i in v)
- return false
- return true
- }
- return true
- }
- /**
- * 对个位数前补零
- */
- const formatNumber = n => {
- n = n.toString()
- return n[1] ? n : '0' + n
- }
- /**
- * 日期时间格式化
- * 2018-01-01 23:59:59
- */
- const formatDateTime = (date, { dateStr = '-', medianStr = ' ', timeStr = ':' } = {}) => {
- const year = date.getFullYear()
- const month = date.getMonth() + 1
- const day = date.getDate()
- const hour = date.getHours()
- const minute = date.getMinutes()
- const second = date.getSeconds()
- return [year, month, day].map(formatNumber).join(dateStr) + medianStr + [hour, minute, second].map(formatNumber).join(timeStr)
- }
- /**
- * 日期格式化
- * 2018-01-01
- */
- const formatDate = (date, dateStr = '-') => {
- const year = date.getFullYear()
- const month = date.getMonth() + 1
- const day = date.getDate()
- return [year, month, day].map(formatNumber).join(dateStr)
- }
- /**
- * 时间格式化
- * 23:59:59
- */
- const formatTime = (date, timeStr = ':') => {
- const hour = date.getHours()
- const minute = date.getMinutes()
- const second = date.getSeconds()
- return [hour, minute, second].map(formatNumber).join(timeStr)
- }
- /**
- * 路径格式化
- */
- const formatUrl = (url, obj) => {
- const arr = []
- if (isObj(obj)) {
- for (let i in obj) {
- arr.push(`${i}=${obj[i]}`)
- }
- return url.indexOf('?') < 0 ? url + '?' + arr.join('&') : url + '&' + arr.join('&')
- }
- return url
- }
- /**
- * 判断当前月份的总天数
- */
- const thisMonthLenth = ({ year, month }) => {
- let len = 0
- if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
- len = 31
- } else if (month == 4 || month == 6 || month == 9 || month == 11) {
- len = 30
- } else if (month == 2) {
- if (((year % 4) == 0) && ((year % 100) != 0) || ((year % 400) == 0)) {
- len = 29
- } else {
- len = 28
- }
- }
- return len
- }
- /**
- * 节流
- * fn是我们需要包装的事件回调, interval是时间间隔的阈值
- */
- const throttle = (fn, interval = 800) => {
- // last为上一次触发回调的时间
- let last = 0
- // 将throttle处理结果当作函数返回
- return function () {
- // 保留调用时的this上下文
- let context = this
- // 保留调用时传入的参数
- let args = arguments
- // 记录本次触发回调的时间
- let now = +new Date()
- // 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
- if (now - last >= interval) {
- // 如果时间间隔大于我们设定的时间间隔阈值,则执行回调
- last = now;
- fn.apply(context, args);
- }
- }
- }
- /**
- * 防抖
- * fn是我们需要包装的事件回调, delay是每次推迟执行的等待时间
- */
- const debounce = (fn, delay = 800) => {
- // 定时器
- let timer = null
- // 将debounce处理结果当作函数返回
- return function () {
- // 保留调用时的this上下文
- let context = this
- // 保留调用时传入的参数
- let args = arguments
- // 每次事件被触发时,都去清除之前的旧定时器
- if (timer) {
- clearTimeout(timer)
- }
- // 设立新定时器
- timer = setTimeout(function () {
- fn.apply(context, args)
- }, delay)
- }
- }
- /**
- * 加强版节流
- * fn是我们需要包装的事件回调, delay是时间间隔的阈值
- */
- const throttleDebounce = (fn, delay = 800) => {
- // last为上一次触发回调的时间, timer是定时器
- let last = 0, timer = null
- // 将throttle处理结果当作函数返回
- return function () {
- // 保留调用时的this上下文
- let context = this
- // 保留调用时传入的参数
- let args = arguments
- // 记录本次触发回调的时间
- let now = +new Date()
- // 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
- if (now - last < delay) {
- // 如果时间间隔小于我们设定的时间间隔阈值,则为本次触发操作设立一个新的定时器
- clearTimeout(timer)
- timer = setTimeout(function () {
- last = now
- fn.apply(context, args)
- }, delay)
- } else {
- // 如果时间间隔超出了我们设定的时间间隔阈值,那就不等了,无论如何要反馈给用户一次响应
- last = now
- fn.apply(context, args)
- }
- }
- }
- /**
- * 微信授权接口封装
- */
- const wxSetting = ({ scope, text }) => {
- return new Promise((resolve, reject) => {
- wx.getSetting({
- success: res => {
- if (isEmptyObj(res.authSetting)) {
- resolve(Object.assign(res, { type: 1, text: `请手动点击${text}` }))
- } else if (res.authSetting[scope] === true) {
- resolve(Object.assign(res, { type: 2, text: `默认${text}成功` }))
- } else if (res.authSetting[scope] === false) {
- wx.showModal({
- content: `检测到您没打开${text},是否去设置打开?`,
- confirmText: "确认",
- cancelText: "取消",
- success: res => {
- if (res.confirm) {
- wx.openSetting({
- success: res => {
- if (res.authSetting[scope]) {
- resolve(Object.assign(res, { type: 3, text: `手动设置${text}成功` }))
- } else {
- reject(Object.assign(res, { type: 5, text: `没有手动设置${text}` }))
- }
- },
- fail: res => {
- reject(Object.assign(res, { type: 4, text: `打开手动设置${text}失败` }))
- }
- })
- } else {
- reject(Object.assign(res, { type: 3, text: `拒绝打开手动设置${text}` }))
- }
- },
- fail: res => {
- reject(Object.assign(res, { type: 2, text: `弹出${text}提示框失败` }))
- }
- })
- } else {
- wx.authorize({
- scope,
- success: res => {
- resolve(Object.assign(res, { type: 4, text: `自动获取${text}成功` }))
- },
- fail: res => {
- reject(Object.assign(res, { type: 6, text: `自动获取${text}失败` }))
- }
- })
- }
- },
- fail: res => {
- reject(res, { type: 1, text: `获取${text}失败` })
- }
- })
- })
- }
- /**
- * 获取微信用户信息授权
- */
- const getWxUserInfoSetting = cb => {
- wxSetting({ scope: 'scope.userInfo', text: '微信用户信息授权' }).then((res) => {
- wx.setStorageSync('hasUserInfo', 1)
- if (isFn(cb)) cb(1, res)
- }).catch((res) => {
- wx.setStorageSync('hasUserInfo', 0)
- if (res.type != 6) {
- wx.showToast({
- title: res.text,
- icon: 'none'
- })
- }
- setTimeout(() => {
- wx.navigateBack({
- delta: 1
- })
- }, 1200)
- if (isFn(cb)) cb(0, res)
- })
- }
- /**
- * 获取微信定位授权
- */
- const getWxLocationSetting = cb => {
- wxSetting({ scope: 'scope.userLocation', text: '微信定位授权' }).then((res) => {
- wx.setStorageSync('hasPosition', 1)
- if (isFn(cb)) cb(1, res)
- }).catch((res) => {
- wx.setStorageSync('hasPosition', 0)
- wx.showToast({
- title: res.text,
- icon: 'none'
- })
- setTimeout(() => {
- wx.navigateBack({
- delta: 1
- })
- }, 1200)
- if (isFn(cb)) cb(0, res)
- })
- }
- /**
- * 获取微信相机授权
- */
- const getWxCameraSetting = cb => {
- wxSetting({ scope: 'scope.camera', text: '微信相机授权' }).then((res) => {
- wx.setStorageSync('hasCamera', 1)
- if (isFn(cb)) cb(1, res)
- }).catch((res) => {
- wx.setStorageSync('hasCamera', 0)
- wx.showToast({
- title: res.text,
- icon: 'none'
- })
- setTimeout(() => {
- wx.navigateBack({
- delta: 1
- })
- }, 1200)
- if (isFn(cb)) cb(0, res)
- })
- }
- /**
- * 获取系统信息
- */
- const systemInfo = wx.getSystemInfoSync()
- /**
- * 路由跳转
- */
- const routers = () => {
- const fn = (method) => {
- return (e) => {
- const { paras = null, url = null, msg = '暂未开放', delta = 1 } = e && e.currentTarget && e.currentTarget.dataset ? e.currentTarget.dataset : e && !e.currentTarget ? e : {}
- switch (method) {
- case 'navigateBack':
- wx.navigateBack({ delta })
- break
- default:
- if (!url) {
- wx.showToast({
- title: msg,
- icon: 'none'
- })
- return
- }
- wx[method]({
- url: `/${formatUrl(url, method === 'switchTab' ? null : paras)}`,
- success: res => { },
- fail: res => {
- wx.showToast({
- title: '跳转失败',
- icon: 'none'
- })
- }
- })
- }
- }
- }
- const arr = ['reLaunch', 'navigateTo', 'redirectTo', 'switchTab', 'navigateBack']
- const obj = {}
- for (const v of arr) {
- obj[v] = throttleDebounce(fn(v))
- }
- return obj
- }
- /**
- * 查看图片
- */
- const viewImage = throttleDebounce((e, type) => {
- const { images, index, baseurl, url = 'imgUrl' } = type ? e : e.currentTarget.dataset
- const arr = []
- if (isObj(images)) {
- for (const v of images) {
- arr.push(`${baseurl}${v[url] ? v[url] : v}`)
- }
- }
- wx.previewImage({
- current: arr[index],
- urls: arr
- })
- })
- /**
- * 分享控制层
- */
- const sharePage = ({ title = '私塾家', path = 'pages/index/index', imageUrl = null, msg = '转发成功' } = {}) => {
- return {
- title,
- path,
- imageUrl,
- success: res => {
- wx.showToast({
- title: msg,
- icon: 'success'
- })
- }
- }
- }
- /**
- * 获取全局值
- */
- const getGlobalVal = (e1, e2 = e1) => hasVal(getApp().globalData[e1]) ? getApp().globalData[e1] : hasVal(wx.getStorageSync(e2)) ? wx.getStorageSync(e2) : null
- /**
- * 统一调用微信支付
- */
- const wxPayment = ({ timeStamp = '', nonceStr = '', packageValue = '', signType = '', paySign = '' }) => {
- return new Promise((resolve, reject) => {
- wx.requestPayment({
- timeStamp,
- nonceStr,
- package: packageValue,
- signType,
- paySign,
- success: res => {
- if (res.errMsg == 'requestPayment:ok') {
- wx.showToast({
- title: '支付成功',
- icon: 'success'
- })
- resolve(res)
- } else {
- wx.showToast({
- title: '支付失败',
- icon: 'none'
- })
- reject(res)
- }
- },
- fail: res => {
- wx.showToast({
- title: '支付取消',
- icon: 'none'
- })
- reject(res)
- }
- })
- })
- }
- /**
- * 获取最新版本
- */
- const getUpdateManager = () => {
- const updateManager = wx.getUpdateManager()
- updateManager.onCheckForUpdate(res => {
- const { hasUpdate } = res
- if (hasUpdate) {
- wx.showToast({
- title: '已发现新版本哦',
- icon: 'none'
- })
- }
- })
- updateManager.onUpdateReady(() => {
- wx.showModal({
- title: '更新提示',
- content: '新版本已经准备好,是否重启应用?',
- success(res) {
- if (res.confirm) {
- updateManager.applyUpdate()
- }
- }
- })
- })
- updateManager.onUpdateFailed(() => {
- wx.showToast({
- title: '新版本下载失败',
- icon: 'none'
- })
- })
- }
- /**
- * fetch 网络请求封装
- * @param url{String} url【请求后台路径,默认必穿项,否则报错】
- * @param paras{Object} paras【请求后台路径拼接的参数,默认为空】
- * @param method{String} method【网络请求方法,默认POST】
- * @param data{Object} data【自定义传的参数数据,默认必传项,可为空对象】
- * @param continuousFn{Object} continuousFn: { fn: Function, param: Object } 续弦函数:当接口报登录失效401的时候 记录失效的当前状态,等待自动登录成功后接着运行
- */
- const fetch = ({ url = null, paras = {}, method = 'POST', data = {}, continuousFn = null }) => {
- const { host, loginTime, wechatsys, phoneimei, phonesys, phonetype, version, platform, build, errorText = '出了点小问题' } = getApp().globalData
- const accessToken = getGlobalVal('accessToken') || ''
- const header = { wechatsys, phoneimei, phonesys, phonetype, version, platform, build, "Content-Type": "application/json" }
- const showToast = (text) => {
- wx.showToast({
- title: text || errorText,
- icon: 'none'
- })
- }
- url = formatUrl(host + url, Object.assign({}, paras, { accessToken }))
-
- return new Promise((resolve, reject) => {
- wx.request({
- url,
- data,
- method,
- header,
- success: e => {
- const { statusCode, data } = e
- const { code, msg } = data
- switch (~~statusCode) {
- case 200:
- switch (~~code) {
- case 999:
- resolve(data)
- break
- default:
- if (url.indexOf('/user/checkToken') < 0) {
- showToast(msg)
- }
- reject(e)
- }
- if (loginTime > 0) {
- getApp().globalData.loginTime = 0
- }
- break
- case 401:
- getApp().globalData.loginTime = loginTime + 1
- if (loginTime < 2) {
- getApp().globalData.continuousFn = continuousFn
- getApp().login()
- } else {
- showToast('登录失效,稍后再试')
- reject(e)
- }
- break
- default:
- showToast()
- reject(e)
- }
- },
- fail: e => {
- showToast()
- reject(e)
- },
- complete: e => {
- getApp().globalData.isPending = true
- console.log({ url, request: data, response: e.data, globalData: getApp().globalData })
- }
- })
- })
- }
- /**
- * uploadFile 上传文件封装
- * @param url{String} url【请求后台路径,默认必穿项,否则报错】
- * @param paras{Object} paras【请求后台路径拼接的参数,默认为空】
- * @param file{String} file【微信小程序生成的临时文件资源路径】
- * @param data{Object} data【自定义传的参数数据,默认必传项,可为空对象】
- * @param continuousFn{Object} continuousFn: { fn: Function, param: Object } 续弦函数:当接口报登录失效401的时候 记录失效的当前状态,等待自动登录成功后接着运行
- */
- const uploadFile = ({ url = null, paras = {}, file = null, data = {}, continuousFn = null }) => {
- const { host, loginTime, wechatsys, phoneimei, phonesys, phonetype, version, platform, build, errorText = '出了点小问题' } = getApp().globalData
- const accessToken = getGlobalVal('accessToken') || ''
- const header = { wechatsys, phoneimei, phonesys, phonetype, version, platform, build, "Content-Type": "application/json" }
- const showToast = (text) => {
- wx.showToast({
- title: text || errorText,
- icon: 'none'
- })
- }
- url = formatUrl(host + url, Object.assign({}, paras, { accessToken }))
- return new Promise((resolve, reject) => {
- const files = isArr(file) ? file : [file]
- const len = files.length
- const arr = []
- let i = 0
- const Fn = (f) => {
- const uploadTask = wx.uploadFile({
- url,
- filePath: f,
- name: 'files',
- formData: data,
- header,
- success: e => {
- const { statusCode } = e
- const { code, msg, data } = JSON.parse(e.data)
- switch (~~statusCode) {
- case 200:
- switch (~~code) {
- case 999:
- arr.push(data.pics[0].filePath)
- if (i < len - 1) {
- ++i
- Fn(files[i])
- } else {
- resolve(arr)
- }
- break
- default:
- showToast(msg)
- reject(e)
- }
- if (loginTime > 0) {
- getApp().globalData.loginTime = 0
- }
- break
- case 401:
- getApp().globalData.loginTime = loginTime + 1
- if (loginTime < 2) {
- getApp().globalData.continuousFn = continuousFn
- getApp().login()
- } else {
- showToast('登录失效,稍后再试')
- reject(e)
- }
- break
- default:
- showToast()
- reject(e)
- }
- },
- fail: e => {
- showToast()
- reject(e)
- },
- complete: e => {
- getApp().globalData.isPending = true
- uploadTask.abort()
- wx.hideLoading()
- console.log({ url, request: data, response: e.data, globalData: getApp().globalData })
- }
- })
- uploadTask.onProgressUpdate((res) => {
- progress && progress(res)
- const { progress } = res
- const progressNumber = ~~(progress / len + 100 / len * i)
- wx.showLoading({
- title: `已上传(${progressNumber}%)`
- })
- if (progressNumber == 100) {
- wx.hideLoading()
- }
- })
- }
- Fn(files[i])
- })
- }
- export {
- hasVal,
- isStr,
- isFn,
- isArr,
- isObj,
- isEmptyObj,
- formatNumber,
- formatDateTime,
- formatDate,
- formatTime,
- formatUrl,
- thisMonthLenth,
- throttle,
- debounce,
- throttleDebounce,
- wxSetting,
- getWxUserInfoSetting,
- getWxLocationSetting,
- getWxCameraSetting,
- systemInfo,
- routers,
- viewImage,
- sharePage,
- getGlobalVal,
- wxPayment,
- getUpdateManager,
- fetch,
- uploadFile,
- }
|