# app_script_history

id: 61934a2099324840d69f7771
scriptid: 60a321f05db27838e0c014bf
tablename: app_script
clientip: 10.255.0.2
username: sa
createdate: 2021.11.16 14:16:37.000
script:
//@comment (group=,caption=得到当前操作员待归档图片对应的GGUID,needRightControl=false)
function getImagePoolGGUID() {
    var ret = runTask("get_dzpz_imgpool_id_of_current_user", {});
    return JSON.parse(ret).gguid;

}

function getImagePoolBlockSize() {
    var ret = runTask("get_dzpz_imgpool_id_of_current_user", {});
    return JSON.parse(ret).blockSize;

}


//@comment (group=,caption=保存当前的缩略图大小,needRightControl=false)
function setImagePoolBlockSize(id, blockSize) {
    runSQL("", " update  dzpz_imgpool set blocksize=" + blockSize + " where gguid='" + id + "'  ");
}


//@comment (group=,caption=得到待归档的图片清单,needRightControl=true)
function loadImagePoolData() {
    var config = JSON.parse(runTask("get_dzpz_imgpool_id_of_current_user", {}));

    //排除掉回收站的图片
    var sql = "select * from " + config.logTable + "  where  gguid='" + config.gguid +
        "'  and ifnull(info2,'')=''  order by info1 asc, filename asc ";
    println(sql);
    var ds = newDataStore(config.dbpool, sql); // info1 是客户端文件创建的时间，以它排序厅。
    ds.setOnceRetrieveCount(500);

    var n = ds.retrieve();

    var ret = [];
    for (var i = 0; i < n; i++) {
        ret.push(JSON.parse(ds.getJSONRow(i, true)));
    }

    return { success: true, totalCount: ds.getDBRowCount(), data: ret };

}

function getTotalImageCount() {
    var config = JSON.parse(runTask("get_dzpz_imgpool_id_of_current_user", {}));

    //排除掉回收站的图片
    var sql = "select count(*) as c from " + config.logTable + "  where  gguid='" + config.gguid +
        "'  and ifnull(info2,'')=''    ";
    println(sql);
    var ds = newDataStore(config.dbpool, sql); // info1 是客户端文件创建的时间，以它排序厅。


    ds.retrieve();
    println(ds.getSelectLastRetrieved());

    return ds.getInt(0, "c");

}

//@comment (group=,caption=保存监控目录设置,needRightControl=false)
function setMonitePath(hostName, path) {
    var ds = newDataStore("", "select * from dzpz_client");
    ds.setUpdateProperty("dzpz_client", "id", "*", "id");
    ds.retrieve(" hostname='" + hostName + "'");
    if (ds.getRowCount() == 0) {
        var newid = newGUID();
        ds.insertRow(0);
        ds.setValue(0, "id", newid);
        ds.setValue(0, "gguid", newid);
        ds.setValue(0, "billno", newid);
        ds.setValue(0, "userid", 1);
        ds.setValue(0, "username", '管理员');
        ds.setValue(0, "billtype", '');
        ds.setValue(0, "hostname", hostName);
    }
    ds.setValue(0, "path", path);
    ds.update(true);
    println(ds.getError().getMessage());

}


//@comment (group=,caption=获取指定机器的监控目录,needRightControl=false)
function getMonitePath(hostName) {
    return getStringFromSQL("select path from dzpz_client where  hostname='" + hostName + "'");
}


//@comment (group=,caption=构建凭证附件清单,needRightControl=false)
function getPZFJ(id) {
    var ds = newDataStore("", "select id , url_img , url_thumbnail ,groupname , info1 from  dzpz_pzfj where  gguid='" + id + "'  order by info2 asc,groupname , info1 asc ");
    var n = ds.retrieve();
    var ret = [];
    for (var i = 0; i < n; i++) {
        ret.push(JSON.parse(ds.getJSONRow(i, true)));
    }
    return ret;

}



//@comment (group=,caption=把凭证中的附件图片回归到待归档池中,needRightControl=false)
function putImageBackToPool(id) {
    println(id);
    return JSON.parse(runTask("凭证附件移除", { id: id }));
}


//@comment (group=,caption=追加图片到凭证中,needRightControl=false)
function addImageToPZ(pzid, images) {
    return JSON.parse(runTask("追加图片到凭证中", { pzid: pzid, images: images }));
}

function deletePZAndPutBackToPool(id) {
    return JSON.parse(runTask("删除凭证所有图片回归池中", { id: id }));
}

function moveImageToRecycle(id) {
    var config = JSON.parse(runTask("get_dzpz_imgpool_id_of_current_user", {}));
    runSQL(config.dbpool, " update " + config.logTable + " set info2='回收站' where id='" + id + "'  ", true);


}

//@comment (group=,caption=凭证号前缀,needRightControl=false)
function getPZHPrefix(corpid,ym) {
    return runTask("getPZHPrefix", { ym: ym ,corpid:corpid });

}
//@comment (group=,caption=凭证号长度,needRightControl=false)
function getPZHLen(corpid) {
    return parseInt(runTask("getPZHLen", {corpid:corpid}));
}

function getLastPZH(corpid, ym) {
    var t = getStringFromSQL("select max(pzh) from dzpz_pz where corpid='" + corpid + "' and ym=" + ym);
    return t;
}


function do_imageRotate(id, rt) {
    var ret = imageRotate("", "dzpz_imgpool_fileupload", id, rt);
    println(JSON.stringify(ret));
    return ret;
}


function reorderImageFileIndex(imgs) {

}


id: 61934a2099324840d69f7779
scriptid: 60a321f05db27838e0c014bf
tablename: app_script
clientip: 10.255.0.2
username: sa
createdate: 2021.11.16 14:17:14.000
script:
//@comment (group=,caption=得到当前操作员待归档图片对应的GGUID,needRightControl=false)
function getImagePoolGGUID() {
    var ret = runTask("get_dzpz_imgpool_id_of_current_user", {});
    return JSON.parse(ret).gguid;

}

function getImagePoolBlockSize() {
    var ret = runTask("get_dzpz_imgpool_id_of_current_user", {});
    return JSON.parse(ret).blockSize;

}


//@comment (group=,caption=保存当前的缩略图大小,needRightControl=false)
function setImagePoolBlockSize(id, blockSize) {
    runSQL("", " update  dzpz_imgpool set blocksize=" + blockSize + " where gguid='" + id + "'  ");
}


//@comment (group=,caption=得到待归档的图片清单,needRightControl=true)
function loadImagePoolData() {
    var config = JSON.parse(runTask("get_dzpz_imgpool_id_of_current_user", {}));

    //排除掉回收站的图片
    var sql = "select * from " + config.logTable + "  where  gguid='" + config.gguid +
        "'  and ifnull(info2,'')=''  order by info1 asc, filename asc ";
    println(sql);
    var ds = newDataStore(config.dbpool, sql); // info1 是客户端文件创建的时间，以它排序厅。
    ds.setOnceRetrieveCount(500);

    var n = ds.retrieve();

    var ret = [];
    for (var i = 0; i < n; i++) {
        ret.push(JSON.parse(ds.getJSONRow(i, true)));
    }

    return { success: true, totalCount: ds.getDBRowCount(), data: ret };

}

function getTotalImageCount() {
    var config = JSON.parse(runTask("get_dzpz_imgpool_id_of_current_user", {}));

    //排除掉回收站的图片
    var sql = "select count(*) as c from " + config.logTable + "  where  gguid='" + config.gguid +
        "'  and ifnull(info2,'')=''    ";
    println(sql);
    var ds = newDataStore(config.dbpool, sql); // info1 是客户端文件创建的时间，以它排序厅。


    ds.retrieve();
    println(ds.getSelectLastRetrieved());

    return ds.getInt(0, "c");

}

//@comment (group=,caption=保存监控目录设置,needRightControl=false)
function setMonitePath(hostName, path) {
    var ds = newDataStore("", "select * from dzpz_client");
    ds.setUpdateProperty("dzpz_client", "id", "*", "id");
    ds.retrieve(" hostname='" + hostName + "'");
    if (ds.getRowCount() == 0) {
        var newid = newGUID();
        ds.insertRow(0);
        ds.setValue(0, "id", newid);
        ds.setValue(0, "gguid", newid);
        ds.setValue(0, "billno", newid);
        ds.setValue(0, "userid", 1);
        ds.setValue(0, "username", '管理员');
        ds.setValue(0, "billtype", '');
        ds.setValue(0, "hostname", hostName);
    }
    ds.setValue(0, "path", path);
    ds.update(true);
    println(ds.getError().getMessage());

}


//@comment (group=,caption=获取指定机器的监控目录,needRightControl=false)
function getMonitePath(hostName) {
    return getStringFromSQL("select path from dzpz_client where  hostname='" + hostName + "'");
}


//@comment (group=,caption=构建凭证附件清单,needRightControl=false)
function getPZFJ(id) {
    // 在图片池中，info2 表示是否是垃圾箱， 在附件表中，info2记录的是手工调整后的顺序号
    var ds = newDataStore("", "select id , url_img , url_thumbnail ,groupname , info1 from  dzpz_pzfj where  gguid='" + id + "'  order by info2 asc,groupname , info1 asc ");
    var n = ds.retrieve();
    var ret = [];
    for (var i = 0; i < n; i++) {
        ret.push(JSON.parse(ds.getJSONRow(i, true)));
    }
    return ret;

}



//@comment (group=,caption=把凭证中的附件图片回归到待归档池中,needRightControl=false)
function putImageBackToPool(id) {
    println(id);
    return JSON.parse(runTask("凭证附件移除", { id: id }));
}


//@comment (group=,caption=追加图片到凭证中,needRightControl=false)
function addImageToPZ(pzid, images) {
    return JSON.parse(runTask("追加图片到凭证中", { pzid: pzid, images: images }));
}

function deletePZAndPutBackToPool(id) {
    return JSON.parse(runTask("删除凭证所有图片回归池中", { id: id }));
}

function moveImageToRecycle(id) {
    var config = JSON.parse(runTask("get_dzpz_imgpool_id_of_current_user", {}));
    runSQL(config.dbpool, " update " + config.logTable + " set info2='回收站' where id='" + id + "'  ", true);


}

//@comment (group=,caption=凭证号前缀,needRightControl=false)
function getPZHPrefix(corpid,ym) {
    return runTask("getPZHPrefix", { ym: ym ,corpid:corpid });

}
//@comment (group=,caption=凭证号长度,needRightControl=false)
function getPZHLen(corpid) {
    return parseInt(runTask("getPZHLen", {corpid:corpid}));
}

function getLastPZH(corpid, ym) {
    var t = getStringFromSQL("select max(pzh) from dzpz_pz where corpid='" + corpid + "' and ym=" + ym);
    return t;
}


function do_imageRotate(id, rt) {
    var ret = imageRotate("", "dzpz_imgpool_fileupload", id, rt);
    println(JSON.stringify(ret));
    return ret;
}


function reorderImageFileIndex(imgs) {

}


id: 61934a2099324840d69f7780
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.16 14:25:13.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id, true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {



        let verifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            verifyCount++;
            showInfoPane("* 正在审核确认...");
            do_sh1(i, function () {
                verifyCount--;
                console.info(verifyCount);
                if (verifyCount == 0) hideInfoPane();
            })
        }


    });
}



function cb_unverify_onClick() {
    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {



        let unverifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            unverifyCount++;
            showInfoPane("* 正在取消确认...");
            do_sh2(i, function () {
                unverifyCount--;
                console.info(unverifyCount);
                if (unverifyCount == 0) hideInfoPane();
            });
        }


    });
}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function  isVerified ()
{ 
    var row= book.getDataSource('dzpz_pz').currentBindRow  ;
    var verifiername= $dzpz_pz_ds.getString( row,"verifiername");
    
    if( verifiername!='')
    {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                rotateImg(sheet, id, '90');

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;

                rotateImg(sheet, id, '270');

            }
        );



    }
}


function rotateImg(sheet, id, degree, delayMS) {
    if (delayMS == undefined) delayMS = 300;



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID
        g_turningCount++;
        showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');

        do_imageRotate(id, degree, function (ret) {
            g_turnedCount++;
            if (ret.success) {
                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }

            //正在转，已经转与需要转的数量对上时， 旋转结束
            if (g_turnNeedCount == g_turnedCount) {
                hideInfoPane();
                 if( g_turnNeedCount>1) $.alert('旋转完成');  //  >1表示批量，需要提醒一下， ==1 表示单张， 不需要提醒
            }

        });
    }, delayMS);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

    var row= book.getDataSource('dzpz_pz').currentBindRow  ;
    var verifiername= $dzpz_pz_ds.getString( row,"verifiername");
    if( verifiername!='')
    {
        toastr.error("已经校验的凭证不允许旋转");
        return;
    }

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {
        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;

        setTimeout(function () {
            for (var i = 0; i < selection.length; i++) {
                rotateImg(sheet, selection[i].id, degree, i * 500);
            }
        }, 10);
    });

}


id: 61934a2099324840d69f7786
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.16 14:25:37.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id, true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {



        let verifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            verifyCount++;
            showInfoPane("* 正在审核确认...");
            do_sh1(i, function () {
                verifyCount--;
                console.info(verifyCount);
                if (verifyCount == 0) hideInfoPane();
            })
        }


    });
}



function cb_unverify_onClick() {
    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {



        let unverifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            unverifyCount++;
            showInfoPane("* 正在取消确认...");
            do_sh2(i, function () {
                unverifyCount--;
                console.info(unverifyCount);
                if (unverifyCount == 0) hideInfoPane();
            });
        }


    });
}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function  isVerified ()
{ 
    var row= book.getDataSource('dzpz_pz').currentBindRow  ;
    var verifiername= $dzpz_pz_ds.getString( row,"verifiername");
    
    if( verifiername!='')
    {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                rotateImg(sheet, id, '90');

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;

                rotateImg(sheet, id, '270');

            }
        );



    }
}


function rotateImg(sheet, id, degree, delayMS) {
    if (delayMS == undefined) delayMS = 300;



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID
        g_turningCount++;
        showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');

        do_imageRotate(id, degree, function (ret) {
            g_turnedCount++;
            if (ret.success) {
                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }

            //正在转，已经转与需要转的数量对上时， 旋转结束
            if (g_turnNeedCount == g_turnedCount) {
                hideInfoPane();
                 if( g_turnNeedCount>1) $.alert('旋转完成');  //  >1表示批量，需要提醒一下， ==1 表示单张， 不需要提醒
            }

        });
    }, delayMS);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

   if( isVerified()) return;  //校对过的不允许再旋转

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {
        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;

        setTimeout(function () {
            for (var i = 0; i < selection.length; i++) {
                rotateImg(sheet, selection[i].id, degree, i * 500);
            }
        }, 10);
    });

}


id: 61934a2099324840d69f778c
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.16 14:25:55.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id, true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {



        let verifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            verifyCount++;
            showInfoPane("* 正在审核确认...");
            do_sh1(i, function () {
                verifyCount--;
                console.info(verifyCount);
                if (verifyCount == 0) hideInfoPane();
            })
        }


    });
}



function cb_unverify_onClick() {
    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {



        let unverifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            unverifyCount++;
            showInfoPane("* 正在取消确认...");
            do_sh2(i, function () {
                unverifyCount--;
                console.info(unverifyCount);
                if (unverifyCount == 0) hideInfoPane();
            });
        }


    });
}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function isVerified() {
    var row = book.getDataSource('dzpz_pz').currentBindRow;
    var verifiername = $dzpz_pz_ds.getString(row, "verifiername");

    if (verifiername != '') {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '90');

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '270');

            }
        );



    }
}


function rotateImg(sheet, id, degree, delayMS) {
    if (delayMS == undefined) delayMS = 300;



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID
        g_turningCount++;
        showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');

        do_imageRotate(id, degree, function (ret) {
            g_turnedCount++;
            if (ret.success) {
                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }

            //正在转，已经转与需要转的数量对上时， 旋转结束
            if (g_turnNeedCount == g_turnedCount) {
                hideInfoPane();
                if (g_turnNeedCount > 1) $.alert('旋转完成');  //  >1表示批量，需要提醒一下， ==1 表示单张， 不需要提醒
            }

        });
    }, delayMS);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

    if (isVerified()) return;  //校对过的不允许再旋转

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {
        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;

        setTimeout(function () {
            for (var i = 0; i < selection.length; i++) {
                rotateImg(sheet, selection[i].id, degree, i * 500);
            }
        }, 10);
    });

}


id: 61934a2099324840d69f7792
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.16 14:27:48.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id, true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {



        let verifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            verifyCount++;
            showInfoPane("* 正在审核确认...");
            do_sh1(i, function () {
                verifyCount--;
                console.info(verifyCount);
                if (verifyCount == 0) hideInfoPane();
            })
        }


    });
}



function cb_unverify_onClick() {
    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {



        let unverifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            unverifyCount++;
            showInfoPane("* 正在取消确认...");
            do_sh2(i, function () {
                unverifyCount--;
                console.info(unverifyCount);
                if (unverifyCount == 0) hideInfoPane();
            });
        }


    });
}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function isVerified() {
    var row = book.getDataSource('dzpz_pz').currentBindRow;
    var verifiername = $dzpz_pz_ds.getString(row, "verifiername");

    if (verifiername != '') {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '90');

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '270');

            }
        );



    }
}


function rotateImg(sheet, id, degree, delayMS) {
    if (delayMS == undefined) delayMS = 300;



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID
        g_turningCount++;
        showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');

        do_imageRotate(id, degree, function (ret) {
            g_turnedCount++;
            if (ret.success) {
                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }

            //正在转，已经转与需要转的数量对上时， 旋转结束
            if (g_turnNeedCount == g_turnedCount) {
                hideInfoPane();
                if (g_turnNeedCount > 1) $.alert('旋转完成');  //  >1表示批量，需要提醒一下， ==1 表示单张， 不需要提醒
            }

        });
    }, delayMS);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    if( isVerified()) return;  //校对过的不允许再调整顺序

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

    if (isVerified()) return;  //校对过的不允许再旋转

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {
        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;

        setTimeout(function () {
            for (var i = 0; i < selection.length; i++) {
                rotateImg(sheet, selection[i].id, degree, i * 500);
            }
        }, 10);
    });

}


id: 61934fc099324840d69f7798
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.16 14:29:21.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id, true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消校对");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {



        let verifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            verifyCount++;
            showInfoPane("* 正在审核确认...");
            do_sh1(i, function () {
                verifyCount--;
                console.info(verifyCount);
                if (verifyCount == 0) hideInfoPane();
            })
        }


    });
}



function cb_unverify_onClick() {
    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {



        let unverifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            unverifyCount++;
            showInfoPane("* 正在取消确认...");
            do_sh2(i, function () {
                unverifyCount--;
                console.info(unverifyCount);
                if (unverifyCount == 0) hideInfoPane();
            });
        }


    });
}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function isVerified() {
    var row = book.getDataSource('dzpz_pz').currentBindRow;
    var verifiername = $dzpz_pz_ds.getString(row, "verifiername");

    if (verifiername != '') {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '90');

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '270');

            }
        );



    }
}


function rotateImg(sheet, id, degree, delayMS) {
    if (delayMS == undefined) delayMS = 300;



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID
        g_turningCount++;
        showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');

        do_imageRotate(id, degree, function (ret) {
            g_turnedCount++;
            if (ret.success) {
                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }

            //正在转，已经转与需要转的数量对上时， 旋转结束
            if (g_turnNeedCount == g_turnedCount) {
                hideInfoPane();
                if (g_turnNeedCount > 1) $.alert('旋转完成');  //  >1表示批量，需要提醒一下， ==1 表示单张， 不需要提醒
            }

        });
    }, delayMS);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    if( isVerified()) return;  //校对过的不允许再调整顺序

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

    if (isVerified()) return;  //校对过的不允许再旋转

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {
        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;

        setTimeout(function () {
            for (var i = 0; i < selection.length; i++) {
                rotateImg(sheet, selection[i].id, degree, i * 500);
            }
        }, 10);
    });

}


id: 6193504f99324840d69f7e95
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.19 16:43:48.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id, true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消校对");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {



        let verifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            verifyCount++;
            showInfoPane("* 正在审核确认...");
            do_sh1(i, function () {
                verifyCount--;
                console.info(verifyCount);
                if (verifyCount == 0) hideInfoPane();
            })
        }


    });
}



function cb_unverify_onClick() {
    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {



        let unverifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            unverifyCount++;
            showInfoPane("* 正在取消确认...");
            do_sh2(i, function () {
                unverifyCount--;
                console.info(unverifyCount);
                if (unverifyCount == 0) hideInfoPane();
            });
        }


    });
}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function isVerified() {
    var row = book.getDataSource('dzpz_pz').currentBindRow;
    var verifiername = $dzpz_pz_ds.getString(row, "verifiername");

    if (verifiername != '') {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '90');

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '270');

            }
        );



    }
}


function rotateImg(sheet, id, degree, delayMS) {
    if (delayMS == undefined) delayMS = 300;



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID
        g_turningCount++;
        showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');

        do_imageRotate(id, degree, function (ret) {
            g_turnedCount++;
            if (ret.success) {
                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }

            //正在转，已经转与需要转的数量对上时， 旋转结束
            if (g_turnNeedCount == g_turnedCount) {
                hideInfoPane();
                if (g_turnNeedCount > 1) $.alert('旋转完成');  //  >1表示批量，需要提醒一下， ==1 表示单张， 不需要提醒
            }

        });
    }, delayMS);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    if( isVerified()) return;  //校对过的不允许再调整顺序

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

    if (isVerified()) return;  //校对过的不允许再旋转

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {
        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;

        setTimeout(function () {
            for (var i = 0; i < selection.length; i++) {
                rotateImg(sheet, selection[i].id, degree, i * 50);
            }
        }, 10);
    });

}


id: 61988c3a99324840d69f804f
scriptid: 60ac944d5db2f5d22859c6de
tablename: app_script
clientip: 10.255.0.2
username: sa
createdate: 2021.11.20 13:49:10.000
script:
/*
凭证中的某个附件移除，并还原到待归档图片池中
  1 记录移除
  2 移到 待归档图片池中
  3  几个标记数据还愿

*/

function main(arg) {

    println(arg);
    var p = JSON.parse(arg);
    var id = p.id;  // dzpz_pz.id 
    println("id=" + id);


    if (getIntFromSQL( "select  verifierid  from dzpz_pz  where id='" + id + "' ") > 0) return { success: false, message: '凭证已审核，禁止删除' };
    if (getIntFromSQL( "select  userid  from dzpz_pz  where id='" + id + "' ") != toString(currentUserId())) return { success: false, message: '您不是该凭证归档人，禁止删除' };


    //得到当前操作员待归档图片对应的GGUID
    var t = runTask("get_dzpz_imgpool_id_of_current_user", {});
    var gguid = JSON.parse(t).gguid;


    var dzpz_pzfj_ds = newDataStore("", "select * from dzpz_pzfj "); //凭证附件
    dzpz_pzfj_ds.setUpdateProperty("dzpz_pzfj", "id", "*", "id");
    dzpz_pzfj_ds.retrieve(" gguid='" + id + "' "); //检索出所有图片


    //待归档的图片池
    var dzpz_imgpool_fileupload_ds = newDataStore("", "select * from dzpz_imgpool_fileupload");
    dzpz_imgpool_fileupload_ds.setUpdateProperty("dzpz_imgpool_fileupload", "id", "*", "id");

    var RC = dzpz_pzfj_ds.getRowCount();
    for (var i = RC - 1; i >= 0; i--) {

        var row = dzpz_imgpool_fileupload_ds.insertRow(9999);
        cloneRow(dzpz_pzfj_ds, i, dzpz_imgpool_fileupload_ds, row);

        //数据调整

        dzpz_imgpool_fileupload_ds.setValue(row, "groupname", '附件');  //把类型改成 凭证
        dzpz_imgpool_fileupload_ds.setValue(row, "gguid", gguid);
        dzpz_imgpool_fileupload_ds.setValue(row, "tablename", "dzpz_imgpool");
         
        //删除源
        dzpz_pzfj_ds.deleteRow(i);
    }

    //删除凭证
    dzpz_pzfj_ds.executeAfterUpdate(" delete from  dzpz_pz  where id='" + id + "' ");

    var err = '' + updateAll(dzpz_pzfj_ds, dzpz_imgpool_fileupload_ds);

    if (err == '') return { success: true };
    println(err);
    return { success: false, message: err };

}

function cloneRow(dzpz_pzfj_ds, sr, dzpz_imgpool_fileupload_ds, row) {
    for (var i = 0; i < dzpz_pzfj_ds.getColumnCount(); i++) {
        var col = dzpz_pzfj_ds.getColumnName(i);
        var value = dzpz_pzfj_ds.getValue(sr, i);
        dzpz_imgpool_fileupload_ds.setValue(row, col, value);
    }
}


id: 61988c3a99324840d69f807b
scriptid: 60ac750d5db2f5d22859c4c0
tablename: app_script
clientip: 10.255.0.2
username: sa
createdate: 2021.11.20 13:49:33.000
script:
/*
凭证中的某个附件移除，并还原到待归档图片池中
  1 记录移除
  2 移到 待归档图片池中
  3  几个标记数据还愿

*/

function main(arg) {

    println( arg); 
    var p = JSON.parse(arg);
    var id = p.id;  // dzpz_pzfj.id 
    println( "id="+ id);

   
    //得到当前操作员待归档图片对应的GGUID
    var t = runTask("get_dzpz_imgpool_id_of_current_user", {});
    var gguid = JSON.parse(t).gguid;


    var dzpz_pzfj_ds = newDataStore("", "select * from dzpz_pzfj "); //凭证附件
    dzpz_pzfj_ds.setUpdateProperty("dzpz_pzfj", "id", "*", "id");
    dzpz_pzfj_ds.retrieve(" id='"+ id+"' ");
    var pzid = dzpz_pzfj_ds.getString(0,"gguid");
    println( "select  verifierid  from dzpz_pz  where id='"+pzid+"' ");
    if( getIntFromSQL("select  verifierid  from dzpz_pz  where id='"+pzid+"' ")>0)
    {
        println("已审核，禁止删除附件");
     return { success:false, message:'凭证已审核，禁止删除'};
    }
    

    //待归档的图片池
    var dzpz_imgpool_fileupload_ds = newDataStore("", "select * from dzpz_imgpool_fileupload");
    dzpz_imgpool_fileupload_ds.setUpdateProperty("dzpz_imgpool_fileupload", "id", "*", "id");


    var row = dzpz_imgpool_fileupload_ds.insertRow(9999);

    cloneRow(dzpz_pzfj_ds, dzpz_imgpool_fileupload_ds, row);

    //数据调整


    dzpz_imgpool_fileupload_ds.setValue(row, "groupname", '附件');  //把类型改成 凭证

    dzpz_imgpool_fileupload_ds.setValue(row, "gguid", gguid);
    dzpz_imgpool_fileupload_ds.setValue(row, "tablename", "dzpz_imgpool");
    

    //删除源
    //当 
    dzpz_pzfj_ds.deleteRow(0);

    //更新附件数量
    
    dzpz_pzfj_ds.executeAfterUpdate(" update dzpz_pz  set attachmentcount= (select count(*) from dzpz_pzfj where gguid='"+ pzid+"' ) , "+
     " fj = (select count(*) from dzpz_pzfj where gguid='"+ pzid+"' and groupname='附件' ) , "+
     " pz = (select count(*) from dzpz_pzfj where gguid='"+ pzid+"' and groupname='凭证'  )  "+
               "   where id='"+ pzid+"' ");

    var err = '' + updateAll(dzpz_pzfj_ds, dzpz_imgpool_fileupload_ds);

    if (err == '') return { success: true };
    println(err);
    return { success: false, message: err };

}

function cloneRow(dzpz_pzfj_ds, dzpz_imgpool_fileupload_ds, row) {
    for (var i = 0; i < dzpz_pzfj_ds.getColumnCount(); i++) {
        var col = dzpz_pzfj_ds.getColumnName(i);
        var value = dzpz_pzfj_ds.getValue(0, i);
        dzpz_imgpool_fileupload_ds.setValue(row, col, value);
    }
}


id: 6198bc6c99324840d69f8097
scriptid: 609d4b105db2b0a331d6bf04
tablename: app_script
clientip: 10.255.0.2
username: sa
createdate: 2021.11.20 17:14:21.000
script:
//为每个操作员创建一个待归档图片单据 ， 所有单据都先上传到这个单据中做附件
function main(arg) {
    var gguid = '';
    runSQL(""," create unique index ui_dzpz_imgpool_userid on dzpz_imgpool (userid) ");

    var ds = newDataStore("", "select * from dzpz_imgpool  ");
    ds.setUpdateProperty("dzpz_imgpool", "id", "*", "id");
    println ( "currentUserId="+ currentUserId());
    ds.retrieve(" userid='" + currentUserId() + "'");
    println( ds.getSelectLastRetrieved());
    if (ds.getRowCount() == 1) {
        gguid = ds.getString(0, "gguid");
    } else {

        println( "new record");
        ds.insertRow(0);
        gguid = newGUID();
        ds.setValue(0, "id", gguid);
        ds.setValue(0, "gguid", gguid);
        ds.setValue(0, "billno", gguid);
        ds.setValue(0, "billdate", newDate());
        ds.setValue(0, "billtype", '');
        ds.setValue(0, "userid", currentUserId());
        ds.setValue(0, "username", currentUserShowName());
        ds.setValue(0, "deleteflag", 0);
        ds.setValue(0, "blocksize", 128);
        

        if (ds.update(true)) {
            error = ds.getError().getMessage();
            println(error);
            return { success: false, message: error };
        }else
        {
            ds.retrieve(" userid='" + currentUserId() + "'");
            gguid = ds.getString(0, "gguid");
        }
    }

    var blockSize=  ds.getInt(0,"blocksize");
    if( blockSize==0) blockSize=128; 

    //提供图片上传的必要的参数
    var config = { "serverIndex": "2", 
                    "dbpool": "default", 
                    "logTable": "dzpz_imgpool_fileupload", 
                    "blockSize": blockSize, 
                    "imgMaxSize": 1920, 
                    "groupName": "附件",
                     "tableName": "dzpz_imgpool", 
                     "gguid": gguid, 
                     "path": "dzpz_imgpool/"+ date2yyyymmdd(newDate(), "/"), 
                     "maxThumbnailSize": 512 ,
                     "responseType":"JSON"  //表示上传成功捂返回 JSON格式的结果
             }

    println(JSON.stringify(config));
    return config; 


}


id: 619908d9993208680e522618
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.21 10:21:24.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id, true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消校对");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {



        let verifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            verifyCount++;
            showInfoPane("* 正在审核确认...");
            do_sh1(i, function () {
                verifyCount--;
                console.info(verifyCount);
                if (verifyCount == 0) hideInfoPane();
            })
        }


    });
}



function cb_unverify_onClick() {
    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {



        let unverifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            unverifyCount++;
            showInfoPane("* 正在取消确认...");
            do_sh2(i, function () {
                unverifyCount--;
                console.info(unverifyCount);
                if (unverifyCount == 0) hideInfoPane();
            });
        }


    });
}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function isVerified() {
    var row = book.getDataSource('dzpz_pz').currentBindRow;
    var verifiername = $dzpz_pz_ds.getString(row, "verifiername");

    if (verifiername != '') {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '90');

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '270');

            }
        );



    }
}


function rotateImg(sheet, id, degree, callback) {



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID

        do_imageRotate(id, degree, function (ret) {

            g_turningCount++;
            showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');

            if (ret.success) {
                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }
            if (callback) callback();

        

        });
    }, 100);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    if (isVerified()) return;  //校对过的不允许再调整顺序

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

    if (isVerified()) return;  //校对过的不允许再旋转

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {

        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;
        /*
                setTimeout(function () {
                    for (var i = 0; i < selection.length; i++) {
                        rotateImg(sheet, selection[i].id, degree, i * 1000);
                    }
                }, 10);
                */

        asyncPool(2, selection, function (item, array) {
            return new Promise(function (resolve, reject) {

                console.dir(item);
                rotateImg(sheet, item.id, degree,
                    function () { //注意，在旋转完成后，再设置resolve 表示本任务已完成，而不是直接就resolve ,不然最后的 then 执行时机不对，这么处理，就会在全部旋转完成后，再执行then中的脚本，而不是旋转任务全部发起后就执行 then 
                         resolve(item)
                          });

            });
        }).then(function () {

            setTimeout(function () {
              
                hideInfoPane();
                toastr.info("旋转完成");
            }, 500);
        });

    });

}




function asyncPool(poolLimit, array, iteratorFn) {
    let i = 0;
    const ret = [];
    const executing = [];
    const enqueue = function () {
        if (i === array.length) {
            return Promise.resolve();
        }
        const item = array[i++];
        const p = Promise.resolve().then(() => iteratorFn(item, array));
        ret.push(p);

        let r = Promise.resolve();

        if (poolLimit <= array.length) {
            const e = p.then(() => executing.splice(executing.indexOf(e), 1));
            executing.push(e);
            if (executing.length >= poolLimit) {
                r = Promise.race(executing);
            }
        }

        return r.then(() => enqueue());
    };
    return enqueue().then(() => Promise.all(ret));
}


function test1() {


    asyncPool(3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function (item, array) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                console.info(item);
                resolve(item)
            }, 1000);

        });
    }).then(function () {
        console.info("over");
    });

}


id: 619908d9993208680e52261e
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.21 10:23:53.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id, true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消校对");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {



        let verifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            verifyCount++;
            showInfoPane("* 正在审核确认...");
            do_sh1(i, function () {
                verifyCount--;
                console.info(verifyCount);
                if (verifyCount == 0) hideInfoPane();
            })
        }


    });
}



function cb_unverify_onClick() {
    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {



        let unverifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            unverifyCount++;
            showInfoPane("* 正在取消确认...");
            do_sh2(i, function () {
                unverifyCount--;
                console.info(unverifyCount);
                if (unverifyCount == 0) hideInfoPane();
            });
        }


    });
}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function isVerified() {
    var row = book.getDataSource('dzpz_pz').currentBindRow;
    var verifiername = $dzpz_pz_ds.getString(row, "verifiername");

    if (verifiername != '') {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '90');

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '270');

            }
        );



    }
}


function rotateImg(sheet, id, degree, callback) {



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID

        do_imageRotate(id, degree, function (ret) {


            if (ret.success) {

                g_turningCount++;
                showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');


                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }
            if (callback) callback();



        });
    }, 100);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    if (isVerified()) return;  //校对过的不允许再调整顺序

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

    if (isVerified()) return;  //校对过的不允许再旋转

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {

        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;
        /*
                setTimeout(function () {
                    for (var i = 0; i < selection.length; i++) {
                        rotateImg(sheet, selection[i].id, degree, i * 1000);
                    }
                }, 10);
                */

        asyncPool(2, selection, function (item, array) {
            return new Promise(function (resolve, reject) {

                console.dir(item);
                rotateImg(sheet, item.id, degree,
                    function () { //注意，在旋转完成后，再设置resolve 表示本任务已完成，而不是直接就resolve ,不然最后的 then 执行时机不对，这么处理，就会在全部旋转完成后，再执行then中的脚本，而不是旋转任务全部发起后就执行 then 
                        resolve(item)
                    });

            });
        }).then(function () {

            setTimeout(function () {

                hideInfoPane();
                toastr.info("旋转完成");
            }, 500);
        });

    });

}




function asyncPool(poolLimit, array, iteratorFn) {
    let i = 0;
    const ret = [];
    const executing = [];
    const enqueue = function () {
        if (i === array.length) {
            return Promise.resolve();
        }
        const item = array[i++];
        const p = Promise.resolve().then(() => iteratorFn(item, array));
        ret.push(p);

        let r = Promise.resolve();

        if (poolLimit <= array.length) {
            const e = p.then(() => executing.splice(executing.indexOf(e), 1));
            executing.push(e);
            if (executing.length >= poolLimit) {
                r = Promise.race(executing);
            }
        }

        return r.then(() => enqueue());
    };
    return enqueue().then(() => Promise.all(ret));
}


function test1() {


    asyncPool(3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function (item, array) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                console.info(item);
                resolve(item)
            }, 1000);

        });
    }).then(function () {
        console.info("over");
    });

}


id: 619908d9993208680e522624
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.21 10:24:51.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id, true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消校对");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {



        let verifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            verifyCount++;
            showInfoPane("* 正在审核确认...");
            do_sh1(i, function () {
                verifyCount--;
                console.info(verifyCount);
                if (verifyCount == 0) hideInfoPane();
            })
        }


    });
}



function cb_unverify_onClick() {
    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {



        let unverifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            unverifyCount++;
            showInfoPane("* 正在取消确认...");
            do_sh2(i, function () {
                unverifyCount--;
                console.info(unverifyCount);
                if (unverifyCount == 0) hideInfoPane();
            });
        }


    });
}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function isVerified() {
    var row = book.getDataSource('dzpz_pz').currentBindRow;
    var verifiername = $dzpz_pz_ds.getString(row, "verifiername");

    if (verifiername != '') {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '90');

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '270');

            }
        );



    }
}


function rotateImg(sheet, id, degree, callback) {



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID

        do_imageRotate(id, degree, function (ret) {


            if (ret.success) {

                g_turningCount++;
                showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');


                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }
            if (callback) callback();



        });
    }, 100);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    if (isVerified()) return;  //校对过的不允许再调整顺序

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

    if (isVerified()) return;  //校对过的不允许再旋转

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {

        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;
        /*
                setTimeout(function () {
                    for (var i = 0; i < selection.length; i++) {
                        rotateImg(sheet, selection[i].id, degree, i * 1000);
                    }
                }, 10);
                */

        asyncPool(4 , selection, function (item, array) {
            return new Promise(function (resolve, reject) {

                console.dir(item);
                rotateImg(sheet, item.id, degree,
                    function () { //注意，在旋转完成后，再设置resolve 表示本任务已完成，而不是直接就resolve ,不然最后的 then 执行时机不对，这么处理，就会在全部旋转完成后，再执行then中的脚本，而不是旋转任务全部发起后就执行 then 
                        resolve(item)
                    });

            });
        }).then(function () {

            setTimeout(function () {

                hideInfoPane();
                toastr.info("旋转完成");
            }, 500);
        });

    });

}




function asyncPool(poolLimit, array, iteratorFn) {
    let i = 0;
    const ret = [];
    const executing = [];
    const enqueue = function () {
        if (i === array.length) {
            return Promise.resolve();
        }
        const item = array[i++];
        const p = Promise.resolve().then(() => iteratorFn(item, array));
        ret.push(p);

        let r = Promise.resolve();

        if (poolLimit <= array.length) {
            const e = p.then(() => executing.splice(executing.indexOf(e), 1));
            executing.push(e);
            if (executing.length >= poolLimit) {
                r = Promise.race(executing);
            }
        }

        return r.then(() => enqueue());
    };
    return enqueue().then(() => Promise.all(ret));
}


function test1() {


    asyncPool(3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function (item, array) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                console.info(item);
                resolve(item)
            }, 1000);

        });
    }).then(function () {
        console.info("over");
    });

}


id: 619908d9993208680e52262a
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.21 10:24:53.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id, true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消校对");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {



        let verifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            verifyCount++;
            showInfoPane("* 正在审核确认...");
            do_sh1(i, function () {
                verifyCount--;
                console.info(verifyCount);
                if (verifyCount == 0) hideInfoPane();
            })
        }


    });
}



function cb_unverify_onClick() {
    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {



        let unverifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            unverifyCount++;
            showInfoPane("* 正在取消确认...");
            do_sh2(i, function () {
                unverifyCount--;
                console.info(unverifyCount);
                if (unverifyCount == 0) hideInfoPane();
            });
        }


    });
}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function isVerified() {
    var row = book.getDataSource('dzpz_pz').currentBindRow;
    var verifiername = $dzpz_pz_ds.getString(row, "verifiername");

    if (verifiername != '') {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '90');

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '270');

            }
        );



    }
}


function rotateImg(sheet, id, degree, callback) {



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID

        do_imageRotate(id, degree, function (ret) {


            if (ret.success) {

                g_turningCount++;
                showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');


                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }
            if (callback) callback();



        });
    }, 100);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    if (isVerified()) return;  //校对过的不允许再调整顺序

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

    if (isVerified()) return;  //校对过的不允许再旋转

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {

        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;
        /*
                setTimeout(function () {
                    for (var i = 0; i < selection.length; i++) {
                        rotateImg(sheet, selection[i].id, degree, i * 1000);
                    }
                }, 10);
                */

        asyncPool(8 , selection, function (item, array) {
            return new Promise(function (resolve, reject) {

                console.dir(item);
                rotateImg(sheet, item.id, degree,
                    function () { //注意，在旋转完成后，再设置resolve 表示本任务已完成，而不是直接就resolve ,不然最后的 then 执行时机不对，这么处理，就会在全部旋转完成后，再执行then中的脚本，而不是旋转任务全部发起后就执行 then 
                        resolve(item)
                    });

            });
        }).then(function () {

            setTimeout(function () {

                hideInfoPane();
                toastr.info("旋转完成");
            }, 500);
        });

    });

}




function asyncPool(poolLimit, array, iteratorFn) {
    let i = 0;
    const ret = [];
    const executing = [];
    const enqueue = function () {
        if (i === array.length) {
            return Promise.resolve();
        }
        const item = array[i++];
        const p = Promise.resolve().then(() => iteratorFn(item, array));
        ret.push(p);

        let r = Promise.resolve();

        if (poolLimit <= array.length) {
            const e = p.then(() => executing.splice(executing.indexOf(e), 1));
            executing.push(e);
            if (executing.length >= poolLimit) {
                r = Promise.race(executing);
            }
        }

        return r.then(() => enqueue());
    };
    return enqueue().then(() => Promise.all(ret));
}


function test1() {


    asyncPool(3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function (item, array) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                console.info(item);
                resolve(item)
            }, 1000);

        });
    }).then(function () {
        console.info("over");
    });

}


id: 619908d9993208680e522630
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.21 10:26:17.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id, true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消校对");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {



        let verifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            verifyCount++;
            showInfoPane("* 正在审核确认...");
            do_sh1(i, function () {
                verifyCount--;
                console.info(verifyCount);
                if (verifyCount == 0) hideInfoPane();
            })
        }


    });
}



function cb_unverify_onClick() {
    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {



        let unverifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            unverifyCount++;
            showInfoPane("* 正在取消确认...");
            do_sh2(i, function () {
                unverifyCount--;
                console.info(unverifyCount);
                if (unverifyCount == 0) hideInfoPane();
            });
        }


    });
}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function isVerified() {
    var row = book.getDataSource('dzpz_pz').currentBindRow;
    var verifiername = $dzpz_pz_ds.getString(row, "verifiername");

    if (verifiername != '') {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '90');

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '270');

            }
        );



    }
}


function rotateImg(sheet, id, degree, callback) {



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID

        do_imageRotate(id, degree, function (ret) {


            if (ret.success) {

                g_turningCount++;
                showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');


                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }
            if (callback) callback();



        });
    }, 100);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    if (isVerified()) return;  //校对过的不允许再调整顺序

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

    if (isVerified()) return;  //校对过的不允许再旋转

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {

        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;
        /*
                setTimeout(function () {
                    for (var i = 0; i < selection.length; i++) {
                        rotateImg(sheet, selection[i].id, degree, i * 1000);
                    }
                }, 10);
                */

        asyncPool(16 , selection, function (item, array) {
            return new Promise(function (resolve, reject) {

                console.dir(item);
                rotateImg(sheet, item.id, degree,
                    function () { //注意，在旋转完成后，再设置resolve 表示本任务已完成，而不是直接就resolve ,不然最后的 then 执行时机不对，这么处理，就会在全部旋转完成后，再执行then中的脚本，而不是旋转任务全部发起后就执行 then 
                        resolve(item)
                    });

            });
        }).then(function () {

            setTimeout(function () {

                hideInfoPane();
                toastr.info("旋转完成");
            }, 500);
        });

    });

}




function asyncPool(poolLimit, array, iteratorFn) {
    let i = 0;
    const ret = [];
    const executing = [];
    const enqueue = function () {
        if (i === array.length) {
            return Promise.resolve();
        }
        const item = array[i++];
        const p = Promise.resolve().then(() => iteratorFn(item, array));
        ret.push(p);

        let r = Promise.resolve();

        if (poolLimit <= array.length) {
            const e = p.then(() => executing.splice(executing.indexOf(e), 1));
            executing.push(e);
            if (executing.length >= poolLimit) {
                r = Promise.race(executing);
            }
        }

        return r.then(() => enqueue());
    };
    return enqueue().then(() => Promise.all(ret));
}


function test1() {


    asyncPool(3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function (item, array) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                console.info(item);
                resolve(item)
            }, 1000);

        });
    }).then(function () {
        console.info("over");
    });

}


id: 6199ae7f993208680e52263c
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.21 10:33:44.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id, true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消校对");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {



        let verifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            verifyCount++;
            showInfoPane("* 正在审核确认...");
            do_sh1(i, function () {
                verifyCount--;
                console.info(verifyCount);
                if (verifyCount == 0) hideInfoPane();
            })
        }


    });
}



function cb_unverify_onClick() {
    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {



        let unverifyCount = 0;
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            unverifyCount++;
            showInfoPane("* 正在取消确认...");
            do_sh2(i, function () {
                unverifyCount--;
                console.info(unverifyCount);
                if (unverifyCount == 0) hideInfoPane();
            });
        }


    });
}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function isVerified() {
    var row = book.getDataSource('dzpz_pz').currentBindRow;
    var verifiername = $dzpz_pz_ds.getString(row, "verifiername");

    if (verifiername != '') {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '90');

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '270');

            }
        );



    }
}


function rotateImg(sheet, id, degree, callback) {



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID

        do_imageRotate(id, degree, function (ret) {


            if (ret.success) {

                g_turningCount++;
                showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');


                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }
            if (callback) callback();



        });
    }, 100);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    if (isVerified()) return;  //校对过的不允许再调整顺序

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

    if (isVerified()) return;  //校对过的不允许再旋转

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {

        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;
        /*
                setTimeout(function () {
                    for (var i = 0; i < selection.length; i++) {
                        rotateImg(sheet, selection[i].id, degree, i * 1000);
                    }
                }, 10);
                */

        asyncPool(4 , selection, function (item, array) {
            return new Promise(function (resolve, reject) {

                console.dir(item);
                rotateImg(sheet, item.id, degree,
                    function () { //注意，在旋转完成后，再设置resolve 表示本任务已完成，而不是直接就resolve ,不然最后的 then 执行时机不对，这么处理，就会在全部旋转完成后，再执行then中的脚本，而不是旋转任务全部发起后就执行 then 
                        resolve(item)
                    });

            });
        }).then(function () {

            setTimeout(function () {

                hideInfoPane();
                toastr.info("旋转完成");
            }, 500);
        });

    });

}




function asyncPool(poolLimit, array, iteratorFn) {
    let i = 0;
    const ret = [];
    const executing = [];
    const enqueue = function () {
        if (i === array.length) {
            return Promise.resolve();
        }
        const item = array[i++];
        const p = Promise.resolve().then(() => iteratorFn(item, array));
        ret.push(p);

        let r = Promise.resolve();

        if (poolLimit <= array.length) {
            const e = p.then(() => executing.splice(executing.indexOf(e), 1));
            executing.push(e);
            if (executing.length >= poolLimit) {
                r = Promise.race(executing);
            }
        }

        return r.then(() => enqueue());
    };
    return enqueue().then(() => Promise.all(ret));
}


function test1() {


    asyncPool(3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function (item, array) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                console.info(item + "   "+ new Date());
                resolve(item)
            }, 1000);

        });
    }).then(function () {
        console.info("over");
    });

}


id: 6199ae7f993208680e522642
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.21 11:49:12.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id, true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消校对");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {
        let rows = [];
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            rows.push(i);
        };

        showInfoPane("* 正在审核确认...");
        asyncPool(4, rows, function (i, rows) {
            return new Promise(function (resolve, reject) {
                showInfoPane("* 正在审核确认 " + i + "...");
                do_sh1(i, function () {
                    resolve(i);
                });
            });
        }).then(function (v) {
            hideInfoPane();
            toastr.info("审核完成");
        });

    });
}



function cb_unverify_onClick() {

    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {
        var rows = [];
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            rows.push(i);
        };

        showInfoPane("* 正在取消确认...");
        asyncPool(4, rows, function (i, rows) {
            return new Promise(function (resolve, reject) {
                do_sh2(i, function () {
                    resolve(i);
                });
            });
        }).then(function (v) {
            hideInfoPane();
            toastr.info("取消确认完成");
        });

    });


}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function isVerified() {
    var row = book.getDataSource('dzpz_pz').currentBindRow;
    var verifiername = $dzpz_pz_ds.getString(row, "verifiername");

    if (verifiername != '') {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '90');

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '270');

            }
        );



    }
}


function rotateImg(sheet, id, degree, callback) {



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID

        do_imageRotate(id, degree, function (ret) {


            if (ret.success) {

                g_turningCount++;
                showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');


                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }
            if (callback) callback();



        });
    }, 100);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    if (isVerified()) return;  //校对过的不允许再调整顺序

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

    if (isVerified()) return;  //校对过的不允许再旋转

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {

        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;
        /*
                setTimeout(function () {
                    for (var i = 0; i < selection.length; i++) {
                        rotateImg(sheet, selection[i].id, degree, i * 1000);
                    }
                }, 10);
                */

        asyncPool(4 , selection, function (item, array) {
            return new Promise(function (resolve, reject) {

                console.dir(item);
                rotateImg(sheet, item.id, degree,
                    function () { //注意，在旋转完成后，再设置resolve 表示本任务已完成，而不是直接就resolve ,不然最后的 then 执行时机不对，这么处理，就会在全部旋转完成后，再执行then中的脚本，而不是旋转任务全部发起后就执行 then 
                        resolve(item)
                    });

            });
        }).then(function () {

            setTimeout(function () {

                hideInfoPane();
                toastr.info("旋转完成");
            }, 500);
        });

    });

}




function asyncPool(poolLimit, array, iteratorFn) {
    let i = 0;
    const ret = [];
    const executing = [];
    const enqueue = function () {
        if (i === array.length) {
            return Promise.resolve();
        }
        const item = array[i++];
        const p = Promise.resolve().then(() => iteratorFn(item, array));
        ret.push(p);

        let r = Promise.resolve();

        if (poolLimit <= array.length) {
            const e = p.then(() => executing.splice(executing.indexOf(e), 1));
            executing.push(e);
            if (executing.length >= poolLimit) {
                r = Promise.race(executing);
            }
        }

        return r.then(() => enqueue());
    };
    return enqueue().then(() => Promise.all(ret));
}


function test1() {


    asyncPool(3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function (item, array) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                console.info(item + "   "+ new Date());
                resolve(item)
            }, 1000);

        });
    }).then(function () {
        console.info("over");
    });

}


id: 6199ae7f993208680e52264b
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.21 11:51:23.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id, true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消校对");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {
        let rows = [];
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            rows.push(i);
        };

        showInfoPane("* 正在审核确认...");
        asyncPool(4, rows, function (i, rows) {
            return new Promise(function (resolve, reject) {
                showInfoPane("* 正在审核确认 " + i  );
                do_sh1(i, function () {
                    resolve(i);
                });
            });
        }).then(function (v) {
            hideInfoPane();
            toastr.info("审核完成");
        });

    });
}



function cb_unverify_onClick() {

    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {
        var rows = [];
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            rows.push(i);
        };

        showInfoPane("* 正在取消确认...");
        asyncPool(4, rows, function (i, rows) {
            return new Promise(function (resolve, reject) {
                showInfoPane("* 正在取消确认"+i);
                do_sh2(i, function () {
                    resolve(i);
                });
            });
        }).then(function (v) {
            hideInfoPane();
            toastr.info("取消确认完成");
        });

    });


}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function isVerified() {
    var row = book.getDataSource('dzpz_pz').currentBindRow;
    var verifiername = $dzpz_pz_ds.getString(row, "verifiername");

    if (verifiername != '') {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '90');

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '270');

            }
        );



    }
}


function rotateImg(sheet, id, degree, callback) {



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID

        do_imageRotate(id, degree, function (ret) {


            if (ret.success) {

                g_turningCount++;
                showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');


                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }
            if (callback) callback();



        });
    }, 100);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    if (isVerified()) return;  //校对过的不允许再调整顺序

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

    if (isVerified()) return;  //校对过的不允许再旋转

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {

        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;
        /*
                setTimeout(function () {
                    for (var i = 0; i < selection.length; i++) {
                        rotateImg(sheet, selection[i].id, degree, i * 1000);
                    }
                }, 10);
                */

        asyncPool(4 , selection, function (item, array) {
            return new Promise(function (resolve, reject) {

                console.dir(item);
                rotateImg(sheet, item.id, degree,
                    function () { //注意，在旋转完成后，再设置resolve 表示本任务已完成，而不是直接就resolve ,不然最后的 then 执行时机不对，这么处理，就会在全部旋转完成后，再执行then中的脚本，而不是旋转任务全部发起后就执行 then 
                        resolve(item)
                    });

            });
        }).then(function () {

            setTimeout(function () {

                hideInfoPane();
                toastr.info("旋转完成");
            }, 500);
        });

    });

}




function asyncPool(poolLimit, array, iteratorFn) {
    let i = 0;
    const ret = [];
    const executing = [];
    const enqueue = function () {
        if (i === array.length) {
            return Promise.resolve();
        }
        const item = array[i++];
        const p = Promise.resolve().then(() => iteratorFn(item, array));
        ret.push(p);

        let r = Promise.resolve();

        if (poolLimit <= array.length) {
            const e = p.then(() => executing.splice(executing.indexOf(e), 1));
            executing.push(e);
            if (executing.length >= poolLimit) {
                r = Promise.race(executing);
            }
        }

        return r.then(() => enqueue());
    };
    return enqueue().then(() => Promise.all(ret));
}


function test1() {


    asyncPool(3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function (item, array) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                console.info(item + "   "+ new Date());
                resolve(item)
            }, 1000);

        });
    }).then(function () {
        console.info("over");
    });

}


id: 619a0e78993208680e522775
scriptid: 60d095db993254220bd851a3
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.21 17:23:24.000
script:
/**
 * 表单初始化完成后，执行此事件
 */
//@comment (group=表单事件,caption=表单初始化完成)
function formOpen() {
    book.showTabOnWhere = 'none';
    onPushMessage("dr_info", function (info) {
        if (info == 'over') {
            hideInfoPane();
        } else {
            showInfoPane(info);
        };

    })

}

//导入excel文件
function cb_importXLS_onClick(sheet, cell, button) {

    book.readXLS(function (data) {
        // alert(JSON.stringify(data));
        showInfoPane("*正在导入");
        backend_importExcelData(data[Object.keys(data)[0]], function (ret) {
            //console.dir(ret);
            hideInfoPane();
            if (ret.success) {
                toastr.info('导入成功');
                smartRetrieve(book.getWorkSheet("main"), "pzdj");
                smartRetrieve(book.getWorkSheet("detail"), "pzdjex");
                
            } else {
                toastr.warning(ret.message);
            }
        });
    });
}

/**
 * 按钮点击事件
 * 当某个按钮被点击时， 首先触发  {按钮名称}_onClick 事件，然后触发 buttonOnClick事件
 * @param sheet  工作表
 * @param cell   按钮所在的单元格
 * @param button 按钮对象
 */
function cb_downloadTemplateFile_onClick(sheet, cell, button) {
    var title = "年度\t调整期间\t凭证号\t凭证日期\t科目代码\t科目名称\t核算账号编码\t入库单号\t是否已过账\t摘要\t制单人";
    var data = [];
    data.push(title);
    data.push("2021\t6\t210600001\t2021.06.01\t5501\t营业费用\t\tRK0001\t否\t这是凭证摘要\t张三");
    data.push("2021\t6\t210600001\t2021.06.01\t1002\t银行存款\tY71MZ413H1\t\t否\t这是凭证摘要\t张三");


    var f = $('#form_toexcel')[0];
    f.filename.value = "凭证资料导入模板.xlsx";
    f.data.value = JSON.stringify(data);
    f.submit();

}


id: 619a0e78993208680e522782
scriptid: 60d095db993254220bd8519f
tablename: app_script
clientip: 10.255.0.2
username: sa
createdate: 2021.11.21 17:25:52.000
script:
//后端导入excel数据包
function backend_importExcelData(excelData) {
    var ret = {
        'success': false,
        'message': ''
    }
    // return { success: false, message: excelData }
    var dsn = '';
    var masterTable = 'pzdj';
    var tableName = 'pzdjex';
    //ret.message="select id,userid,verifiername from pzdj where gguid='" + currentGUID() + "'";
    //return ret;

    var ds = newDataStore(dsn, "select id,userid,verifiername from pzdj where gguid='" + currentGUID() + "'");
    ds.setOnceRetrieveCount(1);
    ds.retrieve('');
    if (ds.getRowCount() == 0) {
        ret.message = '请保存单据后再操作此功能!';
        return ret;
    }
    // if (ds.getString(0, "userid") != currentUserId()) {
    //     ret.message = '由于您不是制单人，不允许对当前单据做导入操作!';
    //     return ret;
    // }
    if (ds.getString(0, "verifiername") != '') {
        ret.message = '单据已审核，不允许导入操作!';
        return ret;
    }

    runSQL(dsn, "delete from " + tableName + " where gguid='" + currentGUID() + "'");

    //**********************************************
    //导入的标准功能
    var colLabel2ColName = {
        "年度": "y",
        "期间": "m",
        "凭证号": "pzh",
        "科目代码": "kmdm",
        "科目名称": "kmmc",
        "凭证日期": "pzrq",
        "核算账号编码": "code",
        "入库单号": "rkdh",
        "是否已过账": "posted",
        "摘要": "bz",
        "制单人": "zdr"
    }


    //var excelSheet;
    //for (var p in excelData) {
    //    excelSheet = excelData[p];
    //}

    var excelSheet = excelData;

    //分析字段对应关系
    var excelColIndex2ColName = {}; //excel 中的列号对应的中文题头
    var excelColName2ColIndex = {}; //中文题头对应的excel中的列号
    // var colLabel2ColName = {}; //中文题头对应到表的字段名


    var duplicateLabelCount = {};
    var colCount = 50; //最多几个列

    var headRow = 0; //题头在第几行
    var dataStartRow = 1; // 数据行从第几行开始
    //有时可能表头有多行合并，所以要检测一下
    for (var i = 0; i < colCount; i++) {
        var v = trim(sys_excelSafeValue(excelSheet, headRow, i));
        if (v == '')
            continue;
        if (duplicateLabelCount[v] == undefined) {
            duplicateLabelCount[v] = 0;
        }
        duplicateLabelCount[v] = duplicateLabelCount[v] + 1;

        if (duplicateLabelCount[v] > 1)
            v = v + duplicateLabelCount[v];
        //拼上后缀

        excelColIndex2ColName['' + i] = v;
        excelColName2ColIndex[v] = '' + i;
    }

    //println(JSON.toString(excelColName2ColIndex));
    //println(JSON.toString(excelColIndex2ColName));

    var RC = excelSheet.length;

    var data = [];
    for (var row = dataStartRow; row < RC; row++) {
        if (sys_excelSafeValue(excelSheet, row, 1) == null) break; //空行，直接结束
        var oneRowData = {};
        data.push(oneRowData);
        for (var label in excelColName2ColIndex) {
            var excelCol = excelColName2ColIndex[label];
            var dbCol = colLabel2ColName[label];
            if (dbCol != null) {
                oneRowData[dbCol] = sys_excelSafeValue(excelSheet, row, excelCol);
            }
        }

    }
    //println(JSON.toString(data));

    pushMessage("dr_info", "开始导入...", currentUserId());

    var gguid = currentGUID();
    var userid = currentUserId();
    var username = currentUserName();
    var lastmodifieddate = newDate();
    // println('import_ph:' + import_ph);



    var ds = newDataStore(dsn, "select * from " + tableName);
    ds.setUpdateProperty(tableName, "id", "*", "id");
    for (var i = 0; i < data.length; i++) {
        var row = ds.insertRow(99999);
        pushMessage("dr_info", "导入进度：" + (i + 1) + "/" + data.length, currentUserId());

        var rowData = data[i];
        for (var col in rowData) {
            var value = rowData[col];
            ds.setValue(row, col, value);
        }
        ds.setValue(row, "id", newGuid());
        ds.setValue(row, "gguid", gguid);
        ds.setValue(row, "userid", userid);
        ds.setValue(row, "username", username);
        ds.setValue(row, "lastmodifieddate", lastmodifieddate);
    }

    pushMessage("dr_info", "正在写入数据库...", currentUserId());

    if (ds.update(true)) {
        // $alert('导入完成');
        ret.success = true;
        ret.message = ds.getString(0, "userid");

        //更新起始记账期和截止记账期
        var master_ds = newDataStore(dsn, "select * from " + masterTable);
        master_ds.setUpdateProperty(masterTable, "id", "*", "id");
        master_ds.retrieve("gguid='" + currentGUID() + "'");
        master_ds.setValue(0, "jzq_start", getStringFromSQL2(dsn, "select min(y*100+m) as t from pzdjex where gguid='" + currentGUID() + "'"));
        master_ds.setValue(0, "jzq_end", getStringFromSQL2(dsn, "select max(y*100+m) as t from pzdjex where gguid='" + currentGUID() + "'"));
        master_ds.update(true)
    } else {
        ret.message = ds.getError().getMessage();
    }
    pushMessage('dr_info', 'over', currentUserId());

    return ret;
}

function sys_excelSafeValue(sheet, row, col) {
    if (row > sheet.length - 1) return null;
    var dataRow = sheet[row];
    if (dataRow == null) return null;
    if (col > dataRow.length - 1) return null;
    return dataRow[col];

}


id: 619a59ed993208680e522f29
scriptid: 619a5454993208680e52298b
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.21 22:46:28.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.getWorkSheet("filter").cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.getWorkSheet("filter").cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.getWorkSheet("filter").cells("pzh_prefix").setValue(pzh_prefix);


    });

    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}



/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "img_id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.getWorkSheet("filter").cells("corpid").getValueString();
        var ym = book.getWorkSheet("filter").cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.getWorkSheet("filter").cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.getWorkSheet("凭证详情").getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }

    });
    book.getWorkSheet("凭证详情").yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {

    }

}

//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.getWorkSheet("list").View.forceCurrentEditControlGiveUpFocus();

    var v = book.getWorkSheet("list").cells('selection').getValueInt();

    book.getWorkSheet("list").paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.getWorkSheet("list").paintPermit = true;
}





/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        return;
        
        let brick = sheet.getBrick(name);
        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-crop",   // 字符图标
            "查看大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {
                let img = $('#' + id).find('.image');
                let url = img.attr("largeimage");
                open(url);
            });


    }
}

/**
 * 图片控件中显示大图时添加水印图片
 * @param sheet   所在Sheet
 * @param name  图片控件的名称

 * @return  返回水印图片的url地址 ，如果返回  '' 则表示不添加水印图片
 */
//@comment (group=图片控件,caption=鼠标在某个图片上释放)
function imageOnPopupWithWatermark(sheet , name ) {

    var info= currentUserShowName( ) +""+ formatDate( new Date() , "yyyy.MM.dd-HH:mm");
    
    return "watermark?watermark="+info;
    
}


id: 619adb0d993208680e52320a
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.22 09:52:40.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id, true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消校对");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {
        let rows = [];
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            rows.push(i);
        };

        showInfoPane("* 正在审核确认...");
        asyncPool(4, rows, function (i, rows) {
            return new Promise(function (resolve, reject) {
                showInfoPane("* 正在审核确认 " + i  );
                do_sh1(i, function () {
                    resolve(i);
                });
            });
        }).then(function (v) {
            hideInfoPane();
            toastr.info("审核完成");
        });

    });
}



function cb_unverify_onClick() {

    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {
        var rows = [];
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            rows.push(i);
        };

        showInfoPane("* 正在取消确认...");
        asyncPool(4, rows, function (i, rows) {
            return new Promise(function (resolve, reject) {
                showInfoPane("* 正在取消确认"+i);
                do_sh2(i, function () {
                    resolve(i);
                });
            });
        }).then(function (v) {
            hideInfoPane();
            toastr.info("取消确认完成");
        });

    });


}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function isVerified() {
    var row = book.getDataSource('dzpz_pz').currentBindRow;
    var verifiername = $dzpz_pz_ds.getString(row, "verifiername");

    if (verifiername != '') {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '90' ,function(){hideInfoPane();});

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '270',function(){hideInfoPane();});

            }
        );



    }
}


function rotateImg(sheet, id, degree, callback) {



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID

        do_imageRotate(id, degree, function (ret) {


            if (ret.success) {

                g_turningCount++;
                showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');


                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }
            if (callback) callback();



        });
    }, 100);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    if (isVerified()) return;  //校对过的不允许再调整顺序

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

    if (isVerified()) return;  //校对过的不允许再旋转

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {

        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;
        /*
                setTimeout(function () {
                    for (var i = 0; i < selection.length; i++) {
                        rotateImg(sheet, selection[i].id, degree, i * 1000);
                    }
                }, 10);
                */

        asyncPool(4 , selection, function (item, array) {
            return new Promise(function (resolve, reject) {

                console.dir(item);
                rotateImg(sheet, item.id, degree,
                    function () { //注意，在旋转完成后，再设置resolve 表示本任务已完成，而不是直接就resolve ,不然最后的 then 执行时机不对，这么处理，就会在全部旋转完成后，再执行then中的脚本，而不是旋转任务全部发起后就执行 then 
                        resolve(item)
                    });

            });
        }).then(function () {

            setTimeout(function () {

                hideInfoPane();
                toastr.info("旋转完成");
            }, 500);
        });

    });

}




function asyncPool(poolLimit, array, iteratorFn) {
    let i = 0;
    const ret = [];
    const executing = [];
    const enqueue = function () {
        if (i === array.length) {
            return Promise.resolve();
        }
        const item = array[i++];
        const p = Promise.resolve().then(() => iteratorFn(item, array));
        ret.push(p);

        let r = Promise.resolve();

        if (poolLimit <= array.length) {
            const e = p.then(() => executing.splice(executing.indexOf(e), 1));
            executing.push(e);
            if (executing.length >= poolLimit) {
                r = Promise.race(executing);
            }
        }

        return r.then(() => enqueue());
    };
    return enqueue().then(() => Promise.all(ret));
}


function test1() {


    asyncPool(3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function (item, array) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                console.info(item + "   "+ new Date());
                resolve(item)
            }, 1000);

        });
    }).then(function () {
        console.info("over");
    });

}


id: 619b07f9993208680e523464
scriptid: 60d095db993254220bd8519f
tablename: app_script
clientip: 10.255.0.2
username: sa
createdate: 2021.11.22 11:16:55.000
script:
//后端导入excel数据包
function backend_importExcelData(excelData) {
    var ret = {
        'success': false,
        'message': ''
    }
    // return { success: false, message: excelData }
    var dsn = '';
    var masterTable = 'pzdj';
    var tableName = 'pzdjex';
    //ret.message="select id,userid,verifiername from pzdj where gguid='" + currentGUID() + "'";
    //return ret;

    var ds = newDataStore(dsn, "select id,userid,verifiername from pzdj where gguid='" + currentGUID() + "'");
    ds.setOnceRetrieveCount(1);
    ds.retrieve('');
    if (ds.getRowCount() == 0) {
        ret.message = '请保存单据后再操作此功能!';
        return ret;
    }
    // if (ds.getString(0, "userid") != currentUserId()) {
    //     ret.message = '由于您不是制单人，不允许对当前单据做导入操作!';
    //     return ret;
    // }
    if (ds.getString(0, "verifiername") != '') {
        ret.message = '单据已审核，不允许导入操作!';
        return ret;
    }

    runSQL(dsn, "delete from " + tableName + " where gguid='" + currentGUID() + "'");

    //**********************************************
    //导入的标准功能
    var colLabel2ColName = {
        "年度": "y",
        "调整期间": "m",
        "期间": "m",
        "凭证号": "pzh",
        "会计科目代码": "kmdm",
        "会计科目名称": "kmmc",
        "财会支出明细编码": "ckzcmxdm",
        "财会支出明细名称": "ckzcmxmc",
        "预会支出明细编码": "ykzcmxdm",
        "预会支出明细名称": "ykzcmxmc",
        "凭证日期": "pzrq",
        "核算账号编码": "code",
        "入库单号": "rkdh",
        "是否已过账": "posted",
        "摘要": "bz",
        "制单人": "zdr"
    }

    "年度\t调整期间\t凭证号\t凭证日期\t会计科目代码\t会计科目名称\t财会支出明细编码\t财会支出明细名称\t预会支出明细编码\t预会支出明细名称\t核算账号编码\t入库单号\t是否已过账\t摘要\t制单人";


    //var excelSheet;
    //for (var p in excelData) {
    //    excelSheet = excelData[p];
    //}

    var excelSheet = excelData;

    //分析字段对应关系
    var excelColIndex2ColName = {}; //excel 中的列号对应的中文题头
    var excelColName2ColIndex = {}; //中文题头对应的excel中的列号
    // var colLabel2ColName = {}; //中文题头对应到表的字段名


    var duplicateLabelCount = {};
    var colCount = 50; //最多几个列

    var headRow = 0; //题头在第几行
    var dataStartRow = 1; // 数据行从第几行开始
    //有时可能表头有多行合并，所以要检测一下
    for (var i = 0; i < colCount; i++) {
        var v = trim(sys_excelSafeValue(excelSheet, headRow, i));
        if (v == '')
            continue;
        if (duplicateLabelCount[v] == undefined) {
            duplicateLabelCount[v] = 0;
        }
        duplicateLabelCount[v] = duplicateLabelCount[v] + 1;

        if (duplicateLabelCount[v] > 1)
            v = v + duplicateLabelCount[v];
        //拼上后缀

        excelColIndex2ColName['' + i] = v;
        excelColName2ColIndex[v] = '' + i;
    }

    //println(JSON.toString(excelColName2ColIndex));
    //println(JSON.toString(excelColIndex2ColName));

    var RC = excelSheet.length;

    var data = [];
    for (var row = dataStartRow; row < RC; row++) {
        if (sys_excelSafeValue(excelSheet, row, 1) == null) break; //空行，直接结束
        var oneRowData = {};
        data.push(oneRowData);
        for (var label in excelColName2ColIndex) {
            var excelCol = excelColName2ColIndex[label];
            var dbCol = colLabel2ColName[label];
            if (dbCol != null) {
                oneRowData[dbCol] = sys_excelSafeValue(excelSheet, row, excelCol);
            }
        }

    }
    //println(JSON.toString(data));

    pushMessage("dr_info", "开始导入...", currentUserId());

    var gguid = currentGUID();
    var userid = currentUserId();
    var username = currentUserName();
    var lastmodifieddate = newDate();
    // println('import_ph:' + import_ph);



    var ds = newDataStore(dsn, "select * from " + tableName);
    ds.setUpdateProperty(tableName, "id", "*", "id");
    for (var i = 0; i < data.length; i++) {
        var row = ds.insertRow(99999);
        pushMessage("dr_info", "导入进度：" + (i + 1) + "/" + data.length, currentUserId());

        var rowData = data[i];
        for (var col in rowData) {
            var value = rowData[col];
            ds.setValue(row, col, value);
        }
        ds.setValue(row, "id", newGuid());
        ds.setValue(row, "gguid", gguid);
        ds.setValue(row, "userid", userid);
        ds.setValue(row, "username", username);
        ds.setValue(row, "lastmodifieddate", lastmodifieddate);
    }

    pushMessage("dr_info", "正在写入数据库...", currentUserId());

    if (ds.update(true)) {
        // $alert('导入完成');
        ret.success = true;
        ret.message = ds.getString(0, "userid");

        //更新起始记账期和截止记账期
        var master_ds = newDataStore(dsn, "select * from " + masterTable);
        master_ds.setUpdateProperty(masterTable, "id", "*", "id");
        master_ds.retrieve("gguid='" + currentGUID() + "'");
        master_ds.setValue(0, "jzq_start", getStringFromSQL2(dsn, "select min(y*100+m) as t from pzdjex where gguid='" + currentGUID() + "'"));
        master_ds.setValue(0, "jzq_end", getStringFromSQL2(dsn, "select max(y*100+m) as t from pzdjex where gguid='" + currentGUID() + "'"));
        master_ds.update(true)
    } else {
        ret.message = ds.getError().getMessage();
    }
    pushMessage('dr_info', 'over', currentUserId());

    return ret;
}

function sys_excelSafeValue(sheet, row, col) {
    if (row > sheet.length - 1) return null;
    var dataRow = sheet[row];
    if (dataRow == null) return null;
    if (col > dataRow.length - 1) return null;
    return dataRow[col];

}


id: 619b35ad99328907cafee6b7
scriptid: 617cc6bb99328c3820c0b3a7
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.22 18:37:25.000
script:
/**
 * 表单初始化完成后，执行此事件
 */
//@comment (group=表单事件,caption=表单初始化完成)
function formOpen() {
    book.showTabOnWhere = 'none';
    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);
}

/**
 * 单元格单击事件。仅当点击处有一个有效单元格时才触发本事件。当在有效行列之外点击时， 不触发本事件。
 * 当在有效行列之内但该坐标处并没有创建单元格时，也不会触发。
 * 注：当通过row,col定位到一个单元格时，如果在模板设计时并没有对该单元格做任何属性设置，那么此坐标处是空的，并不存在单元格对象，这种情况很少见
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {


    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'q_hz') {
        let sheet_mx = book.getWorkSheet("mx");
        sheet_mx.cells("st_corpid").setValue($q_hz_ds.getString(innerRow, "corpid"));
        let ym = $q_hz_ds.getString(innerRow, "ym");
        sheet_mx.cells("st_y").setValue(ym.substring(0, 4));
        sheet_mx.cells("st_m").setValue(ym.substring(4, 6));
        //book.getWorkSheet("mx").cells("st_corpid").setValue("001");
    }
    let value = cell.getValueDouble(innerRow);
    if (bind != null && bind.dataSource == 'q_hz' && bind.DBCol == 'pzsl_dj_wpic' && value > 0) cell_pzsl_dj_wpic_onClick(sheet, cell, innerRow, event);//未影像化凭证列表
    if (bind != null && bind.dataSource == 'q_hz' && bind.DBCol == 'pzsl_pic_wdj' && value > 0) cell_pzsl_pic_wdj_onClick(sheet, cell, innerRow, event);//未登记凭证列表

}

//@comment (group=,caption=已登记未影像化的凭证列表,needRightControl=false)
function cell_pzsl_dj_wpic_onClick(sheet, cell, innerRow, event) {
    book.getWorkSheet("mx").cells("st_status").setValue(1);
    book.getWorkSheet("mx").float('fa fa-cog', "凭证列表",
        {
            my: 'right-center',
            at: 'right-center',
            autoposition: 'down',
            offsetX: -5,
            offsetY: 5
        }, { width: 700, height: "90%" });
    smartRetrieve(book.getWorkSheet("mx_list"), "q_mx");

}
//@comment (group=,caption=未登记凭证列表,needRightControl=false)
function cell_pzsl_pic_wdj_onClick(sheet, cell, innerRow, event) {
    book.getWorkSheet("mx").cells("st_status").setValue(-1);
    book.getWorkSheet("mx").float('fa fa-cog', "凭证列表",
        {
            my: 'right-center',
            at: 'right-center',
            autoposition: 'down',
            offsetX: -5,
            offsetY: 5
        }, { width: 700, height: "90%" });
    smartRetrieve(book.getWorkSheet("mx_list"), "q_mx");

}

/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'q_mx') {
        //重新加载凭证图片列表

        let id = $q_mx_ds.getString(row, "id");
        let pzh = $q_mx_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}


function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.getWorkSheet("mx").getBrick('FJ');
    FJ.buildGridly(data, function () {
        
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, pzh, false);
            }
        }

    });
    book.getWorkSheet("mx").yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}


//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}


id: 619b35ad99328907cafee6c1
scriptid: 617cc6bb99328c3820c0b3a7
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.22 18:42:22.000
script:
/**
 * 表单初始化完成后，执行此事件
 */
//@comment (group=表单事件,caption=表单初始化完成)
function formOpen() {
    book.showTabOnWhere = 'none';
    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);
}

/**
 * 单元格单击事件。仅当点击处有一个有效单元格时才触发本事件。当在有效行列之外点击时， 不触发本事件。
 * 当在有效行列之内但该坐标处并没有创建单元格时，也不会触发。
 * 注：当通过row,col定位到一个单元格时，如果在模板设计时并没有对该单元格做任何属性设置，那么此坐标处是空的，并不存在单元格对象，这种情况很少见
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {


    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'q_hz') {
        let sheet_mx = book.getWorkSheet("mx");
        sheet_mx.cells("st_corpid").setValue($q_hz_ds.getString(innerRow, "corpid"));
        let ym = $q_hz_ds.getString(innerRow, "ym");
        sheet_mx.cells("st_y").setValue(ym.substring(0, 4));
        sheet_mx.cells("st_m").setValue(ym.substring(4, 6));
        //book.getWorkSheet("mx").cells("st_corpid").setValue("001");
    }
    let value = cell.getValueDouble(innerRow);
    if (bind != null && bind.dataSource == 'q_hz' && bind.DBCol == 'pzsl_dj_wpic' && value > 0) cell_pzsl_dj_wpic_onClick(sheet, cell, innerRow, event);//未影像化凭证列表
    if (bind != null && bind.dataSource == 'q_hz' && bind.DBCol == 'pzsl_pic_wdj' && value > 0) cell_pzsl_pic_wdj_onClick(sheet, cell, innerRow, event);//未登记凭证列表

}

//@comment (group=,caption=已登记未影像化的凭证列表,needRightControl=false)
function cell_pzsl_dj_wpic_onClick(sheet, cell, innerRow, event) {
    book.getWorkSheet("mx").cells("st_status").setValue(1);
    // book.getWorkSheet("mx").float('fa fa-cog', "凭证列表",
    //     {
    //         my: 'right-center',
    //         at: 'right-center',
    //         autoposition: 'down',
    //         offsetX: -5,
    //         offsetY: 5
    //     }, { width: 700, height: "90%" });
    smartRetrieve(book.getWorkSheet("mx_list"), "q_mx");
    book.setActiveSheet("mx");
}
//@comment (group=,caption=未登记凭证列表,needRightControl=false)
function cell_pzsl_pic_wdj_onClick(sheet, cell, innerRow, event) {
    book.getWorkSheet("mx").cells("st_status").setValue(-1);
    book.getWorkSheet("mx").float('fa fa-cog', "凭证列表",
        {
            my: 'right-center',
            at: 'right-center',
            autoposition: 'down',
            offsetX: -5,
            offsetY: 5
        }, { width: 700, height: "90%" });
    smartRetrieve(book.getWorkSheet("mx_list"), "q_mx");

}

/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'q_mx') {
        //重新加载凭证图片列表

        let id = $q_mx_ds.getString(row, "id");
        let pzh = $q_mx_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}


function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.getWorkSheet("mx").getBrick('FJ');
    FJ.buildGridly(data, function () {

        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, pzh, false);
            }
        }

    });
    book.getWorkSheet("mx").yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}


//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}


id: 619b35ad99328907cafee6c7
scriptid: 617cc6bb99328c3820c0b3a7
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.22 18:42:55.000
script:
/**
 * 表单初始化完成后，执行此事件
 */
//@comment (group=表单事件,caption=表单初始化完成)
function formOpen() {
    book.showTabOnWhere = 'none';
    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);
}

/**
 * 单元格单击事件。仅当点击处有一个有效单元格时才触发本事件。当在有效行列之外点击时， 不触发本事件。
 * 当在有效行列之内但该坐标处并没有创建单元格时，也不会触发。
 * 注：当通过row,col定位到一个单元格时，如果在模板设计时并没有对该单元格做任何属性设置，那么此坐标处是空的，并不存在单元格对象，这种情况很少见
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {


    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'q_hz') {
        let sheet_mx = book.getWorkSheet("mx");
        sheet_mx.cells("st_corpid").setValue($q_hz_ds.getString(innerRow, "corpid"));
        let ym = $q_hz_ds.getString(innerRow, "ym");
        sheet_mx.cells("st_y").setValue(ym.substring(0, 4));
        sheet_mx.cells("st_m").setValue(ym.substring(4, 6));
        //book.getWorkSheet("mx").cells("st_corpid").setValue("001");
    }
    let value = cell.getValueDouble(innerRow);
    if (bind != null && bind.dataSource == 'q_hz' && bind.DBCol == 'pzsl_dj_wpic' && value > 0) cell_pzsl_dj_wpic_onClick(sheet, cell, innerRow, event);//未影像化凭证列表
    if (bind != null && bind.dataSource == 'q_hz' && bind.DBCol == 'pzsl_pic_wdj' && value > 0) cell_pzsl_pic_wdj_onClick(sheet, cell, innerRow, event);//未登记凭证列表

}

//@comment (group=,caption=已登记未影像化的凭证列表,needRightControl=false)
function cell_pzsl_dj_wpic_onClick(sheet, cell, innerRow, event) {
    book.getWorkSheet("mx").cells("st_status").setValue(1);
    // book.getWorkSheet("mx").float('fa fa-cog', "凭证列表",
    //     {
    //         my: 'right-center',
    //         at: 'right-center',
    //         autoposition: 'down',
    //         offsetX: -5,
    //         offsetY: 5
    //     }, { width: 700, height: "90%" });
    smartRetrieve(book.getWorkSheet("mx_list"), "q_mx");
    book.setActiveSheet("mx");
}
//@comment (group=,caption=未登记凭证列表,needRightControl=false)
function cell_pzsl_pic_wdj_onClick(sheet, cell, innerRow, event) {
    book.getWorkSheet("mx").cells("st_status").setValue(-1);
    book.setActiveSheet("mx");
    // book.getWorkSheet("mx").float('fa fa-cog', "凭证列表",
    //     {
    //         my: 'right-center',
    //         at: 'right-center',
    //         autoposition: 'down',
    //         offsetX: -5,
    //         offsetY: 5
    //     }, { width: 700, height: "90%" });
    smartRetrieve(book.getWorkSheet("mx_list"), "q_mx");

}

/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'q_mx') {
        //重新加载凭证图片列表

        let id = $q_mx_ds.getString(row, "id");
        let pzh = $q_mx_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}


function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.getWorkSheet("mx").getBrick('FJ');
    FJ.buildGridly(data, function () {

        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, pzh, false);
            }
        }

    });
    book.getWorkSheet("mx").yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}


//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}


id: 619b35ad99328907cafee6cd
scriptid: 617cc6bb99328c3820c0b3a7
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.22 18:45:53.000
script:
/**
 * 表单初始化完成后，执行此事件
 */
//@comment (group=表单事件,caption=表单初始化完成)
function formOpen() {
    book.showTabOnWhere = 'none';
    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);
}

/**
 * 单元格单击事件。仅当点击处有一个有效单元格时才触发本事件。当在有效行列之外点击时， 不触发本事件。
 * 当在有效行列之内但该坐标处并没有创建单元格时，也不会触发。
 * 注：当通过row,col定位到一个单元格时，如果在模板设计时并没有对该单元格做任何属性设置，那么此坐标处是空的，并不存在单元格对象，这种情况很少见
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {


    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'q_hz') {
        let sheet_mx = book.getWorkSheet("mx");
        sheet_mx.cells("st_corpid").setValue($q_hz_ds.getString(innerRow, "corpid"));
        let ym = $q_hz_ds.getString(innerRow, "ym");
        sheet_mx.cells("st_y").setValue(ym.substring(0, 4));
        sheet_mx.cells("st_m").setValue(ym.substring(4, 6));
        //book.getWorkSheet("mx").cells("st_corpid").setValue("001");
    }
    let value = cell.getValueDouble(innerRow);
    if (bind != null && bind.dataSource == 'q_hz' && bind.DBCol == 'pzsl_dj_wpic' && value > 0) cell_pzsl_dj_wpic_onClick(sheet, cell, innerRow, event);//未影像化凭证列表
    if (bind != null && bind.dataSource == 'q_hz' && bind.DBCol == 'pzsl_pic_wdj' && value > 0) cell_pzsl_pic_wdj_onClick(sheet, cell, innerRow, event);//未登记凭证列表

}

//@comment (group=,caption=已登记未影像化的凭证列表,needRightControl=false)
function cell_pzsl_dj_wpic_onClick(sheet, cell, innerRow, event) {
    book.getWorkSheet("mx").cells("st_status").setValue(1);
    // book.getWorkSheet("mx").float('fa fa-cog', "凭证列表",
    //     {
    //         my: 'right-center',
    //         at: 'right-center',
    //         autoposition: 'down',
    //         offsetX: -5,
    //         offsetY: 5
    //     }, { width: 700, height: "90%" });
    smartRetrieve(book.getWorkSheet("mx_list"), "q_mx");
    book.setActiveSheet("mx");
}
//@comment (group=,caption=未登记凭证列表,needRightControl=false)
function cell_pzsl_pic_wdj_onClick(sheet, cell, innerRow, event) {
    book.getWorkSheet("mx").cells("st_status").setValue(-1);
    book.setActiveSheet("mx");
    // book.getWorkSheet("mx").float('fa fa-cog', "凭证列表",
    //     {
    //         my: 'right-center',
    //         at: 'right-center',
    //         autoposition: 'down',
    //         offsetX: -5,
    //         offsetY: 5
    //     }, { width: 700, height: "90%" });
    smartRetrieve(book.getWorkSheet("mx_list"), "q_mx");

}

/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'q_mx') {
        //重新加载凭证图片列表

        let id = $q_mx_ds.getString(row, "id");
        let pzh = $q_mx_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}


function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.getWorkSheet("mx").getBrick('FJ');
    FJ.buildGridly(data, function () {

        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, pzh, false);
            }
        }

    });
    book.getWorkSheet("mx").yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}


//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}

/**
 * 按钮点击事件
 * 当某个按钮被点击时， 首先触发  {按钮名称}_onClick 事件，然后触发 buttonOnClick事件
 * @param sheet  工作表
 * @param cell   按钮所在的单元格
 * @param button 按钮对象
 */
function cb_return_onClick(sheet, cell, button) {
    book.setActiveSheet("main");

}


id: 619b769899328907cafee741
scriptid: 617cc6bb99328c3820c0b3a7
tablename: app_template
clientip: 10.255.0.2
username: sa
createdate: 2021.11.22 21:42:36.000
script:
/**
 * 表单初始化完成后，执行此事件
 */
//@comment (group=表单事件,caption=表单初始化完成)
function formOpen() {
    book.showTabOnWhere = 'none';
    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);
}

/**
 * 单元格单击事件。仅当点击处有一个有效单元格时才触发本事件。当在有效行列之外点击时， 不触发本事件。
 * 当在有效行列之内但该坐标处并没有创建单元格时，也不会触发。
 * 注：当通过row,col定位到一个单元格时，如果在模板设计时并没有对该单元格做任何属性设置，那么此坐标处是空的，并不存在单元格对象，这种情况很少见
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {


    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'q_hz') {
        let sheet_mx = book.getWorkSheet("mx");
        sheet_mx.cells("st_corpid").setValue($q_hz_ds.getString(innerRow, "corpid"));
        let ym = $q_hz_ds.getString(innerRow, "ym");
        sheet_mx.cells("st_y").setValue(ym.substring(0, 4));
        sheet_mx.cells("st_m").setValue(ym.substring(4, 6));
        //book.getWorkSheet("mx").cells("st_corpid").setValue("001");
    }
    let value = cell.getValueDouble(innerRow);
    if (bind != null && bind.dataSource == 'q_hz' && bind.DBCol == 'pzsl_dj_wpic' && value > 0) cell_pzsl_dj_wpic_onClick(sheet, cell, innerRow, event);//未影像化凭证列表
    if (bind != null && bind.dataSource == 'q_hz' && bind.DBCol == 'pzsl_pic_wdj' && value > 0) cell_pzsl_pic_wdj_onClick(sheet, cell, innerRow, event);//未登记凭证列表

}

//@comment (group=,caption=已登记未影像化的凭证列表,needRightControl=false)
function cell_pzsl_dj_wpic_onClick(sheet, cell, innerRow, event) {
    book.getWorkSheet("mx").cells("st_status").setValue(1);
    // book.getWorkSheet("mx").float('fa fa-cog', "凭证列表",
    //     {
    //         my: 'right-center',
    //         at: 'right-center',
    //         autoposition: 'down',
    //         offsetX: -5,
    //         offsetY: 5
    //     }, { width: 700, height: "90%" });
    smartRetrieve(book.getWorkSheet("mx_list"), "q_mx");
    book.setActiveSheet("mx");
}
//@comment (group=,caption=未登记凭证列表,needRightControl=false)
function cell_pzsl_pic_wdj_onClick(sheet, cell, innerRow, event) {
    book.getWorkSheet("mx").cells("st_status").setValue(-1);
    book.setActiveSheet("mx");
    // book.getWorkSheet("mx").float('fa fa-cog', "凭证列表",
    //     {
    //         my: 'right-center',
    //         at: 'right-center',
    //         autoposition: 'down',
    //         offsetX: -5,
    //         offsetY: 5
    //     }, { width: 700, height: "90%" });
    smartRetrieve(book.getWorkSheet("mx_list"), "q_mx");

}

/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'q_mx') {
        //重新加载凭证图片列表

        let id = $q_mx_ds.getString(row, "id");
        let pzh = $q_mx_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}


function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.getWorkSheet("mx_img").getBrick('FJ');
    FJ.buildGridly(data, function () {

        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, pzh, false);
            }
        }

    });
    book.getWorkSheet("mx").yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}


//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}

/**
 * 按钮点击事件
 * 当某个按钮被点击时， 首先触发  {按钮名称}_onClick 事件，然后触发 buttonOnClick事件
 * @param sheet  工作表
 * @param cell   按钮所在的单元格
 * @param button 按钮对象
 */
function cb_return_onClick(sheet, cell, button) {
    book.setActiveSheet("main");

}


id: 619c5fc20374337c889d176f
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 192.168.1.77
username: sa
createdate: 2021.11.23 15:02:28.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id, pzh,true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消校对");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, pzh,false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {
        let rows = [];
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            rows.push(i);
        };

        showInfoPane("* 正在审核确认...");
        asyncPool(4, rows, function (i, rows) {
            return new Promise(function (resolve, reject) {
                showInfoPane("* 正在审核确认 " + i  );
                do_sh1(i, function () {
                    resolve(i);
                });
            });
        }).then(function (v) {
            hideInfoPane();
            toastr.info("审核完成");
        });

    });
}



function cb_unverify_onClick() {

    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {
        var rows = [];
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            rows.push(i);
        };

        showInfoPane("* 正在取消确认...");
        asyncPool(4, rows, function (i, rows) {
            return new Promise(function (resolve, reject) {
                showInfoPane("* 正在取消确认"+i);
                do_sh2(i, function () {
                    resolve(i);
                });
            });
        }).then(function (v) {
            hideInfoPane();
            toastr.info("取消确认完成");
        });

    });


}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function isVerified() {
    var row = book.getDataSource('dzpz_pz').currentBindRow;
    var verifiername = $dzpz_pz_ds.getString(row, "verifiername");

    if (verifiername != '') {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '90' ,function(){hideInfoPane();});

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '270',function(){hideInfoPane();});

            }
        );



    }
}


function rotateImg(sheet, id, degree, callback) {



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID

        do_imageRotate(id, degree, function (ret) {


            if (ret.success) {

                g_turningCount++;
                showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');


                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }
            if (callback) callback();



        });
    }, 100);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    if (isVerified()) return;  //校对过的不允许再调整顺序

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

    if (isVerified()) return;  //校对过的不允许再旋转

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {

        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;
        /*
                setTimeout(function () {
                    for (var i = 0; i < selection.length; i++) {
                        rotateImg(sheet, selection[i].id, degree, i * 1000);
                    }
                }, 10);
                */

        asyncPool(4 , selection, function (item, array) {
            return new Promise(function (resolve, reject) {

                console.dir(item);
                rotateImg(sheet, item.id, degree,
                    function () { //注意，在旋转完成后，再设置resolve 表示本任务已完成，而不是直接就resolve ,不然最后的 then 执行时机不对，这么处理，就会在全部旋转完成后，再执行then中的脚本，而不是旋转任务全部发起后就执行 then 
                        resolve(item)
                    });

            });
        }).then(function () {

            setTimeout(function () {

                hideInfoPane();
                toastr.info("旋转完成");
            }, 500);
        });

    });

}




function asyncPool(poolLimit, array, iteratorFn) {
    let i = 0;
    const ret = [];
    const executing = [];
    const enqueue = function () {
        if (i === array.length) {
            return Promise.resolve();
        }
        const item = array[i++];
        const p = Promise.resolve().then(() => iteratorFn(item, array));
        ret.push(p);

        let r = Promise.resolve();

        if (poolLimit <= array.length) {
            const e = p.then(() => executing.splice(executing.indexOf(e), 1));
            executing.push(e);
            if (executing.length >= poolLimit) {
                r = Promise.race(executing);
            }
        }

        return r.then(() => enqueue());
    };
    return enqueue().then(() => Promise.all(ret));
}


function test1() {


    asyncPool(3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function (item, array) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                console.info(item + "   "+ new Date());
                resolve(item)
            }, 1000);

        });
    }).then(function () {
        console.info("over");
    });

}


id: 619c5fc20374337c889d177d
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 192.168.1.77
username: sa
createdate: 2021.11.23 15:03:19.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id,true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消校对");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {
        let rows = [];
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            rows.push(i);
        };

        showInfoPane("* 正在审核确认...");
        asyncPool(4, rows, function (i, rows) {
            return new Promise(function (resolve, reject) {
                showInfoPane("* 正在审核确认 " + i  );
                do_sh1(i, function () {
                    resolve(i);
                });
            });
        }).then(function (v) {
            hideInfoPane();
            toastr.info("审核完成");
        });

    });
}



function cb_unverify_onClick() {

    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {
        var rows = [];
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            rows.push(i);
        };

        showInfoPane("* 正在取消确认...");
        asyncPool(4, rows, function (i, rows) {
            return new Promise(function (resolve, reject) {
                showInfoPane("* 正在取消确认"+i);
                do_sh2(i, function () {
                    resolve(i);
                });
            });
        }).then(function (v) {
            hideInfoPane();
            toastr.info("取消确认完成");
        });

    });


}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function isVerified() {
    var row = book.getDataSource('dzpz_pz').currentBindRow;
    var verifiername = $dzpz_pz_ds.getString(row, "verifiername");

    if (verifiername != '') {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '90' ,function(){hideInfoPane();});

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '270',function(){hideInfoPane();});

            }
        );



    }
}


function rotateImg(sheet, id, degree, callback) {



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID

        do_imageRotate(id, degree, function (ret) {


            if (ret.success) {

                g_turningCount++;
                showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');


                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }
            if (callback) callback();



        });
    }, 100);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    if (isVerified()) return;  //校对过的不允许再调整顺序

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

    if (isVerified()) return;  //校对过的不允许再旋转

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {

        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;
        /*
                setTimeout(function () {
                    for (var i = 0; i < selection.length; i++) {
                        rotateImg(sheet, selection[i].id, degree, i * 1000);
                    }
                }, 10);
                */

        asyncPool(4 , selection, function (item, array) {
            return new Promise(function (resolve, reject) {

                console.dir(item);
                rotateImg(sheet, item.id, degree,
                    function () { //注意，在旋转完成后，再设置resolve 表示本任务已完成，而不是直接就resolve ,不然最后的 then 执行时机不对，这么处理，就会在全部旋转完成后，再执行then中的脚本，而不是旋转任务全部发起后就执行 then 
                        resolve(item)
                    });

            });
        }).then(function () {

            setTimeout(function () {

                hideInfoPane();
                toastr.info("旋转完成");
            }, 500);
        });

    });

}




function asyncPool(poolLimit, array, iteratorFn) {
    let i = 0;
    const ret = [];
    const executing = [];
    const enqueue = function () {
        if (i === array.length) {
            return Promise.resolve();
        }
        const item = array[i++];
        const p = Promise.resolve().then(() => iteratorFn(item, array));
        ret.push(p);

        let r = Promise.resolve();

        if (poolLimit <= array.length) {
            const e = p.then(() => executing.splice(executing.indexOf(e), 1));
            executing.push(e);
            if (executing.length >= poolLimit) {
                r = Promise.race(executing);
            }
        }

        return r.then(() => enqueue());
    };
    return enqueue().then(() => Promise.all(ret));
}


function test1() {


    asyncPool(3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function (item, array) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                console.info(item + "   "+ new Date());
                resolve(item)
            }, 1000);

        });
    }).then(function () {
        console.info("over");
    });

}


id: 619c5fc20374337c889d1796
scriptid: 60d0840b0c749ebb22855746
tablename: app_script
clientip: 192.168.1.77
username: sa
createdate: 2021.11.23 15:06:47.000
script:
function main(arg)
{
    var p= JSON.parse(arg);
    var id= p.id;
    var overwrite= p.overwrite; 

    // info2 是手工调整顺序后的序号 ，如果没有手工调整顺序，那么info2应该都是null , 
    // 这样，如果手工调整了顺序，那么以手工调整后的顺序来排序，
    //否则以(groupname优先排序，它通常是“凭证”，“附件”) 凭证排在前，附件排在后 ，同类型（groupname）文件的按原始日期来排序，

    var pzh= getStringFromSQL( "select pzh from dzpz_pz where id='"+id+"'");
    ) ;
    return createArchive("dzpz", id ,"info2 asc , groupname , info1 asc ", overwrite , 
            {left:20,top:20,url:url} ,  //左上角加一个印章图片
            pzh //右上角把凭证号打上，便于查看
            );


}


id: 619c5fc20374337c889d17aa
scriptid: 60d0840b0c749ebb22855746
tablename: app_script
clientip: 192.168.1.77
username: sa
createdate: 2021.11.23 15:12:32.000
script:
function main(arg) {
    var p = JSON.parse(arg);
    var id = p.id;
    var overwrite = p.overwrite;

    // info2 是手工调整顺序后的序号 ，如果没有手工调整顺序，那么info2应该都是null , 
    // 这样，如果手工调整了顺序，那么以手工调整后的顺序来排序，
    //否则以(groupname优先排序，它通常是“凭证”，“附件”) 凭证排在前，附件排在后 ，同类型（groupname）文件的按原始日期来排序，

    var tds = newDataStore("", "select pzh , corpid from dzpz_pz where id='" + id + "'");
    tds.retrieve();
    var pzh = tds.getString(0, "pzh");
    var coprid = tds.getString(0, "corpid");

    var url = getStringFromSQL("select url_img  from basic_corp_seal a , basic_corp b where a.gguid=b.gguid and a.groupname='电子印章' and b.code= '" + corpid + "' ");


    return createArchive("dzpz", id, "info2 asc , groupname , info1 asc ", overwrite,
        {
            left: 20, 
            top: 20,
            url: url
        },  //左上角加一个印章图片
        pzh //右上角把凭证号打上，便于查看
    );


}


id: 619c5fc20374337c889d17b2
scriptid: 60d0840b0c749ebb22855746
tablename: app_script
clientip: 192.168.1.77
username: sa
createdate: 2021.11.23 15:13:30.000
script:
function main(arg) {
    var p = JSON.parse(arg);
    var id = p.id;
    var overwrite = p.overwrite;

    // info2 是手工调整顺序后的序号 ，如果没有手工调整顺序，那么info2应该都是null , 
    // 这样，如果手工调整了顺序，那么以手工调整后的顺序来排序，
    //否则以(groupname优先排序，它通常是“凭证”，“附件”) 凭证排在前，附件排在后 ，同类型（groupname）文件的按原始日期来排序，

    var tds = newDataStore("", "select pzh , corpid from dzpz_pz where id='" + id + "'");
    tds.retrieve();
    var pzh = tds.getString(0, "pzh");
    var coprid = tds.getString(0, "corpid");

    var url = getStringFromSQL("select url_img  from basic_corp_seal a , basic_corp b where a.gguid=b.gguid and a.groupname='电子印章' and b.code= '" + corpid + "' ");


    //把附件打包成一个PDF
    return createArchive("dzpz", id,
        "info2 asc , groupname , info1 asc ",  //附件排序规则
        overwrite, //是否强行重新生成
        {
            left: 20,
            top: 20,
            url: url
        },  //左上角加一个印章图片
        pzh //右上角把凭证号打上，便于查看
    );


}


id: 619c5fc20374337c889d17bc
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 192.168.1.77
username: sa
createdate: 2021.11.23 15:17:27.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

function viewPDF( id)
{
    var url=  get_PZ_PDF_URL(url);
    open(url);
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id,true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消校对");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {
        let rows = [];
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            rows.push(i);
        };

        showInfoPane("* 正在审核确认...");
        asyncPool(4, rows, function (i, rows) {
            return new Promise(function (resolve, reject) {
                showInfoPane("* 正在审核确认 " + i  );
                do_sh1(i, function () {
                    resolve(i);
                });
            });
        }).then(function (v) {
            hideInfoPane();
            toastr.info("审核完成");
        });

    });
}



function cb_unverify_onClick() {

    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {
        var rows = [];
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            rows.push(i);
        };

        showInfoPane("* 正在取消确认...");
        asyncPool(4, rows, function (i, rows) {
            return new Promise(function (resolve, reject) {
                showInfoPane("* 正在取消确认"+i);
                do_sh2(i, function () {
                    resolve(i);
                });
            });
        }).then(function (v) {
            hideInfoPane();
            toastr.info("取消确认完成");
        });

    });


}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function isVerified() {
    var row = book.getDataSource('dzpz_pz').currentBindRow;
    var verifiername = $dzpz_pz_ds.getString(row, "verifiername");

    if (verifiername != '') {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '90' ,function(){hideInfoPane();});

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '270',function(){hideInfoPane();});

            }
        );



    }
}


function rotateImg(sheet, id, degree, callback) {



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID

        do_imageRotate(id, degree, function (ret) {


            if (ret.success) {

                g_turningCount++;
                showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');


                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }
            if (callback) callback();



        });
    }, 100);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    if (isVerified()) return;  //校对过的不允许再调整顺序

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

    if (isVerified()) return;  //校对过的不允许再旋转

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {

        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;
        /*
                setTimeout(function () {
                    for (var i = 0; i < selection.length; i++) {
                        rotateImg(sheet, selection[i].id, degree, i * 1000);
                    }
                }, 10);
                */

        asyncPool(4 , selection, function (item, array) {
            return new Promise(function (resolve, reject) {

                console.dir(item);
                rotateImg(sheet, item.id, degree,
                    function () { //注意，在旋转完成后，再设置resolve 表示本任务已完成，而不是直接就resolve ,不然最后的 then 执行时机不对，这么处理，就会在全部旋转完成后，再执行then中的脚本，而不是旋转任务全部发起后就执行 then 
                        resolve(item)
                    });

            });
        }).then(function () {

            setTimeout(function () {

                hideInfoPane();
                toastr.info("旋转完成");
            }, 500);
        });

    });

}




function asyncPool(poolLimit, array, iteratorFn) {
    let i = 0;
    const ret = [];
    const executing = [];
    const enqueue = function () {
        if (i === array.length) {
            return Promise.resolve();
        }
        const item = array[i++];
        const p = Promise.resolve().then(() => iteratorFn(item, array));
        ret.push(p);

        let r = Promise.resolve();

        if (poolLimit <= array.length) {
            const e = p.then(() => executing.splice(executing.indexOf(e), 1));
            executing.push(e);
            if (executing.length >= poolLimit) {
                r = Promise.race(executing);
            }
        }

        return r.then(() => enqueue());
    };
    return enqueue().then(() => Promise.all(ret));
}


function test1() {


    asyncPool(3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function (item, array) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                console.info(item + "   "+ new Date());
                resolve(item)
            }, 1000);

        });
    }).then(function () {
        console.info("over");
    });

}


id: 619c958a0374337c889d17c2
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 192.168.1.77
username: sa
createdate: 2021.11.23 15:17:31.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

function viewPDF( id)
{
    var url=  get_PZ_PDF_URL(url);
    openWindow(url);
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id,true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消校对");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {
        let rows = [];
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            rows.push(i);
        };

        showInfoPane("* 正在审核确认...");
        asyncPool(4, rows, function (i, rows) {
            return new Promise(function (resolve, reject) {
                showInfoPane("* 正在审核确认 " + i  );
                do_sh1(i, function () {
                    resolve(i);
                });
            });
        }).then(function (v) {
            hideInfoPane();
            toastr.info("审核完成");
        });

    });
}



function cb_unverify_onClick() {

    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {
        var rows = [];
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            rows.push(i);
        };

        showInfoPane("* 正在取消确认...");
        asyncPool(4, rows, function (i, rows) {
            return new Promise(function (resolve, reject) {
                showInfoPane("* 正在取消确认"+i);
                do_sh2(i, function () {
                    resolve(i);
                });
            });
        }).then(function (v) {
            hideInfoPane();
            toastr.info("取消确认完成");
        });

    });


}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function isVerified() {
    var row = book.getDataSource('dzpz_pz').currentBindRow;
    var verifiername = $dzpz_pz_ds.getString(row, "verifiername");

    if (verifiername != '') {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '90' ,function(){hideInfoPane();});

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '270',function(){hideInfoPane();});

            }
        );



    }
}


function rotateImg(sheet, id, degree, callback) {



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID

        do_imageRotate(id, degree, function (ret) {


            if (ret.success) {

                g_turningCount++;
                showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');


                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }
            if (callback) callback();



        });
    }, 100);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    if (isVerified()) return;  //校对过的不允许再调整顺序

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

    if (isVerified()) return;  //校对过的不允许再旋转

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {

        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;
        /*
                setTimeout(function () {
                    for (var i = 0; i < selection.length; i++) {
                        rotateImg(sheet, selection[i].id, degree, i * 1000);
                    }
                }, 10);
                */

        asyncPool(4 , selection, function (item, array) {
            return new Promise(function (resolve, reject) {

                console.dir(item);
                rotateImg(sheet, item.id, degree,
                    function () { //注意，在旋转完成后，再设置resolve 表示本任务已完成，而不是直接就resolve ,不然最后的 then 执行时机不对，这么处理，就会在全部旋转完成后，再执行then中的脚本，而不是旋转任务全部发起后就执行 then 
                        resolve(item)
                    });

            });
        }).then(function () {

            setTimeout(function () {

                hideInfoPane();
                toastr.info("旋转完成");
            }, 500);
        });

    });

}




function asyncPool(poolLimit, array, iteratorFn) {
    let i = 0;
    const ret = [];
    const executing = [];
    const enqueue = function () {
        if (i === array.length) {
            return Promise.resolve();
        }
        const item = array[i++];
        const p = Promise.resolve().then(() => iteratorFn(item, array));
        ret.push(p);

        let r = Promise.resolve();

        if (poolLimit <= array.length) {
            const e = p.then(() => executing.splice(executing.indexOf(e), 1));
            executing.push(e);
            if (executing.length >= poolLimit) {
                r = Promise.race(executing);
            }
        }

        return r.then(() => enqueue());
    };
    return enqueue().then(() => Promise.all(ret));
}


function test1() {


    asyncPool(3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function (item, array) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                console.info(item + "   "+ new Date());
                resolve(item)
            }, 1000);

        });
    }).then(function () {
        console.info("over");
    });

}


id: 619c958a0374337c889d17d4
scriptid: 60c4bd735db2478f9c5a1118
tablename: app_script
clientip: 192.168.1.77
username: sa
createdate: 2021.11.23 15:19:40.000
script:
//@comment (group=,caption=构建凭证附件清单,needRightControl=false)
function getPZFJ(id) {
    var ds = newDataStore("", "select id ,   url_img , url_thumbnail ,groupname , info1 from  dzpz_pzfj where  gguid='" + id + "'  order by info2 asc, groupname ,  info1 asc ");
    var n = ds.retrieve();
    println( ds.getSelectLastRetrieved());
    
    var ret = [];
    for (var i = 0; i < n; i++) {
        ret.push(JSON.parse(ds.getJSONRow(i, true)));
    }
    return ret;

}

function get_PZ_PDF_URL(id)
{
    return  getStringFromSQL( "select url_img from app_archive where gguid='"+id+"'" ) ;
}
function reOrderImage(ids)
{
    var sqls=[];
    for( var i=0;i<ids.length;i++)
    {
        var xh= right('0000'+(i+1) ,4);
        sqls.push("update dzpz_pzfj set info2 ='"+xh+"' where id='"+ids[i]+"' ");
    }
    runSQL("", sqls, true); 
    println("调整顺序完成");

}


//@comment (group=,caption=凭证号前缀,needRightControl=false)
function getPZHPrefix(corpid, ym) {
    return runTask("getPZHPrefix", { corpid: corpid, ym: ym });

}
//@comment (group=,caption=凭证号长度,needRightControl=false)
function getPZHLen(corpid) {
    return parseInt(runTask("getPZHLen", { corpid: corpid }));
}



//@comment (group=,caption=凭证审核或取消审核,needRightControl=false)
function do_sh(id, sh) {


    //if (!isRoleGrantedToUser(currentUserId(), "60c81b135db2d209d074b697")) return { success: false, message: "没有审核权限" };



    var dzpz_ds = newDataStore("", "select * from dzpz_pz where id='" + id + "'");
    dzpz_ds.setUpdateProperty("dzpz_pz", "id", "*", "id");
    dzpz_ds.retrieve();
    if (dzpz_ds.getRowCount() == 0) {
        return { success: false, message: "凭证不存在" };
    }
    if (sh) //做审核
    {
        var verifierid = dzpz_ds.getInt(0, "verifierid");
        if (verifierid != 0) return {
            success: true, verifierid: verifierid,
            verifiername: dzpz_ds.getString(0, "verifiername"),
            verifieddate: dzpz_ds.getString(0, "verifieddate"), message: "凭证已审核，不需要重复审核"
        };
        dzpz_ds.setValue(0, "verifierid", currentUserId());
        dzpz_ds.setValue(0, "verifiername", currentUserShowName());
        dzpz_ds.setValue(0, "verifieddate", newDate());

        if (!dzpz_ds.update(true)) return { success: false, message: dzpz_ds.getError().getMessage() };

        //审核后，归档
        runTask("pz_image2pdf", {
            id: id,
            overwrite: true  //如果已存在，删除并重新生成
        });

        return {
            success: true,
            verifierid: dzpz_ds.getString(0, "verifierid"),
            verifiername: dzpz_ds.getString(0, "verifiername"),
            verifieddate: dzpz_ds.getString(0, "verifieddate")
        };

    } else {
        var verifierid = dzpz_ds.getInt(0, "verifierid");
        println(verifierid);
        if (verifierid == 0) return { success: true, message: "凭证尚未审核，不需要取消审核" };
        if (verifierid != currentUserId()) {
            if (!isRoleGrantedToUser(currentUserId(), "60c81b135db2d209d074b6a7") && currentUserId() != 1) {

                return { success: false, message: "必须由审核人或超级审核员来取消审核" };
            }
        }
        dzpz_ds.setValue(0, "verifierid", null);
        dzpz_ds.setValue(0, "verifiername", null);
        dzpz_ds.setValue(0, "verifieddate", null);

        if (!dzpz_ds.update(true)) return { success: false, message: dzpz_ds.getError().getMessage() };
        return { success: true };
    }

}



//@comment (group=,caption=图片旋转,needRightControl=false)
function do_imageRotate(id, rt) {
    var ret = imageRotate("", "dzpz_pzfj", id, rt);
    println(JSON.stringify(ret));
    return ret;
}


id: 619c958a0374337c889d17dc
scriptid: 60c4bd735db2478f9c5a111c
tablename: app_template
clientip: 192.168.1.77
username: sa
createdate: 2021.11.23 15:23:42.000
script:
var pzh_prefix;
var pzh_length;

var fullScreenDiv = null;



function formOpen() {
    book.showTabOnWhere = 'none';
    //加载帐套信息及年月
    var corpid = book.sheet0.cells("corpid").getValueString();
    runTask("当前记帐期", { corpid: corpid }, function (ym) {
        if (ym == null || ym == 'null') return;
        //得到年月后，获取凭证号相关设置
        pzh_len = getPZHLen(corpid);

        book.sheet0.cells("ym").setValue(ym);

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);


    });

    book.sheet2.getBrick('FJ').selectionMode = 'multi'; //图片设置成多选模式


    // 追加一些CSS类 ，用于凭证号标记
    $(document.body).append(`<style>
                        .pzh {position:absolute;left:0;bottom:0px; 
                                height:24px; line-height:24px;width:100%; 
                                background-color:#40af40a0; 
                                color:white;font-weight:bold;font-size:12px;text-align:center;}
                        .delete_pzh { position:absolute; right:0; width:40px; height:14px; top:0; text-align:right; 
                                    vertical-align:top; font-size:12px; color:gray;padding-right:5px;}      
                        .delete_pzh:hover { color:white;}      
                          
                        </style>
                    `);


}

function cb_check_onClick() {
    smartRetrieve(book.sheet0, "pzh_check", true, false, function () { //检索完后回调
        if ($pzh_check_ds.rowCount == 0) {
            toastr.success("凭证号检测通过");

        } else {
            book.sheet3.popup('fa fa-cog', '缺失的凭证', 250, 350, true, true, {});
        }
    });
}


/**
 * 多行结果集当前焦点行发生变化
 * @param dsname  结果集名称
 * @param row  行号
 */
function currentBindRowChanged(dsname, row) {
    if (dsname == 'dzpz_pz') {
        //重新加载凭证图片列表

        let id = $dzpz_pz_ds.getString(row, "id");
        let pzh = $dzpz_pz_ds.getString(row, "pzh");
        loadPZ(pzh, id);

    }
}

function viewPDF( id)
{
    var url=  get_PZ_PDF_URL(id);
    openWindow(url);
}

/**
 * 单元格的值发生了改变
 * @param sheet  所在的工作表
 * @param cell  单元格对象
 * @param oldValue  原先的值
 * @param newValue 变化后的值
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChanged(sheet, cell, oldValue, newValue, innerRow) {

    //如果是绑定了数据库的，强烈不建议使用本事件，换用结果集变化事件 itemChanged

    //通过别名来判断
    if (cell.alias == 'ym') {
        var corpid = book.sheet0.cells("corpid").getValueString();
        var ym = book.sheet0.cells("ym").getValue();

        pzh_prefix = getPZHPrefix(corpid, ym);
        book.sheet0.cells("pzh_prefix").setValue(pzh_prefix);
    }




}

function loadPZ(pzh, id) {
    let data = getPZFJ(id); //得到凭证的所有图片
    let FJ = book.sheet2.getBrick('FJ');
    FJ.buildGridly(data, function () {
        let shortPZH = pzh;//.substring(pzh_prefix.length);
        //加载图片完成后， 如果是凭证，那么加上凭证号信息
        for (let i = 0; i < data.length; i++) {
            if (data[i].groupname == '凭证') {
                setPZH(data[i].id, shortPZH, false);
            }
        }




    });
    g_selectedAll = false; //加载一个凭证的图片后 ，默认是不全选中的
    book.sheet2.yOffset = 0; //垂直卷滚条归位
}


//@comment (group=凭证号,caption=设置图片的凭证号,needRightControl=false)
function setPZH(id, pzh, needDeleteButton) {
    if (needDeleteButton == undefined) needDeleteButton = true
    find_pzh(id, true, needDeleteButton).find('.no').text(pzh);
}

//@comment (group=凭证号,caption=查找或创建凭证号标记对象,needRightControl=false)
function find_pzh(id, create_if_not_exists, needDeleteButton) {

    if (needDeleteButton == undefined) needDeleteButton = true;

    var d = $('#' + id);
    if (!d) {
        $.alert(id + "不存在");
        return null;
    }

    var ret = d.find('.pzh');
    if (ret.length == 0) {
        if (create_if_not_exists) //如果需要创建，则创建它
        {
            d.append(`<div class="pzh" >
                        <div class="no"></div>
                        <div class="delete_pzh"  ${needDeleteButton ? "" : " style='display:none' "} ><i class="fa fa-close" onclick="removePZH('${id}');  event.preventDefault(); event.stopPropagation();"> </i></div>
                      </div>`);
        }
        ret = d.find('.pzh');
    }
    return ret;

}



/**
 * 单元格单击事件
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被点击
 * @param event 事件对象
 */
//@comment (group=单元格事件,caption=单元格点击)
function cellOnClick(sheet, cell, innerRow, event) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_pz') {
        if (bind.DBCol == 'c_sh1') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") != 0) return; //已审核，不要再审核
            do_sh1(innerRow);
        }
        if (bind.DBCol == 'c_sh2') {
            if ($dzpz_pz_ds.getInt(innerRow, "verifierid") == 0) return; //没有审核，不需要取消审核
            do_sh2(innerRow);
        }
    }

}

function do_sh1(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    let pzh = $dzpz_pz_ds.getString(innerRow, "pzh");

    do_sh(id,true, function (ret)  //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", ret.verifierid);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", ret.verifiername);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", ret.verifieddate);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "审核成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "取消校对");

        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}

function do_sh2(innerRow, callback) {
    let id = $dzpz_pz_ds.getString(innerRow, "id");
    do_sh(id, false, function (ret) //后台执行
    {
        if (ret.success) {
            $dzpz_pz_ds.setValue(innerRow, "verifierid", null);
            $dzpz_pz_ds.setValue(innerRow, "verifiername", null);
            $dzpz_pz_ds.setValue(innerRow, "verifieddate", null);
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", "取消成功");
            $dzpz_pz_ds.setValue(innerRow, "c_sh1", "审核");
            $dzpz_pz_ds.setValue(innerRow, "c_sh2", "");


        } else {
            $dzpz_pz_ds.setValue(innerRow, "tipinfo", ret.message);

        }
        if (callback) callback();
    });
}



//@comment (group=工具函数,caption=全选或取消全选)
function seletOrUnSelectAll() {
    //让selection单元格失去编辑焦点，不然再点击，它不会触发单元格的点击事件，因为此时点击的编辑框对象，不会触发单元格的点击
    book.sheet1.View.forceCurrentEditControlGiveUpFocus();

    var v = book.sheet1.cells('selection').getValueInt();

    book.sheet1.paintPermit = false;
    $dzpz_pz_ds.setValueWithTrigger = false;
    for (var i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        $dzpz_pz_ds.setValue(i, "selected", v);
    }
    $dzpz_pz_ds.setValueWithTrigger = true;
    book.sheet1.paintPermit = true;
}


function cb_verify_onClick() {
    $confirm('', '确信要对选中的凭证做审核确认吗?', function () {
        let rows = [];
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            rows.push(i);
        };

        showInfoPane("* 正在审核确认...");
        asyncPool(4, rows, function (i, rows) {
            return new Promise(function (resolve, reject) {
                showInfoPane("* 正在审核确认 " + i  );
                do_sh1(i, function () {
                    resolve(i);
                });
            });
        }).then(function (v) {
            hideInfoPane();
            toastr.info("审核完成");
        });

    });
}



function cb_unverify_onClick() {

    $confirm('', '确信要对选中的凭证做取消审核吗?', function () {
        var rows = [];
        for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
            if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
            rows.push(i);
        };

        showInfoPane("* 正在取消确认...");
        asyncPool(4, rows, function (i, rows) {
            return new Promise(function (resolve, reject) {
                showInfoPane("* 正在取消确认"+i);
                do_sh2(i, function () {
                    resolve(i);
                });
            });
        }).then(function (v) {
            hideInfoPane();
            toastr.info("取消确认完成");
        });

    });


}


function cb_package_onClick() {

    let ids = [];
    for (let i = 0; i < $dzpz_pz_ds.rowCount; i++) {
        if ($dzpz_pz_ds.getInt(i, "selected") == 0) continue;
        ids.push($dzpz_pz_ds.getString(i, "id"));
    }

    if (ids.length == 0) {
        toastr.info("至少选中一张凭证");
        return;
    }

    $confirm('', '确信要将选中的凭证打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        runTask("打包下载", { fileName: formatDate(newDate(), "yyyyMMddHHmm") + ".zip", ids: ids },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    openWindow(ret.url);
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

function isVerified() {
    var row = book.getDataSource('dzpz_pz').currentBindRow;
    var verifiername = $dzpz_pz_ds.getString(row, "verifiername");

    if (verifiername != '') {
        toastr.error("已经校对的凭证不允许执行此操作");
        return true;
    }
    return false;
}


/**
 * 图片控件初始化完成
 * @param sheet   所在Sheet
 * @param config  图片控件的名称
 *@param data  该图片的详细信息
 *
 */
//@comment (group=图片控件,caption=图片控件初始化完成)
function imageGridlyInited(sheet, name, data) {


    if (name == "FJ") {
        //图片都初始化后， 定制右上角的工具栏，最多可加5个工具按 钮
        let brick = sheet.getBrick(name);

        brick.addToolButton(1  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-repeat",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '90' ,function(){hideInfoPane();});

            }
        );


        brick.addToolButton(2  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-eye",   // 字符图标
            "浏览大图",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                brick.popupShow(id);

            }
        );


        brick.addToolButton(3  //在从右往左数第2个工作栏位置添加一个工具按钮
            , "fa-rotate-left",   // 字符图标
            "旋转图片",  // 鼠标悬停的提示信息
            "green", //按钮背景色
            function (id) {  //点击后的回调函数
                g_turningCount = 0;
                g_turnedCount = 0;
                g_turnNeedCount = 1;
                if (isVerified()) return;  //校对过的不允许再旋转

                rotateImg(sheet, id, '270',function(){hideInfoPane();});

            }
        );



    }
}


function rotateImg(sheet, id, degree, callback) {



    let brick = sheet.getBrick('FJ');
    setTimeout(function () {
        //toastr.info(id);  // id 是当前操作的图片对应数据的ID

        do_imageRotate(id, degree, function (ret) {


            if (ret.success) {

                g_turningCount++;
                showInfoPane('*正在旋转图片' + g_turningCount + "/" + g_turnNeedCount + ' ...');


                //把数据中的图片替换，
                for (let i = 0; i < brick.data.length; i++) {
                    if (brick.data[i].id == id) {
                        //属性从新的属性中替换 
                        for (let prop in brick.data[i]) {
                            brick.data[i][prop] = ret.data[prop];
                        }
                        break;
                    }
                }
                //把缩略图的图片地址替换 ， 

                let img = $('#' + id).find('.image');
                img.attr("src", ret.data.url_thumbnail);
                img.attr('largeimage', ret.data.url_img);
                //把大图预览的地址替换掉
                //book.sheet0.cells("imgPreview").setValue(ret.data.url_img);

            }
            if (callback) callback();



        });
    }, 100);

}


/**
 * 图片控件中的图片控件顺序发生变化
 * @param sheet   所在Sheet
 * @param name  图片控件的名称
 *@param  ids  当前顺序下的图片的ID数组
 *
 *
 *
 */
//@comment (group=图片控件,caption=图片顺序被改变)
function imageOrderChanged(sheet, name, ids) {

    if (isVerified()) return;  //校对过的不允许再调整顺序

    reOrderImage(ids, function (ret) { }); //放一个空的回调函数让它异步执行，不卡界面

}


var g_selectedAll = false;
function cb_selectallimg_onClick() { g_selectedAll = !g_selectedAll; doSelect(g_selectedAll); }


function doSelect(b) {
    var imgPool = book.sheet2.getBrick('FJ');
    if (b) {
        imgPool.selectAll();
    } else {
        imgPool.unSelectAll();
    }
}


function cb_turnLeft_onClick() {
    turnSelection('270');

}

function cb_turnRight_onClick() {

    turnSelection('90');
}

var g_turningCount = 0;
var g_turnedCount = 0;

function turnSelection(degree) {

    if (isVerified()) return;  //校对过的不允许再旋转

    var sheet = book.sheet2;
    var imgPool = sheet.getBrick('FJ');
    // 当前选中的
    var selection = imgPool.getSelectedImageList();
    if (selection.length == 0) {
        toastr.error("至少选中一张图片");
        return;
    }


    $confirm("提示", "确信要对选中的" + selection.length + "张图片做旋转吗?", function () {

        g_turningCount = 0;
        g_turnedCount = 0;
        g_turnNeedCount = selection.length;
        /*
                setTimeout(function () {
                    for (var i = 0; i < selection.length; i++) {
                        rotateImg(sheet, selection[i].id, degree, i * 1000);
                    }
                }, 10);
                */

        asyncPool(4 , selection, function (item, array) {
            return new Promise(function (resolve, reject) {

                console.dir(item);
                rotateImg(sheet, item.id, degree,
                    function () { //注意，在旋转完成后，再设置resolve 表示本任务已完成，而不是直接就resolve ,不然最后的 then 执行时机不对，这么处理，就会在全部旋转完成后，再执行then中的脚本，而不是旋转任务全部发起后就执行 then 
                        resolve(item)
                    });

            });
        }).then(function () {

            setTimeout(function () {

                hideInfoPane();
                toastr.info("旋转完成");
            }, 500);
        });

    });

}




function asyncPool(poolLimit, array, iteratorFn) {
    let i = 0;
    const ret = [];
    const executing = [];
    const enqueue = function () {
        if (i === array.length) {
            return Promise.resolve();
        }
        const item = array[i++];
        const p = Promise.resolve().then(() => iteratorFn(item, array));
        ret.push(p);

        let r = Promise.resolve();

        if (poolLimit <= array.length) {
            const e = p.then(() => executing.splice(executing.indexOf(e), 1));
            executing.push(e);
            if (executing.length >= poolLimit) {
                r = Promise.race(executing);
            }
        }

        return r.then(() => enqueue());
    };
    return enqueue().then(() => Promise.all(ret));
}


function test1() {


    asyncPool(3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function (item, array) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                console.info(item + "   "+ new Date());
                resolve(item)
            }, 1000);

        });
    }).then(function () {
        console.info("over");
    });

}


id: 619da50c03744eb6d3e72b67
scriptid: 60fa600f9932563b7c99bb03
tablename: app_template
clientip: 192.168.1.77
username: sa
createdate: 2021.11.24 11:19:40.000
script:
var g_currentUserIsOwner = false; //当前人是不是起草人




/**
 * 表单初始化完成后，执行此事件
 */
//@comment (group=表单事件,caption=表单初始化完成)
function formOpen() {
    book.showTabOnWhere = 'none';
    book.getWorkSheet('下载清单').visible = false;



    if ($dzpz_dy_ds.getString(0, "ziptaskid") == '') {
        book.sheet1.getBrick('cb_cancel').visible = false;
    }

    if (currentUserId() == $dzpz_dy_ds.getInt(0, "userid")) {
        g_currentUserIsOwner = true;
    }
    //按gguid分开接收消息，避免多个打包的消息混在一起
    onPushMessage("打包下载" + currentGUID(), function (info) {
        console.info(info);
        var msg = JSON.parse(info);
        if (msg.action == 'info') {
            console.info(msg.info);
            if (g_currentUserIsOwner) showInfoPane(msg.info);
        }

        if (msg.action == 'gameOver') {
            var result = msg.result;
            //$.alert(JSON.stringify(result));


            $dzpz_dy_ds.setValue(0, "ziptaskid", '', false);//清除打包任务id，因为已经ok了，但不要触发保存
            //不需要保存 ，因为打包完成脚本中已经回填了，仅在界面上回填一下， 方便显示下载清单
            $dzpz_dy_ds.setValue(0, "zipresult", JSON.stringify(result.zipFiles), false);

            console.dir(result);

            cb_package_onClick();

            hideInfoPane();
        }
        if (msg.action == 'over') {

            hideInfoPane();
        }

        if (msg.action == 'error') {
            $.alert(msg.info);
            hideInfoPane();
        }
    })

    $('.navbar-fixed-top').css("z-index", 1);

}
/**
 * 按钮点击事件
 * 当某个按钮被点击时， 首先触发  {按钮名称}_onClick 事件，然后触发 buttonOnClick事件
 * @param sheet  工作表
 * @param cell   按钮所在的单元格
 * @param button 按钮对象
 */
//@comment (group=按钮点击事件,caption=下载模板,needRightControl=false)
function cb_downloadTemplateFile_onClick(sheet, cell, button) {
    var title = "序号\t凭证号\t科目代码\t核算账号编号\t摘要";
    var data = [];
    data.push(title);
    data.push("1\t0001\t1001\tRD0001\tABC");
    data.push("2\t0002\t5501\tRD0002\tBBB");

    var f = $('#form_toexcel')[0];
    f.filename.value = "凭证调阅模板.xlsx";
    f.data.value = JSON.stringify(data);
    f.submit();

}

/**
 * 按钮点击事件
 * 当某个按钮被点击时， 首先触发  {按钮名称}_onClick 事件，然后触发 buttonOnClick事件
 * @param sheet  工作表
 * @param cell   按钮所在的单元格
 * @param button 按钮对象
 */
//@comment (group=按钮点击事件,caption=导入模板,needRightControl=false)
function cb_importFromExcelFile_onClick(sheet, cell, button) {
    toastr.info("*自动保存，准备导入");
    form.save(false, function () {
        book.readXLS(function (data) {
            showInfoPane("*正在导入");
            setTimeout(function () {
                importData(data);
            }, 10);
        });
    });

}



function safeValue(sheet, row, col) {
    if (row > sheet.length - 1) return null;
    var dataRow = sheet[row];
    if (dataRow == null) return null;
    if (col > dataRow.length - 1) return null;
    return dataRow[col];

}

//@comment (group=,caption=从Excel导入数据,needRightControl=false)
function importData(excelData) {
    var excelSheet = excelData[Object.keys(excelData)[0]];


    var headRow = 0; //题头在第几行
    var dataStartRow = 1;// 数据行从第几行开始

    var RC = excelSheet.length;

    book.sheet0.paintPermit = false;

    for (let row = dataStartRow; row < RC; row++) {
        let data = {
            pzh: safeValue(excelSheet, row, 1) || '',
            kmdm: safeValue(excelSheet, row, 2) || '',
            code: safeValue(excelSheet, row, 3) || '',
            memo: safeValue(excelSheet, row, 4) || '',
        }
        alert(JSON.stringify(data));
        if (data.pzh == '') continue;
        let r = $dzpz_dymx_ds.insertRow(99999);
        $dzpz_dymx_ds.setValue(r, data);
    }


    showInfoPane("*正在保存并检测凭证号");
    form.save(false, function () {


        book.sheet0.paintPermit = false;
        toastr.info("导入完成");

    });
}




var dymx_changed = false;
/**
 * dsname结果集保存前，对row进行数据校验 ，
 * @param dsname 结果集名称
 * @param row  第row行
 * @returns {boolean} true表示检验通过， false表示校验不通过，update被终止
 */
function validate(dsname, row) {
    if (dsname == 'dzpz_dymx') dymx_changed = true;
    return true;
}

/**
 * 数据集中的数据发生变化
 * @param dsname 数据集名称
 * @param row   数据行号
 * @param col    字段名
 * @param oldValue   原值
 * @param newValue  新值
 */
function itemChanged(dsname, row, col, oldValue, newValue) {
    if (col == 'corpid') dymx_changed = true;

}



/**
 * 单据保存成功后执行本事件。如果单据不需要保存，或保存失败，则不执行本事件
 * @param GUID 当前单据的GGUID
 * @param action 当前单据正在进行的动作，比如 edit , view
 */
function afterSaveSuccessful(GGUID, action) {
    if (dymx_changed) form.loadBill(GGUID); //如果明细有变化，那么保存成功后，重新加载单据，因为在单据保存后，模板后端脚本中会同时更新  pz_id 及 bz
    dymx_changed = false;
}


//@comment (group=按钮点击事件,caption=取消打包,needRightControl=false)
function cb_redo_pack_onClick() {

    $confirm('', '确信要清除压缩文件吗?', function () {

        $dzpz_dy_ds.setValue(0, "ziptaskid", '');
        $dzpz_dy_ds.setValue(0, "zipresult", '');
        form.save(false);
        $q_result_ds.reset();

    });


}

//@comment (group=按钮点击事件,caption=,needRightControl=false)
function cb_cancel_onClick() {

    $confirm('', '确信要终止打包吗?', function () {
        showInfoPane("*正在终止打包...");
        runTask("终止打包", {
            id: $dzpz_dy_ds.getString(0, "ziptaskid")
        },
            function (ret) {
                ret = JSON.parse(ret);
                if (ret.success) {
                    $dzpz_dy_ds.setValue(0, "ziptaskid", '');
                    $dzpz_dy_ds.setValue(0, "zipresult", '');

                    form.save(false);
                    hideInfoPane();
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

//@comment (group=按钮点击事件,caption=,needRightControl=false)
function cb_package_onClick() {

    var ziptaskid = $dzpz_dy_ds.getString(0, "ziptaskid");
    if (ziptaskid != '') {
        toastr.info("正在压缩中...，请稍候");
        return;
    }

    var zipResult = $dzpz_dy_ds.getString(0, "zipresult");
    if (zipResult == '') {
        toastr.info("正在压缩文件，请稍候");
        do_package(currentGUID(), function (ret) {

            if (ret.success) {
                $dzpz_dy_ds.setValue(0, "ziptaskid", ret.zipTaskId, false); //后台已经回写了，就里只要界面上更新就ok
            }
        });
        return;
    }

    zipResult = zipResult.replace(/&action=view/g, '&action=download');
    zipResult = JSON.parse(zipResult);
    $q_result_ds.reset();
    for (var i = 0; i < zipResult.length; i++) {
        var one = zipResult[i];
        var row = $q_result_ds.insertRow(999);
        $q_result_ds.setValue(row, one);


    }

    book.getWorkSheet('下载清单').popup("", "下载清单", 600, 300, true, true);
}



function cb_package_onClick___() {

    if (form.isSaveNeeded()) {
        toastr.info("请先保存");
        return;
    }

    let ids = [];
    for (let i = 0; i < $dzpz_dymx_ds.rowCount; i++) {
        if ($dzpz_dymx_ds.getString(i, "pz_id") == '') {
            toastr.error("第" + (i + 1) + "行的凭证号不存在，请核对");
            return;
        }
        ids.push($dzpz_dymx_ds.getString(i, "pz_id"));
    }

    if (ids.length == 0) {
        toastr.info("没有凭证清单");
        return;
    }

    $confirm('', '确信要打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        let fileName = formatDate(newDate(), "yyyyMMddHHmm") + ".zip";
        runTask("打包下载", {
            fileName: fileName,
            gguid: currentGUID(),
            ids: ids,
            watermark: $dzpz_dy_ds.getString(0, "billno") + "[" + $dzpz_dy_ds.getString(0, "reader") + "]" +
                formatDate(newDate(), "yyyy.MM.dd HH:mm")
        },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    let t = window.location.href;
                    let p = t.indexOf("billedit");
                    t = t.substring(0, p);
                    let url = t + ret.url;
                    $.alert(` <a href="${url}" target="_blank">点击下载${fileName}</a>`, `打包完成`);
                } else {
                    toastr.error(ret.message);
                }
            });

    });

}

/**
 * 按钮点击事件
 * 当某个按钮被点击时， 首先触发  {按钮名称}_onClick 事件，然后触发 buttonOnClick事件
 * @param sheet  工作表
 * @param cell   按钮所在的单元格
 * @param button 按钮对象
 */
//@comment (group=按钮点击事件,caption=调取凭证列表,needRightControl=false)
function cb_pzlist_onClick(sheet, cell, button) {
    // if (form.isSaveNeeded()) {
    //     toastr.info("请先保存");
    //     return;
    // }
    book.getWorkSheet("凭证资料查询").float('fa fa-cog', "凭证资料查询",
        {
            my: 'right-center',
            at: 'right-center',
            autoposition: 'down',
            offsetX: -5,
            offsetY: 5
        }, { width: '70%', height: '90%' });
    smartRetrieve(book.getWorkSheet("凭证资料查询"), "q_pzdjex")
}


/**
 * 按钮点击事件
 * 当某个按钮被点击时， 首先触发  {按钮名称}_onClick 事件，然后触发 buttonOnClick事件
 * @param sheet  工作表
 * @param cell   按钮所在的单元格
 * @param button 按钮对象
 */
//@comment (group=按钮点击事件,caption=选入,needRightControl=false)
function cb_import_onClick(sheet, cell, button) {
    book.getWorkSheet("detail").paintPermit = false;
    let row = book.getDataSource("dzpz_dymx").currentBindRow;

    for (var i = 0; i < $q_pzdjex_ds.getRowCount(); i++) {
        if ($q_pzdjex_ds.getString(i, "selected") == '1') {
            if ($dzpz_dymx_ds.getString(row, "pzh") != '' || row < 0) row = $dzpz_dymx_ds.insertRow(row + 1);
            $dzpz_dymx_ds.setValue(row, {
                pzh: $q_pzdjex_ds.getValue(i, "pzh"),
                kmdm: $q_pzdjex_ds.getValue(i, "kmdm"),
                code: $q_pzdjex_ds.getValue(i, "code"),
                memo: $q_pzdjex_ds.getString(i, "bz")
            });
        }
    }
    book.getDataSource("dzpz_dymx").currentBindRow = row;
    book.getWorkSheet("detail").View.insureSelectionOnScreen(null, false);
    do_removeDuplicated(); //删除重复项

    //********删除行号***********************************
    book.getWorkSheet("凭证资料查询").paintPermit = false;
    for (var i = $q_pzdjex_ds.getRowCount() - 1; i >= 0; i--) {
        if ($q_pzdjex_ds.getString(i, "selected") == '1') $q_pzdjex_ds.deleteRow(i);
    }
    book.getWorkSheet("凭证资料查询").paintPermit = true;
    //**************************************************

    book.getWorkSheet("detail").paintPermit = true;
    book.getWorkSheet("main").paintPermit = true;
}

/**
 * 按钮点击事件
 * 当某个按钮被点击时， 首先触发  {按钮名称}_onClick 事件，然后触发 buttonOnClick事件
 * @param sheet  工作表
 * @param cell   按钮所在的单元格
 * @param button 按钮对象
 */
//@comment (group=按钮点击事件,caption=,needRightControl=false)
function cb_opensheet_dr_onClick(sheet, cell, button) {
    book.getWorkSheet("凭证列表").float('fa fa-cog', "导入凭证列表",
        {
            my: 'right-center',
            at: 'right-center',
            autoposition: 'down',
            offsetX: -5,
            offsetY: 5
        }, { width: 400, height: '80%' });

}

/**
 * 按钮点击事件
 * 当某个按钮被点击时， 首先触发  {按钮名称}_onClick 事件，然后触发 buttonOnClick事件
 * @param sheet  工作表
 * @param cell   按钮所在的单元格
 * @param button 按钮对象
 */
//@comment (group=按钮点击事件,caption=粘贴界面导入,needRightControl=false)
function cb_dr_onClick(sheet, cell, button) {

    book.getWorkSheet("detail").paintPermit = false;
    let row = book.getDataSource("dzpz_dymx").currentBindRow;
    let pzlist = sheet.cells('pzlist').getValueString().split('\n');
    for (let i = 0; i < pzlist.length; i++) {
        if (pzlist[i] !== '') {
            if ($dzpz_dymx_ds.getString(row, "pzh") != '' || row < 0) row = $dzpz_dymx_ds.insertRow(row + 1);

            $dzpz_dymx_ds.setValue(row, {
                pzh: pzlist[i]
            });
        }
    }
    sheet.cells('pzlist').setValue(null);
    sheet.floatPanelClose();

    book.getWorkSheet("detail").paintPermit = true;

}
/**
 * 单元格因为被编辑而改变。当用户通过编辑单元的值而让单元格发生值改变时本事件被触发。
 * 注意，当使用脚本 sheet.cells(row,col).setValue ( value) 来改变单元格的值时，本事件并不触发
 * @param sheet
 * @param cell
 * @param newValue
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChangedByEdit(sheet, cell, newValue, innerRow) {

    //通过数据库绑定情况来判断

    //通过别名来判断
    if (sheet.name == 'detail' && cell.alias == 'st_selectAll') {
        let ds = $dzpz_dymx_ds;
        sheet.paintPermit = false;
        for (var i = 0; i < ds.getRowCount(); i++) {
            ds.setValue(i, "selected", newValue);
        }
        sheet.paintPermit = true;
    }
    if (sheet.name == '凭证资料查询' && cell.alias == 'st_selectAll') {
        let ds = $q_pzdjex_ds;
        sheet.paintPermit = false;
        for (var i = 0; i < ds.getRowCount(); i++) {
            ds.setValue(i, "selected", newValue);
        }
        sheet.paintPermit = true;
    }

    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_dymx' && bind.DBCol == 'pzh') {
        showInfoPane('*正在分析凭证号');
        setTimeout(function () {
            do_paste_pzlist(innerRow, newValue) //写入凭证号
        }, 100);
    }
    if (bind != null && bind.dataSource == 'dzpz_dy' && bind.DBCol == 'reader') {
        $dzpz_dy_ds.setValue(0, {
            watermark: '【' + $dzpz_dy_ds.getString(0, "reader") + '】' + formatDate($dzpz_dy_ds.getValue(0, "billdate"), 'yyyy.mm.dd') + '-凭证调阅'
        })
    }



}

/**
 * 单元格编辑时粘贴内容后触发此事件。
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被粘贴了内容
 * @param text 当前单元格编辑框中的内容，并不一定是粘贴的内容，是单元格编辑框中原有的内容加上粘贴的内容
 */
//@comment (group=单元格事件,caption=单元格粘贴内容)
function cellOnPaste(sheet, cell, innerRow, text) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_dymx' && bind.DBCol == 'pzh') {
        sheet.View.forceCurrentEditControlGiveUpFocus();
    }

}


/**
 * 按钮点击事件
 * 当某个按钮被点击时， 首先触发  {按钮名称}_onClick 事件，然后触发 buttonOnClick事件
 * @param sheet  工作表
 * @param cell   按钮所在的单元格
 * @param button 按钮对象
 */
//@comment (group=do,caption=凭证列表粘贴凭证清单后自动后插并赋值,needRightControl=false)
function do_paste_pzlist(innerRow, newValue) {
    
    if (newValue == null || newValue == '') return;
    let data = newValue.split(' ');
    book.getWorkSheet("detail").paintPermit = false;
    let row = innerRow;
    for (let i = 0; i < data.length; i++) {
        //row = $dzpz_dymx_ds.insertRow(row + 1);
        if (data[i] != '') {
            $dzpz_dymx_ds.setValue(row, {
                pzh: data[i],
                selected: 1
            });
            if (i < data.length - 1) row = $dzpz_dymx_ds.insertRow(row + 1);
        }
    }
    book.getDataSource("dzpz_dymx").currentBindRow = row;
    book.getWorkSheet("detail").View.insureSelectionOnScreen(null, false);
    do_removeDuplicated(); //删除重复项
    book.getWorkSheet("detail").paintPermit = true;
    book.getWorkSheet("main").paintPermit = true;
    hideInfoPane();
}







//@comment (group=,caption=异步打包,needRightControl=false)
function async_package() {

    if (form.isSaveNeeded()) {
        toastr.info("请先保存");
        return;
    }

    let ids = [];
    for (let i = 0; i < $dzpz_dymx_ds.rowCount; i++) {
        if ($dzpz_dymx_ds.getString(i, "pz_id") == '') {
            toastr.error("第" + (i + 1) + "行的凭证号不存在，请核对");
            return;
        }
        ids.push($dzpz_dymx_ds.getString(i, "pz_id"));
    }

    if (ids.length == 0) {
        toastr.info("没有凭证清单");
        return;
    }

    $confirm('', '确信要重新打包吗?', function () {
        showInfoPane("*正在后台打包...");
        let fileName = $dzpz_dy_ds.getString(0, "reader") +
            formatDate(newDate(), "yyyy.MM.dd HH:mm") + "调阅凭证.zip";
        runTask("后台打包", {
            gguid: currentGUID(),
            fileName: fileName,
            ids: ids,
            watermark: $dzpz_dy_ds.getInt(0, "needwatermark") == 0 ? "" : $dzpz_dy_ds.getString(0, "watermark"),
            mergePDF: $dzpz_dy_ds.getString(0,"filetype") =='pdf' //是否合并成一个pdf文件
        },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    $dzpz_dy_ds.setValue(0, "ziptaskid", ret.zipTaskId);
                    form.save(false);
                    hideInfoPane();

                } else {
                    toastr.error(ret.message);
                }
            });

    });


}

//@comment (group=按钮点击事件,caption=标记重复,needRightControl=false)
function cb_qc_onClick() {
    showInfoPane("*正在检测重复的凭证");
    var map = {};
    for (var i = 0; i < $dzpz_dymx_ds.rowCount; i++) {
        var pzh = $dzpz_dymx_ds.getString(i, "pzh");
        if (pzh == '') continue;
        if (map[pzh] == undefined) map[pzh] = []; //每个凭证号映射到一个数组，记录它所在的行号
        map[pzh].push(i); // 记录下凭证号对应的行号

    }

    book.getWorkSheet('detail').paintPermit = false;
    for (pzh in map) {
        var rows = map[pzh];
        $dzpz_dymx_ds.setValue(rows[0], "bz", "");
        for (var i = 1; i < rows.length; i++) {
            $dzpz_dymx_ds.setValue(rows[i], "bz", "与第" + (rows[0] + 1) + "行重复");
        }
    }
    book.getWorkSheet('detail').paintPermit = true;
    hideInfoPane();
}

//@comment (group=按钮点击事件,caption=删除重复的,needRightControl=false)
function cb_removeDuplicated_onClick() {

    $confirm('', '确信要清除重复的凭证号吗?', function () {

        do_removeDuplicated()

    });

}


//@comment (group=do,caption=执行删除重复的,needRightControl=false)
function do_removeDuplicated() {

    showInfoPane("*正在删除重复的凭证");
    book.getWorkSheet('detail').paintPermit = false;
    var pzhs = []; //凭证号清单
    var rows = [];// 需要删除的行号
    for (var i = 0; i < $dzpz_dymx_ds.rowCount; i++) {
        var pzh = $dzpz_dymx_ds.getString(i, "pzh");
        if (pzhs.contains(pzh)) //此凭证号此前已经出现过
        {
            rows.push(i);//  需要删除
        } else {
            pzhs.push(pzh); //没有出现过，那么加它到凭证号清单中
        }
    }
    //现在反着删除
    for (var i = rows.length - 1; i >= 0; i--) {
        $dzpz_dymx_ds.deleteRow(rows[i]);
    }
    //form.save(false);
    book.getWorkSheet('detail').paintPermit = false;
    hideInfoPane();
}



/**
 * 按钮点击事件
 * 当某个按钮被点击时， 首先触发  {按钮名称}_onClick 事件，然后触发 buttonOnClick事件
 * @param sheet  工作表
 * @param cell   按钮所在的单元格
 * @param button 按钮对象
 */
//@comment (group=按钮点击事件,caption=批量删除已选中记录,needRightControl=false)
function cb_selectedRow_delete_onClick(sheet, cell, button) {
    $confirm("提示", "确定要删除选中的记录吗?", function () {
        book.getWorkSheet('detail').paintPermit = false;
        for (let i = $dzpz_dymx_ds.getRowCount() - 1; i >= 0; i--) {
            if ($dzpz_dymx_ds.getInt(i, "selected") == 1) $dzpz_dymx_ds.deleteRow(i);
        }
        if ($dzpz_dymx_ds.getRowCount() == 0) $dzpz_dymx_ds.insertRow(0);
        book.getWorkSheet('detail').cells("st_selectAll").setValue(0);
        book.getWorkSheet('detail').paintPermit = true;
    }, function () { });



}


id: 619da50c03744eb6d3e72b6d
scriptid: 60fa600f9932563b7c99bb03
tablename: app_template
clientip: 192.168.1.77
username: sa
createdate: 2021.11.24 11:20:58.000
script:
var g_currentUserIsOwner = false; //当前人是不是起草人




/**
 * 表单初始化完成后，执行此事件
 */
//@comment (group=表单事件,caption=表单初始化完成)
function formOpen() {
    book.showTabOnWhere = 'none';
    book.getWorkSheet('下载清单').visible = false;



    if ($dzpz_dy_ds.getString(0, "ziptaskid") == '') {
        book.sheet1.getBrick('cb_cancel').visible = false;
    }

    if (currentUserId() == $dzpz_dy_ds.getInt(0, "userid")) {
        g_currentUserIsOwner = true;
    }
    //按gguid分开接收消息，避免多个打包的消息混在一起
    onPushMessage("打包下载" + currentGUID(), function (info) {
        console.info(info);
        var msg = JSON.parse(info);
        if (msg.action == 'info') {
            console.info(msg.info);
            if (g_currentUserIsOwner) showInfoPane(msg.info);
        }

        if (msg.action == 'gameOver') {
            var result = msg.result;
            //$.alert(JSON.stringify(result));


            $dzpz_dy_ds.setValue(0, "ziptaskid", '', false);//清除打包任务id，因为已经ok了，但不要触发保存
            //不需要保存 ，因为打包完成脚本中已经回填了，仅在界面上回填一下， 方便显示下载清单
            $dzpz_dy_ds.setValue(0, "zipresult", JSON.stringify(result.zipFiles), false);

            console.dir(result);

            cb_package_onClick();

            hideInfoPane();
        }
        if (msg.action == 'over') {

            hideInfoPane();
        }

        if (msg.action == 'error') {
            $.alert(msg.info);
            hideInfoPane();
        }
    })

    $('.navbar-fixed-top').css("z-index", 1);

}
/**
 * 按钮点击事件
 * 当某个按钮被点击时， 首先触发  {按钮名称}_onClick 事件，然后触发 buttonOnClick事件
 * @param sheet  工作表
 * @param cell   按钮所在的单元格
 * @param button 按钮对象
 */
//@comment (group=按钮点击事件,caption=下载模板,needRightControl=false)
function cb_downloadTemplateFile_onClick(sheet, cell, button) {
    var title = "序号\t凭证号\t科目代码\t核算账号编号\t摘要";
    var data = [];
    data.push(title);
    data.push("1\t0001\t1001\tRD0001\tABC");
    data.push("2\t0002\t5501\tRD0002\tBBB");

    var f = $('#form_toexcel')[0];
    f.filename.value = "凭证调阅模板.xlsx";
    f.data.value = JSON.stringify(data);
    f.submit();

}

/**
 * 按钮点击事件
 * 当某个按钮被点击时， 首先触发  {按钮名称}_onClick 事件，然后触发 buttonOnClick事件
 * @param sheet  工作表
 * @param cell   按钮所在的单元格
 * @param button 按钮对象
 */
//@comment (group=按钮点击事件,caption=导入模板,needRightControl=false)
function cb_importFromExcelFile_onClick(sheet, cell, button) {
    toastr.info("*自动保存，准备导入");
    form.save(false, function () {
        book.readXLS(function (data) {
            showInfoPane("*正在导入");
            setTimeout(function () {
                importData(data);
            }, 10);
        });
    });

}



function safeValue(sheet, row, col) {
    if (row > sheet.length - 1) return null;
    var dataRow = sheet[row];
    if (dataRow == null) return null;
    if (col > dataRow.length - 1) return null;
    return dataRow[col];

}

//@comment (group=,caption=从Excel导入数据,needRightControl=false)
function importData(excelData) {
    var excelSheet = excelData[Object.keys(excelData)[0]];


    var headRow = 0; //题头在第几行
    var dataStartRow = 1;// 数据行从第几行开始

    var RC = excelSheet.length;

    book.sheet0.paintPermit = false;

    for (let row = dataStartRow; row < RC; row++) {
        let data = {
            pzh: safeValue(excelSheet, row, 1) || '',
            kmdm: safeValue(excelSheet, row, 2) || '',
            code: safeValue(excelSheet, row, 3) || '',
            memo: safeValue(excelSheet, row, 4) || '',
        }
        alert(JSON.stringify(data));
        if (data.pzh == '') continue;
        let r = $dzpz_dymx_ds.insertRow(99999);
        $dzpz_dymx_ds.setValue(r, data);
    }


    showInfoPane("*正在保存并检测凭证号");
    form.save(false, function () {


        book.sheet0.paintPermit = false;
        toastr.info("导入完成");

    });
}




var dymx_changed = false;
/**
 * dsname结果集保存前，对row进行数据校验 ，
 * @param dsname 结果集名称
 * @param row  第row行
 * @returns {boolean} true表示检验通过， false表示校验不通过，update被终止
 */
function validate(dsname, row) {
    if (dsname == 'dzpz_dymx') dymx_changed = true;
    return true;
}

/**
 * 数据集中的数据发生变化
 * @param dsname 数据集名称
 * @param row   数据行号
 * @param col    字段名
 * @param oldValue   原值
 * @param newValue  新值
 */
function itemChanged(dsname, row, col, oldValue, newValue) {
    if (col == 'corpid') dymx_changed = true;

}



/**
 * 单据保存成功后执行本事件。如果单据不需要保存，或保存失败，则不执行本事件
 * @param GUID 当前单据的GGUID
 * @param action 当前单据正在进行的动作，比如 edit , view
 */
function afterSaveSuccessful(GGUID, action) {
    if (dymx_changed) form.loadBill(GGUID); //如果明细有变化，那么保存成功后，重新加载单据，因为在单据保存后，模板后端脚本中会同时更新  pz_id 及 bz
    dymx_changed = false;
}


//@comment (group=按钮点击事件,caption=取消打包,needRightControl=false)
function cb_redo_pack_onClick() {

    $confirm('', '确信要清除压缩文件吗?', function () {

        $dzpz_dy_ds.setValue(0, "ziptaskid", '');
        $dzpz_dy_ds.setValue(0, "zipresult", '');
        form.save(false);
        $q_result_ds.reset();

    });


}

//@comment (group=按钮点击事件,caption=,needRightControl=false)
function cb_cancel_onClick() {

    $confirm('', '确信要终止打包吗?', function () {
        showInfoPane("*正在终止打包...");
        runTask("终止打包", {
            id: $dzpz_dy_ds.getString(0, "ziptaskid")
        },
            function (ret) {
                ret = JSON.parse(ret);
                if (ret.success) {
                    $dzpz_dy_ds.setValue(0, "ziptaskid", '');
                    $dzpz_dy_ds.setValue(0, "zipresult", '');

                    form.save(false);
                    hideInfoPane();
                } else {
                    toastr.error(ret.message);
                }
            });

    });
}

//@comment (group=按钮点击事件,caption=,needRightControl=false)
function cb_package_onClick() {

    var ziptaskid = $dzpz_dy_ds.getString(0, "ziptaskid");
    if (ziptaskid != '') {
        toastr.info("正在压缩中...，请稍候");
        return;
    }

    var zipResult = $dzpz_dy_ds.getString(0, "zipresult");
    if (zipResult == '') {
        toastr.info("正在压缩文件，请稍候");
        do_package(currentGUID(), function (ret) {

            if (ret.success) {
                $dzpz_dy_ds.setValue(0, "ziptaskid", ret.zipTaskId, false); //后台已经回写了，就里只要界面上更新就ok
            }
        });
        return;
    }

    zipResult = zipResult.replace(/&action=view/g, '&action=download');
    zipResult = JSON.parse(zipResult);
    $q_result_ds.reset();
    for (var i = 0; i < zipResult.length; i++) {
        var one = zipResult[i];
        var row = $q_result_ds.insertRow(999);
        $q_result_ds.setValue(row, one);


    }

    book.getWorkSheet('下载清单').popup("", "下载清单", 600, 300, true, true);
}



function cb_package_onClick___() {

    if (form.isSaveNeeded()) {
        toastr.info("请先保存");
        return;
    }

    let ids = [];
    for (let i = 0; i < $dzpz_dymx_ds.rowCount; i++) {
        if ($dzpz_dymx_ds.getString(i, "pz_id") == '') {
            toastr.error("第" + (i + 1) + "行的凭证号不存在，请核对");
            return;
        }
        ids.push($dzpz_dymx_ds.getString(i, "pz_id"));
    }

    if (ids.length == 0) {
        toastr.info("没有凭证清单");
        return;
    }

    $confirm('', '确信要打包下载吗?', function () {
        showInfoPane("*正在压缩打包...");
        let fileName = formatDate(newDate(), "yyyyMMddHHmm") + ".zip";
        runTask("打包下载", {
            fileName: fileName,
            gguid: currentGUID(),
            ids: ids,
            watermark: $dzpz_dy_ds.getString(0, "billno") + "[" + $dzpz_dy_ds.getString(0, "reader") + "]" +
                formatDate(newDate(), "yyyy.MM.dd HH:mm")
        },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    let t = window.location.href;
                    let p = t.indexOf("billedit");
                    t = t.substring(0, p);
                    let url = t + ret.url;
                    $.alert(` <a href="${url}" target="_blank">点击下载${fileName}</a>`, `打包完成`);
                } else {
                    toastr.error(ret.message);
                }
            });

    });

}

/**
 * 按钮点击事件
 * 当某个按钮被点击时， 首先触发  {按钮名称}_onClick 事件，然后触发 buttonOnClick事件
 * @param sheet  工作表
 * @param cell   按钮所在的单元格
 * @param button 按钮对象
 */
//@comment (group=按钮点击事件,caption=调取凭证列表,needRightControl=false)
function cb_pzlist_onClick(sheet, cell, button) {
    // if (form.isSaveNeeded()) {
    //     toastr.info("请先保存");
    //     return;
    // }
    book.getWorkSheet("凭证资料查询").float('fa fa-cog', "凭证资料查询",
        {
            my: 'right-center',
            at: 'right-center',
            autoposition: 'down',
            offsetX: -5,
            offsetY: 5
        }, { width: '70%', height: '90%' });
    smartRetrieve(book.getWorkSheet("凭证资料查询"), "q_pzdjex")
}


/**
 * 按钮点击事件
 * 当某个按钮被点击时， 首先触发  {按钮名称}_onClick 事件，然后触发 buttonOnClick事件
 * @param sheet  工作表
 * @param cell   按钮所在的单元格
 * @param button 按钮对象
 */
//@comment (group=按钮点击事件,caption=选入,needRightControl=false)
function cb_import_onClick(sheet, cell, button) {
    book.getWorkSheet("detail").paintPermit = false;
    let row = book.getDataSource("dzpz_dymx").currentBindRow;

    for (var i = 0; i < $q_pzdjex_ds.getRowCount(); i++) {
        if ($q_pzdjex_ds.getString(i, "selected") == '1') {
            if ($dzpz_dymx_ds.getString(row, "pzh") != '' || row < 0) row = $dzpz_dymx_ds.insertRow(row + 1);
            $dzpz_dymx_ds.setValue(row, {
                pzh: $q_pzdjex_ds.getValue(i, "pzh"),
                kmdm: $q_pzdjex_ds.getValue(i, "kmdm"),
                code: $q_pzdjex_ds.getValue(i, "code"),
                memo: $q_pzdjex_ds.getString(i, "bz")
            });
        }
    }
    book.getDataSource("dzpz_dymx").currentBindRow = row;
    book.getWorkSheet("detail").View.insureSelectionOnScreen(null, false);
    do_removeDuplicated(); //删除重复项

    //********删除行号***********************************
    book.getWorkSheet("凭证资料查询").paintPermit = false;
    for (var i = $q_pzdjex_ds.getRowCount() - 1; i >= 0; i--) {
        if ($q_pzdjex_ds.getString(i, "selected") == '1') $q_pzdjex_ds.deleteRow(i);
    }
    book.getWorkSheet("凭证资料查询").paintPermit = true;
    //**************************************************

    book.getWorkSheet("detail").paintPermit = true;
    book.getWorkSheet("main").paintPermit = true;
}

/**
 * 按钮点击事件
 * 当某个按钮被点击时， 首先触发  {按钮名称}_onClick 事件，然后触发 buttonOnClick事件
 * @param sheet  工作表
 * @param cell   按钮所在的单元格
 * @param button 按钮对象
 */
//@comment (group=按钮点击事件,caption=,needRightControl=false)
function cb_opensheet_dr_onClick(sheet, cell, button) {
    book.getWorkSheet("凭证列表").float('fa fa-cog', "导入凭证列表",
        {
            my: 'right-center',
            at: 'right-center',
            autoposition: 'down',
            offsetX: -5,
            offsetY: 5
        }, { width: 400, height: '80%' });

}

/**
 * 按钮点击事件
 * 当某个按钮被点击时， 首先触发  {按钮名称}_onClick 事件，然后触发 buttonOnClick事件
 * @param sheet  工作表
 * @param cell   按钮所在的单元格
 * @param button 按钮对象
 */
//@comment (group=按钮点击事件,caption=粘贴界面导入,needRightControl=false)
function cb_dr_onClick(sheet, cell, button) {

    book.getWorkSheet("detail").paintPermit = false;
    let row = book.getDataSource("dzpz_dymx").currentBindRow;
    let pzlist = sheet.cells('pzlist').getValueString().split('\n');
    for (let i = 0; i < pzlist.length; i++) {
        if (pzlist[i] !== '') {
            if ($dzpz_dymx_ds.getString(row, "pzh") != '' || row < 0) row = $dzpz_dymx_ds.insertRow(row + 1);

            $dzpz_dymx_ds.setValue(row, {
                pzh: pzlist[i]
            });
        }
    }
    sheet.cells('pzlist').setValue(null);
    sheet.floatPanelClose();

    book.getWorkSheet("detail").paintPermit = true;

}
/**
 * 单元格因为被编辑而改变。当用户通过编辑单元的值而让单元格发生值改变时本事件被触发。
 * 注意，当使用脚本 sheet.cells(row,col).setValue ( value) 来改变单元格的值时，本事件并不触发
 * @param sheet
 * @param cell
 * @param newValue
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行发生变化
 */
function cellValueChangedByEdit(sheet, cell, newValue, innerRow) {

    //通过数据库绑定情况来判断

    //通过别名来判断
    if (sheet.name == 'detail' && cell.alias == 'st_selectAll') {
        let ds = $dzpz_dymx_ds;
        sheet.paintPermit = false;
        for (var i = 0; i < ds.getRowCount(); i++) {
            ds.setValue(i, "selected", newValue);
        }
        sheet.paintPermit = true;
    }
    if (sheet.name == '凭证资料查询' && cell.alias == 'st_selectAll') {
        let ds = $q_pzdjex_ds;
        sheet.paintPermit = false;
        for (var i = 0; i < ds.getRowCount(); i++) {
            ds.setValue(i, "selected", newValue);
        }
        sheet.paintPermit = true;
    }

    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_dymx' && bind.DBCol == 'pzh') {
        showInfoPane('*正在分析凭证号');
        setTimeout(function () {
            do_paste_pzlist(innerRow, newValue) //写入凭证号
        }, 100);
    }
    if (bind != null && bind.dataSource == 'dzpz_dy' && bind.DBCol == 'reader') {
        $dzpz_dy_ds.setValue(0, {
            watermark: '【' + $dzpz_dy_ds.getString(0, "reader") + '】' + formatDate($dzpz_dy_ds.getValue(0, "billdate"), 'yyyy.mm.dd') + '-凭证调阅'
        })
    }



}

/**
 * 单元格编辑时粘贴内容后触发此事件。
 * @param sheet
 * @param cell
 * @param innerRow   当单元格没有绑定数据库或绑定到单行数据库时，本参数无意义。如果绑定一个
 * 多行数据库，则表示该单元所绑定的字段的第 innerRow行被粘贴了内容
 * @param text 当前单元格编辑框中的内容，并不一定是粘贴的内容，是单元格编辑框中原有的内容加上粘贴的内容
 */
//@comment (group=单元格事件,caption=单元格粘贴内容)
function cellOnPaste(sheet, cell, innerRow, text) {

    //通过别名来判断
    if (cell.alias == 'XXX') {

    }

    //通过数据库绑定情况来判断
    let bind = cell.bind;
    if (bind != null && bind.dataSource == 'dzpz_dymx' && bind.DBCol == 'pzh') {
        sheet.View.forceCurrentEditControlGiveUpFocus();
    }

}


/**
 * 按钮点击事件
 * 当某个按钮被点击时， 首先触发  {按钮名称}_onClick 事件，然后触发 buttonOnClick事件
 * @param sheet  工作表
 * @param cell   按钮所在的单元格
 * @param button 按钮对象
 */
//@comment (group=do,caption=凭证列表粘贴凭证清单后自动后插并赋值,needRightControl=false)
function do_paste_pzlist(innerRow, newValue) {
    
    if (newValue == null || newValue == '') return;
    let data = newValue.split(' ');
    book.getWorkSheet("detail").paintPermit = false;
    let row = innerRow;
    for (let i = 0; i < data.length; i++) {
        //row = $dzpz_dymx_ds.insertRow(row + 1);
        if (data[i] != '') {
            $dzpz_dymx_ds.setValue(row, {
                pzh: data[i],
                selected: 1
            });
            if (i < data.length - 1) row = $dzpz_dymx_ds.insertRow(row + 1);
        }
    }
    book.getDataSource("dzpz_dymx").currentBindRow = row;
    book.getWorkSheet("detail").View.insureSelectionOnScreen(null, false);
    do_removeDuplicated(); //删除重复项
    book.getWorkSheet("detail").paintPermit = true;
    book.getWorkSheet("main").paintPermit = true;
    hideInfoPane();
}







//@comment (group=,caption=异步打包,needRightControl=false)
function async_package() {

    if (form.isSaveNeeded()) {
        toastr.info("请先保存");
        return;
    }

    let ids = [];
    for (let i = 0; i < $dzpz_dymx_ds.rowCount; i++) {
        if ($dzpz_dymx_ds.getString(i, "pz_id") == '') {
            toastr.error("第" + (i + 1) + "行的凭证号不存在，请核对");
            return;
        }
        ids.push($dzpz_dymx_ds.getString(i, "pz_id"));
    }

    if (ids.length == 0) {
        toastr.info("没有凭证清单");
        return;
    }

    $confirm('', '确信要重新打包吗?', function () {
        showInfoPane("*正在后台打包...");
        let fileName = $dzpz_dy_ds.getString(0, "reader") +
            formatDate(newDate(), "yyyy.MM.dd HH:mm") + "调阅凭证.zip";
        runTask("后台打包", {
            gguid: currentGUID(),
            fileName: fileName,
            ids: ids,
            watermark: $dzpz_dy_ds.getInt(0, "needwatermark") == 0 ? "" : $dzpz_dy_ds.getString(0, "billno")+"/"+ formatDate($dzpz_dy_ds.getValue(0, "billdate"),"yyyy.MM.dd HH:mm")+"/"+$dzpz_dy_ds.getString(0, "watermark"),
            mergePDF: $dzpz_dy_ds.getString(0,"filetype") =='pdf' //是否合并成一个pdf文件
        },
            function (ret) {
                ret = JSON.parse(ret);
                hideInfoPane();
                if (ret.success) {
                    $dzpz_dy_ds.setValue(0, "ziptaskid", ret.zipTaskId);
                    form.save(false);
                    hideInfoPane();

                } else {
                    toastr.error(ret.message);
                }
            });

    });


}

//@comment (group=按钮点击事件,caption=标记重复,needRightControl=false)
function cb_qc_onClick() {
    showInfoPane("*正在检测重复的凭证");
    var map = {};
    for (var i = 0; i < $dzpz_dymx_ds.rowCount; i++) {
        var pzh = $dzpz_dymx_ds.getString(i, "pzh");
        if (pzh == '') continue;
        if (map[pzh] == undefined) map[pzh] = []; //每个凭证号映射到一个数组，记录它所在的行号
        map[pzh].push(i); // 记录下凭证号对应的行号

    }

    book.getWorkSheet('detail').paintPermit = false;
    for (pzh in map) {
        var rows = map[pzh];
        $dzpz_dymx_ds.setValue(rows[0], "bz", "");
        for (var i = 1; i < rows.length; i++) {
            $dzpz_dymx_ds.setValue(rows[i], "bz", "与第" + (rows[0] + 1) + "行重复");
        }
    }
    book.getWorkSheet('detail').paintPermit = true;
    hideInfoPane();
}

//@comment (group=按钮点击事件,caption=删除重复的,needRightControl=false)
function cb_removeDuplicated_onClick() {

    $confirm('', '确信要清除重复的凭证号吗?', function () {

        do_removeDuplicated()

    });

}


//@comment (group=do,caption=执行删除重复的,needRightControl=false)
function do_removeDuplicated() {

    showInfoPane("*正在删除重复的凭证");
    book.getWorkSheet('detail').paintPermit = false;
    var pzhs = []; //凭证号清单
    var rows = [];// 需要删除的行号
    for (var i = 0; i < $dzpz_dymx_ds.rowCount; i++) {
        var pzh = $dzpz_dymx_ds.getString(i, "pzh");
        if (pzhs.contains(pzh)) //此凭证号此前已经出现过
        {
            rows.push(i);//  需要删除
        } else {
            pzhs.push(pzh); //没有出现过，那么加它到凭证号清单中
        }
    }
    //现在反着删除
    for (var i = rows.length - 1; i >= 0; i--) {
        $dzpz_dymx_ds.deleteRow(rows[i]);
    }
    //form.save(false);
    book.getWorkSheet('detail').paintPermit = false;
    hideInfoPane();
}



/**
 * 按钮点击事件
 * 当某个按钮被点击时， 首先触发  {按钮名称}_onClick 事件，然后触发 buttonOnClick事件
 * @param sheet  工作表
 * @param cell   按钮所在的单元格
 * @param button 按钮对象
 */
//@comment (group=按钮点击事件,caption=批量删除已选中记录,needRightControl=false)
function cb_selectedRow_delete_onClick(sheet, cell, button) {
    $confirm("提示", "确定要删除选中的记录吗?", function () {
        book.getWorkSheet('detail').paintPermit = false;
        for (let i = $dzpz_dymx_ds.getRowCount() - 1; i >= 0; i--) {
            if ($dzpz_dymx_ds.getInt(i, "selected") == 1) $dzpz_dymx_ds.deleteRow(i);
        }
        if ($dzpz_dymx_ds.getRowCount() == 0) $dzpz_dymx_ds.insertRow(0);
        book.getWorkSheet('detail').cells("st_selectAll").setValue(0);
        book.getWorkSheet('detail').paintPermit = true;
    }, function () { });



}


