/* ================================================================================= * 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替换成
,将<>替换成可显示 * 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, '>'); //txt = txt.replace(/\|/g, '
'); } txt = txt.replace(/\n/g, '
'); 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 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 { ufparam.file = gf; } var [err, retupfile] = await this.go(uni.uploadFile(ufparam)); 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'); } } }); } } }); } };