// 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('请先登录')
							reject(res.data) // 链式回调0

							// uni.reLaunch({
							// 	url: '/login/login',
							// })
						})
					}
					// 嵌套式回调
					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富文本专用)
	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;
								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.reLaunch({
					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) 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) {
				// util.alert('请先登录')
				// 失败
				reject()
			} else {
				// 成功
				resolve()
				// 回调
				cb ? cb() : ''
			}
		})
	},

	/**
	 * 清除登录状态
	 * @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.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