// 公共常量、方法库
let $lj = {}; //export对象
let self = $lj;
//库内private变量、方法

import {productInfo, storageKeySet, eventNameSet} from "./project-set"

// 服务器地址
// 判断打包时环境
let defaultBaseUrl = "http://8.134.222.185:9076"
// if (process.env.NODE_ENV === 'development') {
//     defaultBaseUrl = "http://192.168.31.104:9076";
// }
// let apiUrl = baseUrl + "/api.ashx";
const defaultIp = "www.fiscm.cn";
const defaultPort = "30066";
const openWinAnimationType = "movein";
const AnimationSubType = "from_right";
const openWinAnimationDuration = 220;
const openWinDelay = 220;
const toastDuration = 3000;
const toastLocation = "middle";
const showProgressAnimationType = "fade";
const showProgressTitle = "努力加载中...";
const showProgressText = "先喝杯茶...";
const timeOutRequest = 180000;
const imageSize = 300;
const imageQuality = 100;
let longjoeAPI;
let baseUrl;
// 静默登录白名单（未有token验证的接口）
let whiteList = ["NotifyUsersKicked", "RpTimeOperateAppInit", "GetTVUpdate"];
// 通用token
$lj.token = "";
// 通用：单据名称
$lj.billcodeStyleName = {};
// 设备唯一码
$lj.deviceId = "";

function initBaseUrl() {
    if (!baseUrl) {
        // let baseUrlSetting = $lj.getStorage("baseUrl");
        // if (baseUrlSetting) {
        //     baseUrl = baseUrlSetting;
        // } else {
            baseUrl = defaultBaseUrl;
        // }
    }
    return true;
}

function resetBaseUrl(newUrl) {
    if (newUrl) {
        $lj.setStorage("baseUrl", newUrl);
        baseUrl = newUrl;
    }
}
let serverAddressInited = false;
/**
 * 被动配置链接参数
 * @returns Boolean
 */
function initLongjoeAPI(callback) {
    if (!longjoeAPI) {
        console.log("---------------------------requiring longjoeapi module-----------------------");
        longjoeAPI = api.require('longjoeAPI');
        $lj.getAppDeviceId().then(() => {
            let storageDeviceId = $lj.getStorage('deviceId');
            if (!storageDeviceId) {
                $lj.setStorage('deviceId', $lj.deviceId);
            }
        });
    }
    // if (!serverAddressInited){
    //     let serverConnectParams = $lj.getStorage("serverConnectParams");
    //     if (!serverConnectParams || JSON.stringify(serverConnectParams) == '{}') {
    //         alert("未设置服务器连接参数，请在登陆页面重新设置");
    //         return false;
    //     }
    //     console.log(' 被动 initLongjoeAPI serverConnectParams :>>>>>>>>>>>>>>>>>>>>>', JSON.stringify(serverConnectParams));

    //     longjoeAPI.setServerAddress(serverConnectParams, function (ret){
    //         // 连接初始化/重置完成
    //         if (callback){
    //             callback();
    //         }
    //     });
    //     serverAddressInited = true;
    // } else {
    //     if (callback){
    //         callback();
    //     }
    // }
    return true;
}

/**
 * 主动配置链接参数
 * @returns 
 */
$lj.initServerConnect = function(callback) {
    if (!longjoeAPI) {
        console.log("---------------------------requiring longjoeapi module-----------------------");
        longjoeAPI = api.require('longjoeAPI');
        $lj.getAppDeviceId().then(() => {
            let storageDeviceId = $lj.getStorage('deviceId');
            if (!storageDeviceId) {
                $lj.setStorage('deviceId', $lj.deviceId);
            }
        });
    }
    let serverConnectParams = $lj.getStorage("serverConnectParams");
    if (!serverConnectParams || JSON.stringify(serverConnectParams) == '{}') {
        alert("未设置服务器连接参数，请在登陆页面重新设置");
        return false;
    }
    console.log('initServerConnect serverConnectParams :>>>>>>>>>>>>>>>>>>>>>', JSON.stringify(serverConnectParams));
    longjoeAPI.setServerAddress(serverConnectParams, function (ret){
        // 连接初始化/重置完成
        if (callback){
            callback();
        }
    });
}
$lj.watchConnectChanged = function (){
    $lj.removeEventListener('longjoeAPI_connectModeChanged');
    $lj.addEventListener('longjoeAPI_connectModeChanged',function(res) {
        console.log(' ConnectModeChanged :>>>>>>>>>>>>>>>>>>>>>', JSON.stringify(res));
        let getRequestWay = $lj.getPrefs('serverCurrentRequestWay');
        console.log(' getRequestWay :>>>>>>>>>>>>>>>>>>>>>', JSON.stringify(getRequestWay));
        let requestWay = res.value.mode;
        if (getRequestWay != requestWay) {
            $lj.setPrefs('serverCurrentRequestWay', requestWay);
            switch (requestWay) {
                case 'DIRECT':
                    $lj.toast('IP连接中...', 1000, 'bottom');
                    break;
                case 'TRANSIT':
                    $lj.toast('中转连接中...', 1000, 'bottom');
                    break;
            }
        }
    })
}

let isAndroid = (/android/gi).test(navigator.appVersion);

function uzStorage() {
    let ls = window.localStorage;
    if (isAndroid) {
        ls = os.localStorage();
    }
    return ls;
}

//外部可调用的public部分
$lj.isIPad = function() {
    if (api.systemType === "ios"){
        let width = Math.min(api.screenWidth,api.screenHeight);
        let height = Math.max(api.screenWidth,api.screenHeight);
        if (height/width < 1.5){
            return true;
        }
    }
    return false;
};
$lj.getAppBarHeight = function () {
    return 48 + api.safeArea.top;
};
$lj.fixStatusBar = function (el) {
    el.style.paddingTop = api.safeArea.top + 'px';
    return el.offsetHeight;
};
$lj.fixTabBar = function (el) {
    let currentStyle = window.getComputedStyle(el);
    let currentPaddingBottom;
    let targetPaddingBottom = api.safeArea.bottom;
    if (currentStyle.paddingBottom) {
        currentPaddingBottom = Number(currentStyle.paddingBottom.replace('px', ''));
        if (currentPaddingBottom >= targetPaddingBottom) {
            return;
        }
        targetPaddingBottom += currentPaddingBottom;
    }
    el.style.paddingBottom = targetPaddingBottom + 'px';
    if (!el.style.height && currentStyle.display === 'inline-block') {
        el.style.height = el.offsetHeight + api.safeArea.bottom + 'px';
    }
    return el.offsetHeight;
};
$lj.constant = {
    articleImgWidth: 78,
    articleImgHeight: 78,
    cacheDir: ""
};
$lj.initServerConnectParams = function () {
    let serverConnectParams = $lj.getStorage("serverConnectParams");
    if (typeof serverConnectParams !== "object") {
        serverConnectParams = {};
        serverConnectParams.ip = defaultIp;
        serverConnectParams.port = defaultPort;
        $lj.setStorage("serverConnectParams", serverConnectParams);
    }
};
$lj.getCacheDir = function (callback) {
    if ($lj.constant.cacheDir) {
        callback($lj.constant.cacheDir);
        return;
    }
    initLongjoeAPI();
    longjoeAPI.getLJFile(function (ret) {
            if (ret) {
                if (ret.errMsg) {
                    alert("获取文件路径失败" + ret.errMsg);
                } else {
                    $lj.constant.cacheDir = ret.filedir;
                    callback($lj.constant.cacheDir);
                    console.warn("ret.filedir:", ret.filedir)
                }
            } else {
                console.log("获取文件路径失败");
            }
        }
    );
};
let base64TranModule;
$lj.getBase64TranModule = function () {
    // https://www.apicloud.com/mod_detail/26860
    if (!base64TranModule) {
        base64TranModule = api.require('trans');
    }
    return base64TranModule;
};
let fileHelperModule;
$lj.getFileHelperModule = function () {
    // https://www.apicloud.com/mod_detail/61264
    if (!fileHelperModule) {
        fileHelperModule = api.require("fs");
    }
    return fileHelperModule;
};
let qrScnner;
$lj.getQrScanner = function () {
    if (!qrScnner) {
        qrScnner = api.require('FNScanner');
    }
    var permission = ['camera', 'photos'];
    return new Promise((resolve, reject) => { 
        $lj.getPermission(permission).then(result => {
            result && resolve(qrScnner);
        })
    })
};
$lj.getPageParam = function () {
    return api.pageParam;
};
$lj.closeWin = function (name) {
    if (name) {
        api.closeWin({name: name});
    } else {
        api.closeWin();
    }
};
$lj.getLastDay = function (year, month) {
    var new_year = year;    //取当前的年份         
    var new_month = month++;//取下一个月的第一天，方便计算（最后一天不固定）         
    if (month > 12) {
        new_month -= 12;        //月份减
        new_year++;            //年份增         
    }
    var new_date = new Date(new_year, new_month, 1); //取当年当月中的第一天
    var last_day = (new Date(new_date.getTime() - 1000 * 60 * 60 * 24)).getDate();
    return last_day;//获取当月最后一天日期          

};
$lj.getDateObject = function (date) {
    if (api.systemType === "ios" && typeof date === "string") {
        if (date.indexOf(' ') > -1 && date.indexOf('.') > -1) {
            return new Date(Date.parse(date.replace(/ /g, 'T')))
        } else {
            return new Date(date.replace(/-/g, '/'));
        }
    }
    return new Date(date);
};
$lj.dateformat = function (date, fmt) {
    if (!date) {
        return undefined;
    }
    let dateObject = $lj.getDateObject(date);
    if (!fmt) {
        fmt = "yyyy-MM-dd hh:mm:ss";
    }
    let o = {
        "M+": dateObject.getMonth() + 1, //月份
        "d+": dateObject.getDate(), //日
        "h+": dateObject.getHours(), //小时
        "m+": dateObject.getMinutes(), //分
        "s+": dateObject.getSeconds(), //秒
        "q+": Math.floor((dateObject.getMonth() + 3) / 3), //季度
        "S": dateObject.getMilliseconds() //毫秒
    };
    if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (dateObject.getFullYear() + "").substr(4 - RegExp.$1.length));
    for (let k in o)
        if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
    return fmt;
};
$lj.dateAdd = function (date, yearDiff, monthDiff, dayDiff) {
    let result = new Date(date);
    if (dayDiff) {
        result = new Date(result.getTime() + dayDiff * 24 * 60 * 60 * 1000);
    }
    if (monthDiff) {
        let month = result.getMonth() + monthDiff;
        if (month < 0) {
            result = new Date(result.getFullYear() - 1, month + 12, result.getDate(), result.getHours(), result.getMinutes(), result.getSeconds());
        } else if (month > 11) {
            result = new Date(result.getFullYear() + 1, month - 12, result.getDate(), result.getHours(), result.getMinutes(), result.getSeconds());
        } else {
            result = new Date(result.getFullYear(), month, result.getDate(), result.getHours(), result.getMinutes(), result.getSeconds());
        }
    }
    if (yearDiff) {
        result = new Date(result.getFullYear() + yearDiff, month, result.getDate(), result.getHours(), result.getMinutes(), result.getSeconds());
    }
    return result;
};
$lj.getDiffDays = function(begindate, enddate) {
    var bdt = Date.parse(begindate);
    console.log("begindate:" + bdt)
    var edt = Date.parse(enddate);
    console.log("enddate:" + edt)
    var days = edt - bdt;
    console.log("diffdays:" + Math.floor(days / (1000 * 60 * 60 * 24)))
    return Math.round(days / (1000 * 60 * 60 * 24));
}
$lj.getDiffHours = function(s1, s2) {
    var reDate = /\d{4}-\d{1,2}-\d{1,2} /;
    s1 = new Date((reDate.test(s1) ? s1 : '2018-1-1 ' + s1).replace(/-/g, '/'));
    s2 = new Date((reDate.test(s2) ? s2 : '2018-1-1 ' + s2).replace(/-/g, '/'));
    var ms = s2.getTime() - s1.getTime();
    if (ms < 0) return 0;
    return Math.floor(ms / 1000 / 60 / 60);  //小时
}
$lj.checkPower = function (funcid) {
    let userInfo = $lj.getStorage("user");
    if (userInfo && userInfo.rsltFunids) {
        for (let enabledId of userInfo.rsltFunids) {
            if (enabledId == funcid) {
                return true;
            }
        }
    }
    return false;
};
$lj.getOptionValue = function(optionid) {
    let userInfo = $lj.getStorage("userInfo");
    if (userInfo && userInfo.optionList) {
        for (let option of userInfo.optionList) {
            if (Number(option.optionid) == optionid) {
                return option.optionvalue;
            }
        }
    }
    return undefined;
}
// 验证手机号码、电话号码格式格式
$lj.checkTel = function (tel) {
    return /^(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}$/.test(tel);
};

$lj.strLastOne = function (str) {
    return str.substring(str.length - 1, str.length);
};

$lj.moneyFormat = function (num, rightLength, turnUnit) {
    if (isNaN(Number(num))) {
        return num;
    }
    if (typeof rightLength === "undefined") {
        rightLength = 2;
    }
    if (typeof turnUnit === "undefined") {
        turnUnit = false
    }
    let strarr = num ? num.toString().split('.') : ['0'];
    // 整数部分
    let left = strarr[0];
    let result = (Number(num) < 0 ? "-" : "") + left.split('').reverse().join('').match(/(\d{1,3})/g).join(',').split('').reverse().join('');
    // 小数部分
    if (rightLength > 0) {
        result += ".";
        let right = strarr[1] ? strarr[1] : "";

        for (let i = 0; i < rightLength; i++) {
            if (typeof right[i] === "undefined") {
                result += "0"
            } else {
                result += right[i];
            }
        }
    }
    if (turnUnit) {
        result = left.length > 4 ? $lj.moneyFormat(parseInt(left) / 10000) + "万" : result;
    }
    return result;
};
// 获取图片的http地址
$lj.getPicUrl = function (picdata, width, height) {
    initBaseUrl();
    if (picdata.indexOf('/img.ashx') !== 0) {
        return picdata;
    }
    let result = baseUrl + picdata;
    if (width) {
        result += '&w=' + width;
    }
    if (height) {
        result += '&h=' + height;
    }
    return result;
};
$lj.postLJRequest = function (method, requestbody, callback, errcallback, hideprogress, hideErrMsg, progressParams) {
    // return postLJTCPRequest(method, requestbody, callback, errcallback, hideprogress, hideErrMsg, progressParams);
    return postLJHTTPRequest(method, requestbody, callback, errcallback, hideprogress, hideErrMsg, progressParams);
};

// 发送HTTP请求：直接发送请求
function postLJHTTPRequest(method, requestbody, callback, errcallback, hideprogress, hideErrMsg, progressParams) {
    let hidErrMsgParm = (typeof arguments[5] === "undefined" || arguments[5] == null) ? true : arguments[5];
    if (!initBaseUrl()) {
        return;
    }
    // let url = baseUrl + "/api.ashx";
    // let data = {
    //     method: method,
    //     requestbody: requestbody
    // };
    let url = baseUrl + "/api/common/" + method;
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("method:" + method);
    console.log("requestbody:" + JSON.stringify(requestbody));
    if (!hideprogress) {
        api.showProgress(progressParams);
    }
    if (api) {
        let start = new Date().getTime();
        api.ajax({
            url: url,
            method: 'post',
            headers: {
                'Content-Type': 'application/json;charset=utf-8'
            },
            data: {
                body: requestbody,
            }
        }, function (ret, err) {
            let end = new Date().getTime();
            let m = (end - start) / 1000;
            console.log("耗时:" + m + "秒");
            console.log("结果:" + JSON.stringify(ret));
            err && console.log("结果err:" + JSON.stringify(err));
            console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
            api.hideProgress();
            if (ret) {
                // if (ret.ErrMsg) {
                //     self.toast(ret.ErrMsg, 2000);
                //     if (errcallback != null) {
                //         errcallback();
                //     }
                // } else {
                //     callback(ret);
                // }

                if (!hideprogress) {
                    api.hideProgress();
                }
                if (ret.ErrMsg === "请求超时" && api.systemType === "ios") {
                    $lj.toast('请求超时');
                    if (errcallback) {
                        errcallback(ret);
                    }
                    return;
                }
                if (!ret.ErrMsg && ret.errCode) {
                    ret.ErrMsg = ret.errCode;
                }
                if (ret.ErrMsg) {
                    errcallback && errcallback(ret);
                    // 默认异常处理
                    if (ret.errCode === "连接池请求异常") {
                        $lj.toast("连接失败，网络异常或服务停止!");
                    } else if (ret.ErrMsg.indexOf("会话") >= 0 || ret.ErrMsg.indexOf("已与服务器失联") >= 0) {
                        $lj.toast(ret.ErrMsg);
                        $lj.sendEvent("token_overdue");
                        // $lj.silentLogin(() => {
                        //     $lj.RpTimeOperateAppInit()
                        // }, method + "@" + start);
                    } else if (ret.ErrMsg.indexOf("未知的客户端类型") >= 0) {
                        
                    } else if (ret.DebugMsg) {
                        alert(ret.DebugMsg);
                    } else {
                        hidErrMsgParm && alert(ret.ErrMsg);
                    }
                } else {
                    if (callback) {
                        callback(ret);
                    }
                }
            } else {
                api.alert({
                    msg: ('网络异常,请稍后！')
                });
            }
        });
    } else {
        $.post(url, requestbody, callback, 'json');
    }
}

// 发送TCP请求：通过调用原生模块发送TCP请求
function postLJTCPRequest(method, requestbody, callback, errcallback, hideprogress, hideErrMsg, progressParams) {
    let hidErrMsgParm = (typeof arguments[5] === "undefined" || arguments[5] == null) ? true : arguments[5];
    initLongjoeAPI(() => {
        let data = {
            method: method,
            requestbody: JSON.stringify(requestbody)
        };
        console.warn("-------------------------------------------------------------------------------");
        console.warn("method:" + method);
        console.log("requestbody:" + JSON.stringify(requestbody));
        if (!hideprogress) {
            api.showProgress(progressParams);
        }
        let ifTimeOut = 1;
        let start = new Date().getTime();
        longjoeAPI.postLJRequest(
            data,
            function (ret, err) {
                let end = new Date().getTime();
                let m = (end - start) / 1000;
                console.warn("=================================================");
                console.warn("method:" + method);
                console.log("耗时:" + m + "秒");
                console.log("结果:" + JSON.stringify(ret));
                console.log("-------------------------------------------------------------------------------");
                if (ret) {
                    ifTimeOut = 0;
                    if (!hideprogress) {
                        api.hideProgress();
                    }

                    // if (ret.errCode === "连接池请求异常") {
                    //     ret.ErrMsg = "连接失败，网络异常或服务停止!";
                    //     if (hidErrMsgParm) {
                    //         return;
                    //     }
                    // }
                    if (ret.ErrMsg === "请求超时" && api.systemType === "ios") {
                        $lj.toast('请求超时');
                        if (errcallback) {
                            errcallback(ret);
                        }
                        return;
                    }
                    // if (ret.ErrMsg === "用户名或密码错误") {
                    //     $lj.toast(ret.ErrMsg);
                    //     $lj.sendEvent("token_overdue");
                    //     return;
                    // }
                    if (!ret.ErrMsg && ret.errCode) {
                        ret.ErrMsg = ret.errCode;
                    }
                    if (ret.ErrMsg) {
                        errcallback && errcallback(ret);
                        // 默认异常处理
                        if (ret.errCode === "连接池请求异常") {
                            $lj.toast("连接失败，网络异常或服务停止!");
                        } else if (ret.ErrMsg.indexOf("会话") >= 0 || ret.ErrMsg.indexOf("已与服务器失联") >= 0) {
                            $lj.toast(ret.ErrMsg);
                            $lj.sendEvent("token_overdue");
                            // $lj.silentLogin(() => {
                            //     $lj.RpTimeOperateAppInit()
                            // }, method + "@" + start);
                        } else if (ret.ErrMsg.indexOf("未知的客户端类型") >= 0) {
                            
                        } else if (ret.DebugMsg) {
                            alert(ret.DebugMsg);
                        } else {
                            hidErrMsgParm && alert(ret.ErrMsg);
                        }
                    } else {
                        // if (whiteList.indexOf(method) == -1 && $lj.hasSendSilentLogin) {
                        //     $lj.hasSendSilentLogin = false;
                        //     if ($lj.lastTimeSilentLogin == 0) {
                        //         $lj.lastTimeSilentLogin = end;
                        //     }
                        // }
                        if (callback) {
                            callback(ret);
                        }
                    }
                } else {
                    api.alert({
                        msg: ('网络异常,请稍后！')
                    });
                }
            }
        );
        setTimeout(function () {
            if (ifTimeOut === 1) {
                if (!hideprogress) {
                    api.hideProgress();
                }
            }
        }, timeOutRequest);
    });
}

/**
 * 静默登录，同一账户下，防止页面跳转，
 * hasSendSilentLogin：是否拦截重复的静默登录
 * lastTimeSilentLogin：拦截后，第一次连接时间；避免超时响应带来的问题
 */
$lj.hasSendSilentLogin = false;
$lj.lastTimeSilentLogin = 0;
$lj.silentLogin = function(callback, method) {
    if ($lj.hasSendSilentLogin) {
        console.log('~~~~~静默正在进行了，终止发送！！！！！！！！！ :>> ', method);
        return false;
    }
    let start = method.split("@")[1];
    if ($lj.lastTimeSilentLogin - start > 0) {
        console.log('已成功重新连接！！！！！！');
        return false;
    }
    $lj.hasSendSilentLogin = true;
    $lj.lastTimeSilentLogin = 0;
    console.log('~~静默登录开始~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :>> ', method);
    let currentAccount = $lj.getStorage("lastLoginAccount");
    if (!currentAccount) {
        $lj.sendEvent("token_overdue");
        return false;
    }
    let usercode, password, rememberUser;
    let lastUser = $lj.getStorage("loginRememberUser");
    let userHistory = $lj.getUserAccHistoryAccount(currentAccount);
    if (lastUser) {
        rememberUser = true;
        usercode = lastUser;
        password = userHistory[lastUser];
    } else {
        $lj.sendEvent("token_overdue");
        return false;
    }

    var requestData = {
        account: currentAccount,
        userid: usercode,
        password: password,
        phoneUUID: $lj.deviceId,
        clientType:10,
        typeName:'L1APP'
    };
    $lj.postLJRequest("Login", requestData, function (ret) {
        if (ret) {
            let oldToken = $lj.getStorage("token");
            ret.usercode = usercode;
            let token = ret.token;
            $lj.setStorage("token", token);
            $lj.token = JSON.parse(JSON.stringify(ret.token));
            // $lj.token = token;
            let reportHabit = $lj.getStorage("reportHabit");
            if (!reportHabit) {
                $lj.setStorage("reportHabit", {});
            }
            $lj.setStorage("user", ret);
            // userHistory[usercode] = password;
            // $lj.setStorage('userHistory', rememberUser ? userHistory : {});

            // 缓存本地登录账号
            let accountList = $lj.getStorage('cacheAccount');
            if (!accountList) {
                accountList = [];
            }
            accountList.forEach((acc) => {
                acc.checked = false;
                if (acc.account == currentAccount && acc.usercode == ret.usercode) {
                    acc.token = ret.token;
                    acc.username = ret.username;
                    acc.checked = true;
                }
            })
            $lj.setStorage('cacheAccount', accountList);

            // if(oldToken){
            //     $lj.postLJRequest("NotifyUsersKicked", {tokens: [oldToken], fromClient: 1}, function(ret) {
            //         callback();
            //     }, function() {}, true);
            // } else {
                callback()
            // }
        }
    }, function(ret) {
        if (ret && ret.ErrMsg) {
            $lj.toast(ret.ErrMsg);
        }
        $lj.hasSendSilentLogin = false;
        $lj.sendEvent("token_overdue");
    }, false);
};
$lj.RpTimeOperateAppInit = function () {
    var requestData = {
        token: $lj.getStorage("token")
    };
    $lj.postLJRequest("RpTimeOperateAppInit", requestData, function (ret) {
        $lj.toast("静默登录成功", 1000, "bottom");
        $lj.sendEvent("login_success", {reload: false});
    },function(ret){
        if (ret.ErrMsg) {
            $lj.toast("初始化数据仓库基础资料失败!");
        }
    })
}


/**
 * 设置偏好数据，数据会存储到本地文件系统。
 * @param {*} key 
 * @param {*} value 
 * @returns 
 */
$lj.setPrefs = function (key, value) {
    if (!storageKeySet.has(key)) {
        console.error("longjoe-public: storageKey: [" + key + "] is undefined or deprecated");
        return;
    }
    let v = value;
    if (typeof v === 'object') {
        v = JSON.stringify(v);
        v = 'obj-' + v;
    } else {
        v = 'str-' + v;
    }
    api.setPrefs({
        key: key,
        value: v
    });
};
/**
 * 获取偏好设置值
 * @param {*} key 
 * @param {*} sync 
 * @returns 
 */
$lj.getPrefs = function (key) {
    if (!storageKeySet.has(key)) {
        console.error("longjoe-public: storageKey: [" + key + "] is undefined or deprecated");
        return;
    }
    //同步返回结果：
    let v = api.getPrefs({
        sync: true,
        key: key
    });
    if (v.indexOf('obj-') === 0) {
        v = v.slice(4);
        return JSON.parse(v);
    } else if (v.indexOf('str-') === 0) {
        return v.slice(4);
    }
};
// 设置本地数据库数据
$lj.setStorage = function (key, value) {
    if (!storageKeySet.has(key)) {
        console.error("longjoe-public: storageKey: [" + key + "] is undefined or deprecated");
        return;
    }
    if (arguments.length === 2) {
        let v = value;
        if (typeof v === 'object') {
            v = JSON.stringify(v);
            v = 'obj-' + v;
        } else {
            v = 'str-' + v;
        }
        let ls = uzStorage();
        if (ls) {
            ls.setItem(key, v);
        }
    }
};
// 获取本地数据库数据
$lj.getStorage = function (key) {
    if (!storageKeySet.has(key)) {
        console.error("longjoe-public: storageKey: [" + key + "] is undefined or deprecated");
        return;
    }
    let ls = uzStorage();
    if (ls) {
        let v = ls.getItem(key);
        if (!v) {
            return;
        }
        if (v.indexOf('obj-') === 0) {
            v = v.slice(4);
            return JSON.parse(v);
        } else if (v.indexOf('str-') === 0) {
            return v.slice(4);
        }
    }
};
// 设置点击两次返回键退出应用
$lj.setKeybackClose = function () {
    let count = 0;
    let time1, time2;
    self.addEventListener('keyback', function (ret, err) {
        if (count === 0) {
            time1 = new Date().getTime();
            count = 1;
            self.toast('再按一次返回键退出');
        } else if (count === 1) {
            time2 = new Date().getTime();
            if (time2 - time1 < 3000) {
                api.closeWidget({
                    id: api.appId,
                    retData: {
                        name: 'closeWidget'
                    },
                    silent: true
                });
            } else {
                count = 0;
                self.toast('再按一次返回键退出');
            }
        }
    });
};
// 小提示
$lj.toast = function (msg, duration, location, callback) {
    let _duration = (typeof arguments[1] === "undefined" || arguments[1] == null) ? toastDuration : arguments[1];
    let _location = (typeof arguments[2] === "undefined" || arguments[2] == null) ? toastLocation : arguments[2];
    var global = api.systemType == "ios" ? false : true; //iOS12 true无效
    api.toast({
        msg: msg,
        duration: _duration,
        location: _location,
        global: global
    });
    if (typeof callback === "function") {
        setTimeout(callback, duration);
    }
};
// 加载框
$lj.showProgress = function (title, text, modal, animationType) {
    let _title = (typeof arguments[0] === "undefined" || arguments[0] == null) ? showProgressTitle : arguments[0];
    let _text = (typeof arguments[1] === "undefined" || arguments[1] == null) ? showProgressText : arguments[1];
    let _modal = (typeof arguments[2] === "undefined" || arguments[2] == null) ? true : arguments[2];
    let _animationType = (typeof arguments[3] === "undefined" || arguments[3] == null) ? showProgressAnimationType : arguments[3];
    api.showProgress({
        style: 'default',
        animationType: _animationType,
        title: _title,
        text: _text,
        modal: _modal
    });
};
// 监听事件
$lj.addEventListener = function (eventName, callback, extra) {
    if (!eventNameSet.has(eventName)) {
        console.error("longjoe-public: EventName: [" + eventName + "] is undefined or deprecated");
        return;
    }
    let _extra = (typeof arguments[2] === "undefined" || arguments[2] == null) ? {} : arguments[2];
    api.addEventListener({
        name: eventName,
        extra: _extra
    }, function (ret, err) {
        if (typeof callback === "function") {
            callback(ret);
        }
    });
};
// 触发事件
$lj.sendEvent = function (eventName, extra) {
    if (!eventNameSet.has(eventName)) {
        console.error("longjoe-public: EventName: [" + eventName + "] is undefined or deprecated");
        return;
    }
    let _extra = (typeof arguments[1] === "undefined" || arguments[1] == null) ? {} : arguments[1];
    api.sendEvent({
        name: eventName,
        extra: _extra
    });
};
$lj.removeEventListener = function (eventName) {
    api.removeEventListener({
        name: eventName
    });
};
// 打开新窗口
$lj.openWin = function (name, pageParam, bounces, reload, bgColor, animateDirection) {
    let _pageParam = (typeof arguments[1] === "undefined" || arguments[1] == null) ? api.pageParam : arguments[1];
    let _bounces = (typeof arguments[2] === "undefined" || arguments[2] == null) ? false : arguments[2];
    let _reload = (typeof arguments[3] === "undefined" || arguments[3] == null) ? false : arguments[3];
    let _bgColor = (typeof arguments[4] === "undefined" || arguments[4] == null) ? 'rgba(0,0,0,0)' : arguments[4];
    let _animateDirection = (typeof arguments[5] === "undefined" || arguments[5] == null) ? AnimationSubType : arguments[5];
    let url = getTargetUrl(name);
    if (!url) {
        return;
    }
    console.log("openingWin: " + url);
    console.log("openingWin: _pageParam " + JSON.stringify(_pageParam));
    console.log("openingWin: api " + JSON.stringify(api));
    console.log("openingWin: typeof openWin" + JSON.stringify(typeof api.openWin));
    api.openWin({
        name: name,
        url: url,
        pageParam: _pageParam,
        bgColor: _bgColor,
        bounces: _bounces,
        scrollToTop: true,
        animation: {
            type: openWinAnimationType,
            subType: _animateDirection,
            duration: openWinAnimationDuration
        },
        delay: api.systemType === "ios" ? 0 : openWinDelay,
        reload: _reload,
        allowEdit: true,
        vScrollBarEnabled: false,
        hScrollBarEnabled: false,
        slidBackEnabled: true, // iOS: 支持滑动返回
        slidBackType: "edge", // iOS: 右滑有效区域
    });
};

function getTargetUrl(targetWinName) {
    let winMap = webpackConfigParams.winMap;
    let curentUrl;
    if (api.winName === "root") {
        curentUrl = winMap["main"];
    } else {
        curentUrl = winMap[api.winName];
    }
    let targetUrl = winMap[targetWinName];
    if (!targetUrl) {
        alert("页面丢失：" + targetWinName);
        return;
    }
    let currentUrlStack = curentUrl.split("/");
    let targetUrlStack = targetUrl.split("/");
    let relativeUrl = targetUrl;
    let backStep = currentUrlStack.length - 1;
    for (let i in currentUrlStack) {
        if (currentUrlStack[i] && targetUrlStack[i]) {
            if (currentUrlStack[i] === targetUrlStack[i]) {
                backStep--;
                relativeUrl = relativeUrl.substring(relativeUrl.indexOf('/') + 1);
            } else {
                break;
            }
        }
    }
    if (backStep === 0) {
        relativeUrl = "./" + relativeUrl;
    } else {
        for (let i = 0; i < backStep; i++) {
            relativeUrl = "../" + relativeUrl;
        }
    }
    return relativeUrl + ".html";
}

$lj.getEditHabit = function (properties) {
    if (!properties || !properties instanceof Array) {
        return undefined;
    }
    let userEditHabit = $lj.getStorage("userEditHabit") || {};
    let key = api.winName;
    let habit = userEditHabit[key] || {};
    let result = {};
    for (let prop of properties) {
        result[prop] = habit[prop];
    }
    return result;
};
$lj.setEditHabit = function (data, properties) {
    if (!data || !properties || !properties instanceof Array) {
        return;
    }
    let userEditHabit = $lj.getStorage("userEditHabit") || {};
    let key = api.winName;
    let habit = userEditHabit[key] || {};
    for (let prop of properties) {
        habit[prop] = data[prop];
    }
    userEditHabit[key] = habit;
    $lj.setStorage("userEditHabit", userEditHabit);
};


$lj.oubamaPrintLines = function (lines) {
    initLongjoeAPI();
    let basePrintParams = {
        sendType: 0,  //*必填 int，打印类型 0：打印文字，1：打印条码，2：打印图片（暂不支持）
        printMsg: "", //*必填 string，打印信息
        codeWidth: 1, //*sendtype未1时必填 int, 由于纸长度的原因，宽度width为1-2，宽度为2时最多打印14位，高度heigth为0-255，宽度为1时可通过调整速度和浓度来调整清晰度
        codeHeight: 80, //*sendtype未1时必填 int
        pagerLine: 1, //选填 int, 走纸行数
        concentration: 0, //选填 int，打印浓度设置 1最淡,0正常,2最浓，也可以与速度配合调整浓度
        speed: 7, //选填 int, 打印速度设置 打印速度 0-7 递减，打印图片时速度越慢越顺畅
        lineWidth: 10, //选填 int, 设置行距 0-255
        alignment: 0, //选填 int, 对齐方式 0左对齐，1中间对齐，2右对齐
        underLine: 0, //选填 int, 下划线 0 取消下划线模式1 选择下划线模式(1点宽)2 选择下划线模式(2点宽)
        rigthwidth: 0 //选填 Int, 右间距 0-255
    };
    try {
        for (let line of lines) {
            let printParams = Object.assign(basePrintParams, line);
            longjoeAPI.printSend(printParams, function (ret) {
                if (ret) {
                    if (ret.errMsg) {
                        throw ret.errMsg;
                    }
                } else {
                    throw "获取失败";
                }
            });
        }
    } catch (e) {
        alert(e);
    }
};

$lj.openScanner = async function (callback) {
    let qrScanner = await $lj.getQrScanner();
    qrScanner.openScanner({
        autorotation: false,
        encoding: 1
    }, function (ret, err) {
        if (ret) {
            switch (ret.eventType) {
                case 'success':
                    callback(ret);
                    break;
                case 'cameraError':
                    api.alert({
                        msg: ('访问摄像头失败')
                    });
                    break;
                case 'albumError':
                    api.alert({
                        msg: ('访问相册失败')
                    });
                    break;
                case 'fail':
                    api.alert({
                        title: ret.content,
                        msg: ('扫码失败')
                    });
                    break;
                default:
                    break;
            }
        } else {
            alert(JSON.stringify(err));
        }
    });
};

$lj.apiPushBind = function (userName, userId, callback) {
    var push = api.require('push');
    if (!push) {
        return;
    }
    push.bind({
        userName: userName,
        userId: userId
    }, function (ret, err) {
        if (ret.status) {
            console.log({msg: '绑定成功'});
        } else {
            console.log({msg: err.msg});
        }
    });
};

$lj.apiPushUnBind = function (userName, userId, callback) {
    var push = api.require('push');
    if (!push) {
        return;
    }
    push.unbind({
        userName: userName,
        userId: userId
    }, function (ret, err) {
        if (ret.status) {
            console.log({msg: '解除绑定成功'});
        } else {
            console.log({msg: err.msg});
        }
    });
};
// apicloud 只选选择相册1张图片
$lj.getPicture = async function (callback, size) {
    // 判断访问权限
    var permission = ['storage', 'storage-r', 'storage-w', 'camera', 'photos', 'photos-w'];
    let hasPermission = await $lj.getPermission(permission);
    if(!hasPermission) {
        api.alert("没有相机使用权限,请检查!");
        return;
    }
    var parmImageSize = (typeof arguments[1] === "undefined" || arguments[1] == null) ? imageSize : arguments[1];
    api.actionSheet({
        title: '选择图片来源',
        cancelTitle: '取消',
        buttons: ['照相机', '相册']
    }, function (ret, err) {
        var sourceType;
        switch (ret.buttonIndex) {
            case 1:
                sourceType = 'camera';
                break;
            case 2:
                sourceType = 'album';
                break;
            case 3:
                return;
        }
        api.getPicture({
            sourceType: sourceType,
            encodingType: 'jpg',
            mediaValue: 'pic',
            destinationType: 'base64',
            allowEdit: true,
            quality: 100,
            // targetWidth: screen.width,
            // targetHeight: screen.height,
            saveToPhotoAlbum: false
        }, function (rsp, error) {
            api.showProgress({
                title: '处理图片中',
                text: '请稍候...',
                modal: false
            });
            if (rsp) {
                //DONE:压缩图片
                var oriSize = $lj.calBase64Size(rsp.base64Data);
                console.log("压缩前大小：" + oriSize);
                var img = new Image();
                img.src = rsp.base64Data;
                img.onload = function () {
                    var rate = 1.0000000;

                    if (img.naturalWidth > img.naturalHeight) // 横放
                    {
                        if (img.naturalWidth > 1600 || img.naturalHeight > 1600) {
                            rate = Math.min(1600.0000000 / img.naturalWidth, 1600.0000000 / img.naturalHeight)
                        }
                    }
                    else // 竖放
                    {
                        if (img.naturalWidth > 1600 || img.naturalHeight > 1600) {
                            rate = Math.min(1600.0000000 / img.naturalWidth, 1600.0000000 / img.naturalHeight)
                        }
                    }


                    var targetwidth = img.naturalWidth * rate;
                    var targetheight = img.naturalHeight * rate;
                    var targetquality = imageQuality;

                    $lj.translateImage(rsp.base64Data, {
                        width: targetwidth,
                        height: targetheight,
                        quality: targetquality,
                        imagesize: parmImageSize
                    }, function (base64Codes) {
                        var targetSize = $lj.calBase64Size(base64Codes);
                        console.log("处理后大小" + targetSize);
                        rsp.base64Data = base64Codes;
                        callback(rsp);
                    });
                };


            } else {
                console.log(JSON.stringify(error));
            }
            api.hideProgress();
        });
    });
};

/**
 * apicloud 模块UIAlbumBrowser，多选图片，或拍照
 * @param {*} callback 回调事件
 * @param {Number} max 最多选择几张图片
 * @param {Number} quality 图片压缩质量，0~1
 * @param {Boolean} showCamera 是否显示相机
 */
$lj.getPictureArr = async function(callback, max, quality, showCamera) {
    // 判断访问权限
    var permission = ['storage', 'storage-r', 'storage-w', 'camera', 'photos', 'photos-w'];
    let hasPermission = await $lj.getPermission(permission);
    if(!hasPermission) {
        api.alert("没有相机使用权限,请检查!");
        return;
    }
    var maxSel = (typeof arguments[1] === "undefined" || arguments[1] == null) ? 9 : arguments[1];
    var picQuality = (typeof arguments[2] === "undefined" || arguments[2] == null) ? 0.8 : arguments[2];
    var ifShowCamera = (typeof arguments[3] === "undefined" || arguments[3] == null) ? true : arguments[3];
    var UIAlbumBrowser = api.require('UIAlbumBrowser');
    UIAlbumBrowser.imagePicker({
        max: maxSel,
        showCamera: ifShowCamera,
        animation: true,
        styles: {
            bg: '#000000',
            mark: {
                icon: '',
                position: 'top_right',
                size: 20
            },
            nav: {
                bg: '#000000',
                cancelColor: '#fff',
                cancelSize: 16,
                nextStepColor: '#fff',
                nextStepSize: 16,
                finishText: '确定'
            },
            thumbnail: { //（可选项）返回的缩略图配置，**建议本图片不要设置过大** 若已有缩略图，则使用已有的缩略图。若要重新生成缩略图，可先调用清除缓存接口api.clearCache()。  
                w: 100, //（可选项）数字类型；返回的缩略图的宽；默认：原图的宽度
                h: 100 //（可选项）数字类型；返回的缩略图的宽；默认：原图的高度
            }
        },
    }, function (ret) {
        if (ret.eventType == 'nextStep') {
            var UIAlbumBrowser = api.require('UIAlbumBrowser');
            UIAlbumBrowser.closePicker();
            if (ret.list.length > 0) {
                $lj.dealPicture(ret.list, callback, picQuality)
            }
        } else if (ret.eventType == 'clickCamera' || ret.eventType == "") {
            let List = [];
            List.push({
                path: ret.originalPath
            })
            $lj.dealPicture(List, callback, picQuality)
        }
    });
}

/**
 * 批量处理图片，本地图片转化base64，并压缩
 * @param {*} list 图片数组
 * @param {*} callback 回调事件
 * @param {Number} quality 图片压缩质量，0~1，默认：0.8
 */
$lj.dealPicture = function(list, callback, quality) {
    var picQuality = (typeof arguments[2] === "undefined" || arguments[2] == null) ? 0.8 : arguments[2];
    api.showProgress({
        title: '处理图片中',
        text: '请稍候...',
        modal: false
    });
    var trans = api.require('trans');
    var UIAlbumBrowser = api.require('UIAlbumBrowser');
    list.forEach(el => {
        let path = el.path;
        UIAlbumBrowser.transPath({
            path: path
        }, function(ret, err) {
            if (ret) {
                let name = ret.path.substring(ret.path.lastIndexOf("\/") + 1, ret.path.length);
                trans.decodeImgToBase64({
                    imgPath: ret.path
                }, function (rsp, err) {
                    if (rsp.status) {
                        $lj.compressBase64('data:image/jpeg;base64,' + rsp.base64Str, {quality: picQuality}, function (rett) {
                            if (rett) {
                                let fileType = name.substring(name.lastIndexOf("\.") + 1, name.length);
                                let fileName = name;
                                callback(ret.path, rett, fileType, fileName);
                                api.hideProgress();
                            }
                        })
                    } else {
                        alert(JSON.stringify(err));
                        api.hideProgress();
                        return;
                    }
                });
            } else {
                alert(JSON.stringify(err));
                return;
            }
        });
    });
};

/**
 * apicloud 模块UIAlbumBrowser，多选视频
 * @param {*} callback 
 */
$lj.getVideoFileArr = async function (callback) {
    // 判断访问权限
    var permission = ['storage', 'storage-r', 'storage-w', 'camera', 'photos', 'photos-w'];
    let hasPermission = await $lj.getPermission(permission);
    if(!hasPermission) {
        api.alert("没有相机使用权限,请检查!");
        return;
    }
    let self = this;
    var UIAlbumBrowser = api.require('UIAlbumBrowser');
    UIAlbumBrowser.open({
        max: 9,
        type: "video",
        styles: {
            bg: '#000000',
            mark: {
                icon: '',
                position: 'top_right',
                size: 20
            },
            nav: {
                bg: '#000000',
                cancelColor: '#fff',
                cancelSize: 16,
                nextStepColor: '#fff',
                nextStepSize: 16,
                finishText: '确定'
            }
        },
        rotation: true
    }, function(ret) {
        if (ret) {
            if (ret.eventType == 'confirm') {
                if(ret.list.length > 0){
                    $lj.dealVideo(ret.list, callback);
                }
            }
        }
    });
};

/**
 * 批量处理视频，本地视频转化base64，并压缩
 * @param {*} list 视频数组
 * @param {*} callback 回调事件
 */
$lj.dealVideo = async function(List, callback) {
    let self = this;
    api.showProgress({
        title: '处理视频中',
        text: '请稍候...',
        modal: false
    });
    var trans = api.require('trans');
    var UIAlbumBrowser = api.require('UIAlbumBrowser');
    let ifIos = api.systemType === "ios";
    for (let i = 0; i < List.length; i++) {
        let el = List[i];
        let path = el.videoPath;
        var thumbPath = '';
        UIAlbumBrowser.transPath({
            path: el.thumbPath
        }, function(ret, err) {
            if (ret) {
                trans.decodeImgToBase64({
                    imgPath: ret.path
                }, function (ret, err) {
                    console.log('decodeImgToBase64 ret :>>>>>>>>>>>>>>>>>>>>>', JSON.stringify(ret));
                    if (ret.status) {
                        $lj.compressBase64('data:image/jpeg;base64,' + ret.base64Str, {quality:0.8}, function (ret) {
                            if (ret) {
                                thumbPath = ret;
                            }
                        })
                    } else {
                        api.hideProgress();
                        return;
                    }
                });
            } else {
                alert(JSON.stringify(err));
                return;
            }
        });
        if (ifIos && el.mediaType == 'video') {
            UIAlbumBrowser.transVideoPath({
                path: el.path,
                isSave: true
            }, function(retPath, err) {
                if (retPath) {
                    path = retPath.albumVideoPath;
                    trans.decodeFileToBase64({
                        filePath: path
                    }, function(ret, err) {
                        let name = path.substring(path.lastIndexOf("\/") + 1, path.length);
                        if (ret.status) {
                            var src = 'data:video/mp4;base64,' + ret.base64Str;
                            let fileType = name.substring(name.lastIndexOf("\.") + 1, name.length);
                            let fileName = name;
                            callback(thumbPath, src, fileType, fileName, path);
                            api.hideProgress();
                        } else {
                            api.hideProgress();
                            return;
                        }
                    });
                } else {
                    alert(JSON.stringify(err));
                }
            })
        } else {
            trans.decodeFileToBase64({
                filePath: path
            }, function(ret, err) {
                let name = path.substring(path.lastIndexOf("\/") + 1, path.length);
                if (ret.status) {
                    var src = 'data:video/mp4;base64,' + ret.base64Str;
                    let fileType = name.substring(name.lastIndexOf("\.") + 1, name.length);
                    let fileName = name;
                    callback(thumbPath, src, fileType, fileName, path);
                    api.hideProgress();
                } else {
                    api.hideProgress();
                    return;
                }
            });
        }
    }
};

/**
 * 获取base64文件大小
 * @param base64
 * @returns {string}
 */
$lj.calBase64Size = function (base64) {
    var tag = 'base64,';
    base64 = base64.substring(base64.indexOf(tag) + tag.length);
    var eqTagIndex = base64.indexOf('=');
    base64 = eqTagIndex != -1 ? base64.substring(0, eqTagIndex) : base64;
    var strLen = base64.length;
    var fileSize = strLen - (strLen / 8) * 2;
    // console.log("文件大小:" + (fileSize / 1024).toFixed(1) + 'KB');
    return (fileSize / 1024).toFixed(1);
};

/**
 * 压缩base64
 * @param base64
 * @param parm
 * @param callback
 */
$lj.compressBase64 = function (base64, parm, callback) {
    var img = new Image();
    img.src = base64;
    img.onload = function () {
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        let ratio = img.naturalWidth / img.naturalHeight; //  获取原图比例,为了等比压缩
        canvas.width = 1000;
        canvas.height = 1000 / ratio;
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);    //  画在 canvas 上
        var base64 = canvas.toDataURL("image/jpeg", parm.quality);
        // 回调函数返回base64的值
        callback(base64);
    }
};

$lj.translateImage = function (base64, parm, callback) {
    var img = new Image();
    img.src = base64;
    img.onload = function () {
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        // let ratio = img.naturalWidth / img.naturalHeight; //  获取原图比例,为了等比压缩
        canvas.width = parm.width;
        canvas.height = parm.height;
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);    //  画在 canvas 上
        var base64 = canvas.toDataURL("image/jpeg", parm.quality);
        var size = $lj.calBase64Size(base64);
        while (size > parm.imagesize && parm.quality > 50) {
            parm.quality -= 10;
            base64 = canvas.toDataURL("image/jpeg", parm.quality);
            size = $lj.calBase64Size(base64);
        }

        // 回调函数返回base64的值
        callback(base64);
    }
};


//去除字符串尾部空格或指定字符
$lj.trimEnd = function (str, c) {
    // alert(str);
    if (c == null || c == "") {
        let rg = /s/;
        let i = str.length;
        while (rg.test(str.charAt(--i))) ;
        // alert(i);
        return str.slice(0, i + 1);
    }
    else {
        // let rg = new RegExp(c);
        let i = str.length;
        while (str.charAt(--i) === c) ;
        // alert(i);
        return str.slice(0, i + 1);
    }
};
$lj.queryString2Json = function (string, overwrite) {
    if (!string) {
        return {};
    }
    var obj = {}, pairs = string.split('&'), d = decodeURIComponent, name, value;
    for (let pair of pairs) {
        pair = pair.split('=');
        name = d(pair[0]);
        value = d(pair[1]);
        obj[name] = overwrite || !obj[name] ? value : [].concat(obj[name]).concat(value);
    }
    return obj;
};
/**
 * 全屏浏览图片
 * @param {Array/String} images 图片列表
 * @param {int} index 打开时展示的索引
 * @param {Array/String} md5list 下载图片数据
 */
$lj.photoBrowser = async function (images, index, md5list,only_view = false) {
    // 判断访问权限
    var permission = ['storage', 'storage-r', 'storage-w', 'camera', 'photos', 'photos-w'];
    let hasPermission = await $lj.getPermission(permission);
    if(!hasPermission) {
        api.alert("没有相机使用权限,请检查!");
        return;
    }

    let imgList;
    let showindex;
    let md5listTemp;
    if (typeof images === "string") {
        imgList = [images];
        showindex = 0;
        md5listTemp = [md5list];
    } else {
        imgList = images;
        showindex = index;
        md5listTemp = md5list;
    }
    var photoBrowser = api.require('photoBrowser');
    photoBrowser.open({
        images: imgList,
        activeIndex: showindex,
        placeholderImg: 'widget://res/img/apicloud.png',
        bgColor: '#fff'
    }, function (ret, err) {
        if (ret) {
            if (ret.eventType === "longPress") {
                api.actionSheet({
                    cancelTitle: '取消',
                    buttons: ['下载图片']
                }, function (val, err) {
                    var index = val.buttonIndex;
                    if (index == 1) {
                        if (only_view) {
                            api.alert({
                                msg:'没有下载图片权限!'
                            });
                            return;
                        }
                        var picIndex = ret.index
                        if (md5list && md5list.length > 0) {
                            let user = $lj.getStorage("userInfo");
                            let url;
                            if (user.picBaseUrl) {
                                url = user.picBaseUrl + md5list[picIndex];
                            }
                            var alink = document.createElement("a");
                            alink.href = url;
                            alink.download = "pic"; //图片名
                            alink.click();
                        } else {
                            $lj.checkImgExist(images[picIndex], "jpg", (newPath) => api.saveMediaToAlbum({
                                path: newPath
                            }, function(_res, _err) {
                                if (_res && _res.status) {
                                    api.alert({
                                        msg:'保存成功'
                                    });
                                } else {
                                    api.alert({
                                        msg:'保存失败'
                                    });
                                }
                            }));
                        }
                    }
                });
            }
            if (ret.eventType === "click") {
                photoBrowser.close();
                api.removeEventListener({
                    name: 'keyback'
                });
            }
        } else {
            console.log(JSON.stringify(err));
        }
    });
    $lj.addEventListener("keyback", function () {
        photoBrowser.close();
        api.removeEventListener({
            name: 'keyback'
        });
    });
};
$lj.checkImgExist = function(oldPath,fileType,callback) {
    const fs = $lj.getFileHelperModule();

    let md5 = oldPath;

    let lastIndex = oldPath.lastIndexOf('/'); // 查找最后一个斜杠的位置  
    if (lastIndex !== -1) {  
        md5 = oldPath.slice(lastIndex + 1); // 返回斜杠之后的部分，即文件名  
    }

    fileType = fileType || "jpg";

    $lj.getCacheDir(function (cacheDir) {
        let newPath = cacheDir + "/topic/" + md5 + "." + fileType;
        console.warn("refreshImg getCacheDir:" + cacheDir);
        fs.exist({
            path: newPath
        }, function (ret, err) {
            console.log('newPath ret :>>>>>>>>>>>>>>>>>>>>>', JSON.stringify(ret));
            if (ret.exist) {
                callback(newPath);
                return;
            } else {
                fs.copyTo({
                    oldPath: oldPath,
                    newPath: cacheDir + "/topic"
                }, function(ret, err) {
                    console.log('copyTo ret :>>>>>>>>>>>>>>>>>>>>>', JSON.stringify(ret));
                    if (ret.status) {
                        fs.rename({
                            oldPath: cacheDir + "/topic/" + md5,
                            newPath: newPath
                        }, function (ret, err) {
                            if (ret.status) {
                                callback(newPath);
                            } else {
                                console.error("图片重命名: " + JSON.stringify(err));
                            }
                        });
                    } else {
                        alert('copyTo操作失败，保存中断');
                    }
                });
            }
        });
    });
}
$lj.phoneCall = function (phoneNumber) {
    if (!phoneNumber) {
        return;
    }
    if (!confirm(`确认拨打电话[${phoneNumber}]？`)) {
        return;
    }
    api.call({
        type: 'tel_prompt',
        number: phoneNumber
    });
};
let docHelperModule;
$lj.getDocInteractionModule = function () {
    // https://docs.apicloud.com/Client-API/Func-Ext/docInteraction
    if (!docHelperModule) {
        docHelperModule = api.require("docInteraction");
    }
    return docHelperModule;
};
$lj.selectFile = async function (callback) {
    // 判断访问权限
    var permission = ['storage', 'storage-r', 'storage-w', 'camera', 'photos', 'photos-w'];
    let hasPermission = await $lj.getPermission(permission);
    if(!hasPermission) {
        api.alert("没有相机使用权限,请检查!");
        return;
    }
    $lj.selectDialog("", "请选择附件类型", ['图片', '文件'], function (buttonIndex) {
        if (buttonIndex === 1) {
            api.getPicture({
                mediaValue: 'all',
                allowEdit: true,
                quality: 100
            }, function (ret, error) {
                if (ret) {
                    if (ret.data) {
                        let url = ret.data;
                        $lj.getAttribute(url, function (fileInfo) {
                            callback({
                                url: url,
                                fileName: url.substring(url.lastIndexOf('/') + 1, url.indexOf(".") - 1),
                                fileType: url.substring(url.indexOf(".") + 1),
                                fileSize: fileInfo.size
                            });
                        });
                    }
                } else {
                    alert(JSON.stringify(error));
                }
            });
        } else {
            let fileBrowser = api.require('fileBrowser');
            fileBrowser.open({confirm: true}, function (ret) {
                if (ret) {
                    fileBrowser.close();
                    let url = ret.url;
                    $lj.getAttribute(url, function (fileInfo) {
                        callback({
                            url: url,
                            fileName: url.substring(url.lastIndexOf('/') + 1, url.indexOf(".") - 1),
                            fileType: url.substring(url.indexOf(".") + 1),
                            fileSize: fileInfo.size
                        });
                    });
                }
            });
        }
    });
};
$lj.getAttribute = function (url, callback) {
    let fs = $lj.getFileHelperModule();
    fs.getAttribute({
        path: url
    }, function (ret, err) {
        if (ret.status) {
            callback(ret);
        } else {
            alert(JSON.stringify(err));
        }
    });
};
$lj.getBase64 = function (url, callback) {
    api.readFile({
        path: url
    }, function (ret, err) {
        if (ret.status) {
            alert(JSON.stringify(ret));
            // var data = ret.data;
        } else {
            alert(err.msg);
        }
    });
    // let reader = new FileReader();
    // reader.readAsDataURL(url);
    // alert("getting base64");
    // reader.onloadend = function () {
    //     alert(JSON.stringify(reader));
    //     var base64 = reader.result;
    //     callback({base64:base64});
    // }
    // reader.onload = function () {
    //     alert('load'+JSON.stringify(reader));
    //     var base64 = reader.result;
    //     callback({base64:base64});
    // }
};
let pdfReaderModule;
$lj.getPdfReaderModule = function () {
    if (!pdfReaderModule) {
        pdfReaderModule = api.require("pdfReader");
    }
    return pdfReaderModule;
};
$lj.openFileByUrl = function (path, errcallback) {
    let fs = $lj.getFileHelperModule();
    let existRet = fs.existSync({
        path: path
    });
    if (!existRet.exist) {
        if (errcallback) {
            errcallback({type: 1});
        }
        console.log("文件不存在：" + path);
        // fileMap[md5] = undefined;
        // $lj.setStorage("downloadFileMap", fileMap);
        // $lj.openFile(fileName, fileType, md5);
        return;
    }

    let dotIndex = path.lastIndexOf('.');
    let _path = path;
    if (dotIndex >= 0) {
        _path = _path.substring(_path.lastIndexOf('.') + 1);
    }
    let _fileType = _path.replace(/^\s+|\s+$/g,"").toLowerCase();
    switch (_fileType) {
        case "jpg":
        case "jpeg":
        case "png":
        case "gif":
        case "bmp":
            $lj.photoBrowser(path, 0);
            break;
        case "pdf":
            api.showProgress();
            let pdfReader = $lj.getPdfReaderModule();
            pdfReader.open({
                path: path,
            }, function (ret, err) {
                api.hideProgress();
                if (err) {
                    alert(JSON.stringify(err));
                } else {
                    if (ret.eventType == 'loadFail') {
                        api.alert({
                            msg: "下载文件失败"
                        })
                    }
                }
            });
            break;
        default:
            // doc ppt ...
            let docHelper = $lj.getDocInteractionModule();
            docHelper.open({
                path: path
            }, function (ret, err) {
                if (err) {
                    alert("打开文件失败，可能未安装能打开此文件的应用");
                    console.log(JSON.stringify(err))
                } else {
                    // alert(JSON.stringify(ret));
                }
            });
            break;
    }
};
$lj.openFile = function (fileName, fileType, md5, fileid, requestType) {
    if (!md5) {
        alert("lj-public：未知异常：获取文件MD5失败");
        return;
    }
    if (fileName.lastIndexOf('.') >= 0) {
        fileName = fileName.substring(0, fileName.lastIndexOf('.') - 1);
    }

    let cacheDir = $lj.constant.cacheDir;
    if (!cacheDir) {
        $lj.getCacheDir(function (cacheDir) {
            if (cacheDir) {
                $lj.openFile(fileName, fileType, md5, fileid, requestType);
            }
        });
        return;
    }
    let fs = $lj.getFileHelperModule();
    let path;
    let fileMap = $lj.getStorage("downloadFileMap");
    if (!fileMap) {
        fileMap = {};
        $lj.setStorage("downloadFileMap", fileMap);
    }
    if (fileMap[md5]) {
        path = cacheDir + "/" + fileMap[md5];
        $lj.openFileByUrl(path, function (ret) {
            if (ret.type === 1) {
                // 不存在
                delete fileMap[md5];
                $lj.setStorage("downloadFileMap", fileMap);
                $lj.openFile(fileName, fileType, md5, fileid, requestType);
            }
        });
    } else {
        let token = $lj.getStorage("token");
        let requestAPI, requestBody, dataPropName;
        if (!requestType) { //文件所在，可选项:MailAnnex,OADocAnnex,OADemoAnnex,OAFlowDefAnnex,UFile(默认)
            requestType = "UFile"
        }
        if (fileid) {
            requestAPI = "GetFile";
            requestBody = {token: token, type: requestType, id: fileid};
            dataPropName = "data";
        } else {
            requestAPI = "GetFileDataByMd5";
            requestBody = {token: token, md5: md5};
            dataPropName = "filedata"
        }
        console.log(fileid);
        console.log(JSON.stringify(requestBody));
        $lj.postLJRequest(requestAPI, requestBody, function (ret) {
            let filedata = ret[dataPropName];
            if (filedata) {
                let filename;
                let tryTime = 0;
                let maxTryTimes = 20;
                while (tryTime < maxTryTimes) {
                    filename = fileName + (tryTime ? (`(${tryTime})`) : "") + "." + fileType;
                    let existRet = fs.existSync({
                        path: cacheDir + "/" + filename
                    });
                    console.log(JSON.stringify(existRet));
                    if (!existRet.exist) {
                        break;
                    }
                    tryTime++;
                }
                if (tryTime >= maxTryTimes) {
                    alert("文件下载失败，超出重试次数" + maxTryTimes);
                    return;
                }
                console.error(`!!!!!!!!  renaming ${filedata} to ${filename}  !!!`);
                let oldpath = cacheDir + "/" + filedata;
                let newpath = cacheDir + "/" + filename;
                console.log(oldpath);
                console.log(newpath);
                let renameRet = fs.renameSync({
                    oldPath: oldpath,
                    newPath: newpath
                });
                console.log(JSON.stringify(renameRet));
                if (!renameRet.status) {
                    alert('重命名文件失败！');
                    return;
                }
                let fileMap = $lj.getStorage("downloadFileMap");
                fileMap[md5] = filename;
                $lj.setStorage("downloadFileMap", fileMap);
                $lj.openFile(fileName, fileType, md5, fileid, requestType);
            } else {
                console.error("文件请求失败,md5: " + md5 + (fileid ? (";fileid:" + fileid) : ""));
            }
        });
    }
};

$lj.setAppIconBadge = function (num) {
    api.setAppIconBadge({
        badge: num
    });
};


$lj.setPushListener = function (callback) {
    var push = api.require('push');
    push.setListener(function (ret, err) {
        if (ret) {
            callback(ret);
        } else {
            console.log(JSON.stringify(err));
        }
    });
};

// 获取当前月的第一天
$lj.getCurrentMonthFirst = function () {
    var date = new Date();
    date.setDate(1);
    return date;
};
// 获取当前月的最后一天
$lj.getCurrentMonthLast = function () {
    var date = new Date();
    var currentMonth = date.getMonth();
    var nextMonth = ++currentMonth;
    var nextMonthFirstDay = new Date(date.getFullYear(), nextMonth, 1);
    var oneDay = 1000 * 60 * 60 * 24;
    return new Date(nextMonthFirstDay - oneDay);
};
//按钮确认操作
$lj.confirm = function (title, msg, callback) {
    let pageTitle = (typeof arguments[0] === "undefined" || arguments[0] == null) ? "提示" : arguments[0];
    let pageMsg = (typeof arguments[1] === "undefined" || arguments[1] == null) ? "是否确定操作" : arguments[1];
    api.confirm({
        title: pageTitle,
        msg: pageMsg,
        buttons: ['确定', '取消']
    }, function (ret, err) {
        if (ret.buttonIndex == 1) {
            callback();
        }
    });
};
$lj.selectDialog = function (title, msg, buttons, callback) {
    api.confirm({
        title: title,
        msg: msg,
        buttons: buttons
    }, function (ret, err) {
        callback(ret.buttonIndex);
    });
};

//https://docs.apicloud.com/Client-API/api#35
$lj.prompt = function (title, msg, text, type, callback) {
    api.prompt({
        title: title,
        msg: msg,
        text: text,
        type: type,
        buttons: ['确定', '取消']
    }, function (ret, err) {
        if (ret.buttonIndex == 1) {
            callback(ret.text);
        }
    });
};

$lj.compare = function (propertyName) {
    return function (object1, object2) {
        var value1 = object1[propertyName];
        var value2 = object2[propertyName];
        if (value2 > value1) {
            return -1;
        } else if (value2 < value1) {
            return 1;
        } else {
            return 0;
        }
    }
};


//蓝牙打印模块
$lj.blueToothPrint = function (params, pageWidth, pageHeight) {
    initLongjoeAPI();
    if (typeof pageWidth === 'undefined' || !pageWidth) {
        pageWidth = 586
    }
    if (typeof pageHeight === 'undefined' || !pageHeight) {
        pageHeight = 800
    }
    let size = {pageWidth: pageWidth, pageHeight: pageHeight};
    longjoeAPI.pageSetup(size);
    api.showProgress({
        title: '打印中',
        text: '请稍候...',
        modal: false
    });
    longjoeAPI.printImg(params, function(res) {
        if (res) {
            console.log(JSON.stringify(res));
            if (res.status === 200) {
                alert("打印成功");
            }
            else {
                alert("打印失败:[" + res.status + "]" + res.errMsg);
            }
            api.hideProgress()
        }
    });
};

$lj.blueToothPrint_txt = function (params, pageWidth, pageHeight) {
    initLongjoeAPI();
    // if (typeof pageWidth === 'undefined' || !pageWidth) {
    //     pageWidth = 586
    // }
    // if (typeof pageHeight === 'undefined' || !pageHeight) {
    //     pageHeight = 800
    // }
    // let size = {pageWidth: pageWidth, pageHeight: pageHeight};
    // longjoeAPI.pageSetup(size);
    api.showProgress({
        title: '打印中',
        text: '请稍候...',
        modal: false
    });
    longjoeAPI.printArticle(params, function(res) {
        if (res) {
            console.log(JSON.stringify(res));
            if (res.status === 200) {
                alert("打印成功");
				let obj = {
                    name:res.name,
                    address:res.address
                }
                $lj.setStorage("blueprint",obj)
            }
            else {
                alert("打印失败:[" + res.status + "]" + res.errMsg);
            }
            api.hideProgress()
        }
    });
};

$lj.blueToothPrint_text = function (params, callback) {
    initLongjoeAPI();
    api.showProgress({
        title: '打印中',
        text: '请稍候...',
        modal: false
    });
    longjoeAPI.k329print(params, function(res) {
        if (res) {
            console.log(JSON.stringify(res));
            if (res.status) {
                alert("打印成功");
				let obj = {
                    address:res.address
                }
                $lj.setStorage("blueprint",obj)
                typeof callback === "function" ? callback() : false;
            }
            else {
                alert("打印失败:" + res.errMsg);
            }
            api.hideProgress()
        }
    });
};

$lj.printerStatus = function () {
    initLongjoeAPI();
    longjoeAPI.printerStatus(function(ret) {
        console.log(ret.status);
    })
}


//极光推送https://docs.apicloud.com/Client-API/Open-SDK/ajpush
//初始化
$lj.ajpushInit = function () {
    var ajpush = api.require('jpushVip');
    if (!ajpush){
        return;
    }
    ajpush.setAuth({
        auth:true
    },function(ret) {
        if (ret && ret.status){
            ajpush.init(function (ret) {
                if (ret && ret.status) {
                    console.log("极光推送初始化" + JSON.stringify(ret))
                }
            });
        }
    });
};

$lj.ajpusGetRegistrationId = function (callback) {
    var ajpush = api.require('jpushVip');
    if (!ajpush){
        return;
    }
    ajpush.getRegistrationId(function (ret) {
        if (ret) {
            console.log("获取设备id" + JSON.stringify(ret));
            callback(ret);
        }
    });
};

$lj.setViewPortWidth = function (width) {
    let clientWidth = window.screen.width;
    let viewport = document.querySelector('meta[name="viewport"]');
    let viewportScale = clientWidth / width;
    viewport.setAttribute('content', 'width=' + width + ', initial-scale=' + viewportScale + ', maximum-scale=' + viewportScale + ', user-scalable=0');
};
$lj.getVersion = function () {
    return api.appVersion;
};
$lj.transVersionToInt = function (data) {
    var arr = data.split('.');
    if (arr.length >= 3) {
        var yearStr = arr[0].replace(/[a-zA-Z]/g, "");
        var weekStr = (Array(2).join(0) + arr[1]).slice(-2);
        var num = (Array(2).join(0) + arr[2]).slice(-2);
        return yearStr + weekStr + num;
    } else {
        return ""
    }
};
// 计划弃用
$lj.checkAppUpdate = function (checkPassCallback, updateCallback, progressCallback) {
    if (api.systemType === "ios" || !initLongjoeAPI()) {
        if (checkPassCallback) {
            checkPassCallback();
        }
        return;
    }
    let cacheDir = $lj.constant.cacheDir;
    if (!cacheDir) {
        $lj.getCacheDir(function (cacheDir) {
            if (cacheDir) {
                $lj.checkAppUpdate(checkPassCallback, updateCallback, progressCallback);
            }
        });
        return;
    }
    let updateRequest = {
        appname: productInfo.productCode,
        oldmd5: $lj.getVersion(),
        type: 0
    };
    let serverConnectParams = $lj.getStorage("serverConnectParams");
    if (serverConnectParams.cusid) {
        updateRequest.type = 1;
    }

    $lj.postLJRequest("GetTVUpdate", updateRequest, function (ret) {
        let fileName = productInfo.productCode + "_" + ret.newmd5.replace(/\./g, "_") + ".apk";
        if (ret.apkdata) {
            // 更新
            $lj.updateApp(ret.apkdata, fileName, updateCallback);
        }else if (ret.url) {
            let newpath = cacheDir + "/" + fileName;
            api.download({
                url: ret.url,
                savePath: newpath,
                report: true,
                cache: true,
                allowResume: true
            }, function(ret, err) {
                if (ret.state === 1) {
                    //下载成功
                    $lj.updateApp(fileName, fileName, updateCallback);
                } else {
                    if (progressCallback){
                        progressCallback(ret.percent);
                    }
                }
            });
        } else {
            // 无需更新
            if (checkPassCallback) {
                checkPassCallback();
            }
        }
    }, function () {
        // 网络请求失败
        if (checkPassCallback) {
            checkPassCallback();
        }
    }, null, null, {title: "下载更新中",text: "请勿退出程序"});
};
// 拆分下载更新逻辑
$lj.checkAppUpdate_new = function (beforeRequestCallback, checkPassCallback, downloadCB) {
    // if (api.systemType === "ios" || !initLongjoeAPI()) {
    if (!initLongjoeAPI()) {
        if (checkPassCallback) {
            checkPassCallback();
        }
        return;
    }
    let cacheDir = $lj.constant.cacheDir;
    if (!cacheDir) {
        $lj.getCacheDir(function (cacheDir) {
            if (cacheDir) {
                $lj.checkAppUpdate_new(beforeRequestCallback, checkPassCallback, downloadCB);
            }
        });
        return;
    }
    let appname = productInfo.productCode;
    if (api.systemType === "ios") {
        appname = appname + "_ios"
    }
    let updateRequest = {
        appname: appname,
        oldmd5: $lj.getVersion(),
        type: 0
    };
    let serverConnectParams = $lj.getStorage("serverConnectParams");
    if (serverConnectParams.cusid || api.systemType === "ios") {
        updateRequest.type = 1;
    }
    // 设置额外的参数
    if (beforeRequestCallback) {
        updateRequest = beforeRequestCallback(updateRequest)
    }

    $lj.postLJRequest("GetTVUpdate", updateRequest, function (ret) {
        if (ret.apkdata || ret.url || (updateRequest.hasOwnProperty("skipApkdata") && updateRequest.skipApkdata == 1)) {
            downloadCB(ret);
        } else {
            if (api.systemType === "ios") {
                downloadCB(ret);
            } else if (checkPassCallback) {
                checkPassCallback(202)
            }
        }
    }, function (ret) {
        // 网络请求失败
        if (checkPassCallback) {
            checkPassCallback(404, ret);
        }
    }, true);
};
$lj.download = function(url, savePath, successCB, progressCB, errorCB) {
    api.download({
        url: url,
        savePath: savePath,
        report: true,
        cache: true,
        allowResume: true
    }, function(ret, err) {
        if (ret.state === 1) {
            //下载成功
            successCB && successCB(ret)
        } else {
            progressCB && progressCB(ret)
        }
        if (err) {
            errorCB && errorCB(err)
        }
    });
}
$lj.updateApp = function (rawName, newName, updateCallback) {
    let cacheDir = $lj.constant.cacheDir;
    if (!cacheDir) {
        $lj.getCacheDir(function (cacheDir) {
            if (cacheDir) {
                $lj.updateApp(rawName, newName, updateCallback);
            }
        });
        return;
    }
    let oldpath = cacheDir + "/" + rawName;
    let newpath = cacheDir + "/" + newName;
    console.log(oldpath);
    console.log(newpath);
    if (oldpath != newpath){
        let fs = $lj.getFileHelperModule();
        let renameRet = fs.renameSync({
            oldPath: oldpath,
            newPath: newpath
        });
        console.log(JSON.stringify(renameRet));
        if (!renameRet.status) {
            alert('重命名文件失败！');
            return;
        }
    }
    if (updateCallback) {
        updateCallback({
            appUri: newpath
        });
    }
};
$lj.pushPrintTask = function ({keyname, chnname, parm, parmflag, printername}, callback, errcallback) {
    $lj.postLJRequest("GWPrintByParmFlag", {
        token: $lj.getStorage("token"),
        keyname: keyname,
        chnname: chnname,
        parm: parm,
        parmflag: parmflag,
        printername: printername
    }, callback, errcallback);
};

/**PDA - 使用-start */
$lj.OkSound = function () {
    api.startPlay({
        path: "widget://assets/sound/ok-hint.mp3"
    });
}
$lj.FailSound = function () {
    api.startPlay({
        path: "widget://assets/sound/light-hint.mp3"
    });
    api.notification({
        vibrate:[200,200,200,200,200,200],
    });
}
$lj.WarnSound = function () {
    api.startPlay({
        path: "widget://assets/sound/ding-hint.mp3"
    });
    api.notification({
        vibrate:[200,100],
    });
}
/**PDA - 使用-end */
/**
 * 金额缩略显示
 * @param s 数值
 * @param n 小数保留位数
 * @returns {*}
 */
$lj.numberFormat = function(s,n) {
    n = n !== undefined && n >= 0 && n <= 20 ? n : 2;  
    var sum = Math.abs(Number(s));
    sum = parseFloat((sum + "").replace(/[^\d\.-]/g, "")).toFixed(n) + "";
    let r = n ? "." + sum.split(".")[1] : "";
    var l = sum.split(".")[0].split("").reverse();
    var t = "";  
    for (var i = 0; i < l.length; i++) {  
        t += l[i] + ((i + 1) % 3 == 0 && (i + 1) != l.length ? "," : "");  
    }
    if (s < 0) return "-" + t.split("").reverse().join("") + r;
    return t.split("").reverse().join("") + r;

}

/**
 * 金额缩略显示——简略版 n=3 eg: 1.34k，23.6m
 * @param {Number} s 数值
 * @param {Number} n 数字保留位数
 * @param {Boolean} f 是否中文显示微标
 * @param {Boolean} chn 是否启用中式数值显示，eg: 原：10k，新：1万
 * @returns 
 */
 $lj.numberFormatShort = function(s, n, f, chn) {
    let _f = (typeof arguments[2] === "undefined" || arguments[2] == null) ? undefined : arguments[2];
    let _chn = (typeof arguments[3] === "undefined" || arguments[3] == null) ? undefined : arguments[3];
    if (s == 0) return s;
    n = n !== undefined && n >= 0 && n <= 20 ? n : 2;  
    var i = 0;
    var sum = Number(s);
    _chn && (sum = sum / 10);
    for (; sum >= 1000; i++) {
        sum = sum / 1000;
    }
    var u = "";
    if (_chn) {
        switch(i) {
            case 4:
                u = "十万亿"
                break;
            case 3:
                u = "百亿"
                break;
            case 2:
                u = "千万"
                break;
            case 1:
                u = "万"
                break;
            case 0:
                sum = sum * 10;
                break;
        }
    } else {
        switch(i) {
            case 4: // 万亿
                if (_f) {
                    u = "万亿"
                } else {
                    u = "t"
                }
                break;
            case 3: // 十亿
                if (_f) {
                    u = "十亿"
                } else {
                    u = "b"
                }
                break;
            case 2: // 百万
                if (_f) {
                    u = "百万"
                } else {
                    u = "m"
                }
                break;
            case 1: // 千
                if (_f) {
                    u = "千"
                } else {
                    u = "k"
                }
                break;
        }
    }
    var l = sum.toString().split(".")[0].split("");
    n = n < l.length ? 0 : n - l.length;
    sum = Math.floor((sum + "").replace(/[^\d\.-]/g, "") * Math.pow(10, n)) / Math.pow(10, n);
    sum = parseFloat(sum).toFixed(n);
    return sum + u;
}

/**
 * 中式金额缩略显示
 * @param s 数值
 * @param n 小数保留位数
 * @returns 
 */
 $lj.numberFormatCHN = function(s, n) {
    if (s == 0) return s;
    n = n !== undefined && n >= 0 && n <= 20 ? n : 2;  
    var i = 0;
    var sum = Math.abs(Number(s));
    for (; sum >= 10000; i++) {
        sum = sum / 10000;
    }
    var u = "";
    switch(i) {
        case 3:
            u = "万亿"
            break;
        case 2:
            u = "亿"
            break;
        case 1:
            u = "万"
            break;
    }
    sum = Math.floor((sum + "").replace(/[^\d\.-]/g, "") * Math.pow(10, n)) / Math.pow(10, n);
    sum = parseFloat(sum).toFixed(n);

    var l = sum.split(".")[0].split("").reverse();
    var r = n ? "." + sum.split(".")[1] : "";
    var t = "";  
    for (var i = 0; i < l.length; i++) {  
        t += l[i] + ((i + 1) % 3 == 0 && (i + 1) != l.length ? "," : "");  
    }
    if (s < 0) return "-" + t.split("").reverse().join("") + r + u;
    return t.split("").reverse().join("") + r + u;
}


/**
 * 小数点加、减、乘、除
 * @param {Number} arg1 数1
 * @param {Number} arg2 数2
 * @returns 
 */
$lj.floatAdd = function(arg1,arg2){  
    var r1,r2,m;  
    try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0}  
    try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0}  
    m=Math.pow(10,Math.max(r1,r2));  
    return (arg1*m+arg2*m)/m;  
}
$lj.floatSub = function(arg1,arg2){  
   var r1,r2,m,n;  
   try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0}  
   try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0}  
   m=Math.pow(10,Math.max(r1,r2));  
   //动态控制精度长度  
   n=(r1>=r2)?r1:r2;  
   return ((arg1*m-arg2*m)/m).toFixed(n);  
}
$lj.floatMul = function(arg1,arg2)   {   
    var m=0,s1=arg1.toString(),s2=arg2.toString();   
    try{m+=s1.split(".")[1].length}catch(e){}   
    try{m+=s2.split(".")[1].length}catch(e){}   
    return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m);   
}
$lj.floatMulMore = function(arr)   {   
    var m=0,sum = 1;
    for (const item of arr) {
        if (item) {
            let s1 = item.toString();
            try{m+=s1.split(".")[1].length}catch(e){}   
            sum = sum * Number(s1.replace(".",""))
        }
    }
    return Number(sum)/Math.pow(10,m);  
}
$lj.floatDiv = function(arg1,arg2){   
     var t1=0,t2=0,r1,r2;   
     try{t1=arg1.toString().split(".")[1].length}catch(e){}   
     try{t2=arg2.toString().split(".")[1].length}catch(e){}   

     r1=Number(arg1.toString().replace(".",""));
     r2=Number(arg2.toString().replace(".",""));   
     return (r1/r2)*Math.pow(10,t2-t1);   
}

/**
 * 获取历史记录账套密码
 * @param {string} currentAccount 当前账套名称
 * @returns {Object} 账套密码对象
 */
$lj.getUserAccHistoryAccount = function(currentAccount) {
    let maxList = {};
    let accountList = {};
    let userHistory = $lj.getStorage("userHistory") || {};
    let userHistoryAccount = $lj.getStorage("userHistoryAccount") || [];
    if (userHistoryAccount.length > 0) {
        let index = -1;
        for (let i = 0; i < userHistoryAccount.length; i++) {
            if (userHistoryAccount[i].name == currentAccount) {
                index = i;
                break;
            }
        }
        if (index > -1) {
            accountList = userHistoryAccount[index].account;
        }
    }
    Object.assign(maxList, userHistory, accountList);
    return maxList
}

/**
 * 检测IP地址合法性
 * @param {string} ip 
 * @returns 
 */
$lj.isValidIP = function(ip) {
    var reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
    return reg.test(ip);
}

$lj.getCacheSize = function() {
    api.getCacheSize(function(ret, err) {
        //size:        //缓存大小，单位为Byte，数字类型。（-1：无存储设备、-2：正在准备USB存储设备、-3：无法访问存储设备）
        var size = parseInt(ret.size/1024) + 'KB';
        console.log('缓存大小—————————————————— :>> ', size);
        console.log('缓存大小—————————————————— :>> ', parseInt(ret.size/1024/1024) + 'MB');
    });
}

$lj.clearCache = function() {
    api.clearCache(function() {
        api.toast({
            msg: '清除完成'
        });
        $lj.getCacheSize();
    });
}

/**
 * 匹配L1生成的QrCode 格式：storageID + '{' + localName + '}'
 * @param {string} word 
 * @returns 
 */
$lj.matchStorageQrCode = function(word) {
    let keyWord;
    var reg = /\{(.+?)\}/;
    var reg_g = /\{(.+?)\}/g;
    var result = word.match(reg_g);
    // 选择仓库信息
    if (word.indexOf("{") > -1 && word.indexOf("}") > -1) {
        if (result == null) {
            // 字符串有{}
            // 删除{}
            keyWord = word.replace(/\{\}/, "");
        } else if (result.length) {
            // 当出现一对或多对{}时，只取最后一个有值的那一对{}
            keyWord = result[result.length - 1].match(reg)[1];
        }
    } else {
        // 字符串没有{}
        keyWord = word;
    }
    return keyWord;
}

/**
 * 提取L1生成的QrCode 格式：storageID + '{' + localName + '}'
 * @param {string} word 
 * @returns {object} 0:不符合编码标准；{storageid, locacoded}
 */
$lj.getStorageQrCode = function(word) {
    let keyWord = {};
    let storageid = 0;
    let locacode = "";
    var reg = /\{(.+?)\}/;
    var reg_g = /\{(.+?)\}/g;
    var result = word.match(reg_g);
    // 选择仓库信息
    if (word.indexOf("{") > -1 && word.indexOf("}") > -1) {
        if (result == null) {
            // 字符串有{}
            // 删除{}
            storageid = parseInt(word.replace(/\{\}/, ""));
            keyWord = {
                storageid
            }
        } else if (result.length) {
            // 当出现一对或多对{}时，只取最后一个有值的那一对{}
            storageid = parseInt(word.substring(0, word.indexOf("{")));
            locacode = result[result.length - 1].match(reg)[1];
            keyWord = {
                storageid,
                locacode
            }
        }
    } else {
        // 字符串没有{}
        return 0;
    }
    return keyWord;
}

/**
 * 颜色转码，十六进制编码转rgb 或 rgba
 * @param {String} hex 十六进制编码
 * @param {String/Number} opacity 有提供输出rgba, 缺失输出rgb
 * @returns 
 */
$lj.colorHexToRgb_a = function(hex, opacity) {
    let _opacity = (typeof arguments[1] === "undefined" || arguments[1] == null) ? undefined : arguments[1];
    let color = hex.toLowerCase();
    let pattern = /^#([0-9|a-f]{3}|[0-9|a-f]{6})$/;
    if(color && pattern.test(color)) {

        if(color.length == 4) {
            // 将三位转换为六位
                color = '#' + color[1] + color[1] + color[2] + color[2] + color[3] + color[3];
        }
        if (color.length == 7) {
            //处理六位的颜色值
            let colorNew = [];
            for (var i=1; i<7; i+=2) {
                colorNew.push(parseInt("0x"+color.slice(i, i+2)));  
            }
    
            if (_opacity == undefined) {
                // toRGB
                return "RGB(" + colorNew.join(",") + ")";
            } else {
                // toRGBA
                return "RGBA(" + colorNew.join(",") + "," + _opacity + ")";
            }
        }
        return color;
    }
    return color;
}

/**
 * 业务逻辑：是否开启新仓位模式
 * @param {Object} storage 仓库 
 */
$lj.ifUselocation = function(storage) {
    let bool;
    if(storage.iflocation == 0){
        // 不使用仓位
        bool = false;
    }else{
        let option437 = $lj.getOptionValue(437);
        // 新仓位判断逻辑
        if (option437 == 1 || (option437 == 2 && Number(storage.uselocation) == 1)) {
            bool = true;
        } else {
            bool = false
        }
    }
    return bool;
}

/**
 * 业务逻辑：检测明细：
 * 1、关键数值是否与新仓位数量一致
 * 2、仓位信息是否必填
 * @param {Array} mxList 明细列表
 * @param {Stirng} numProps 目标数量值名称
 * @param {String} locationProp 目标仓位值名称
 * @param {int} stoargeId 目标仓库id
 * @param {Boolean} ifSkipZero 是否跳过数量为0的明细
 * @returns i -1表示通过
 */
$lj.checkMxStorage = function(mxList, numProps, locationProp, stoargeId, ifSkipZero) {
    let ifAllStoarge = (typeof arguments[3] === "undefined" || arguments[3] == null) ? false : true;
    let tgStorage = null; // 目标仓库
    
    // 获取仓库列表
    let storageInfo = $lj.getStorage("storageInfo") || {};
    if (storageInfo.storagePower == null || storageInfo.storagePower == "") {
        $lj.toast("该用户的仓库权限不存在 / 该用户不存在");
        return false;
    }
    if (storageInfo.storagePower == "-1") {
        $lj.toast("你没有仓库权限");
        return false;
    }
    let storageList = storageInfo.storageList;
    
    if (ifAllStoarge) {
        // 整单同一仓库
        for (let j = 0; j < storageList.length; j++) {
            if (storageList[j].storageid == stoargeId) {
                tgStorage = storageList[j];
                break;
            }
        }

        for (let i = 0; i < mxList.length; i++) {
            if (ifSkipZero) {
                if (mxList[i][numProps] == 0 || mxList[i][numProps] == '') {
                    continue;
                }
            }
            let msg = $lj.fnCheckStorage(mxList[i], i + 1, tgStorage, numProps, locationProp);
            if (msg) {
                $lj.toast(msg);
                return i;
            }
        }
    } else {
        // 明细独立仓库
        let lastId = 0;
        for (let i = 0; i < mxList.length; i++) {
            if (ifSkipZero ) {
                if (mxList[i][numProps] == 0 || mxList[i][numProps] == '') {
                    continue;
                }
            }
            // 1：找出仓库信息主体
            if (lastId != mxList[i].storageid) {
                for (let j = 0; j < storageList.length; j++) {
                    if (storageList[j].storageid == mxList[i].storageid) {
                        tgStorage = storageList[j];
                        break;
                    }
                }
                lastId = mxList[i].storageid; // 避免过多重复查询
            }
            let msg = $lj.fnCheckStorage(mxList[i], i + 1, tgStorage, numProps, locationProp);
            if (msg) {
                $lj.toast(msg);
                return i;
            }
        }
    }
    
    return -1;
}
/**
 * 检查仓位逻辑
 * 1、关键数值是否与新仓位数量一致
 * 2、仓位信息是否必填
 * @param {Object} item 明细信息
 * @param {int}} i 索引
 * @param {Object}} tgStorage 仓库信息
 * @param {String} numProps 目标数量值名称
 * @param {String} locationProp 目标仓位值名称
 * @returns errmsg
 */
$lj.fnCheckStorage = function(item, i, tgStorage, numProps, locationProp) {
    // 比较：关键数值是否与新仓位数量一致
    let ifUselocation = $lj.ifUselocation(tgStorage);
    let ifhaslocatext = item[locationProp] == '' || item[locationProp] == '-' || item[locationProp].indexOf('请选择') > -1
    // 检测仓库基本属性
    if (tgStorage.mustloca) {
        // 仓位必填
        if (ifhaslocatext) {
            return `警告：第${i}行仓位必填，请检查`
        }
    } else if (ifhaslocatext) {
        if (ifUselocation) {
            return `警告：第${i}行仓位必填，请检查`
        }
        // 当非必填，且无内容时，跳过验证
        return ''
    }
    if (ifUselocation) {
        // 使用新仓位模式
        if (item[locationProp].indexOf(";") > -1) {
            let location = item[locationProp].split(';');
            let sum = 0;
            location.forEach(item => {
                if (item.indexOf(':') > -1) {
                    sum += Number(item.match(/:(\S*)/)[1]);
                }
            });
            if (sum != Number(item[numProps])) {
                return `警告：第${i}行仓位数量不一致，请检查`
            }
        } else {
            return `警告：第${i}行的仓位格式有误，请检查`
        }
    }
    return ''
}

/**
 * 搜索筛选：刷新用户习惯
 * @param {String} habitKey 用户筛选关键字，一般是ApiName
 * @param {Array/Object} params 筛选关键信息
 * @returns 返回筛选信息
 */
$lj.setUserFilterParams = function (habitKey, params) {
    if (!habitKey) $lj.toast("编程：请传入用户习惯关键id");
    let queryStorage = "userQueryHabit";
    let userhabit = $lj.getStorage(queryStorage) || {};
    let thisHabit = userhabit[habitKey] || {};
    if (params instanceof Array) {
        params.forEach((field) => {
            if (field.type === 'date') {
                thisHabit[field.property] = $lj.getDiffDays(new Date(), field.value);
            } else {
                thisHabit[field.property] = field.value;
            }
        });
    } else {
        for (let key in params) {
            if (key.indexOf('date') > -1) {
                if (params[key] === null) {
                    thisHabit[key] = null;
                } else {
                    thisHabit[key] = $lj.getDiffDays(new Date(), params[key]);
                }
            } else {
                thisHabit[key] = params[key];
            }
        }
    }
    userhabit[habitKey] = thisHabit;
    console.log('记录值 setUserFilterParams thisHabit :>> ', JSON.stringify(thisHabit));
    $lj.setStorage(queryStorage, userhabit);
    return thisHabit;
}
$lj.setUserFilterTitle = function (habitKey, params) {
    if (!habitKey) $lj.toast("编程：请传入用户习惯关键id");
    let titleStorage = "userFilterTitle";
    let userhabit = $lj.getStorage(titleStorage) || {};
    let thisHabit = userhabit[habitKey] || {};
    if (params instanceof Array) {
        params.forEach((field) => {
            if (field.type === 'date') {
                // thisHabit[field.property] = $lj.getDiffDays(new Date(), self.currentQueryParams[field.property]);
            } else {
                thisHabit[field.property] = field.title;
            }
        });
    } else {
        thisHabit = Object.assign({}, thisHabit, params);
    }
    userhabit[habitKey] = thisHabit;
    console.log('只记录名称 setUserFilterTitle thisHabit :>> ', JSON.stringify(thisHabit));
    $lj.setStorage(titleStorage, userhabit);
}
$lj.getUserFilterParams = function (habitKey) {
    if (!habitKey) $lj.toast("编程：请传入用户习惯关键id");
    let queryStorage = "userQueryHabit";
    let userhabit = $lj.getStorage(queryStorage) || {};
    let thisHabit = userhabit[habitKey] || {};

    for (let key in thisHabit) {
        if (key.indexOf('date') > -1) {
            if (typeof thisHabit[key] !== "undefined" && thisHabit[key] !== null) {
                let date = $lj.dateAdd(new Date(), 0, 0, thisHabit[key]);
                if (key.indexOf('begin') > -1) {
                    thisHabit[key] = $lj.parseTime(date, '{y}-{m}-{d} 00:00');
                } else if (key.indexOf('end') > -1) {
                    thisHabit[key] = $lj.parseTime(date, '{y}-{m}-{d} 23:59');
                } else {
                    thisHabit[key] = $lj.parseTime(date);
                }
            }
        }
    }
    return thisHabit;
}
$lj.getUserFilterTitle = function (habitKey) {
    if (!habitKey) $lj.toast("编程：请传入用户习惯关键id");
    let queryStorage = "userFilterTitle";
    let userhabit = $lj.getStorage(queryStorage) || {};
    let thisHabit = userhabit[habitKey] || {};
    return thisHabit;
}


/**
 * Parse the time to string
 * @param {(Object|string|number)} time
 * @param {string} cFormat default: {y}-{m}-{d} {h}:{i}:{s}
 * @returns {string | null}
 */
$lj.parseTime = function(time, cFormat) {
    if (arguments.length === 0 || !time) {
        return null
    }
    let format = cFormat || `{y}-{m}-{d} {h}:{i}:{s}`
    if (api.systemType === "ios") {
        // 时间分割线，ios不支持new Date("2000-01-01"),请使用"/"
        format = format.replace(/-/g, '/');
    }
    let date
    if (typeof time === 'object') {
        date = time
    } else {
        if ((typeof time === 'string')) {
            if ((/^[0-9]+$/.test(time))) {
                time = parseInt(time)
            } else {
                time = time.replace(new RegExp(/-/gm), '/')
            }
        }
  
        if ((typeof time === 'number') && (time.toString().length === 10)) {
            time = time * 1000
        }
        date = new Date(time)
    }
    const formatObj = {
        y: date.getFullYear(),
        m: date.getMonth() + 1,
        d: date.getDate(),
        h: date.getHours(),
        i: date.getMinutes(),
        s: date.getSeconds(),
        a: date.getDay()
    }
    const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
        const value = formatObj[key]
        // Note: getDay() returns 0 on Sunday
        if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
        return value.toString().padStart(2, '0')
    })
    return time_str
}

/**
 * 最近时间-秒差
 * @param {number} time
 * @param {string} option
 * @returns {number} 秒
 */
 function isSameDay(timeStampA, timeStampB) {
    let dateA = new Date(timeStampA);
    let dateB = new Date(timeStampB);
    // return (dateA.setHours(0, 0, 0, 0) == dateB.setHours(0, 0, 0, 0));
    return (dateA.setHours(0, 0, 0, 0) - dateB.setHours(0, 0, 0, 0));

}
$lj.formatTime = function(time, option, ifshort) {
   if (typeof time == "Number") {
       if (('' + time).length === 10) {
         time = parseInt(time) * 1000
       } else {
         time = +time
       }
   }
   const d = new Date(time);
   const now = new Date();
 
   const diff = (now - d) / 1000
 
   if (ifshort) {
       if (diff < 0) {
           // flutter
       } else if (diff < 30) {
         return '刚刚'
       } else if (diff < 3600) {
         // less 1 hour
         return Math.ceil(diff / 60) + '分钟前'
       } else if (diff < 3600 * 6) {
           // 1~6小时
         return Math.ceil(diff / 3600) + '小时前'
       }
       let hourMins = $lj.parseTime(time, '{h}:{i}')
       switch (isSameDay(now, d)) {
           case 0:
               return `今天 ${hourMins}`
           case 86400000:
               return `昨天 ${hourMins}`
           // case 172800000:
           //     return `前天 ${hourMins}`
       }
       if (now.getFullYear() == d.getFullYear()) {
           return  $lj.parseTime(time, '{m}-{d} {h}:{i}')
       } else {
           return  $lj.parseTime(time, '{y}-{m}-{d} {h}:{i}')
       }
   }

   if (option) {
     return  $lj.parseTime(time, option)
   // } else {
   //   return (
   //     d.getMonth() +
   //     1 +
   //     '月' +
   //     d.getDate() +
   //     '日' +
   //     d.getHours() +
   //     '时' +
   //     d.getMinutes() +
   //     '分'
   //   )
   }
}

/**
 * 获取单据名称
 * @param {String} billcode 
 * @returns String
 */
 $lj.getBillcodeName = function (billcode) {
    let firststr = billcode.toUpperCase().match(/[^\u4e00-\u9fa5\d,\.，。]+/)[0];
    if ($lj.billcodeStyleName.hasOwnProperty(firststr)) {
        return $lj.billcodeStyleName[firststr]
    } else {
        let billstyle = '';
        let userInfo = $lj.getStorage("userInfo");
        if (userInfo && userInfo.billcodeList) {
            for (let bcode of userInfo.billcodeList) {
                if (bcode.formername.split(',').indexOf(firststr.toUpperCase()) > -1) {
                    billstyle = bcode.billstyle;
                    break;
                }
            }
        }
        if (billstyle) {
            $lj.billcodeStyleName[firststr] = billstyle;
            return billstyle
        } else {
            $lj.toast('未定义单据名称')
        }
    }
}

$lj.stringEqualsIgnoreCase = function (a,b) {
    if (a && b){
        return a.toLowerCase() == b.toLowerCase();
    } else {
        return a == b;
    }
}

/**
 * 安卓PDA：Mobydata 扫描识别器匹配安装
 */
$lj.registerDecodeReceiver = function() {
    if (!longjoeAPI) {
        console.log("---------------------------registerDecodeReceiver requiring longjoeapi module-----------------------");
        longjoeAPI = api.require('longjoeAPI');
    }
    longjoeAPI.registerDecodeReceiver();
}

/**
 * 格式化版本号
 * @param {string} version 版本号
 * @returns 
 */
$lj.transClientVerToInt = function (version) {
    let arr = version.split('.');
    var yearStr = (Array(2).join(0) + arr[0].replace(new RegExp("[a-zA-Z]"), "")).slice(-2);
    var weekStr = (Array(2).join(0) + arr[1]).slice(-2);
    var num = (Array(2).join(0) + arr[2]).slice(-2);
    return yearStr + weekStr + num;
}

/**
 * 深度复制对象（含函数）
 * @param {*} target 目标对象
 * @param {*} other 基础对象
 * @returns 
 */
$lj.deepCopyFn = function(obj){
    let objToString = Object.prototype.toString.call(obj);
    if ( objToString === '[object Object]' || objToString === '[object Arrty]') {
        var result = Array.isArray(obj) ? [] : {};
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                if (typeof obj[key] === 'object') {
                    result[key] = $ljTvBoard.deepCopyFn(obj[key]);  // 如果是对象，再次调用该方法自身
                } else {
                    result[key] = obj[key];
                }
            }
        }
        return result;
    } else {
        return obj
    }
}

$lj.sensitiveData = function(value, type) {
    if(!value) return '';
    value = value.toString();
    if (type == "identity") {
        // 身份证
        return value.replace(/(\w{6})\w*(\w{4})/, '$1******$2');
    } else if (type == "phone") {
        // 电话
        return value.replace(/(\w{3})\w*(\w{4})/, '$1******$2');
    } else if (type == "name") {
        // 姓名
        if (value.length > 3) {
            const start = new Array(2).join('*' + '*')
            const end = value.slice(-1)
            return `${start}${end}`
        } else {
            const start = new Array(value.length).join('*')
            const end = value.slice(-1)
            return `${start}${end}`
        }
    } else {
        // 金额
        return "****";
    }
};

/**
 * apicloud模块：phoneInfoMore
 * 获取手机MAC地址
 */
$lj.getMacAddress = function() {
    return new Promise((resolve, reject) => {
        var phoneInfoMore = api.require('phoneInfoMore');
        phoneInfoMore.getMacAddressNew(function(ret, err) {
            console.warn('getMacAddress ret :>>>>>>>>>>>>>>>>>>>>>', JSON.stringify(ret));
            var result = undefined;
            if (ret == "02:00:00:00:00:00" || err) {
                result = '';
            } else {
                result = ret;
            }
            resolve(result)
        });
    })
}

/**
 * apicloud模块：phoneInfoPlus
 * 获取UUID。注意：Android获取uuid需要“READ_PHONE_STATE”权限，此权限为敏感权限，需要在隐私政策中说明，否则上架应用市场可能无法通过审核。
 * @returns 
 */
$lj.getUUIDToPhoneInfoPlus = function() {
    return new Promise((resolve, reject) => {
        var phoneInfoPlus = api.require('phoneInfoPlus');
        var permission = ['phone-r'];
        var resultList = api.hasPermission({
            list: permission
        });
        if (resultList[0].granted) {
            phoneInfoPlus.getUUID(function(ret) {
                var result = '';
                if (ret.hasOwnProperty('uuid')) {
                    result = ret.uuid;
                }
                resolve(result)
            });
        } else {
            reject('')
        }
    })
}

$lj.getAppDeviceId = async function() {
    var deviceId = '';

    /**超级权限，修改设备唯一码 */
    let storageDeviceId = $lj.getStorage('deviceId');
    if (storageDeviceId) {
        $lj.deviceId = storageDeviceId;
        return;
    }

    await $lj.getUUIDToPhoneInfoPlus().then((val) => {
        deviceId = val;
    }, (err) => {
        deviceId = '';
    });
    if (!deviceId && api.systemType != "ios") {
        deviceId = await $lj.getMacAddress();
    }
    if (!deviceId) {
        deviceId = api.deviceId;
    }
    $lj.deviceId = deviceId;
}

$lj.getFjFile = function(params,callback) {
    try {
        if(!params.fjdata.hasOwnProperty("billtype")) {
            throw new Error("缺少billtype参数,请检查!")
        }

        if(!params.hasOwnProperty("token")) {
            params.token = $lj.getStorage("token")
        }

        $lj.postLJRequest('GetFjFile', params, function (ret) {
            if(ret && ret.FjFileList.length > 0) {
                callback && callback(ret);
            }
        })
    } catch(e) {
        alert("获取附件信息失败:" + e);
    }
}

$lj.getPermission = function(powers) {
    return new Promise((res,rej) => {
        let hasPermission = api.hasPermission({
            list: powers
        });

        if(hasPermission[0].granted) {
            res(true);
        } else {
            api.requestPermission({
                list: powers,
                code: 1
            },function(ret){
                if (!ret.list[0].granted) {
                    rej(ret);
                    return;
                }
                res(true);
            })
        }
    })
}

$lj.getStorageInfo = async function(immediately = false) {
    const storageKey = 'storageInfo';
    const storageData = $lj.getStorage(storageKey);

    if (!immediately && storageData) {
        const { storageList, timestamp } = storageData;

        const currentTime = new Date().getTime();
        const cachedTime = new Date(timestamp).getTime();
        const hoursDifference = (currentTime - cachedTime) / (1000 * 60 * 60);

        // 判断缓存中是否存在仓库信息，且缓存时间未超过24小时
        if (storageList && timestamp && hoursDifference < 24) {
            return storageData;
        }
    }

    // 缓存不存在或时间超过24小时，访问接口获取仓库数据
    async function fetchStorageData() {
        return new Promise((resolve,reject) => {
            $lj.postLJRequest("PDA_GetStorageInfo", {
                token: $lj.getStorage("token"),
                type: 0
            },(ret) => {
                resolve(ret);
            },(err) => {
                reject(err);
            })
        });
    }

    const result = await fetchStorageData();
    const updatedData = {
        storageList: result.storageList,
        storagePower: result.storagePower,
        storage_newPower: result.storage_newPower,
        locaList: [],
        timestamp: new Date().toISOString()
    };

    // 更新缓存
    $lj.setStorage(storageKey,updatedData);
    return updatedData;
}

$lj.getLocaList = async function(param,key = "storageid") {
    const storageKey = 'storageInfo';

    const storageData = $lj.getStorage(storageKey);
    const storage = storageData.storageList;

    // 遍历找出仓库列表下storageId与传入的storageId是否相同
    const warehouse = storage.find(wh => wh[key] === param);
    // 判断仓库下的children是否存在
    if (warehouse.children) {
        const { children } = warehouse;
        const { timestamp } = warehouse.children;

        const currentTime = new Date().getTime();
        const cachedTime = new Date(timestamp).getTime();
        const hoursDifference = (currentTime - cachedTime) / (1000 * 60 * 60);
        // 判断缓存时间是否超过24小时
        if (children && timestamp && hoursDifference < 24) {
            return children.localist;
        }
    }
    // 缓存不存在或时间超过24小时，访问接口获取仓位数据
    async function fetchLocaData(storageId) {
        return new Promise((resolve,reject) => {
            $lj.postLJRequest("PDA_GetStorageInfo", {
                token: $lj.getStorage("token"),
                type: 1,
                storageid: storageId
            },(ret) => {
                resolve(ret.locaList);
            },(err) => {
                reject(err);
            })
        });
    }

    const children = await fetchLocaData(warehouse.storageid);
    warehouse.children = {
        localist: children,
        timestamp: new Date().toISOString()
    };

    // 更新storageInfo缓存
    $lj.setStorage(storageKey,storageData);
    return children;
}

/**
 * 创建一个从 object 中选中/保留的属性的对象。
 * @param {*} obj 
 * @param {*} keys 
 * @returns 
 */
$lj.pick = function(obj, keys) {
    var result = {};
    for (var i = 0; i < keys.length; i++) {
        var key = keys[i];
        if (obj.hasOwnProperty(key)) {
            result[key] = obj[key];
        }
    }
    return result;
}

/**
 * 创建一个从 object 中排除指定属性的对象。
 * @param {*} obj 
 * @param {*} keys 
 * @returns 
 */
$lj.omit = function(obj, keys) {
    var result = {};
    for (var key in obj) {
        if (obj.hasOwnProperty(key) && keys.indexOf(key) === -1) {
            result[key] = obj[key];
        }
    }
    return result;
}

$lj.defaultsDeep = function(target, ...sources) {
    sources.forEach(source => {
        if ($lj.isObject(source)) {
            Object.keys(source).forEach(key => {
                if (Array.isArray(source[key])) {
                    // If the source value is an array, ensure the target also has an array
                    if (!Array.isArray(target[key])) {
                        target[key] = [];
                    }
                    // Merge arrays element-wise
                    source[key].forEach((item, index) => {
                        if ($lj.isObject(item)) {
                            if (!$lj.isObject(target[key][index])) {
                                target[key][index] = {};
                            }
                            $lj.defaultsDeep(target[key][index], item);
                        } else {
                            if (target[key][index] === undefined) {
                                target[key][index] = item;
                            }
                        }
                    });
                } else if ($lj.isObject(source[key])) {
                    if (!target[key]) {
                        target[key] = {};
                    }
                    $lj.defaultsDeep(target[key], source[key]);
                } else {
                    if (target[key] === undefined) {
                        target[key] = source[key];
                    }
                }
            });
        }
    });
    return target;
}

$lj.postCommonLJRequest = function (method, requestbody, itemname, callback, errcallback, hideprogress, hideErrMsg, progressParams) {
    let params = {
        queryParams: requestbody,
        pageindex: 0,
        pagesize: 0,
        dsname: method,
        dwname: "JLH_WEB",
        itemname: itemname,
        ifcompress: 0,
        token: $lj.getStorage("token"),
    }
    return $lj.postLJRequest("CommonDynamicSelect", params, callback, errcallback, hideprogress, hideErrMsg, progressParams);
}

$lj.getCommonColumns = function (columns) {
    let _col = columns.map(col => {
        if (col.limited && $lj.isFunction(col.limited)) {
            col.limited = col.limited();
        }
        return {
            ...col,
            label: col.title,
            property: col.field,
            // type: col.datatype
        }
    });

    return _col.filter(t => !t.limited);
}

$lj.setExtraColumns = function (columns, extra) {
    return columns.map(col => {
        let item = extra.find(item => item.field == col.field);
        if (item) {
            console.log('$lj.setExtraColumns item :>> ', JSON.stringify($lj.defaultsDeep(col, item)));
            return $lj.defaultsDeep(col, item)
        } else {
            return col;
        }
    });
}

/**
 * @description: 判断值是否未某个类型
 */
function is(val, type) {
    return Object.prototype.toString.call(val) === `[object ${type}]`;
}
  
/**
 * @description:  是否为函数
 */
$lj.isFunction = function (val) {
    return is(val, "Function");
}

$lj.isObject = function (val) {
    return val !== null && is(val, "Object");
}

/**
 * @description form表单检测，数值检测
 * @param rule
 * @param value
 * @param callback
 * @returns
 */
$lj.numCheck = function(rule, value, callback) {
    // 我这里不是必填的，如果是必填的再判断一下value === ''
    let capital = /^[0-9.]*$/;
    if (!capital.test(value)) {
      callback(new Error(`请输入整数或小数`));
    } else {
      let data = JSON.stringify(value);
      let arr = data.split("");
      let mix = data.indexOf(".");
      if (mix != -1) {
        if (mix == 0 || mix == arr.length - 1) {
          callback(new Error(`小数点不能在第一位或最后一位`));
          return;
        }
        let dianNum = arr.filter((x) => x == ".");
        if (dianNum.length > 1) {
          callback(new Error(`小数点只能有一个`));
          return;
        }
        callback();
      } else {
        callback();
      }
    }
  };
  

export default $lj
