/*
=================================================================================
* License: GPL-2.0 license
* Author: 众产®  https://ciy.cn/code
* Version: 0.1.16
=================================================================================
app函数库
 * alert			(await)默认alert
 * toast			(await)默认提示
 * getpage			获取当前/上页页面
 * setuserstorage	保存用户信息、字典缓存、积分埋点
 * appupdate		APP自动更新
 * connectbt		连接蓝牙
 * CiyWebSocket		websocket客户端类
 
 app&page函数库
 * getme			获取本地me缓存
 * callfunc			(await)服务端ajax请求
 * lang				多语言
 * uperr			错误捕获处理
 * json_parse		字符串转json
 * json_string		json转字符串
 * getstorage		读取storage
 * setstorage		写入storage
 * clearstorage		清空所有storage
 * removestorage	删除storage

page函数库
 * gourl			页面跳转。支持 http[web]、![原型]、*[alert提示]、$[需登录常规url]、常规url
 * goweb			带授权的打开H5页面
 * goloc			按经纬度打开地图
 * gophone			拨打电话
 * goani			持续生成动画
 * copyboard		拷贝文本
 
 * isfloat0			校验float是否0
 * isarray			判断变量是否array
 * isobject			判断变量是否object
 * islocalmedia		判断文件名是否本地文件
 * isimg			是否图片
 * isvideo			是否视频
 * file_ext			获取文件扩展名
 * file_stor		ud url转绝对url
 * hasstr			字符串是否包含另一个字符串
 * ccode			以id查询字典中的值
 * scode			以ids查询字典中的多个name
 * mcode			以id查询字典中的多级name
 * bcode			以int查询字典中的多个name
 * enbase64			base64编码
 * svg2bg			将svg转成backgroundImage语法
 
 * topad0			数字前面补0
 * tonumtho			整数部分千分位显示
 * tonumdec			小数部分
 * tostr			转字符串
 * toint			转整数
 * tofloat			转小数
 * tostamp			转时间戳
 * todatetime		时间戳转日期时间
 * tofix			处理小数显示
 * tounit			显示多级单位
 * tocyc			显示周期 月/天/分钟
 * tomsk			显示文字遮罩
 * totimespan		将时间转成 xx天后/xx小时前
 * totimesec		将秒数转成 xx天/xx小时
 * totimepoint		将数字转成 xx:xx[:xx]
 * todayage			返回日龄天数
 * tobr				将\n替换成<br/>，将<>替换成可显示
 
 * pagenoscroll		页面滚动控制
 * settheme			设置暗黑模式
 * setfont			设置敬老模式
 * executepnt		触发积分埋点
 * setTabbar		设置Tabbar

 * getauth			(await)获取用户信息，未登录调起登录界面，填充me/g
 * scanqr			(await)扫二维码
 * popmenu			(await)弹出上拉菜单
 * toast			(await)提示
 * alert			(await)alert弹出框
 * askmsg			(await)询问弹出框
 * inputmsg			(await)输入弹出框
 * sleep			(await)延迟毫秒
 * load_ciydict		(await)获取远程静态dict
 * load_svgicon		(await)获取远程静态svgicon
 
 * shareparam		分享链接转换
 * getstrparam		解析简易参数
 * urlparam			解析url
 * arrayfind		从数组中匹配值。返回index
 * objdeepmerge		object合并，自动避开静态字典，自动处理带id数组
 * objtolist		将object并入list数组
 * objclone			深度复制obj
 * str2date			字符串转Date
 * bin2hex			bin转hex字符串
 * hex2bin			hex字符串转bin
 
 * style2obj		将style属性转成object
 * nopower			权限检查
 * getroute			获取route
 * com_getpage		组件中获取页面句柄
 * com_gethdft		(await)组件中获取页面标题栏/导航栏高度
 * getrefs			(await)稳定获取ref
 * getrefsSync		确保已加载com的同步函数
 * getrect			(await)获取元素尺寸
 * file_upload1		(await)上传单个文件返回url
 * file_uploads		(await)上传多个文件
 * go/goe			(await)golang式异步错误处理
 
 page生命周期函数
 * onLoad			页面初始化。存储upid，构建post
 * onShow			页面显示调用。设置暗黑主题/敬老字体
 * onPageScroll		页面滚动事件。scrollcbs传递函数引用

page默认数据
 * init				初始交互数据
 * srv				默认微服务指向
 * opn				页面urlget参数
 * me				用户状态
 * g				用户及字典数据引用
 * pagedata			页面间数据传递 替代vuex\Pinia
 * jsnurl			指向动态服务器(多个)。默认t
 * header_*			页面边角尺寸
 * footer_*			页面边角尺寸

*/
export default {
	install(ap, app) {
		ap.config.globalProperties._proptest = () => {}; //代码受限
		ap.directive('swipe', { //微信小程序暂时无法使用，app/h5支持
			mounted: function(el, binding) {
				console.log('wx?', el, binding);
			}
		});
		app.methods.launch = function() {
			var app = this;
			// #ifdef MP-WEIXIN
			var sys_system = wx.getSystemSetting();
			var sys_window = wx.getWindowInfo();
			var sys_appinfo = wx.getAppBaseInfo();
			var sys_appauth = wx.getAppAuthorizeSetting();
			var sys_device = wx.getDeviceInfo();
			console.log('sys_system', sys_system);
			console.log('sys_window', sys_window);
			console.log('sys_appinfo', sys_appinfo);
			console.log('sys_appauth', sys_appauth);
			console.log('sys_device', sys_device);
			var sys = {
				...sys_system,
				...sys_window,
				...sys_appinfo,
				...sys_appauth,
				...sys_device
			};
			if (!sys.screenHeight) {
				sys = uni.getSystemInfoSync();
				console.log('getSystemInfoSync', sys);
			}
			// #endif
			// #ifndef MP-WEIXIN
			var sys = uni.getSystemInfoSync();
			// #endif
			app.globalData._sysinfo = sys;
			app.globalData.ciy_page_data = {};
			app.globalData._header_statusbar_height = sys.statusBarHeight;
			if (sys.safeAreaInsets)
				app.globalData._footer_safe_height = sys.safeAreaInsets.bottom;
			else if (sys.safeArea)
				app.globalData._footer_safe_height = sys.screenHeight - sys.safeArea.bottom;
			else
				app.globalData._footer_safe_height = 0;
			app.globalData._header_title_height = 40;
			app.globalData._header_title_margin = 0;
			// #ifdef MP-WEIXIN
			var menubtn = wx.getMenuButtonBoundingClientRect();
			console.log('menubtn', menubtn);
			app.globalData._menubtn = menubtn;
			app.globalData._header_title_margin = sys.screenWidth - menubtn.left;
			app.globalData._header_title_height = (menubtn.top - sys.statusBarHeight) * 2 + menubtn.height;

			try {
				app.globalData.plugin_wechatsi = requirePlugin("WechatSI");
				app.globalData.plugin_wechatsi_manager = app.globalData.plugin_wechatsi.getRecordRecognitionManager();
			} catch (e) {
				console.log('err', e);
			}
			// #endif
		};
		app.methods.lang = function(str) {
			var app = this;
			if (typeof(app.$t) == 'function')
				return app.$t(str);
			return str;
		};
		app.methods.alert = async function(content) {
			return new Promise((resolve, reject) => {
				var opt = {
					content: content,
					showCancel: false
				};
				opt.success = res => {
					resolve(true);
				};
				uni.showModal(opt);
			}).catch(e => {
				return e;
			});
		};
		app.methods.toast = async function(content, icon) {
			return new Promise((resolve, reject) => {
				if (typeof(icon) === 'function') {
					cb = icon;
					icon = 'none';
				}
				if (!icon)
					icon = 'none';
				uni.showToast({
					title: content,
					icon: icon
				});
				setTimeout(function() {
					resolve();
				}, 2000);
			}).catch(e => {
				return e;
			});
		};
		app.methods.getpage = function(idx) { //idx 0当前页，1上一页
			var ps = getCurrentPages();
			var p = null;
			idx = idx || 0;
			if (idx == 1) {
				if (ps.length == 1)
					return null;
				p = ps[ps.length - 2];
			} else {
				p = ps[ps.length - 1];
			}
			// #ifdef MP-WEIXIN
			p = p.$vm;
			// #endif
			return p;
		};
		app.methods.getme = function() {
			var me = this.getstorage("me");
			if (!me)
				return {
					id: 0
				};
			return me;
		};
		app.methods.uperr = function(type, msg) {
			console.warn('uperr', type, msg);
			var errdata = {};
			errdata.type = type;
			errdata.t = parseInt(new Date().getTime() / 1000);
			errdata.msg = '';
			if (typeof(msg) == 'object')
				errdata.msg = this.json_string(msg);
			else
				errdata.msg = msg + '';
			this.globalData.errdata.push(errdata);
			this.setstorage('err', this.globalData.errdata);
		};
		app.methods.json_parse = function(data) {
			try {
				if (data.length > 0 && data[0] != '[' && data[0] != '{') {
					var ind = data.indexOf('{');
					if (ind == -1)
						return null;
					if (ind > 0)
						data = data.substring(ind);
				}
				return JSON.parse(data);
			} catch (e) {
				console.error('json_parse', e);
			}
			return null;
		};
		app.methods.json_string = function(data) {
			try {
				return JSON.stringify(data);
			} catch (e) {
				console.error('json_string', e);
			}
			return '';
		};
		app.methods.callfunc = async function(opt) {
			//成功{code:1,...}
			//失败{errmsg:'错误信息'}
			//func				
			//data = null		无post数据，GET方法
			//catch=0			不缓存，>0缓存
			//loadhide=true		默认false，取消加载中显示  loadtxt
			var app = this;
			return new Promise((resolve, reject) => {
				opt = opt || {};
				if (opt.func.substring(0, 4) == 'http')
					url = opt.func;
				else {
					opt.srv = opt.srv || app.globalData.srv;
					var url = app.globalData.jsnurl[opt.srv];
					if (!url)
						return reject({
							errmsg: 'srv无法匹配:' + opt.srv
						});
					if (opt.func.indexOf('?') > -1)
						url += opt.func;
					else
						url += app.globalData.jsnajax + opt.func;
				}
				opt.cache = opt.cache || 0; // 0不缓存 >0 对比时间，是否请求
				if (opt.cache > 0) {
					if (!opt.cachekey) {
						opt.cachekey = 'f_' + opt.func;
						for (var i in opt.data) {
							if (i == 'once' || i == '_pf')
								continue;
							if (typeof(opt.data[i]) === 'object')
								continue;
							opt.cachekey += '_' + i.substring(0, 1) + opt.data[i];
						}
					}
					if (opt.cache > 1) {
						var dat = app.getstorage(opt.cachekey);
						var t = new Date().getTime() - (typeof(dat) == 'object' ? dat.t : 0);
						if (t < opt.cache * 1000) {
							if (opt.pagethis && opt.pagethis._stopPullDown) {
								opt.pagethis._stopPullDown = false;
								uni.stopPullDownRefresh();
							}
							return resolve(dat.d);
						}
					}
				}
				if (!opt.loadhide) {
					opt._showload = setTimeout(function() {
						opt._showloaded = true;
						uni.showToast({
							title: opt.loadtxt || '加载中',
							icon: 'loading',
							duration: 3000,
							mask: true
						});
					}, 500);
				}
				var header = {};
				opt.data = opt.data || {};
				if (app.globalData._wxappid)
					opt.data._appid = app.globalData._wxappid;
				if (opt.pagethis)
					opt.data = Object.assign({}, opt.pagethis.opn, opt.data);

				const makeRequest = () => {
					header['ciyauth'] = app.getstorage("_" + app.globalData.tokenfield);
					opt.data._pf = 'MB' + new Date().getTime() + '_' + parseInt(80000000 + Math.random() * 10000000);
					uni.request({
						url: url,
						data: opt.data,
						withCredentials: true,
						dataType: 'text',
						method: opt.data ? 'POST' : 'GET',
						header: header,
						fail: res => {
							var errmsg = res.errMsg || 'nofind errMsg.';
							if (errmsg.indexOf('fail abort') > 0)
								errmsg = '网络信号不好';
							else if (errmsg.indexOf('equest:fail timeout') > 0)
								errmsg = '网络访问超时';
							else if (errmsg.indexOf('equest:fail') > 0)
								errmsg = '网络不可用';
							return reject({
								errmsg: errmsg
							});
						},
						complete: res => {
							if (opt._showload) {
								clearTimeout(opt._showload);
								if (opt._showloaded)
									uni.hideToast();
							}
							if (opt.pagethis && opt.pagethis._stopPullDown) {
								opt.pagethis._stopPullDown = false;
								uni.stopPullDownRefresh();
							}
						},
						success: res => {
							var json = app.json_parse(res.data);
							if (json === null) {
								res._url = url;
								res._post = opt.data;
								app.uperr("h5.noajaxjson", res);
								return reject({
									errmsg: '返回JSON错误:' + res.statusCode
								});
							}
							var dictversion = res.header[app.globalData.tokenfield + 're'];
							if (dictversion) {
								console.log('restorage new', dictversion);
								app.globalData._restorage = true; //通知app.vue自动刷新
							}
							var newauth = '';
							for (var i in res.header) {
								if (i.toLowerCase() == '_ciyauth')
									newauth = res.header[i];
							}
							if (!newauth)
								newauth = json['_ciyauth'];
							if (newauth) {
								console.log('newauth new', newauth);
								app.setstorage('_' + app.globalData.tokenfield, newauth);
							}
							if (json.code != 1) {
								if (json.code == 2) {
									app.removestorage('me');
									var pg = app.getpage();
									if (!pg.isPage)
										return reject({
											errmsg: ''
										});
									pg.getauth().then(res => {
										if (res.me.id > 0)
											makeRequest();
										else
											uni.navigateBack();
									});
									return;
								} else {
									return reject(json);
								}
							}
							try {
								//delete json.code;
								if (opt.cache > 0) {
									app.setstorage(opt.cachekey, {
										d: json,
										t: new Date().getTime()
									});
								}
								return resolve(json);
							} catch (e) {
								res._url = url;
								res._post = opt.data;
								res._cache = e;
								app.uperr("h5.ajaxrun", res);
								return reject({
									errmsg: '请求错误:' + e.message
								});
							}
						}
					});
				}
				makeRequest();
			}).catch(e => {
				if (e.error != 'NULL') {
					//app.toast(e.errmsg);
				}
				return e;
			});
		};
		app.methods.setuserstorage = function(json) {
			var app = this;
			app.setstorage("me", json.me);
			var pnttrack = app.getstorage('_pnttrack', {});
			if (!(pnttrack instanceof Object))
				pnttrack = {};
			var day = new Date();
			day.setHours(0, 0, 0, 0);
			day = parseInt(day.getTime() / 1000);
			for (var pt in json.pnttrack) {
				let track = json.pnttrack[pt];
				let cnt = 0;
				if (pnttrack[track.id])
					cnt = pnttrack[track.id].pnt;
				pnttrack[track.id] = {
					name: track.name,
					p: track.point,
					h24: track.limh24,
					day: day,
					cnt: cnt
				}
			}
			app.setstorage("_pnttrack", pnttrack);

			var sav = app.getstorage('g', {});
			var arr = json.storage;
			for (var code in arr) {
				if (code == 'cata') {
					for (var c in arr[code]) {
						if (arr[code][c].cbid > 0)
							continue;
						var types = arr[code][c].codeid;
						var codes = new Array();
						for (var d in arr[code]) {
							if (arr[code][d].cbid != arr[code][c].id)
								continue;
							var cs = {};
							cs.id = arr[code][d].codeid;
							cs.name = arr[code][d].name;
							if (arr[code][d].extdata)
								cs.extdata = arr[code][d].extdata;
							if (arr[code][d].clas)
								cs.clas = arr[code][d].clas;
							if (arr[code][d].isuse != 1)
								cs.isuse = arr[code][d].isuse;
							if (arr[code][d].upid > 0) {
								for (var i in arr[code]) {
									if (arr[code][d].upid == arr[code][i].id) {
										cs.upid = arr[code][i].codeid;
										break;
									}
								}
							}
							codes.push(cs);
						}
						if (types)
							sav[types] = codes;
					}
				} else {
					sav[code] = arr[code];
				}
			}
			app.setstorage('g', sav);
			return {
				me: json.me
			}
		};
		app.methods.appupdate = async function(plat, cb) {
			var app = this;
			// #ifdef APP-PLUS
			plus.runtime.getProperty(plus.runtime.appid, async widgetInfo => {
				app.callfunc({
					func: 'login.getappver',
					showload: false,
					data: {
						vercode: widgetInfo.versionCode
					},
					success: async json => {
						if (!json.url)
							return app.toast('已经是最新版本');
						if (json.must && typeof(cb) == 'function') {
							if (!await cb(json.verinfo))
								return;
						}
						app.toast('更新中...');
						uni.downloadFile({
							url: json.url,
							success: res => {
								if (res.statusCode !== 200)
									return app.alert('更新文件下载失败' + json.url);
								plus.runtime.install(res.tempFilePath, {
									force: true
								}, function() {
									app.toast('更新成功，即将热重启', () => {
										plus.runtime.restart();
									});
								}, function(e) {
									console.log(e);
									app.alert('更新失败:' + e.message);
								});
							}
						});
					}
				});
			});
			// #endif
			// #ifdef MP-WEIXIN
			if (plat != 'app') {
				const updateManager = uni.getUpdateManager();
				updateManager.onCheckForUpdate(res => {
					console.log('onCheckForUpdate', res);
					if (!res.hasUpdate)
						return app.toast('已经是最新版本');
					app.toast('新版本更新中...');
					updateManager.onUpdateReady(async res => {
						console.log('onUpdateReady', res);
						if (typeof(cb) == 'function') {
							if (await cb('新版本已经准备好，是否重启应用？'))
								updateManager.applyUpdate();
						}
					});
					updateManager.onUpdateFailed(res => {
						console.log('onUpdateFailed', res);
						app.alert('更新失败，请重新启动微信再试');
					});
				});
			}
			// #endif
		};
		app.methods.connectbt = function(devup, devtype, deviceid) {
			var app = this;
			if (app.globalData.dev_bt[devup]) {
				app.globalData.dev_bt[devup].bt_devclose();
			} else {
				app.globalData.dev_bt[devup] = new cbt.CBTBase(devup, devtype);
			}
			var btdev = app.globalData.dev_bt[devup];
			btdev.oncreated = services => {
				btdev.setwrt(services);
			}
			// btdev.onfail = res => {
			// }
			// btdev.onsuccess = res => {
			// }
			btdev.bt_devopen(deviceid);
		};
		app.methods.getstorage = function(key, def) {
			def = def || '';
			var x = uni.getStorageSync(key);
			if (x == '')
				return def;
			var json = this.json_parse(x);
			if (json !== null)
				return json;
			return x;
		};
		app.methods.setstorage = function(key, val) {
			if (val === undefined)
				return this.removestorage(key);
			var x = val;
			if (typeof(val) == 'object')
				x = JSON.stringify(val);
			return uni.setStorageSync(key, x);
		};
		app.methods.clearstorage = function() {
			return uni.clearStorageSync();
		};
		app.methods.removestorage = function(key) {
			var keylen = key.length - 1;
			if (key.substring(keylen) != '*')
				return uni.removeStorageSync(key);
			key = key.substring(0, keylen);
			var keys = uni.getStorageInfoSync();
			for (var i in keys.keys) {
				if (keys.keys[i].substring(0, keylen) == key)
					uni.removeStorageSync(keys.keys[i]);
			}
		};

		ap.mixin({
			data() {
				return {
					header_statusbar_height: 0, //顶部状态栏(时间电池、躲过刘海/镂空位置)
					header_title_height: 40, //顶部标题栏高度(正好容纳胶囊)
					header_title_margin: 0, //顶部标题栏左右留白(正好躲过胶囊，且可使文字居中)
					footer_safe_height: 0, //底部安全高度(躲过刘海屏、底部横线等)
					pageclass: 'dark',
					editdata: {},
					pagedata: {}, //外部g.page_init
					isPage: false,
					jsnurl: {},
					pageno: 0,
					init: {},
					srv: 't',
					meta: {
						theme: 'light',
						bgcolor: '#ffffff',
						styles: {
							'min-height': '100vh',
							'background-color': '#ffffff',
							'color': '#000000'
						},
						style: 'min-height:100vh;background-color:#ffffff;color:#000000;',
						fontsize: '16px',
						pulldown: true,
					},
					opn: {}, //页面传参
					me: {},
					//g: {}, //本地与dydict整合，onshow更新本地，同时合并dydict。
				};
			},
			created() {}, //全局混入的 created 钩子被调用
			mounted() {},
			onLoad(opn) {
				this.isPage = true;
				if (opn.scene) {
					var scene = decodeURIComponent(opn.scene);
					console.log(scene);
					var obj = this.getstrparam(scene);
					for (var i in obj)
						opn[i] = obj[i];
				}
				this.opn = opn;
				var upid = this.toint(this.opn.upid);
				if (upid > 0)
					this.setstorage('upid', upid);
				this.pagepost = { //page快捷检索post值
					query: {}
				};
				this.header_statusbar_height = app.globalData._header_statusbar_height;
				this.header_title_height = app.globalData._header_title_height;
				this.header_title_margin = app.globalData._header_title_margin;
				this.footer_safe_height = app.globalData._footer_safe_height;
				this.pagedata = app.globalData.ciy_page_data;
				this.jsnurl = app.globalData.jsnurl;
				//this.constant = {maxtimes: 9999999999999};
				this.me = this.getme();
				// if (app.globalData.ciy_page_g)
				// 	this.g = app.globalData.ciy_page_g;
				// else
				// 	this.g = this.getstorage('g', {});
				uni.hideTabBar({
					fail: res => {}
				});
			},
			computed: {
				g() {
					if (app.globalData.ciy_page_g)
						return app.globalData.ciy_page_g;
					else
						return this.getstorage('g', {});
				}
			},
			onShow() {
				this.settheme();
				this.setfont();
				this.me = this.getme();
				// var ref = this.getrefsSync('tabbar');
				// if (ref)
				// 	ref.loadtabbardata();
			},
			onPageScroll(e) {
				var app = getApp();
				if (Object.keys(app.globalData.scrollcbs).length == 0)
					return;
				for (var i in app.globalData.scrollcbs) {
					app.globalData.scrollcbs[i](e);
				}
			},
			methods: {
				showe(e) {
					console.log('showe', e);
					return '';
				},
				callfunc(opt) {
					opt.pagethis = this;
					return getApp().callfunc(opt);
				},
				calltxt(opt) {
					return new Promise((resolve, reject) => {
						opt = opt || {};
						uni.request({
							url: opt.url,
							data: opt.data,
							dataType: 'text',
							method: opt.data ? 'POST' : 'GET',
							header: opt.header,
							fail: res => {
								var errmsg = res.errMsg || 'nofind errMsg.';
								if (errmsg.indexOf('fail abort') > 0)
									errmsg = '网络信号不好';
								else if (errmsg.indexOf('equest:fail timeout') > 0)
									errmsg = '网络访问超时';
								else if (errmsg.indexOf('equest:fail') > 0)
									errmsg = '网络不可用';
								return reject({
									errmsg: errmsg
								});
							},
							success: res => {
								if (res.statusCode == 200)
									return resolve(res.data);
								return reject({
									errmsg: res.data
								});
							}
						});
					});
				},
				getme() {
					return getApp().getme();
				},
				uperr(type, msg) {
					return getApp().uperr(type, msg);
				},
				json_parse(data) {
					return getApp().json_parse(data);
				},
				json_string(data) {
					try {
						return JSON.stringify(data);
					} catch (e) {
						console.log('json_string', e);
					}
					return '';
				},
				getstorage(key, def) {
					var app = getApp();
					return app.getstorage(key, def);
				},
				setstorage(key, val) {
					var app = getApp();
					return app.setstorage(key, val);
				},
				clearstorage() {
					return uni.clearStorageSync();
				},
				removestorage(key) {
					var app = getApp();
					return app.removestorage(key);
				},
				lang(str) {
					if (typeof(this.$t) == 'function')
						return this.$t(str);
					return str;
				},

				async gourl(b, type, initdata, initkey) { //url支持 http[web]、![原型]、*[alert提示]、$[需登录常规url]、常规url
					var url = '';
					if (typeof(b) != 'string') {
						url = b.currentTarget.dataset.url;
						if (!initdata) {
							initdata = b.currentTarget.dataset.data;
						}
						if (!initkey) {
							initkey = b.currentTarget.dataset.key;
						}
					} else {
						url = b;
					}
					if (!initdata)
						initdata = {};
					if (!initkey)
						initkey = 'base';
					if (!url)
						return console.warn('gourl传参错误:' + url);
					var app = getApp();
					if (url.substring(0, 4) == 'http') {
						this.goweb(url, name);
					} else if (url.substring(0, 1) == '!') {
						var dmos = url.substring(1).split('|');
						if (dmos.length < 2)
							dmos[1] = '';
						uni.navigateTo({
							url: '/pages/pub/web?web=' + encodeURIComponent(app.globalData.demourl + '?menuid=' + dmos[0] + '&title=no&tag=' + dmos[1]) + (dmos[2] ? '&name=' + dmos[2] : ''),
							animationType: 'pop-in',
							animationDuration: 1000
						});
					} else if (url.substring(0, 1) == '*') {
						this.alert(url.substring(1));
					} else {
						if (url.substring(0, 1) == '$') {
							url = url.substring(1);
							var auth = await this.getauth();
							if (auth.me.id == 0)
								return;
						}
						if (url.substring(0, 1) == '%') {
							url = url.substring(1);
							var auth = await this.getauth('info');
							if (auth.me.id == 0)
								return;
						}
						if (url.substring(0, 1) == '^') {
							url = url.substring(1);
							var auth = await this.getauth('real');
							if (auth.me.id == 0)
								return;
						}
						if (url.substring(0, 1) == '&') {
							url = url.substring(1);
							var auth = await this.getauth('bank');
							if (auth.me.id == 0)
								return;
						}
						if (url.substring(0, 1) == '*') {
							url = url.substring(1);
							var auth = await this.getauth('cciy');
							if (auth.me.id == 0)
								return;
						}
						app.globalData.ciy_page_data[initkey] = {
							...initdata
						};
						if (this.isPage)
							app.globalData.ciy_page_g = this.g;
						if (type == 'redirect') {
							uni.redirectTo({
								url: url,
								animationType: 'pop-in',
								animationDuration: 1000,
								fail: res => {
									uni.switchTab({
										url: url,
										fail: res => {
											return this.toast(name + ' 未定义链接:' + url);
										}
									});
								}
							});
						} else {
							uni.navigateTo({
								url: url,
								animationType: 'pop-in',
								animationDuration: 1000,
								fail: res => {
									uni.switchTab({
										url: url,
										fail: res => {
											return this.toast(name + ' 未定义链接:' + url);
										}
									});
								}
							});
						}
					}
				},
				goweb(url, name) {
					var app = getApp();
					url += (url.indexOf('?') == -1) ? '?' : '&';
					url += '_ciyauth=' + app.getstorage('_' + app.globalData.tokenfield);
					uni.navigateTo({
						url: '/pages/pub/web?web=' + encodeURIComponent(url) + (name ? '&name=' + name : ''),
						animationType: 'pop-in',
						animationDuration: 1000
					});
				},
				goloc(lat, lng, bet) {
					bet = bet || 10000000;
					uni.openLocation({
						latitude: this.tofloat(lat) / bet,
						longitude: this.tofloat(lng) / bet
					});
				},
				gophone(phone) {
					if (!phone)
						return;
					uni.makePhoneCall({
						phoneNumber: phone
					});
				},
				async goani(opn, cb, othcb) {
					return new Promise(async (resolve, reject) => {
						var aniinit = {
							timingFunction: 'ease',
							transformOrigin: '50% 50% 0',
							delay: 0
						};
						if (typeof(opn) == 'string')
							opn = {
								anis: opn
							};
						opn.init = opn.init || aniinit;
						if (typeof(opn.anis) == 'string') {
							var anist = opn.anis.split('|');
							var aniarr = [];
							for (var i in anist) {
								if (anist[i] == 'hide') {
									aniarr.push({
										hide: true
									});
									continue;
								}
								var stp = anist[i].split(',');
								var dur = 0;
								for (var s in stp) {
									var pre = stp[s].substring(0, 2);
									var val = stp[s].substring(2);
									if (pre == 'ra')
										aniarr.push({
											rotate: parseFloat(val)
										});
									else if (pre == 'rx')
										aniarr.push({
											rotateX: parseFloat(val)
										});
									else if (pre == 'ry')
										aniarr.push({
											rotateY: parseFloat(val)
										});
									else if (pre == 'rz')
										aniarr.push({
											rotateZ: parseFloat(val)
										});
									else if (pre == 'sa')
										aniarr.push({
											scale: parseFloat(val)
										});
									else if (pre == 'sx')
										aniarr.push({
											scaleX: parseFloat(val)
										});
									else if (pre == 'sy')
										aniarr.push({
											scaleY: parseFloat(val)
										});
									else if (pre == 'sz')
										aniarr.push({
											scaleZ: parseFloat(val)
										});
									else if (pre == 'ta')
										aniarr.push({
											translate: val
										});
									else if (pre == 'tx')
										aniarr.push({
											translateX: val
										});
									else if (pre == 'ty')
										aniarr.push({
											translateY: val
										});
									else if (pre == 'tz')
										aniarr.push({
											translateZ: val
										});
									else if (pre == 'wa')
										aniarr.push({
											skew: parseFloat(val)
										});
									else if (pre == 'wx')
										aniarr.push({
											skewX: parseFloat(val)
										});
									else if (pre == 'wy')
										aniarr.push({
											skewY: parseFloat(val)
										});
									else if (pre == 'op')
										aniarr.push({
											opacity: parseFloat(val)
										});
									else if (pre == 'bc')
										aniarr.push({
											backgroundColor: val
										});
									else if (pre == 'ww')
										aniarr.push({
											width: val
										});
									else if (pre == 'hh')
										aniarr.push({
											height: val
										});
									else if (pre == 'tt')
										aniarr.push({
											top: val
										});
									else if (pre == 'll')
										aniarr.push({
											left: val
										});
									else if (pre == 'bb')
										aniarr.push({
											bottom: val
										});
									else if (pre == 'rr')
										aniarr.push({
											right: val
										});
									else
										dur = this.toint(stp[s]);
								}
								aniarr.push({
									step: {
										duration: dur
									}
								});
							}
							opn.anis = aniarr;
						}
						var animation = uni.createAnimation(opn.init);
						for (var aa in opn.anis) {
							var key = Object.keys(opn.anis[aa])[0];
							var val = opn.anis[aa][key];
							if (key == 'step') {
								val.duration = this.toint(val.duration);
								if (val.duration < 16)
									val.duration = 100;
								animation.step(val);
								cb(animation.export());
								await this.sleep(val.duration);
								animation = uni.createAnimation(opn.init);
							} else if (key == 'hide') {
								if (typeof(othcb) == 'function')
									othcb(key, val);
							} else if (animation[key]) {
								if (typeof(val) == 'object')
									animation[key](...val);
								else
									animation[key](val);
							}
						}
						resolve();
					}).catch(e => {
						return e;
					});
				},
				copyboard(b, bsilent) {
					if (this.isobject(b))
						b = b.currentTarget.dataset.text;
					if (!b)
						return;
					uni.setClipboardData({
						data: b
					});
					if (!bsilent)
						app.toast('已复制到剪贴板');
				},

				isfloat0(num) {
					num = parseFloat(num);
					if (isNaN(num))
						return true;
					return (num < 0.001 && num > -0.001);
				},
				isarray(value) {
					return Object.prototype.toString.call(value).toLowerCase().indexOf('object array') > -1;
				},
				isobject(value) {
					return Object.prototype.toString.call(value).toLowerCase().indexOf('object object') > -1;
				},
				islocalmedia(file) {
					if (!file)
						return false;
					if (file.substring(0, 9) == 'wxfile://')
						return true;
					return false;
				},
				isimg(file) {
					var ext = this.file_ext(file);
					return (["PNG", "JPG", "GIF", "BMP", "WEBP", "SVG"].indexOf(ext) >= 0);
				},
				isvideo(file) {
					var ext = this.file_ext(file);
					return (["MP3", "MP4"].indexOf(ext) >= 0);
				},
				file_ext(file) {
					if (typeof(file) != 'string') {
						if (file.name)
							file = file.name;
						if (file.tempFilePath)
							file = file.tempFilePath;
					}
					var d = file.lastIndexOf('.');
					if (d >= 0) {
						var ext = file.substring(d + 1).toUpperCase();
						if (ext == 'JPEG' || ext == 'JPE')
							return 'JPG';
						return ext;
					}
					return '';
				},
				file_stor(url, pre) {
					if (!url)
						return '';
					if (this.islocalmedia(url))
						return url;
					if (url.substring(0, 4).toLowerCase() == 'http')
						return url;
					var app = getApp();
					var cdnurl = app.globalData.storlist[url.substring(0, 1)];
					if (this.isobject(cdnurl)) {
						var fast = false;
						if (url.indexOf('banner') > -1)
							fast = true;
						if (pre)
							fast = true;
						if (fast)
							cdnurl = cdnurl.fast;
						else
							cdnurl = cdnurl.all;
					}
					return cdnurl + url.substring(1) + (pre ? pre : '');
				},
				hasstr(str, find) {
					if (!str)
						return false;
					return str.indexOf(find) > -1;
				},
				ccode(arr, value, field, nonestr) {
					field = field || 'name';
					nonestr = nonestr || '--';
					if (typeof(arr) != 'object') {
						arr = this.g[arr] || this.init[arr];
						if (typeof(arr) != 'object')
							return '!';
					}
					for (var i = 0; i < arr.length; i++) {
						if (arr[i].id == value) {
							if (field == 'idx')
								return i;
							if (field == '_obj')
								return arr[i];
							if (arr[i][field])
								return arr[i][field];
							return nonestr;
						}
					}
					if (field == '_obj')
						return null;
					if (value < 1)
						return nonestr;
					return ''; //[' + value + ']';
				},
				scode(arr, ids, field) {
					if (typeof(arr) != 'object')
						return ['!'];
					ids = ids || '';
					var vals = ids.split(',');
					var names = [];
					for (var v = 0; v < vals.length; v++) {
						for (var i = 0; i < arr.length; i++) {
							if (arr[i].id != vals[v])
								continue;
							if (field)
								names.push(arr[i][field]);
							else
								names.push(arr[i]);
						}
					}
					return names;
				},
				mcode(arr, value, field) {
					if (typeof(arr) != 'object')
						return [];
					var ret = [];
					for (var x = 0; x < 100; x++) {
						var bfind = false;
						for (var i = 0; i < arr.length; i++) {
							if (arr[i].id == value) {
								bfind = true;
								value = arr[i].upid;
								if (field)
									ret.unshift(arr[i][field]);
								else
									ret.unshift(arr[i]);
								break;
							}
						}
						if (!bfind)
							break;
					}
					return ret;
				},
				bcode(arr, value, field) {
					if (typeof(arr) != 'object')
						return ['!'];
					var names = [];
					for (var i = 0; i < arr.length; i++) {
						if ((value & (1 << i))) {
							if (field)
								names.push(arr[i][field]);
							else
								names.push(arr[i]);
						}
					}
					return names;
				},
				enbase64(str) {
					var c1, c2, c3;
					var base64EncodeChars =
						"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
					var i = 0,
						len = str.length,
						string = '';
					while (i < len) {
						c1 = str.charCodeAt(i++) & 255;
						if (i == len) {
							string += base64EncodeChars.charAt(c1 >> 2);
							string += base64EncodeChars.charAt((c1 & 3) << 4);
							string += "==";
							break;
						}
						c2 = str.charCodeAt(i++);
						if (i == len) {
							string += base64EncodeChars.charAt(c1 >> 2);
							string += base64EncodeChars.charAt(((c1 & 3) << 4) | ((c2 & 240) >> 4));
							string += base64EncodeChars.charAt((c2 & 15) << 2);
							string += "=";
							break;
						}
						c3 = str.charCodeAt(i++);
						string += base64EncodeChars.charAt(c1 >> 2);
						string += base64EncodeChars.charAt(((c1 & 3) << 4) | ((c2 & 240) >> 4));
						string += base64EncodeChars.charAt(((c2 & 15) << 2) | ((c3 & 192) >> 6));
						string += base64EncodeChars.charAt(c3 & 63)
					}
					return string;
				},
				svg2bg(svg) {
					if (!svg)
						return '';
					if (svg.substring(0, 4) == 'url(')
						return svg;
					return "url('data:image/svg+xml;charset=utf-8;base64," + this.enbase64(svg) + "')";
				},

				topad0(num, length) {
					if ((num + "").length > length)
						return num;
					return (Array(length).join('0') + num).slice(-length);
				},
				tonumtho(num) {
					return this.toint(num).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
				},
				tonumdec(num, showzero, len) {
					len = len || 2; // 与tofix不同点，小数长度不变，如 1.10
					var m2 = Math.round((num - parseInt(num)) * Math.pow(10, len));
					if (m2 == 0) {
						if (showzero)
							return '.' + '0'.repeat(len);
						else
							return '';
					}
					m2 = m2 + '';
					if (m2.length < len)
						m2 = '0'.repeat(len - m2.length) + m2;
					return '.' + m2;
				},
				tocciy(cciy) {
					if (!cciy || cciy == '0') //cciy必须为字符串，否则js无法处理
						return '';
					return 'cx' + cciy.substring(0, 1) + '...' + cciy.substring(cciy.length - 6);
				},
				tostr(obj) {
					if (!obj)
						return '';
					if (typeof(obj) == 'object')
						return JSON.stringify(obj).replace(/"/g, '“');
					return obj + '';
				},
				toint(val, defval) {
					defval = defval || 0;
					var ret = parseInt(val);
					if (isNaN(ret))
						return defval;
					else if (ret == undefined)
						return defval;
					else
						return ret;
				},
				tofloat(val, defval) {
					defval = defval || 0;
					var ret = parseFloat(val);
					if (isNaN(ret))
						return defval;
					else
						return ret;
				},
				tostamp(dt) {
					if (dt === undefined)
						dt = new Date();
					var t = dt.getTime();
					if (isNaN(t))
						return 0;
					return parseInt(t / 1000);
				},
				todatetime(time, format, nostr) {
					nostr = nostr || '--';
					if (time == 0)
						return nostr;
					var t;
					if (time instanceof Date) {
						if (time.getTime() == 0)
							return nostr;
						t = time;
					} else if (time == -1)
						t = new Date();
					else
						t = new Date(time * 1000);
					var year = t.getFullYear();
					var month = t.getMonth() + 1;
					var month0 = month < 10 ? '0' + month : month;
					var day = t.getDate();
					var day0 = day < 10 ? '0' + day : day;
					var hour = t.getHours();
					var hour0 = hour < 10 ? '0' + hour : hour;
					var minute = t.getMinutes();
					var minute0 = minute < 10 ? '0' + minute : minute;
					var second = t.getSeconds();
					var second0 = second < 10 ? '0' + second : second;
					if (format == 'id')
						return day0 + hour0 + minute;
					if (format == 'H')
						return year + "-" + month0 + "-" + day0 + " " + hour0;
					if (format == 'd')
						return year + "-" + month0 + "-" + day0;
					if (format == 'D')
						return year + "年" + month + "月" + day + '日';
					if (format == 'x')
						return month0 + "-" + day0;
					if (format == 'm')
						return year + "-" + month0;
					if (format == 'n')
						return year + "-" + month;
					if (format == 'y')
						return year;
					if (format == 'M')
						return year + "年" + month + '月';
					if (format == 'i')
						return hour0 + ":" + minute0;
					if (format == 's')
						return year + "-" + month0 + "-" + day0 + " " + hour0 + ":" + minute0 + ":" +
							second0;
					if (format == 'st')
						return month0 + "-" + day0 + " " + hour0 + ":" + minute0;
					return year + "-" + month0 + "-" + day0 + " " + hour0 + ":" + minute0;
				},
				tofix(num, length) {
					//length，正数，小数点保留n位，不去0。
					//负数，小数点保留n位，全0则不显示。
					//0，按数长保留，尽量少的位数显示。
					//不填，-4
					num = parseFloat(num);
					if (isNaN(num))
						num = 0;
					if (length === undefined)
						length = -4;
					if (length == 0) {
						if (num >= 1000)
							return parseInt(num);
						var numlen = (parseInt(num) + '').length;
						length = 4 - numlen;
						if (Math.abs(num % 1) < Math.pow(0.1, length))
							return parseInt(num);
						num = num.toFixed(length);
						var y = '.';
						for (var i = 0; i < length; i++)
							y += "0";
						if (num.substring(num.length - length - 1) == y)
							num = num.substring(0, num.length - length - 1);
						return num;
					} else if (length < 0) {
						num = num.toFixed(-length); //xx.xx
						var inde = num.split('.');
						if (inde[1] && /^0+$/.test(inde[1]))
							return inde[0];
						return num.replace(/\.?0+$/, '');
					}
					num = num.toFixed(length);
					return num;
				},
				tounit(ori) {
					var us = ori.split('|');
					if (us.length == 5)
						return '1' + us[4] + us[3] + us[2] + '　1' + us[2] + us[1] + us[0];
					else if (us.length == 3)
						return '1' + us[2] + us[1] + us[0];
					return us[0];
				},
				tocyc(ori) {
					if (ori == 0)
						return '--';
					if (ori < 0)
						return -ori + this.lang('月');
					if (ori >= 86400)
						return parseInt(ori / 86400) + this.lang('天');
					return parseInt(ori / 60) + this.lang('分钟');
				},
				tomsk(ori, pstr) {
					if (!ori)
						return '';
					var retstr = '';
					ori = ori + '';
					if (ori.length > pstr.length) {
						retstr = ori.substring(0, ori.length - pstr.length);
						ori = ori.substring(ori.length - pstr.length);
					}
					for (var i = 0; i < Math.min(ori.length, pstr.length); i++) {
						if (pstr.charAt(i) == '*')
							retstr += '*';
						else
							retstr += ori.charAt(i);
					}
					return retstr;
				},
				totimespan(time, bestr, zero, before) {
					bestr = bestr || '';
					zero = zero || this.lang('time.now');
					if (time == 0 || time === undefined)
						return '--';
					var t = new Date(time * 1000);
					var diff = (new Date() - t) / 1000;
					if (before)
						diff = -diff;
					if (diff < 10) //10秒以内
						return zero;
					return this.totimesec(diff, bestr);
				},
				totimesec(diff, bestr) {
					bestr = bestr || '';
					if (diff < 60) //60秒以内
						return parseInt(diff) + this.lang("秒") + bestr;
					if (diff < 3600) //60分以内
						return parseInt(diff / 60) + this.lang("分钟") + bestr;
					if (diff < 86400) //24小时以内
						return parseInt(diff / 3600) + this.lang("小时") + bestr;
					if (diff < 2592000) //30天以内
						return parseInt(diff / 86400) + this.lang("天") + bestr;
					if (diff < 31536000) //12月以内
						return parseInt(diff / 2592000) + this.lang("个月") + bestr;
					return parseInt(diff / 31536000) + this.lang("年") + bestr;
				},
				totimepoint(time, bsecond) {
					if (time <= 0 || time > 86400)
						return '';
					time--;
					var hour = this.toint(time / 3600);
					var minute = this.toint((time - hour * 3600) / 60);
					var ret = this.topad0(hour, 2) + ':' + this.topad0(minute, 2);
					if (!bsecond)
						return ret;
					var second = time - hour * 3600 - minute * 60;
					ret += ':' + this.topad0(second, 2);
					return ret;
				},
				todayage(time, noday) {
					if (time == 0 || time === undefined)
						return '--';
					var t = new Date(time * 1000);
					var diff = (new Date() - t) / 1000;
					diff = parseInt(diff / 86400) + 1;
					if (diff < 30) //30天以内
						return diff + "天";
					var month = parseInt(diff / 30);
					if (noday)
						return month + '个月';
					return month + '个月 ' + (diff - month * 30) + '天';
				},
				tobr(txt, autohtml) {
					if (!txt)
						return '';
					if (!autohtml) {
						txt = txt.replace(/</g, '&lt;');
						txt = txt.replace(/>/g, '&gt;');
						//txt = txt.replace(/\|/g, '<br/>');
					}
					txt = txt.replace(/\n/g, '<br/>');
					return txt;
				},

				pagenoscroll(b) {
					// #ifdef MP-WEIXIN
					if (b) {
						wx.setPageStyle({
							style: {
								overflow: 'hidden'
							}
						});
					} else {
						wx.setPageStyle({
							style: {
								overflow: 'auto'
							}
						});
						//uni.setPageMeta()
					}
					// #endif

					// #ifdef H5
					if (b) {
						document.body.style.overflow = 'hidden';
					} else {
						document.body.style.overflow = 'auto';
					}
					// #endif
				},
				settheme(theme) {
					if (theme) {
						this.setstorage('_theme', theme);
					} else {
						theme = this.getstorage('_theme');
						if (!theme) {
							if (app.globalData._sysinfo.theme == 'dark')
								theme = 'dark';
						}
					}
					var bgcolor = '#f7f8f8';
					var txtcolor = '#576067'; //txt5
					if (theme == 'dark') {
						bgcolor = '#151a1b';
						txtcolor = '#c2cad0';
					} else {
						theme = 'light';
					}
					this.meta.theme = theme;
					this.meta.bgcolor = bgcolor;
					this.meta.styles['background-color'] = bgcolor;
					this.meta.styles['color'] = txtcolor;
					this.meta.style = Object.keys(this.meta.styles).map(key => key + ':' + this.meta.styles[
						key]).join(';') + ';';
					this.pageclass = theme;
					// // #ifdef MP-WEIXIN
					// wx.setBackgroundTextStyle({
					// 	textStyle: theme
					// })
					// // #endif
				},
				setfont(font) {
					// 空，lg  xl   xxl   xxl
					var app = getApp();
					if (!font) {
						font = this.getstorage('_font');
						if (!font) {
							font = 'def';
							var fsize = app.globalData._sysinfo.fontSizeSetting * app.globalData._sysinfo.fontSizeScaleFactor;
							if (fsize >= 20 && fsize < 30)
								font = 'lg';
							if (fsize >= 30 && fsize < 40)
								font = 'xl';
							else if (fsize >= 40)
								font = 'xxl';
							//标准:16*1=16   1:18*1.1=19.8   2:18*1.12=20.16  3:18*1.125=20.25  4:22*1.4=30.8  5:25*1.55=38.75  max:26*1.65=42.9
						}
					} else {
						this.setstorage('_font', font);
					}
					var fontsize;
					if (font == 'def')
						fontsize = 30;
					else if (font == 'lg')
						fontsize = 40;
					else if (font == 'xl')
						fontsize = 50;
					else if (font == 'xxl')
						fontsize = 60;
					else
						fontsize = this.toint(font);
					if (fontsize < 20)
						fontsize = 30;
					var fz = (fontsize / 750 * app.globalData._sysinfo.windowWidth) + 'px';
					this.meta.styles['font-size'] = fz;
					this.meta.style = Object.keys(this.meta.styles).map(key => key + ':' + this.meta.styles[key]).join(';') + ';';
					this.meta.fontsize = fz;
				},
				executepnt(pntid, post) {
					var me = this.getme();
					if (me.id == 0)
						return;
					var pnttrack = this.getstorage('_pnttrack', {});
					if (!this.isobject(pnttrack[pntid]))
						return;
					var day = this.str2date(this.todatetime(-1, 'd')).getTime() / 1000;
					var cnt = 0;
					if (day == pnttrack[pntid].day) {
						cnt = this.toint(pnttrack[pntid].cnt);
						if (pnttrack[pntid].h24 > 0 && pnttrack[pntid].h24 <= cnt)
							return;
					}
					cnt += this.toint(pnttrack[pntid].p);
					pnttrack[pntid].day = day;
					pnttrack[pntid].cnt = cnt;
					if (!post)
						post = {};
					post.id = pntid;
					this.setstorage('_pnttrack', pnttrack);
					this.callfunc({
						func: 'main.pnt_up',
						loadhide: true,
						data: post
					}).then(res => {
						if (res.code != 1)
							return;
						if (res.msg)
							this.toast(res.msg);
					});
				},
				setTabbar(nameobj) {
					var app = this;
					if (nameobj instanceof Array) {
						app.globalData.tabbarArr = nameobj;
						return;
					}
					if (nameobj instanceof Object) {
						for (var i in app.globalData.tabbarArr) {
							if (!nameobj[app.globalData.tabbarArr[i].name])
								continue;
							var obj = nameobj[app.globalData.tabbarArr[i].name];
							for (var o in obj) {
								app.globalData.tabbarArr[i][o] = obj[o];
							}
						}
					}
					app.getpage().getrefs('tabbar').then(ref => {
						ref.loadtabbardata();
					});
				},

				async getauth(type) {
					return new Promise((resolve, reject) => {
						this.$nextTick(() => {
							this.getrefs('auth').then(ref => {
								ref.Open(auth => {
									if (auth.me.id == 0)
										return resolve(auth);
									this.me = auth.me;
									//this.g = this.objdeepmerge(this.g, this.getstorage('g', {}));
									if (type == 'info' && !this.me.name) {
										this.askmsg('请先填写个人信息').then(res => {
											if (res == 'cancel')
												return;
											uni.redirectTo({
												url: '/pages/me/user_info'
											});
										});
										return;
									}
									if (type == 'real' && !this.me.truename) {
										this.askmsg('请进行实名认证').then(res => {
											if (res == 'cancel')
												return;
											uni.redirectTo({
												url: '/pages/me/safe_real'
											});
										});
										return;
									}
									if (type == 'bank' && !this.me.bankname) {
										this.alert('请填写银行信息').then(res => {
											if (res == 'cancel')
												return;
											uni.redirectTo({
												url: '/pages/me/user_bank'
											});
										});
										return;
									}
									if (type == 'cciy' && this.me.cciy.length < 10) {
										this.alert('请先申请众识码').then(res => {
											if (res == 'cancel')
												return;
											uni.redirectTo({
												url: '/pages/me/safe_ccub'
											});
										});
										return;
									}
									resolve(auth);
								}, type == 'relogin');
							});
						});
					}).catch(e => {
						console.error('getauth error', e);
						return e;
					});
				},
				async scanqr() {
					return new Promise((resolve, reject) => {
						var ret = {};
						if (process.env.NODE_ENV === 'development') {
							this.inputmsg('输入二维码').then(itm => {
								if (!itm.text)
									return;
								ret.type = 'input';
								ret.code = itm.text;
								resolve(ret);
							});
							return;
						}
						var res = uni.scanCode().then(res => {
							ret.type = res.scanType;
							ret.code = res.result;
							if (!ret.code)
								ret.code = res.code;
							resolve(ret);
						}).catch(res => {
							console.log('scanCode err', res);
							resolve({
								type: 'error'
							});
						});
					}).catch(e => {
						return e;
					});
				},
				async popmenu(opn) { //items one rowcount title
					return new Promise((resolve, reject) => {
						this.getrefs('popmenu').then(ref => {
							ref.Open(opn).then(item => {
								if (typeof(opn.closecb) == 'function')
									opn.closecb();
								if (item.url) {
									if (item.data)
										this.gourl(item.url, item.type, {
											...item.data
										}, item.key);
									else
										this.gourl(item.url, item.type);
									return;
								}
								if (item.func && typeof(this[item.func]) == 'function') {
									this[item.func](item);
									return;
								}
								resolve(item);
							});
						});
					}).catch(e => {
						return e;
					});
				},
				async toast(opn) {
					var ref = await this.getrefs('toast');
					if (!ref)
						return this.alert('no find toast');
					return await ref.Open(opn);
				},
				async alert(opn, btns) {
					if (!opn)
						return;
					if (typeof(opn) == 'string') {
						opn = {
							content: opn
						};
					}
					if (btns) {
						opn.btns = btns;
					}
					var ref = await this.getrefs('alert');
					if (!ref)
						return this.alert('no find alert');
					return await ref.Open(opn);
				},
				async askmsg(content, btns) {
					var opn = {
						content
					};
					if (!btns)
						btns = [{
							name: '确定',
							btn: 'ok'
						}, {
							name: '取消',
							btn: 'cancel',
							cls: 'def'
						}];
					else if (typeof(btns) == 'string')
						btns = [{
							name: btns,
							btn: 'ok'
						}, {
							name: '取消',
							btn: 'cancel',
							cls: 'def'
						}];
					opn.btns = btns;
					var ref = await this.getrefs('alert');
					if (!ref)
						return this.alert('no find alert');
					return await ref.Open(opn);
				},
				async inputmsg(opn, btns) {
					if (typeof(opn) == 'string')
						opn = {
							content: opn
						};
					opn = opn || {};
					if (opn.title === undefined)
						opn.title = '操作项';
					opn.ele = opn.ele || 'input';
					if (!btns)
						opn.btns = [{
							name: '确定',
							btn: 'ok'
						}, {
							name: '取消',
							btn: 'cancel',
							cls: 'def'
						}];
					else if (typeof(btns) == 'string')
						opn.btns = [{
							name: btns,
							btn: 'ok'
						}, {
							name: '取消',
							btn: 'cancel',
							cls: 'def'
						}];
					else
						opn.btns = btns;
					var ref = await this.getrefs('alert');
					if (!ref)
						return this.alert('no find alert');
					var ret = await ref.Open(opn);
					if (typeof(ret) == 'string')
						return {
							btn: 'cancel'
						};
					return ret;
				},
				async sleep(ms) {
					return new Promise(resolve => setTimeout(resolve, ms));
				},
				async load_ciydict(url) {
					if (url.indexOf('.local.') === -1)
						url = url.replace('http://', 'https://');
					return new Promise((resolve, reject) => {
						uni.request({
							url: url,
							dataType: 'text',
							method: 'GET',
							fail: res => {
								res._url = url;
								this.uperr("h5.loadjs.fail", res);
								return reject({
									errmsg: 'dict' + res.errMsg
								});
							},
							success: res => {
								var ind = res.data.indexOf('[');
								if (ind == -1)
									return reject({
										errmsg: 'dict数据缺少数组'
									});
								if (res.data.substring(0, 8) != 'var ciy_')
									return reject({
										errmsg: 'dict数据格式错误'
									});
								var name = res.data.substring(8, ind - 1);
								var json = this.json_parse(res.data.substring(ind));
								if (json === null) {
									this.uperr("app.loadjs.json", res);
									return reject({
										errmsg: 'dict数组解析错误'
									});
								}
								return resolve({
									code: 1,
									name: name,
									arr: json
								});
							}
						});
					}).catch(e => {
						return e; //不返回，res为 undefined
					});
				},
				async load_svgicon(url) {
					if (url.indexOf('.local.') === -1)
						url = url.replace('http://', 'https://');
					return new Promise((resolve, reject) => {
						uni.request({
							url: url,
							dataType: 'text',
							method: 'GET',
							fail: res => {
								res._url = url;
								this.uperr("h5.loadsvgicon.fail", res);
								return reject({
									errmsg: 'dict' + res.errMsg
								});
							},
							success: res => {
								var ind = res.data.indexOf(':');
								if (ind == -1)
									return reject({
										errmsg: 'svgicon数据缺少合规图标'
									});
								var lines = res.data.split('\n');
								var svgs = {};
								for (var i in lines) {
									var idx = lines[i].indexOf(':');
									if (idx == -1)
										continue;
									svgs[lines[i].substring(0, idx)] = lines[i].substring(idx + 1);
								}
								return resolve(svgs);
							}
						});
					}).catch(e => {
						return e; //不返回，res为 undefined
					});
				},
				shareparam(opn) {
					var app = getApp();
					var param = {};
					param.title = opn.title;
					if (opn.img)
						param.imageUrl = opn.img;
					if (opn.promise)
						param.promise = opn.promise;
					var urlp = '';
					for (var u in opn.query) {
						urlp += '&' + u + '=' + opn.query[u];
					}
					var me = this.getme();
					if (opn.type == 'message') {
						if (opn.path == app.globalData.sharefirstpage)
							param.path = opn.path + '?upid=' + me.id + urlp;
						else {
							if (app.globalData.sharefirstpage) {
								if (urlp[0] == '&')
									urlp = '?' + urlp.substring(1);
								param.path = app.globalData.sharefirstpage + '?upid=' + me.id + '&u=' + encodeURIComponent(opn.path + urlp);
							} else {
								param.path = opn.path + '?upid=' + me.id + urlp;
							}
						}
					} else {
						param.query = 'upid=' + me.id + urlp;
					}
					console.log('shareparam', param, opn);
					return param;
				},
				getstrparam(str, split) {
					split = split || '|';
					var strs = str.split(split);
					var ret = {};
					for (var i in strs) {
						var ind = strs[i].indexOf('=');
						if (ind == -1)
							continue;
						ret[strs[i].substr(0, ind)] = strs[i].substr(ind + 1);
					}
					return ret;
				},
				setstrparam(obj, split) {
					split = split || '&';
					var strs = [];
					for (var key in obj)
						strs.push(key + '=' + obj[key]);
					return strs.join(split);
				},
				urlparam(url) {
					var obj = {};
					var ind = url.indexOf('?');
					if (ind === -1)
						return obj;
					var pairs = url.substring(ind + 1).split('&');
					for (var p in pairs) {
						var ind = pairs[p].indexOf('=');
						if (ind > -1)
							obj[decodeURIComponent(pairs[p].substring(0, ind))] = decodeURIComponent(pairs[p].substring(ind + 1));
						else
							obj[pairs[p]] = true;
					}
					return obj;
				},
				arrayfind(arr, val, field) {
					for (var i in arr) {
						if (arr[i][field] == val)
							return i;
					}
					return -1;
				},
				objdeepmerge(src, desc, btop) {
					for (const key in desc) {
						if (!desc.hasOwnProperty(key))
							continue;
						if (desc[key] instanceof Array) {
							if (!(src[key] instanceof Array))
								src[key] = [];
							if (key.substring(0, 4) == 'ciy_')
								src[key] = desc[key];
							else {
								let srcidmap = {};
								for (let i in src[key]) {
									srcidmap[src[key][i].id] = parseInt(i) + 1;
								}
								for (let i in desc[key]) {
									if (desc[key][i].id && srcidmap[desc[key][i].id]) {
										src[key][srcidmap[desc[key][i].id] - 1] = this.objdeepmerge(src[key][srcidmap[desc[key][i].id] - 1], desc[key][i]);
										continue;
									}
									if (btop)
										src[key].unshift(desc[key][i]);
									else
										src[key].push(desc[key][i]);
								}
							}
						} else if (desc[key] instanceof Object) {
							src[key] = this.objdeepmerge(src[key] || {}, desc[key]);
						} else {
							if (src[key] != desc[key])
								src[key] = desc[key];
						}
					}
					if (!desc.errmsg && src.errmsg)
						delete src.errmsg;
					return src;
				},
				objtolist(list, data) {
					if (!list || !data)
						return;
					if (!this.isarray(list))
						return;
					if (!this.isobject(data))
						return;
					let idx = this.arrayfind(list, data.id, 'id');
					if (idx == -1)
						list.unshift(data);
					else
						list[idx] = this.objdeepmerge(list[idx], data);
				},
				objclone(obj) {
					if (obj instanceof Date) {
						return new Date(obj.getTime());
					}
					if (obj instanceof Array) {
						var clone = [];
						for (var i = 0; i < obj.length; i++) {
							clone[i] = this.objclone(obj[i]);
						}
						return clone;
					}
					if (obj instanceof Object) {
						var clone = {};
						for (var attr in obj) {
							if (obj.hasOwnProperty(attr))
								clone[attr] = this.objclone(obj[attr]);
						}
						return clone;
					}
					return obj;
				},
				str2date(str) {
					var val = new Date(str.replace(/\-/g, '/'));
					if (isNaN(val.getTime()))
						return new Date(0);
					return val;
				},
				bin2hex(bin) {
					var ret = '';
					for (var i = 0, l = bin.length; i < l; i++) {
						var c = bin.charCodeAt(i).toString(16);
						if (c.length == 1)
							c = '0' + c;
						ret += c;
					}
					return ret;
				},
				hex2bin(hex) {
					var ret = '';
					for (var i = 0; i < hex.length - 1; i += 2) {
						ret += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
					}
					return ret;
				},

				style2obj(sty, moresty) {
					var styleobj = {};
					if (typeof(sty) == 'string') {
						sty.split(';').filter(rule => rule.trim() !== '').forEach(rule => {
							const [key, value] = rule.split(':').map(part => part.trim());
							if (key && value) {
								const camelCaseKey = key.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase());
								styleobj[camelCaseKey] = value;
							}
						});
					} else {
						styleobj = sty || {};
					}
					if (this.isobject(moresty)) {
						for (var i in moresty) {
							if (!styleobj[i])
								styleobj[i] = moresty[i];
						}
					}
					return styleobj;
				},
				nopower(mepower, power) {
					if (mepower == '.*.') //超级管理员
						return false;
					power = '.' + power;
					var dotidx = -1;
					for (let i = 0; i < mepower.length; i++) {
						if (mepower[i] !== '.')
							continue;
						if (dotidx > -1 && dotidx + 1 < i) {
							if (power.indexOf(mepower.substring(dotidx, i)) === -1)
								continue;
							return false; //有权限
						}
						dotidx = i;
					}
					return true; //无权限
				},
				getroute() {
					var fpath;
					if (this.route)
						fpath = '/' + this.route;
					else if (this.__route__)
						fpath = '/' + this.__route__;
					return fpath;
				},
				com_getpage() {
					var thos = this;
					for (var i = 0; i < 50; i++) {
						if (thos.isPage)
							return thos;
						thos = thos.$parent;
						if (!thos)
							return null;
					}
					return null;
				},
				async com_gethdft() {
					var ret = {
						footerheight: 0,
						headerheight: 0
					};
					var compage = this.com_getpage();
					if (!compage)
						return ret;
					var ref = await compage.getrefs('header');
					if (ref && ref.Getheight)
						ret.headerheight = ref.Getheight();
					ref = await compage.getrefs('tabbar');
					if (ref && ref.Getheight)
						ret.footerheight = ref.Getheight();
					else {
						var mainrect = await compage.getrect('.tabbar');
						if (mainrect)
							ret.footerheight = mainrect.height;
					}
					return ret;
				},
				async getrefs(refname) {
					return new Promise((resolve, reject) => {
						var ref = this.getrefsSync(refname);
						if (ref !== null) {
							resolve(ref);
						} else {
							setTimeout(() => {
								ref = this.getrefsSync(refname);
								resolve(ref);
							}, 100);
						}
					}).catch(e => {
						return e;
					});
				},
				getrefsSync(refname, compage) {
					if (!compage)
						compage = this.com_getpage();
					if (compage == null)
						return null;
					if (compage.$refs) {
						if (compage.$refs[refname])
							return compage.$refs[refname];
					}
					if (compage.selectComponent) {
						var ref = compage.selectComponent('#' + refname);
						if (ref)
							return ref.$vm;
					}
					return null;
				},
				async getrect(dom) {
					return new Promise((resolve, reject) => {
						this.$nextTick(() => {
							uni.createSelectorQuery().in(this).select(dom).boundingClientRect(rect => {
								if (rect)
									resolve(rect);
								else
									reject();
							}).exec();
						});
					}).catch(e => {
						return e;
					});
				},
				async file_upload1(imgfile, opn) {
					return new Promise(async (resolve, reject) => {
						if (typeof(imgfile) == 'string')
							imgfile = {
								tempFilePath: imgfile
							};
						await this.file_uploads([imgfile], opn, {
							success(url, file) {
								resolve(url);
							},
							fail(err, gf, al) {
								console.warn(err, gf, al);
								reject('Upload Fail:' + err);
							}
						});
					}).catch(e => {
						return e;
					});
				},
				async file_uploads(files, opn, fn) { //文件批量上传，图片加水印/压缩/尺寸
					//多次返回，不能用Promise，用fn回调
					if (!opn.path) {
						opn.basepath = opn.basepath || 'demo';
						var now = new Date();
						var path = now.getFullYear() + '/' + ('0' + (now.getMonth() + 1)).slice(-2) + ('0' + now.getDate()).slice(-2) + '/' + opn.basepath;
						if (opn.saas) {
							var saasid = this.toint(opn.saas.substring(1));
							path = opn.saas.substring(0, 1) + this.toint(saasid / 1000) + '/' + saasid + '/' + path;
						}
						opn.path = path;
					}
					if (opn.action) {
						if (opn.action.substring(0, 4) != 'http') {
							var uus = opn.action.split('.');
							if (uus.length == 1)
								uus[1] = this.srv;
							opn.action = app.globalData.jsnurl[uus[1]] + 'z/?func=' + uus[0] + '/upload.';
						}
					} else {
						opn.action = app.globalData.jsnurl[app.globalData.srv] + app.globalData.jsnajax + 'upload.';
					}
					if (typeof(fn.fail) != 'function')
						fn.fail = () => {};
					opn.waterfont = opn.waterfont || '36px Arial';
					for (var u in files) {
						(async (gf, tmt) => {
							await this.sleep(tmt);
							var fpath = gf.tempFilePath || gf.tempImagePath || gf.path;
							if (!gf.name)
								gf.name = fpath;
							if (!this.isimg(gf.name))
								return uploadpfile(gf);
							// #ifdef H5
							var fread = new FileReader();
							fread.readAsDataURL(gf);
							var err = await this.goe(this.go_load(fread));
							if (err)
								return fn.fail('FileReader Error', gf, err);
							var img = new Image();
							img.src = fread.result;
							var err = await this.goe(this.go_load(img));
							if (err)
								return fn.fail('h5Image Load Error', gf, err);
							var [width, height] = setimgrect(img);
							var zipjpg = this.toint(opn.zipjpg);
							if (width == 0 && zipjpg == 0 && !opn.watertext)
								return uploadpfile(gf);
							if (width == 0) {
								width = img.width;
								height = img.height;
							}

							var canvas = document.createElement("canvas");
							var ctx = canvas.getContext("2d");
							var attrw = document.createAttribute("width");
							attrw.nodeValue = width;
							var attrh = document.createAttribute("height");
							attrh.nodeValue = height;
							canvas.setAttributeNode(attrw);
							canvas.setAttributeNode(attrh);
							ctx.drawImage(img, 0, 0, width, height);
							waterctx(ctx, width, height);
							if (zipjpg == 0)
								zipjpg = 70;
							var dataurl = canvas.toDataURL("image/jpeg", zipjpg / 100);
							var b64s = dataurl.split(",");
							var b64type = b64s[0].match(/:(.*?);/)[1];
							var ab = atob(b64s[1]);
							var ablen = ab.length;
							var abarr = new Uint8Array(ablen);
							while (ablen--) {
								abarr[ablen] = ab.charCodeAt(ablen);
							}
							uploadpfile(new File([new Blob([abarr], {
								type: b64type
							})], gf.name));
							// #endif

							// #ifndef H5
							var [err, img] = await this.go(uni.getImageInfo({
								src: fpath
							}));
							if (err)
								return fn.fail('getImageInfo Error:' + fpath,
									gf, err);
							var [width, height] = setimgrect(img);
							var zipjpg = this.toint(opn.zipjpg);
							if (width == 0 && zipjpg == 0 && !opn.watertext)
								return uploadpfile(gf);
							if (width == 0) {
								width = img.width;
								height = img.height;
							}
							await this.sleep(100);
							const canvas = wx.createOffscreenCanvas({
								type: '2d',
								width: width,
								height: height,
							});

							const fs = uni.getFileSystemManager();
							var base64Data = fs.readFileSync(img.path, 'base64');
							const ctx = canvas.getContext('2d');
							let image = canvas.createImage();
							image.src = 'data:image/png;base64,' + base64Data;
							var err = await this.goe(this.go_load(image));
							if (err)
								return fn.fail('Image Load Error', gf, err);
							ctx.drawImage(image, 0, 0, width, height);
							waterctx(ctx, width, height);
							if (zipjpg <= 0)
								zipjpg = 70;
							var res = await uni.canvasToTempFilePath({
								canvas: canvas,
								fileType: 'jpg',
								quality: zipjpg / 100
							});
							gf.tempFilePath = res.tempFilePath;
							fs.getFileInfo({
								filePath: res.tempFilePath,
								success: fsize => {
									gf.size = fsize.size;
									uploadpfile(gf);
								}
							});
							// #endif
						})(files[u], 1 + u * 1050);
					}

					var setimgrect = img => {
						var width = 0;
						var height = 0;
						if (opn.imgwidth > 0) {
							if (opn.imgwidth == opn.imgheight) {
								width = height = Math.min(img.width, img.height, opn.imgwidth);
							} else if (img.width > opn.imgwidth) {
								width = opn.imgwidth;
								if (opn.imgheight > 0)
									height = opn.imgheight;
								else
									height = width * img.height / img.width;
							}
						}
						return [width, height];
					};
					var waterctx = (ctx, imgwidth, imgheight) => {
						if (!opn.watertext)
							return;

						if (!this.isarray(opn.watercolors))
							opn.watercolors = ['#fffdea', '#000000'];
						if (!opn.wateralpha)
							opn.wateralpha = 1;
						ctx.globalAlpha = this.tofloat(opn.wateralpha);

						if (opn.watertype == 'full') {
							if (!opn.waterpadding)
								opn.waterpadding = 30;
							if (!opn.waterangle)
								opn.waterangle = -20;
							ctx.font = opn.waterfont;

							const metrics = ctx.measureText(opn.watertext);
							var fontheight = ctx.measureText('啊').width;
							const rad = opn.waterangle * Math.PI / 180;
							const rotatedWidth = Math.abs(metrics.width * Math.cos(rad)) + Math.abs(fontheight * Math.sin(rad));
							const rotatedHeight = Math.abs(metrics.width * Math.sin(rad)) + Math.abs(fontheight * Math.cos(rad));

							const itemWidth = rotatedWidth + opn.waterpadding;
							const itemHeight = rotatedHeight + opn.waterpadding;

							const cols = Math.ceil(imgwidth / itemWidth);
							const rows = Math.ceil(imgheight / itemHeight);

							const placedWatermarks = [];
							for (let i = 0; i < rows * cols * 2; i++) {
								const x = Math.random() * (imgwidth - itemWidth);
								const y = Math.random() * (imgheight - itemHeight);

								let overlap = false;
								for (const placed of placedWatermarks) {
									const dx = Math.abs(x - placed.x);
									const dy = Math.abs(y - placed.y);
									if (dx < itemWidth * 0.8 && dy < itemHeight * 0.8) {
										overlap = true;
										break;
									}
								}

								if (overlap)
									continue;
								placedWatermarks.push({
									x,
									y
								});
								ctx.save();
								ctx.translate(x, y);
								ctx.rotate((opn.waterangle + Math.random() * 5) * Math.PI / 180);
								ctx.fillStyle = opn.watercolors[Math.floor(Math.random() * opn.watercolors.length)];
								ctx.fillText(opn.watertext, 0, 0);
								ctx.restore();
							}
						} else {
							//右下角多行
							ctx.font = opn.waterfont;
							var fontheight = ctx.measureText('啊').width * 1.2;
							var lines = opn.watertext.split('|');
							var y = imgheight - fontheight * lines.length;
							for (var i in lines) {
								if (opn.watercolors.length > 1) {
									ctx.fillStyle = opn.watercolors[1];
									ctx.fillText(lines[i], fontheight + 1, y + 1);
									ctx.fillText(lines[i], fontheight - 1, y - 1);
									ctx.fillText(lines[i], fontheight - 1, y + 1);
									ctx.fillText(lines[i], fontheight + 1, y - 1);
								}
								ctx.fillStyle = opn.watercolors[0];
								ctx.fillText(lines[i], fontheight, y);
								y += fontheight;
							}
						}
						ctx.globalAlpha = 1;
					};
					var uploadpfile = async gf => { //文件多通道上传
						if (opn.maxkb > 0 && gf.size >= opn.maxkb * 1024)
							return fn.fail('MaxSize:' + opn.maxkb + 'KB, This:' + parseInt(gf.size /
								1024) + 'KB', gf);
						var app = getApp();
						var header = {};
						header['ciyauth'] = app.getstorage("_" + app.globalData.tokenfield);
						var filepath = gf.tempFilePath || gf.tempImagePath || gf.path;
						var now = new Date();
						var fext = this.file_ext(gf.name);
						var pathfile = opn.path + '/' + now.getHours() + now.getMinutes() + now
							.getSeconds() + '_' +
							(1000 + Math.round(Math.random() * 8000)) + '.' + fext.toLowerCase();
						if (opn.stor == '/') {
							var needobjurl = false;
							var ufparam = {};
							ufparam.url = opn.action + "upload?pathfile=" + pathfile;
							ufparam.header = header;
							if (opn.post)
								ufparam.formData = opn.post;
							if (filepath) {
								ufparam.filePath = filepath;
								ufparam.name = 'file';
							} else {
								
								var fread = new FileReader();
								fread.readAsDataURL(gf);
								var err = await this.goe(this.go_load(fread));
								if (err)
									return fn.fail('FileReader LoadObjUrl Error', gf, err);
								ufparam.filePath = URL.createObjectURL(gf);
								needobjurl = true;
								ufparam.name = 'file';
							}
							var [err, retupfile] = await this.go(uni.uploadFile(ufparam));
							if (needobjurl)
								URL.revokeObjectURL(ufparam.filePath);
							if (err)
								return fn.fail(err.errMsg, gf, err);
							var jsonup = this.json_parse(retupfile.data);
							if (jsonup === null)
								return fn.fail('JSON Parse ERROR:' + retupfile.data.substr(0, 30),
									gf);
							if (jsonup.code != 1)
								return fn.fail(jsonup.errmsg, gf, jsonup);
							if (typeof(fn.success) == 'function')
								fn.success(jsonup.url, gf);
						} else {
							var [err, s3json] = await this.go(this.callfunc({
								func: opn.action + "s3?pathfile=" + pathfile +
									"&storselect=" + opn.stor
							}));
							if (err)
								return fn.fail(err.errMsg, gf, err);
							if (s3json.code != 1)
								return fn.fail(s3json.errmsg, gf, s3json);
							// #ifdef H5
							//H5，直接xhr
							var xhr = new XMLHttpRequest();
							xhr.open(s3json.method, s3json.url, true);
							for (var i in s3json.headers) {
								xhr.setRequestHeader(i, s3json.headers[i]);
							}
							xhr.onreadystatechange = function() {
								if (xhr.readyState == 4 && xhr.status == 200) {
									if (typeof(fn.success) == 'function')
										fn.success(opn.stor + pathfile, gf);
								} else if (xhr.status != 200) {
									fn.fail('云存储上传失败:' + xhr.status, gf, xhr);
								}
							};
							xhr.send(gf);
							// #endif
							// #ifndef H5
							if (app.globalData.stortransfer.includes(opn.stor)) {
								var ufparam = {};
								ufparam.url = opn.action + "yunsync";
								if (s3json.syncurl)
									ufparam.url = s3json.syncurl;
								s3json.headers = JSON.stringify(s3json.headers);
								ufparam.formData = s3json;
								if (filepath) {
									ufparam.filePath = filepath;
									ufparam.name = 'file';
								} else {
									ufparam.file = gf;
								}
								var retupfile = await uni.uploadFile(ufparam);
								var jsonup = this.json_parse(retupfile.data);
								if (jsonup === null)
									return fn.fail('JSON Parse ERROR:' + retupfile.data.substr(0,
										30), gf, jsonup);
								if (jsonup.code != 1)
									return fn.fail(jsonup.errmsg, gf, jsonup);
								if (typeof(fn.success) == 'function')
									fn.success(opn.stor + pathfile, gf);
							} else {
								console.warn('直传，微信小程序需备案域名，添加域名白名单');
								fn.fail('未支持', gf);
							}
							// #endif
						}
					};
				},
				async go(promise) { //var [err, tmp] = await this.go(this.go_load(img));
					return promise.then((data) => [null, data]).catch((err) => [err, undefined]);
				},
				async goe(promise) { //var err = await this.goe(this.go_load(img));
					return promise.then(() => null).catch((err) => err);
				},
				async go_load(obj, act) {
					return new Promise((resolve, reject) => {
						if (act == 'exec') { //特例
							obj.exec(async data => {
								resolve(data);
							});
						} else {
							obj.onload = (data) => {
								resolve(data);
							}
							obj.onerror = err => {
								console.log('go_load error:', err);
								reject('load error');
							}
						}
					});
				}
			}
		});

	}
};